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 | 
