Implement while

This commit is contained in:
Laria 2022-10-31 15:51:56 +01:00
parent 742bd66b46
commit 97d79754dd
5 changed files with 75 additions and 0 deletions

View file

@ -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)

View file

@ -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

View file

@ -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)
{

View 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

View file

@ -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},
};