script: fix call/dip, add fold/each/unit/cons/cat
This commit is contained in:
parent
053359aaf1
commit
f62dbe9546
139
plugins/script
139
plugins/script
@ -929,37 +929,83 @@ defn (fn_drop)
|
||||
defn (fn_swap)
|
||||
{
|
||||
check_stack (2);
|
||||
struct item *first = pop (ctx);
|
||||
struct item *second = pop (ctx);
|
||||
push (ctx, first);
|
||||
struct item *first = pop (ctx);
|
||||
push (ctx, second);
|
||||
push (ctx, first);
|
||||
return true;
|
||||
}
|
||||
|
||||
defn (fn_call)
|
||||
{
|
||||
check_stack (1);
|
||||
struct item *item = pop (ctx);
|
||||
bool success;
|
||||
// XXX: this behaves differently from if/map/filter
|
||||
if (item->type == ITEM_LIST)
|
||||
success = execute (ctx, get_list (item));
|
||||
else
|
||||
success = execute (ctx, item);
|
||||
item_free (item);
|
||||
struct item *script = pop (ctx);
|
||||
bool success = check_type (ctx, script, ITEM_LIST)
|
||||
&& execute (ctx, get_list (script));
|
||||
item_free (script);
|
||||
return success;
|
||||
}
|
||||
|
||||
defn (fn_dip)
|
||||
{
|
||||
check_stack (2);
|
||||
struct item *item = pop (ctx);
|
||||
if (!fn_call (ctx))
|
||||
{
|
||||
struct item *script = pop (ctx);
|
||||
struct item *item = pop (ctx);
|
||||
bool success = check_type (ctx, script, ITEM_LIST)
|
||||
&& execute (ctx, get_list (script));
|
||||
if (success)
|
||||
push (ctx, item);
|
||||
else
|
||||
item_free (item);
|
||||
item_free (script);
|
||||
return success;
|
||||
}
|
||||
|
||||
defn (fn_unit)
|
||||
{
|
||||
check_stack (1);
|
||||
struct item *item = pop (ctx);
|
||||
push (ctx, new_list (item));
|
||||
return true;
|
||||
}
|
||||
|
||||
defn (fn_cons)
|
||||
{
|
||||
check_stack (2);
|
||||
struct item *list = pop (ctx);
|
||||
struct item *item = pop (ctx);
|
||||
bool success = check_type (ctx, list, ITEM_LIST);
|
||||
item->next = get_list (list);
|
||||
((struct item_list *) list)->head = item;
|
||||
if (success)
|
||||
push (ctx, list);
|
||||
else
|
||||
item_free (list);
|
||||
return success;
|
||||
}
|
||||
|
||||
defn (fn_cat)
|
||||
{
|
||||
check_stack (2);
|
||||
struct item *scnd = pop (ctx);
|
||||
struct item *frst = pop (ctx);
|
||||
if (!check_type (ctx, frst, ITEM_LIST)
|
||||
|| !check_type (ctx, scnd, ITEM_LIST))
|
||||
{
|
||||
item_free (frst);
|
||||
item_free (scnd);
|
||||
return false;
|
||||
}
|
||||
push (ctx, item);
|
||||
|
||||
// XXX: we shouldn't have to do this in O(n)
|
||||
struct item **tail = &((struct item_list *) frst)->head;
|
||||
while (*tail)
|
||||
tail = &(*tail)->next;
|
||||
*tail = get_list (scnd);
|
||||
push (ctx, frst);
|
||||
|
||||
((struct item_list *) scnd)->head = NULL;
|
||||
item_free (scnd);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1054,7 +1100,7 @@ defn (fn_try)
|
||||
bool success = false;
|
||||
if (!check_type (ctx, try, ITEM_LIST)
|
||||
|| !check_type (ctx, catch, ITEM_LIST))
|
||||
goto fail;
|
||||
goto fail;
|
||||
|
||||
if (!execute (ctx, get_list (try)))
|
||||
{
|
||||
@ -1163,6 +1209,59 @@ fail:
|
||||
return success;
|
||||
}
|
||||
|
||||
defn (fn_fold)
|
||||
{
|
||||
check_stack (3);
|
||||
struct item *op = pop (ctx);
|
||||
struct item *null = pop (ctx);
|
||||
struct item *list = pop (ctx);
|
||||
bool success = false;
|
||||
if (!check_type (ctx, op, ITEM_LIST)
|
||||
|| !check_type (ctx, list, ITEM_LIST))
|
||||
{
|
||||
item_free (null);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
push (ctx, null);
|
||||
for (struct item *iter = get_list (list); iter; iter = iter->next)
|
||||
{
|
||||
push (ctx, new_clone (iter));
|
||||
if (!execute (ctx, get_list (op)))
|
||||
goto fail;
|
||||
}
|
||||
success = true;
|
||||
|
||||
fail:
|
||||
item_free (op);
|
||||
item_free (list);
|
||||
return success;
|
||||
}
|
||||
|
||||
defn (fn_each)
|
||||
{
|
||||
check_stack (2);
|
||||
struct item *op = pop (ctx);
|
||||
struct item *list = pop (ctx);
|
||||
bool success = false;
|
||||
if (!check_type (ctx, op, ITEM_LIST)
|
||||
|| !check_type (ctx, list, ITEM_LIST))
|
||||
goto fail;
|
||||
|
||||
for (struct item *iter = get_list (list); iter; iter = iter->next)
|
||||
{
|
||||
push (ctx, new_clone (iter));
|
||||
if (!execute (ctx, get_list (op)))
|
||||
goto fail;
|
||||
}
|
||||
success = true;
|
||||
|
||||
fail:
|
||||
item_free (op);
|
||||
item_free (list);
|
||||
return success;
|
||||
}
|
||||
|
||||
// - - Arithmetic - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
// XXX: why not a `struct item_string *` argument?
|
||||
@ -1534,16 +1633,13 @@ item_list_to_str (const struct item *script, struct buffer *buf)
|
||||
|
||||
// TODO: implement more functions; try to avoid writing it in C
|
||||
//
|
||||
// ? fold
|
||||
// join { list delim -- string } -- string join -> script this
|
||||
//
|
||||
// concat { list list -- list } -- join two lists
|
||||
// -, /, %, ** -- arithmetic
|
||||
// >, !=, <=, >= -- comparison
|
||||
// first -- first character of a string, first element in a list
|
||||
// rest -- [1:] of a string, the "tail" in a list
|
||||
// at { value index -- sub-value } -- get n-th subvalue of a string/list
|
||||
// cons { item value } -- prepend an item to the list/string
|
||||
// <each> step { value program } -- foreach
|
||||
|
||||
static void
|
||||
@ -1577,6 +1673,13 @@ init_runtime_library (void)
|
||||
// List processing
|
||||
register_handler ("map", fn_map);
|
||||
register_handler ("filter", fn_filter);
|
||||
register_handler ("fold", fn_fold);
|
||||
register_handler ("each", fn_each);
|
||||
|
||||
// List manipulation
|
||||
register_handler ("unit", fn_unit);
|
||||
register_handler ("cons", fn_cons);
|
||||
register_handler ("cat", fn_cat);
|
||||
|
||||
// Arithmetic operations
|
||||
register_handler ("*", fn_times);
|
||||
|
Loading…
Reference in New Issue
Block a user