Replace for/break with a try/throw mechanism
This commit is contained in:
parent
aa4b4391f3
commit
1de758b6d6
47
ell.c
47
ell.c
|
@ -852,18 +852,6 @@ set_single_argument (struct context *ctx, struct item *item) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#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 struct item *
|
static struct item *
|
||||||
new_number (double n) {
|
new_number (double n) {
|
||||||
char *s;
|
char *s;
|
||||||
|
@ -946,31 +934,6 @@ defn (fn_if) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
defn (fn_for) {
|
|
||||||
struct item *list = args, *body;
|
|
||||||
if (!list || list->type != ITEM_LIST)
|
|
||||||
return set_error (ctx, "first argument must be a list");
|
|
||||||
if (!(body = list->next) || body->type != ITEM_LIST)
|
|
||||||
return set_error (ctx, "second argument must be a function");
|
|
||||||
|
|
||||||
(void) result;
|
|
||||||
for (struct item *v = list->head; v; v = v->next) {
|
|
||||||
struct item *res = NULL;
|
|
||||||
bool ok = set_single_argument (ctx, 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) {
|
defn (fn_map) {
|
||||||
struct item *body = args, *values;
|
struct item *body = args, *values;
|
||||||
if (!body || body->type != ITEM_LIST)
|
if (!body || body->type != ITEM_LIST)
|
||||||
|
@ -1214,8 +1177,12 @@ init_runtime_library (struct context *ctx) {
|
||||||
const char *definition; ///< The defining script
|
const char *definition; ///< The defining script
|
||||||
} functions[] = {
|
} functions[] = {
|
||||||
{ "unless", "arg _cond _body; if (not (@_cond)) @_body" },
|
{ "unless", "arg _cond _body; if (not (@_cond)) @_body" },
|
||||||
{ "filter", "arg _body _list; map {"
|
{ "filter", "arg _body _list;"
|
||||||
"arg _item; if (@_body @_item) { @_item } } @_list" },
|
"map { arg _i; if (@_body @_i) { @_i } } @_list" },
|
||||||
|
{ "for", "arg _list _body;"
|
||||||
|
"try { map {arg _i; @_body @_i } @_list"
|
||||||
|
"} { arg _e; if (ne? @_e _break) { throw @e } }" },
|
||||||
|
{ "break", "throw _break" },
|
||||||
// TODO: we should be able to apply them to all arguments
|
// TODO: we should be able to apply them to all arguments
|
||||||
{ "ne?", "arg _ne1 _ne2; not (eq? @_ne1 @_ne2)" },
|
{ "ne?", "arg _ne1 _ne2; not (eq? @_ne1 @_ne2)" },
|
||||||
{ "ge?", "arg _ge1 _ge2; not (lt? @_ge1 @_ge2)" },
|
{ "ge?", "arg _ge1 _ge2; not (lt? @_ge1 @_ge2)" },
|
||||||
|
@ -1251,8 +1218,6 @@ init_runtime_library (struct context *ctx) {
|
||||||
&& native_register (ctx, "set", fn_set)
|
&& native_register (ctx, "set", fn_set)
|
||||||
&& native_register (ctx, "list", fn_list)
|
&& native_register (ctx, "list", fn_list)
|
||||||
&& native_register (ctx, "if", fn_if)
|
&& native_register (ctx, "if", fn_if)
|
||||||
&& native_register (ctx, "for", fn_for)
|
|
||||||
&& native_register (ctx, "break", fn_break)
|
|
||||||
&& native_register (ctx, "map", fn_map)
|
&& native_register (ctx, "map", fn_map)
|
||||||
&& native_register (ctx, "print", fn_print)
|
&& native_register (ctx, "print", fn_print)
|
||||||
&& native_register (ctx, "..", fn_concatenate)
|
&& native_register (ctx, "..", fn_concatenate)
|
||||||
|
|
|
@ -2,10 +2,18 @@ set greet {
|
||||||
arg _name
|
arg _name
|
||||||
print 'hello ' @_name '\n'
|
print 'hello ' @_name '\n'
|
||||||
}
|
}
|
||||||
|
set decr {
|
||||||
|
arg _name
|
||||||
|
set @_name (- @@_name 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
set limit 2
|
||||||
for (map { arg _x; .. @_x ! } [
|
for (map { arg _x; .. @_x ! } [
|
||||||
world
|
world
|
||||||
creator
|
creator
|
||||||
|
'darkness, my old friend'
|
||||||
]) {
|
]) {
|
||||||
arg _whom
|
arg _whom
|
||||||
greet @_whom
|
greet @_whom
|
||||||
|
if (= 0 (decr limit)) { break }
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue