diff options
| author | Přemysl Janouch <p.janouch@gmail.com> | 2017-05-21 09:38:18 +0200 | 
|---|---|---|
| committer | Přemysl Janouch <p.janouch@gmail.com> | 2017-05-21 13:19:48 +0200 | 
| commit | 0f4ece88675c63060daf1b4f9993a69c6c05a58e (patch) | |
| tree | f6826c97a092cc761cce0a4f2cd59cdba3fadebe | |
| parent | 1caec277bfff3fe8df9769368d0d84601acd7944 (diff) | |
| download | ell-0f4ece88675c63060daf1b4f9993a69c6c05a58e.tar.gz ell-0f4ece88675c63060daf1b4f9993a69c6c05a58e.tar.xz ell-0f4ece88675c63060daf1b4f9993a69c6c05a58e.zip  | |
Add "break" for breaking out of loops
| -rwxr-xr-x | ell.c | 29 | 
1 files changed, 25 insertions, 4 deletions
@@ -858,9 +858,10 @@ execute_statement  	item_free_list (*result);  	*result = NULL; -	// In that case, `error' is NULL and there's nothing else to do anyway -	if (!ctx->memory_failure) { -		// This creates some form of a stack trace +	// In that case, `error' is NULL and there's nothing else to do anyway. +	// Errors starting with an underscore are exceptions and would not work +	// with stack traces generated this way. +	if (!ctx->memory_failure && ctx->error[0] != '_') {  		char *tmp = ctx->error;  		set_error (ctx, "%s -> %s", name, tmp);  		free (tmp); @@ -885,12 +886,26 @@ execute (struct context *ctx, struct item *body, struct item **result) {  #define defn(name) static bool name \  	(struct context *ctx, struct item *args, struct item **result) +#define E_BREAK "_break" + +static bool +eat_error (struct context *ctx, const char *name) { +	if (!ctx->error || strcmp (ctx->error, name)) +		return false; + +	free (ctx->error); +	ctx->error = NULL; +	return true; +} +  static bool  truthy (struct item *item) {  	return item  		&& ((item->type == ITEM_STRING && item->len != 0) || item->head);  } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +  defn (fn_set) {  	struct item *name = args;  	if (!name || name->type != ITEM_STRING) @@ -946,7 +961,6 @@ defn (fn_if) {  	return true;  } -// TODO: how to break out of the loop?  Catchable error?  Special value?  defn (fn_for) {  	struct item *list = args, *body;  	if (!list || list->type != ITEM_LIST) @@ -960,12 +974,18 @@ defn (fn_for) {  		bool ok = set_arg (ctx, 0, v)  			&& execute (ctx, body->head, &res);  		item_free_list (res); +		if (eat_error (ctx, E_BREAK)) +			break;  		if (!ok)  			return false;  	}  	return true;  } +defn (fn_break) { +	(void) args; (void) result; return set_error (ctx, E_BREAK); +} +  defn (fn_map) {  	struct item *body = args, *values;  	if (!body || body->type != ITEM_LIST) @@ -1054,6 +1074,7 @@ init_native_library (void)  		&& native_register ("list",   fn_list)  		&& native_register ("if",     fn_if)  		&& native_register ("for",    fn_for) +		&& native_register ("break",  fn_break)  		&& native_register ("map",    fn_map)  		&& native_register ("filter", fn_filter)  		&& native_register ("print",  fn_print)  | 
