Browse Source

add operators &&, ||, ??

master
Martin Dørum 3 years ago
parent
commit
bbbd0716ca

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

X("<=", l2_builtin_lteq) X("<=", l2_builtin_lteq)
X(">", l2_builtin_gt) X(">", l2_builtin_gt)
X(">=", l2_builtin_gteq) X(">=", l2_builtin_gteq)
X("&&", l2_builtin_land)
X("||", l2_builtin_lor)
X("??", l2_builtin_first)
X("print", l2_builtin_print) X("print", l2_builtin_print)
X("len", l2_builtin_len) X("len", l2_builtin_len)
X("if", l2_builtin_if) X("if", l2_builtin_if)

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

void l2_vm_step(struct l2_vm *vm); void l2_vm_step(struct l2_vm *vm);
void l2_vm_run(struct l2_vm *vm); void l2_vm_run(struct l2_vm *vm);
size_t l2_vm_gc(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 #endif

+ 4
- 1
lib/parse/parse.c View File

strcmp(str, "<") == 0 || strcmp(str, "<") == 0 ||
strcmp(str, "<=") == 0 || 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( static int parse_expression(

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

X(l2_builtin_gteq, >=) X(l2_builtin_gteq, >=)
#undef X #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) { l2_word l2_builtin_print(struct l2_vm *vm, l2_word argc, l2_word *argv) {
for (size_t i = 0; i < argc; ++i) { for (size_t i = 0; i < argc; ++i) {
if (i != 0) { if (i != 0) {
return l2_vm_error(vm, "Expected 2 or 3 arguments"); 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); l2_word ret_id = l2_vm_alloc(vm, L2_VAL_TYPE_CONTINUATION, 0);
struct l2_vm_value *ret = &vm->values[ret_id]; struct l2_vm_value *ret = &vm->values[ret_id];
ret->extra.cont_call = argv[1]; ret->extra.cont_call = argv[1];
}; };


static l2_word loop_callback(struct l2_vm *vm, l2_word retval, l2_word cont) { 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; return cont;
} }


struct while_context *ctx = (struct while_context *)cont->cont; struct while_context *ctx = (struct while_context *)cont->cont;


if (cont->extra.cont_call == ctx->cond) { 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; cont->extra.cont_call = ctx->body;
return cont_id; return cont_id;
} else { } else {

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

} }
} }


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; l2_word true_atom = vm->values[vm->ktrue].atom;
return l2_value_get_type(val) == L2_VAL_TYPE_ATOM && val->atom == true_atom; return l2_value_get_type(val) == L2_VAL_TYPE_ATOM && val->atom == true_atom;
} }

+ 23
- 0
test/examples/builtins.l2 View File

print (len [10 20]) print (len [10 20])
print (len "Hello") print (len "Hello")
print (len {a: 10; b: 20; c: 30}) 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 ??()

+ 25
- 2
test/examples/builtins.l2.expected View File



print print
(none) (none)
(true) (false) (atom 20)
(true) (false) (atom 23)
100 100
100.5 100.5
255 255
Hello World Hello World
[(none) (true) (false) (atom 20) 100.1 Nope (namespace) (function)]
[(none) (true) (false) (atom 23) 100.1 Nope (namespace) (function)]
(namespace) (namespace) (namespace) (namespace)


len len
2 2
5 5
3 3

&&
(true)
(true)
(false)
(true)
(true)
(false)

||
(false)
(true)
(false)
(true)
(true)
(true)
(false)

??
30
10
hello
(none)

Loading…
Cancel
Save