| $esc:(#include <stdlib.h>) |
| $esc:(#include <stdio.h>) |
| |
| /* |
| * The environment is an opaque type known only to the C implementation. |
| * |
| * It is actually empty but is needed by the cogent to demonstrate that |
| * there is some value that is being changed by the operations on things |
| * outside of the code itself. |
| * |
| * It essentially represents 'the world' to the program. |
| */ |
| typedef void *Env; |
| |
| /* |
| * This is how we embed the code generated by the cogent compiler. |
| * |
| * The makefile is configured to ensure the cogent output is produced as |
| * 'generated.c'. |
| */ |
| #include "generated.c" |
| |
| /* |
| * Our implementation of show_u32 just prints the value using printf. |
| * We need to pass the environment back afterwards which was 'mutated' |
| * by the act of printing to standard output. |
| */ |
| $ty:(Env) show_u32 ($ty:((Env, U32)) args) { |
| printf("%d", args.p2); |
| return args.p1; |
| } |
| |
| /* |
| * As above but for strings being printed directly. |
| */ |
| $ty:(Env) show_string ($ty:((Env, String)) args) { |
| fputs(args.p2, stdout); |
| return args.p1; |
| } |
| |
| /* |
| * This implementation of iterate is fairly straightforward. The |
| * iterator is just a starting value, a condition function, and the loop |
| * body. We just plug all of the sections into the appropriate parts of |
| * a while loop and let it run. |
| */ |
| $ty:(a) $id:iterate ($ty:(Iterator a) iter) { |
| $ty:(a) curr = iter.curr; |
| $ty:(<Continue | Stop>) proceed; |
| |
| proceed = (($spec:(IterCondition a)) iter.condition) (curr); |
| while (proceed.tag == TAG_ENUM_Continue) { |
| curr = (($spec:(IterStep a)) iter.step) (curr); |
| proceed = (($spec:(IterCondition a)) iter.condition) (curr); |
| } |
| |
| /* |
| * We need to return the final value of the loop. This is especially |
| * important if it is or contains any heap values that would |
| * otherwise be leaked but this also contains all of the information |
| * for what has actually occurred in the loop. |
| */ |
| return curr; |
| } |
| |
| /* |
| * Main here just creates 'the world' and passes it to the cogent |
| * program. The cogent program mutates it and we get the result. |
| */ |
| int main(void) { |
| $ty:(Env) env = NULL; |
| env = $esc:prog(env); |
| |
| return EXIT_SUCCESS; |
| } |