Here are some examples (with $-macros) for Cake:
Array Templates
/* copy baz into foo */
/* Two ways to use "$each": */
/* Easier to read, more overhead, can nest */
$each(value, foo) {
printf("%d ", *value);
*value += 1;
}
$print();
/* jQuery-ish syntax, faster, can't nest */
$each(value, foo, {
printf("%d ", *value);
*value += 1;
}) /* <-- Must remember ')' */
Exceptions
/* copy bar into foo */
/* begin try block */
/* Define Array Type */
#define ARRAY_TYPE int
/* Add Extra Member Functions */#define ARRAY_CAKE_TYPE _CAKE_INTEGRAL_TYPE
/*
Define Array_int */
#include <cake/tpl/Array.h>
$main() {
/* foo will be cleaned up @ end of scope */ $
Array(int) f
oo = $new(Array_int);
/* bar will NOT be cleaned up @ end of scope */
Array_int bar;
int b
az[] = {0, 1, 2, 3};
/* copy baz into foo */
$from_c_array
(foo, baz);
/* call "foo.duplicate()" */
bar = $(foo, duplicate);
$print
(foo);
printf("sum = %d\n", $(foo, sum));
/* Two ways to use "$each": */
/* Easier to read, more overhead, can nest */
$each(value, foo) {
printf("%d ", *value);
*value += 1;
}
$print();
/* jQuery-ish syntax, faster, can't nest */
$each(value, foo, {
printf("%d ", *value);
*value += 1;
}) /* <-- Must remember ')' */
$print();
$cleanup(bar); // <-- Must manually clean up
return 0;
}
/* Output:
[0, 1, 2, 3]
sum = 6
0 1 2 3
1 2 3 4
*/
/* Define Array Type */
#define ARRAY_TYPE int
/* Add Extra Member Functions */
#define ARRAY_CAKE_TYPE _CAKE_INTEGRAL_TYPE
/*
Define Array_int */
#include <cake/tpl/Array.h>
$main() {
/* foo will be cleaned up @ end of scope */
$Array(int) foo = $new(Array_int);
int b
ar[] = {0, 1, 2, 3};
/* copy bar into foo */
$from_c_array(foo, bar);
/* begin try block */
$try {
/* automatically increases foo's length */ $
(foo, push_back, 3);
$
(foo, push_back, 7);
printf("foo[270] = %d\n", $(foo, get, 270));
}
/* catch exceptions */
$except(OutOfRange) {
$error("$len(foo) = %d.\n", $len(foo));
}
/* $finally must appear */
$finally {}
return 0;
}
/* Output (stderr):
exception_test.c:27:main :: $len(foo) = 6.
*/
Variadic Math Functions
Ruby-like Block Syntax for Callbacks
#include <cake/Cake.h>
$main() {
printf("%f\n", $avg(1.0, 3, 6, 8.0f))
;
printf("%f\n", $min(-4.3, 99, 428, 4));
return 0;
}
/* Output:
5.5
-4.3
*/
Ruby-like Block Syntax for Callbacks
#include <cake/Cake.h>
/* Define my_int */
typedef struct {
int var;
} my_int;
/* Define Array Type */#define ARRAY_TYPE my_int
/*
Define Array_my_int */
#include <cake/tpl/Array.h>
/* Define Array Type */
#define ARRAY_TYPE int
/* Add Extra Member Functions */#define ARRAY_CAKE_TYPE _CAKE_INTEGRAL_TYPE
/*
Define Array_int */
#include <cake/tpl/Array.h>
$main() {
/* foo will be cleaned up @ end of scope */
$Array(my_int) foo = $new(Array_my_int);
/* bar will be cleaned up @ end of scope */
$Array(int) bar = $new(Array_int);
int b
az[] = {0, 1, 2, 3};
/* Two ways to use "$from_c_array": */
/* Automatic, if array types are the same */
$from_c_array(bar, baz);
/* Define a lambda function to use */
$from_c_array(foo, baz, (val), {
my_int ret = { .var = val };
return ret;
}) /* <-- Remember ')' */
/* GCC supports nested functions */
void myprint(my_int val) {
printf("%d ", val.var);
}
int increment(int value) {
return value + 1;
}
int sum(int val1, my_int val2) {
return val1 + val2.var;
}
/* Call myprint with each element in foo */
$(foo, each, myprint);
$print();
/* The following memory leak is caught */
$map(bar, sum, bar, foo);
$print(bar);
return 0;
}
/* Output:
0 1 2 3
[0, 2, 4, 6]
*/
#include <stdio.h>
#include <cake/Cake_Minimal.h>
$main() {
/* Define a python-like generator function */
$generator(fib, int, int a = 0, int b = 1)
while (1) {
/* return a value, and ... */
$yield(b);
/* execution will resume here next call */
b = a + b;
a = b - a;
}
$end
/* <-- Remember $end */
for (int i = 0; i < 10; i++) {
printf("%d\n", fib());
}
return 0;
}
/* Output:
1
1
2
3
5
8
13
21
34
55
*/
Knuth's Coroutines (State Machines)
#include <stdio.h>
#include <cake/Cake_Minimal.h>
$main() {
/* Declare the coroutines that will be used */
coroutine x, y;
char buffer[50];
/* Define the coroutine x */
$coroutine(x)
while (1) {
sprintf(buffer, "Hello ");
$yield_to(y); /* <-- Note $yield_to() */
}
$end /* <-- Remember $end */
/* Define the coroutine y */
$coroutine(y)
while (1) {
printf("%s World!\n", buffer);
$yield_to(NULL); /* <-- finish */
}
$end /* <-- Remember $end */
/* This macro allows for stack-less execution.
* Pass it the coroutine to start with and
* it will exit when a coroutine yields to NULL
*/
$start_with(x);
return 0;
}
/* Output:
Hello World!
*/
#include <stdio.h>
#include <string.h>
#include <cake/Cake_Minimal.h>
/* Declare the tuple types globally. Be aware,
* there will be issues (like most things in C)
* if they are declared multiple times. */
$tuple_t(int, int);
$tuple_t(int, int, char);
/* A function that returns a tuple */
$tuple_t(int, int, char);
/* A function that returns a tuple */
$tuple(int, int) return2() {
/* Important Syntax! */
/* Important Syntax! */
return ($tuple(int, int)){ 0, 1 };
}
$main() {
int a, b;
/* foo can hold a $tuple(int, int) */
$tuple(int, int) foo;
foo = return2();
/* You can unpack tuples into variables */
$tuple_unpack(return2(), a, b);
/* $tuple_len = the number of elements */
printf("Length = %d\n", $tuple_len(foo));
/* all tuples are statically enumerable */
printf("(%d, %d)\n", $enumerate(foo, 2));
/* $enumerate requires an unsigned integer
* literal. "$enumerate(foo, $tuple_len(foo))"
* is invalid */
* literal. "$enumerate(foo, $tuple_len(foo))"
* is invalid */
int accept3 ($tuple(int, int, char) t) {
return 1;
}
$tuple(int, int, char) bar = { 2, 3, 'g' };
printf("%d\n", accept3(bar));
return 0;
}
/* Output:
Length = 2
(0, 1)
1
*/
/* Output:
Length = 2
(0, 1)
1
*/
#include <stdio.h>
#include <cake/Cake_Minimal.h>
/* $named_prototype requires these args:
* 1: (comma-separated attribute list)
* 2: return type
* 3: function name
* 4+: Each arg to the function must be a pair
* of (type, name) */
$named_prototype((),
void,foo,(int,x),(int,y));void foo( int x, int y ) {
printf("(%d, %d)\n" x, y );
}
$main() {
/* named call */
$named_call(foo, y = 4, x = 5);
/* regular call */
foo(4, 5);
return 0;
}
/* Output:
(5, 4)
(4, 5)
*/