@@ -17,6 +17,9 @@ X("<", l2_builtin_lt) | |||
X("<=", l2_builtin_lteq) | |||
X(">", l2_builtin_gt) | |||
X(">=", l2_builtin_gteq) | |||
X("&&", l2_builtin_land) | |||
X("||", l2_builtin_lor) | |||
X("??", l2_builtin_first) | |||
X("print", l2_builtin_print) | |||
X("len", l2_builtin_len) | |||
X("if", l2_builtin_if) |
@@ -134,7 +134,6 @@ void l2_vm_free(struct l2_vm *vm); | |||
void l2_vm_step(struct l2_vm *vm); | |||
void l2_vm_run(struct l2_vm *vm); | |||
size_t l2_vm_gc(struct l2_vm *vm); | |||
int l2_vm_val_is_true(struct l2_vm *vm, l2_word id); | |||
int l2_vm_val_is_true(struct l2_vm *vm, struct l2_vm_value *val); | |||
#endif |
@@ -26,7 +26,10 @@ static int tok_is_infix(struct l2_token *tok) { | |||
strcmp(str, "<") == 0 || | |||
strcmp(str, "<=") == 0 || | |||
strcmp(str, ">") == 0 || | |||
strcmp(str, ">=") == 0; | |||
strcmp(str, ">=") == 0 || | |||
strcmp(str, "&&") == 0 || | |||
strcmp(str, "||") == 0 || | |||
strcmp(str, "??") == 0; | |||
} | |||
static int parse_expression( |
@@ -181,6 +181,46 @@ X(l2_builtin_gt, >) | |||
X(l2_builtin_gteq, >=) | |||
#undef X | |||
l2_word l2_builtin_land(struct l2_vm *vm, l2_word argc, l2_word *argv) { | |||
for (l2_word i = 0; i < argc; ++i) { | |||
struct l2_vm_value *val = &vm->values[argv[i]]; | |||
if (l2_value_get_type(val) == L2_VAL_TYPE_ERROR) { | |||
return argv[i]; | |||
} | |||
if (!l2_vm_val_is_true(vm, val)) { | |||
return vm->kfalse; | |||
} | |||
} | |||
return vm->ktrue; | |||
} | |||
l2_word l2_builtin_lor(struct l2_vm *vm, l2_word argc, l2_word *argv) { | |||
for (l2_word i = 0; i < argc; ++i) { | |||
struct l2_vm_value *val = &vm->values[argv[i]]; | |||
if (l2_value_get_type(val) == L2_VAL_TYPE_ERROR) { | |||
return argv[i]; | |||
} | |||
if (l2_vm_val_is_true(vm, val)) { | |||
return vm->ktrue; | |||
} | |||
} | |||
return vm->kfalse; | |||
} | |||
l2_word l2_builtin_first(struct l2_vm *vm, l2_word argc, l2_word *argv) { | |||
for (l2_word i = 0; i < argc; ++i) { | |||
if (l2_value_get_type(&vm->values[argv[i]]) != L2_VAL_TYPE_NONE) { | |||
return argv[i]; | |||
} | |||
} | |||
return vm->knone; | |||
} | |||
l2_word l2_builtin_print(struct l2_vm *vm, l2_word argc, l2_word *argv) { | |||
for (size_t i = 0; i < argc; ++i) { | |||
if (i != 0) { | |||
@@ -237,7 +277,7 @@ l2_word l2_builtin_if(struct l2_vm *vm, l2_word argc, l2_word *argv) { | |||
return l2_vm_error(vm, "Expected 2 or 3 arguments"); | |||
} | |||
if (l2_vm_val_is_true(vm, argv[0])) { | |||
if (l2_vm_val_is_true(vm, &vm->values[argv[0]])) { | |||
l2_word ret_id = l2_vm_alloc(vm, L2_VAL_TYPE_CONTINUATION, 0); | |||
struct l2_vm_value *ret = &vm->values[ret_id]; | |||
ret->extra.cont_call = argv[1]; | |||
@@ -258,7 +298,7 @@ struct loop_context { | |||
}; | |||
static l2_word loop_callback(struct l2_vm *vm, l2_word retval, l2_word cont) { | |||
if (l2_vm_val_is_true(vm, retval)) { | |||
if (l2_vm_val_is_true(vm, &vm->values[retval])) { | |||
return cont; | |||
} | |||
@@ -302,7 +342,7 @@ static l2_word while_callback(struct l2_vm *vm, l2_word retval, l2_word 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)) { | |||
if (l2_vm_val_is_true(vm, &vm->values[retval])) { | |||
cont->extra.cont_call = ctx->body; | |||
return cont_id; | |||
} else { |
@@ -774,8 +774,7 @@ 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]; | |||
int l2_vm_val_is_true(struct l2_vm *vm, struct l2_vm_value *val) { | |||
l2_word true_atom = vm->values[vm->ktrue].atom; | |||
return l2_value_get_type(val) == L2_VAL_TYPE_ATOM && val->atom == true_atom; | |||
} |
@@ -71,3 +71,26 @@ print (len []) | |||
print (len [10 20]) | |||
print (len "Hello") | |||
print (len {a: 10; b: 20; c: 30}) | |||
print "\n&&" | |||
print &&() | |||
print &&('true) | |||
print &&('false) | |||
print 'true && 'true | |||
print (&& 10 == 10 20 == 20 30 != 40) | |||
print 'true && 10 | |||
print "\n||" | |||
print ||() | |||
print ||('true) | |||
print ||('false) | |||
print 'true || 'true | |||
print 'true || 'false | |||
print (|| 'false 10 'true) | |||
print (|| 'false 10 'nope) | |||
print "\n??" | |||
print none ?? none ?? 30 ?? 20 | |||
print (?? 10 none none) | |||
print (?? none none "hello") | |||
print ??() |
@@ -57,12 +57,12 @@ | |||
(none) | |||
(true) (false) (atom 20) | |||
(true) (false) (atom 23) | |||
100 | |||
100.5 | |||
255 | |||
Hello World | |||
[(none) (true) (false) (atom 20) 100.1 Nope (namespace) (function)] | |||
[(none) (true) (false) (atom 23) 100.1 Nope (namespace) (function)] | |||
(namespace) (namespace) | |||
len | |||
@@ -71,3 +71,26 @@ len | |||
2 | |||
5 | |||
3 | |||
&& | |||
(true) | |||
(true) | |||
(false) | |||
(true) | |||
(true) | |||
(false) | |||
|| | |||
(false) | |||
(true) | |||
(false) | |||
(true) | |||
(true) | |||
(true) | |||
(false) | |||
?? | |||
30 | |||
10 | |||
hello | |||
(none) |