Implement while
This commit is contained in:
parent
742bd66b46
commit
97d79754dd
5 changed files with 75 additions and 0 deletions
|
|
@ -64,6 +64,7 @@ functionaltest("len")
|
|||
functionaltest("not")
|
||||
functionaltest("type")
|
||||
functionaltest("if")
|
||||
functionaltest("while")
|
||||
|
||||
install(TARGETS apfl DESTINATION lib)
|
||||
install(TARGETS apfl-bin DESTINATION bin)
|
||||
|
|
|
|||
|
|
@ -657,6 +657,8 @@ enum apfl_value_type apfl_get_type(apfl_ctx, apfl_stackidx);
|
|||
void apfl_drop(apfl_ctx, apfl_stackidx);
|
||||
// Move a value to the top of the stack
|
||||
void apfl_move_to_top_of_stack(apfl_ctx, apfl_stackidx);
|
||||
// Copy a value to the top of the stack
|
||||
void apfl_copy(apfl_ctx ctx, apfl_stackidx index);
|
||||
// Push a nil onto the stack
|
||||
void apfl_push_nil(apfl_ctx);
|
||||
// Push a boolean onto the stack
|
||||
|
|
|
|||
|
|
@ -427,6 +427,13 @@ apfl_move_to_top_of_stack(apfl_ctx ctx, apfl_stackidx index)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
apfl_copy(apfl_ctx ctx, apfl_stackidx index)
|
||||
{
|
||||
struct apfl_value value = apfl_stack_must_get(ctx, index);
|
||||
apfl_stack_must_push(ctx, apfl_value_set_cow_flag(value));
|
||||
}
|
||||
|
||||
void
|
||||
apfl_stack_clear(apfl_ctx ctx)
|
||||
{
|
||||
|
|
|
|||
28
src/functional-tests/while.at
Normal file
28
src/functional-tests/while.at
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
===== script =====
|
||||
i = 0
|
||||
while { (not (== i 10)) } {
|
||||
print i
|
||||
i = + i 1
|
||||
}
|
||||
|
||||
i = 0
|
||||
print (while { (not (== i 10)) } {
|
||||
i = + i 1
|
||||
* 10 i
|
||||
})
|
||||
|
||||
print (while {false} {"fail"})
|
||||
|
||||
===== output =====
|
||||
0
|
||||
1
|
||||
2
|
||||
3
|
||||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
8
|
||||
9
|
||||
100
|
||||
nil
|
||||
|
|
@ -274,6 +274,42 @@ type(apfl_ctx ctx)
|
|||
apfl_push_const_string(ctx, typestr(apfl_get_type(ctx, -1)));
|
||||
}
|
||||
|
||||
static void
|
||||
impl_while(apfl_ctx ctx)
|
||||
{
|
||||
size_t argc = apfl_len(ctx, 0);
|
||||
if (argc != 2) {
|
||||
apfl_raise_const_error(ctx, APFL_RESULT_ERR, "while needs 2 functions as arguments");
|
||||
}
|
||||
|
||||
apfl_get_list_member_by_index(ctx, 0, 0);
|
||||
if (apfl_get_type(ctx, -1) != APFL_VALUE_FUNC) {
|
||||
apfl_raise_const_error(ctx, APFL_RESULT_ERR, "while needs 2 functions as arguments");
|
||||
}
|
||||
apfl_get_list_member_by_index(ctx, 0, 1);
|
||||
if (apfl_get_type(ctx, -1) != APFL_VALUE_FUNC) {
|
||||
apfl_raise_const_error(ctx, APFL_RESULT_ERR, "while needs 2 functions as arguments");
|
||||
}
|
||||
|
||||
apfl_drop(ctx, 0);
|
||||
|
||||
apfl_push_nil(ctx); // Return value in case of no iteration
|
||||
|
||||
for (;;) {
|
||||
apfl_copy(ctx, 0);
|
||||
apfl_list_create(ctx, 0);
|
||||
apfl_call(ctx, -2, -1);
|
||||
if (!apfl_is_truthy(ctx, -1)) {
|
||||
break;
|
||||
}
|
||||
|
||||
apfl_drop(ctx, -1);
|
||||
apfl_copy(ctx, 1);
|
||||
apfl_list_create(ctx, 0);
|
||||
apfl_call(ctx, -2, -1);
|
||||
}
|
||||
}
|
||||
|
||||
static const struct global_def globals[] = {
|
||||
{"if", impl_if},
|
||||
{"==", impl_eq},
|
||||
|
|
@ -288,6 +324,7 @@ static const struct global_def globals[] = {
|
|||
{"not", not},
|
||||
{"len", len},
|
||||
{"type", type},
|
||||
{"while", impl_while},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue