Browse Source

while function

master
Martin Dørum 7 months ago
parent
commit
ea4271543e
3 changed files with 62 additions and 4 deletions
  1. 1
    0
      include/lang2/builtins.x.h
  2. 59
    3
      lib/vm/builtins.c
  3. 2
    1
      lib/vm/vm.c

+ 1
- 0
include/lang2/builtins.x.h View File

@@ -21,4 +21,5 @@ X("print", l2_builtin_print)
X("len", l2_builtin_len)
X("if", l2_builtin_if)
X("loop", l2_builtin_loop)
X("while", l2_builtin_while)
#endif

+ 59
- 3
lib/vm/builtins.c View File

@@ -321,7 +321,7 @@ l2_word l2_builtin_if(struct l2_vm *vm, l2_word argc, l2_word *argv) {

struct loop_context {
struct l2_vm_contcontext base;
l2_word cond;
l2_word func;
};

static l2_word loop_callback(struct l2_vm *vm, l2_word retval, l2_word cont) {
@@ -335,7 +335,7 @@ static l2_word loop_callback(struct l2_vm *vm, l2_word retval, l2_word cont) {
static void loop_marker(
struct l2_vm *vm, void *data, void (*mark)(struct l2_vm *vm, l2_word id)) {
struct loop_context *ctx = data;
mark(vm, ctx->cond);
mark(vm, ctx->func);
}

l2_word l2_builtin_loop(struct l2_vm *vm, l2_word argc, l2_word *argv) {
@@ -350,11 +350,67 @@ l2_word l2_builtin_loop(struct l2_vm *vm, l2_word argc, l2_word *argv) {

ctx->base.callback = loop_callback;
ctx->base.marker = loop_marker;
ctx->func = argv[0];

l2_word cont_id = l2_vm_alloc(vm, L2_VAL_TYPE_CONTINUATION, 0);
struct l2_vm_value *cont = &vm->values[cont_id];
cont->extra.cont_call = ctx->func;
cont->cont = &ctx->base;
return cont_id;
}

struct while_context {
struct l2_vm_contcontext base;
l2_word cond, body;
};

static l2_word while_callback(struct l2_vm *vm, l2_word retval, l2_word cont_id) {
struct l2_vm_value *cont = &vm->values[cont_id];
struct while_context *ctx = (struct while_context *)cont->cont;

if (cont->extra.cont_call == ctx->cond) {
if (l2_vm_val_is_true(vm, retval)) {
cont->extra.cont_call = ctx->body;
return cont_id;
} else {
return retval;
}
} else {
struct l2_vm_value *ret = &vm->values[retval];
if (l2_value_get_type(ret) == L2_VAL_TYPE_ERROR) {
return retval;
} else {
cont->extra.cont_call = ctx->cond;
return cont_id;
}
}
}

static void while_marker(
struct l2_vm *vm, void *data, void (*mark)(struct l2_vm *vm, l2_word id)) {
struct while_context *ctx = data;
mark(vm, ctx->cond);
mark(vm, ctx->body);
}

l2_word l2_builtin_while(struct l2_vm *vm, l2_word argc, l2_word *argv) {
if (argc != 2) {
return l2_vm_error(vm, "Expected 2 arguments");
}

struct while_context *ctx = malloc(sizeof(*ctx));
if (ctx == NULL) {
return l2_vm_error(vm, "Allocation failure");
}

ctx->base.callback = while_callback;
ctx->base.marker = while_marker;
ctx->cond = argv[0];
ctx->body = argv[1];

l2_word cont_id = l2_vm_alloc(vm, L2_VAL_TYPE_CONTINUATION, 0);
struct l2_vm_value *cont = &vm->values[cont_id];
cont->extra.cont_call = argv[0];
cont->extra.cont_call = ctx->cond;
cont->cont = &ctx->base;
return cont_id;
}

+ 2
- 1
lib/vm/vm.c View File

@@ -744,5 +744,6 @@ void l2_vm_step(struct l2_vm *vm) {

int l2_vm_val_is_true(struct l2_vm *vm, l2_word id) {
struct l2_vm_value *val = &vm->values[id];
return l2_value_get_type(val) == L2_VAL_TYPE_ATOM && val->atom == vm->ktrue;
l2_word true_atom = vm->values[vm->ktrue].atom;
return l2_value_get_type(val) == L2_VAL_TYPE_ATOM && val->atom == true_atom;
}

Loading…
Cancel
Save