Browse Source

get back to the main loop in continuations

master
Martin Dørum 3 years ago
parent
commit
941da859b5
3 changed files with 46 additions and 17 deletions
  1. 6
    1
      cmd/main.c
  2. 2
    1
      include/lang2/vm/vm.h
  3. 38
    15
      lib/vm/vm.c

+ 6
- 1
cmd/main.c View File

while (!vm->halted) { while (!vm->halted) {
size_t iptr = vm->iptr; size_t iptr = vm->iptr;
printf("\n======\n\n(%d) Will run instr: ", vm->iptr); printf("\n======\n\n(%d) Will run instr: ", vm->iptr);
l2_vm_print_op(vm->ops, vm->opslen, &iptr);
if (vm->need_check_retval) {
printf("(internal)\n");
} else {
l2_vm_print_op(vm->ops, vm->opslen, &iptr);
}

if (fgets(buf, sizeof(buf), stdin) == NULL) { if (fgets(buf, sizeof(buf), stdin) == NULL) {
break; break;
} }

+ 2
- 1
include/lang2/vm/vm.h View File



struct l2_vm { struct l2_vm {
int halted; int halted;
int gc_scheduled;
int need_gc;
int need_check_retval;
unsigned char *ops; unsigned char *ops;
size_t opslen; size_t opslen;
l2_word iptr; l2_word iptr;

+ 38
- 15
lib/vm/vm.c View File



vm->values = realloc(vm->values, sizeof(*vm->values) * vm->valuessize); vm->values = realloc(vm->values, sizeof(*vm->values) * vm->valuessize);
} else { } else {
vm->gc_scheduled = 1;
vm->need_gc = 1;
} }
} }


gc_mark_namespace(vm, val); gc_mark_namespace(vm, val);
} else if (typ == L2_VAL_TYPE_FUNCTION) { } else if (typ == L2_VAL_TYPE_FUNCTION) {
gc_mark(vm, val->func.ns); gc_mark(vm, val->func.ns);
} else if (typ == L2_VAL_TYPE_CONTINUATION && val->cont != NULL) {
if (val->cont->marker != NULL) {
val->cont->marker(vm, val->cont, gc_mark);
}
if (val->cont->args != 0) {
gc_mark(vm, val->cont->args);
} else if (typ == L2_VAL_TYPE_CONTINUATION) {
gc_mark(vm, val->extra.cont_call);
if (val->cont != NULL) {
if (val->cont->marker != NULL) {
val->cont->marker(vm, val->cont, gc_mark);
}
if (val->cont->args != 0) {
gc_mark(vm, val->cont->args);
}
} }
} }
} }
vm->std_error = &std_error.w; vm->std_error = &std_error.w;


vm->halted = 0; vm->halted = 0;
vm->gc_scheduled = 0;
vm->need_gc = 0;
vm->need_check_retval = 0;
vm->ops = ops; vm->ops = ops;
vm->opslen = opslen; vm->opslen = opslen;
vm->iptr = 0; vm->iptr = 0;
struct l2_vm *vm, l2_word func_id, struct l2_vm *vm, l2_word func_id,
l2_word argc, l2_word *argv); l2_word argc, l2_word *argv);


static void after_cfunc_return(struct l2_vm *vm) {
if (
l2_value_get_type(&vm->values[vm->stack[vm->sptr - 1]]) ==
L2_VAL_TYPE_CONTINUATION ||
(vm->sptr >= 2 &&
l2_value_get_type(&vm->values[vm->stack[vm->sptr - 2]]) ==
L2_VAL_TYPE_CONTINUATION)) {
vm->need_check_retval = 1;
}
}

static void after_func_return(struct l2_vm *vm) { static void after_func_return(struct l2_vm *vm) {
// TODO: Rewrite parts of this into a loop. Currently, continuously calling
// a C function with continuations will stack overflow.
struct l2_vm_value *ret = &vm->values[vm->stack[vm->sptr - 1]]; struct l2_vm_value *ret = &vm->values[vm->stack[vm->sptr - 1]];


// If the function returns a continuation, we leave that continuation // If the function returns a continuation, we leave that continuation


// C functions are called differently from language functions // C functions are called differently from language functions
if (typ == L2_VAL_TYPE_CFUNCTION) { if (typ == L2_VAL_TYPE_CFUNCTION) {
// Make this a while loop, because using call_func would
// make the call stack depth unbounded
vm->stack[vm->sptr++] = func->cfunc(vm, argc, argv); vm->stack[vm->sptr++] = func->cfunc(vm, argc, argv);
after_func_return(vm);
after_cfunc_return(vm);
return; return;
} }


} }


void l2_vm_step(struct l2_vm *vm) { void l2_vm_step(struct l2_vm *vm) {
if (vm->need_check_retval) {
vm->need_check_retval = 0;
after_func_return(vm);

if (vm->need_gc) {
vm->need_gc = 0;
l2_vm_gc(vm);
}

return;
}

enum l2_opcode opcode = (enum l2_opcode)vm->ops[vm->iptr++]; enum l2_opcode opcode = (enum l2_opcode)vm->ops[vm->iptr++];


l2_word word; l2_word word;
break; break;
} }


if (vm->gc_scheduled) {
if (vm->need_gc) {
vm->need_gc = 0;
l2_vm_gc(vm); l2_vm_gc(vm);
vm->gc_scheduled = 0;
} }
} }



Loading…
Cancel
Save