diff options
-rw-r--r-- | examples/fib.fwd | 3 | ||||
-rw-r--r-- | examples/guard.fwd | 33 | ||||
-rw-r--r-- | examples/uniq.fwd | 15 | ||||
-rw-r--r-- | lib/fwdlib.hpp | 20 | ||||
-rw-r--r-- | src/lower.c | 17 | ||||
-rw-r--r-- | src/parser.y | 24 |
6 files changed, 94 insertions, 18 deletions
diff --git a/examples/fib.fwd b/examples/fib.fwd index 44ced4a..be2b63f 100644 --- a/examples/fib.fwd +++ b/examples/fib.fwd @@ -14,6 +14,9 @@ fib(int n, (int) res) } } +/* 'extern' println */ +fwd_println(int n); + main() { fib(6) => int n; diff --git a/examples/guard.fwd b/examples/guard.fwd new file mode 100644 index 0000000..6af570d --- /dev/null +++ b/examples/guard.fwd @@ -0,0 +1,33 @@ +/* 'any' doesn't actually exist but at the moment I'm not checking types so as + * long as there's some type identifier here the compiler will not complain, + * will eventually have to fix */ +fwd_println(any a); + +guard(bool cond, () err, () ok) +{ + if cond { + err(); + } else { + ok(); + } +} + +try_print_one(int a) +{ + guard(a < 1) => { + fwd_println("smaller than 1"); + } => ; + + guard(a > 1) => { + fwd_println("larger than 1"); + } => ; + + fwd_println(a); +} + +main() +{ + try_print_one(0); + try_print_one(1); + try_print_one(2); +} diff --git a/examples/uniq.fwd b/examples/uniq.fwd index fa7504a..5945d65 100644 --- a/examples/uniq.fwd +++ b/examples/uniq.fwd @@ -1,5 +1,15 @@ /* not entirely sure about the final syntax just yet but something like this */ +/* 'extern' functions (though some should probably be generic?) */ +fwd_getline( + (optional![string]) next); + +fwd_some(optional![string] o, + (string) next); + +fwd_insert(unordered_set![string] set, string line, + (unordered_set![string]) next); + /* at some point I'll probably add in a type system as well, but for now let's * pretend we're static-dynamic (or dynamic at compiletime? dunno) */ readlines(unordered_set![string] set, (unordered_set![string]) next) @@ -19,6 +29,11 @@ readlines(unordered_set![string] set, (unordered_set![string]) next) } } +fwd_foreach(unordered_set![string] set, + (string) callback); + +fwd_println(string s); + main() { /* fwdlib.hpp uses namespace std, not good practice but allows us to do diff --git a/lib/fwdlib.hpp b/lib/fwdlib.hpp index 3efac61..5c52f65 100644 --- a/lib/fwdlib.hpp +++ b/lib/fwdlib.hpp @@ -10,23 +10,15 @@ using namespace std; -static void fwd_if(auto cond, auto ok, auto fail) -{ - if (cond) - ok(); - else - fail(); -} - static void fwd_getline(auto next) { if (cin.eof()) - next(optional<string>{}); + return next(optional<string>{}); if (string line; getline(cin, line)) - next(optional<string>{line}); + return next(optional<string>{line}); else - next(optional<string>{}); + return next(optional<string>{}); } static void fwd_foreach(auto container, auto next) @@ -38,15 +30,15 @@ static void fwd_foreach(auto container, auto next) static void fwd_some(auto option, auto ok, auto fail) { if (option) - ok(std::move(option.value())); + return ok(std::move(option.value())); else - fail(); + return fail(); } static void fwd_insert(auto container, auto elem, auto next) { container.insert(std::move(elem)); - next(std::move(container)); + return next(std::move(container)); } static void fwd_println(auto elem) diff --git a/src/lower.c b/src/lower.c index 35d16fe..4b9fae9 100644 --- a/src/lower.c +++ b/src/lower.c @@ -123,6 +123,11 @@ static int lower_type_construct(struct type *type) static int lower_type_callable(struct type *type) { + /* std::function has a slight overhead compared to just using auto here, + * but auto doesn't play well with recursive templates like with our + * fib.fwd example, so use std::function for now. Eventually I might + * instead write a C backend or something to have more control over the + * exact semantics, but for now this is good enough. */ printf("std::function<void("); if (lower_types(tcallable_args(type))) @@ -317,8 +322,10 @@ static int lower_if(struct state *state, struct ast *stmt) if (lower_block(state, if_body(stmt))) return -1; - if (!if_else(stmt)) + if (!if_else(stmt)) { + printf("\n"); return 0; + } printf(" else "); if (lower_block(state, if_else(stmt))) @@ -403,6 +410,11 @@ static int lower_closure(struct state *state, struct ast *closure) static int lower_proto(struct ast *proc) { + /* 'extern' functions should be provided to us by whatever framework the + * user is using */ + if (!proc_body(proc)) + return 0; + if (strcmp("main", proc_id(proc)) == 0) printf("int "); else @@ -419,6 +431,9 @@ static int lower_proto(struct ast *proc) static int lower_proc(struct ast *proc) { + if (!proc_body(proc)) + return 0; + if (strcmp("main", proc_id(proc)) == 0) printf("int "); else diff --git a/src/parser.y b/src/parser.y index 97a700e..9f532b9 100644 --- a/src/parser.y +++ b/src/parser.y @@ -93,8 +93,8 @@ %left "::" %nterm <node> top unit proc call closure var expr statement body -%nterm <node> vars exprs statements closures -%nterm <node> opt_vars opt_exprs opt_statements +%nterm <node> vars exprs statements closures trailing_closure +%nterm <node> opt_vars opt_exprs opt_statements opt_trailing_closure %nterm <node> rev_vars rev_exprs rev_closures rev_statements %nterm <node> let if unop binop construct @@ -197,6 +197,9 @@ proc : ID "(" opt_vars ")" body { $$ = gen_proc($[ID], $[opt_vars], NULL, $[body], src_loc(@$)); } + | ID "(" opt_vars ")" ";" { + $$ = gen_proc($[ID], $[opt_vars], NULL, NULL, src_loc(@$)); + } binop : expr "+" expr { $$ = gen_binop(AST_ADD, $1, $3, src_loc(@$)); } @@ -276,8 +279,22 @@ rev_closures : rev_closures closure { $$ = $2; $2->n = $1; } | closure +trailing_closure + : "=>" opt_vars ";" { $$ = gen_closure($[opt_vars], NULL, src_loc(@$));} + +opt_trailing_closure + : trailing_closure + | { $$ = NULL; } + closures - : rev_closures { $$ = reverse_ast_list($1); } + : rev_closures opt_trailing_closure { + if ($[opt_trailing_closure]) { + $[opt_trailing_closure]->n = $[rev_closures]; + $$ = reverse_ast_list($[opt_trailing_closure]); + } else { + $$ = reverse_ast_list($[rev_closures]); + } + } call : expr "(" opt_exprs ")" ";" { @@ -307,6 +324,7 @@ statement : call | let | if + | body | ";" { $$ = gen_empty(src_loc(@$)); } rev_statements |