@@ -1,5 +1,9 @@ | |||
// X macro: Define a macro named X, then include this file, then undef X. | |||
#ifdef X | |||
X("+", l2_builtin_add); | |||
X("-", l2_builtin_sub); | |||
X("*", l2_builtin_mul); | |||
X("/", l2_builtin_div); | |||
X("print", l2_builtin_print); | |||
#endif |
@@ -94,6 +94,7 @@ struct l2_vm { | |||
}; | |||
void l2_vm_init(struct l2_vm *vm, l2_word *ops, size_t opcount); | |||
l2_word l2_vm_alloc(struct l2_vm *vm, enum l2_value_type typ, enum l2_value_flags flags); | |||
void l2_vm_free(struct l2_vm *vm); | |||
void l2_vm_step(struct l2_vm *vm); | |||
void l2_vm_run(struct l2_vm *vm); |
@@ -28,6 +28,7 @@ void l2_gen_flush(struct l2_generator *gen) { | |||
void l2_gen_free(struct l2_generator *gen) { | |||
l2_strset_free(&gen->atomset); | |||
l2_strset_free(&gen->stringset); | |||
free(gen->strings); | |||
} | |||
void l2_gen_halt(struct l2_generator *gen) { | |||
@@ -90,6 +91,7 @@ void l2_gen_string(struct l2_generator *gen, char **str) { | |||
put(gen, L2_OP_RJMP); | |||
l2_word pos = gen->pos; | |||
gen->pos += aligned / sizeof(l2_word); | |||
l2_bufio_put_n(&gen->writer, *str, len); | |||
for (size_t i = len; i < aligned; ++i) { | |||
l2_bufio_put(&gen->writer, '\0'); |
@@ -127,6 +127,7 @@ static void read_string(struct l2_lexer *lexer, struct l2_token *tok) { | |||
while (1) { | |||
int ch = read_ch(lexer); | |||
if (ch == '"') { | |||
tok->v.str[idx] = '\0'; | |||
return; | |||
} else if (ch == EOF) { | |||
tok->kind = L2_TOK_EOF; |
@@ -1,6 +1,7 @@ | |||
#include "strset.h" | |||
#include <string.h> | |||
#include <stdio.h> | |||
// sdbm from http://www.cse.yorku.ca/~oz/hash.html; | |||
// there are probably better algorithms out there |
@@ -2,7 +2,85 @@ | |||
#include <stdio.h> | |||
static void print_val(struct l2_vm *vm, struct l2_vm_value *val) { | |||
switch (l2_vm_value_type(val)) { | |||
case L2_VAL_TYPE_NONE: | |||
printf("(none)"); | |||
break; | |||
case L2_VAL_TYPE_INTEGER: | |||
printf("%zi", val->integer); | |||
break; | |||
case L2_VAL_TYPE_REAL: | |||
printf("%g", val->real); | |||
break; | |||
case L2_VAL_TYPE_BUFFER: | |||
fwrite(val->buffer->data, 1, val->buffer->len, stdout); | |||
break; | |||
case L2_VAL_TYPE_ARRAY: | |||
putchar('['); | |||
for (size_t i = 0; i < val->array->len; ++i) { | |||
if (i != 0) { | |||
printf(", "); | |||
} | |||
print_val(vm, &vm->values[val->array->data[i]]); | |||
} | |||
putchar(']'); | |||
break; | |||
case L2_VAL_TYPE_NAMESPACE: | |||
printf("(namespace)"); | |||
break; | |||
case L2_VAL_TYPE_FUNCTION: | |||
case L2_VAL_TYPE_CFUNCTION: | |||
printf("(function)"); | |||
break; | |||
} | |||
} | |||
l2_word l2_builtin_add(struct l2_vm *vm, struct l2_vm_array *args) { | |||
double sum = 0; | |||
for (size_t i = 0; i < args->len; ++i) { | |||
struct l2_vm_value *val = &vm->values[args->data[i]]; | |||
if (l2_vm_value_type(val) != L2_VAL_TYPE_REAL) { | |||
// TODO: Error | |||
} | |||
sum += val->real; | |||
} | |||
l2_word id = l2_vm_alloc(vm, L2_VAL_TYPE_REAL, 0); | |||
vm->values[id].real = sum; | |||
return id; | |||
} | |||
l2_word l2_builtin_sub(struct l2_vm *vm, struct l2_vm_array *args) { | |||
return 0; | |||
} | |||
l2_word l2_builtin_mul(struct l2_vm *vm, struct l2_vm_array *args) { | |||
return 0; | |||
} | |||
l2_word l2_builtin_div(struct l2_vm *vm, struct l2_vm_array *args) { | |||
return 0; | |||
} | |||
l2_word l2_builtin_print(struct l2_vm *vm, struct l2_vm_array *args) { | |||
printf("hey this is test\n"); | |||
for (size_t i = 0; i < args->len; ++i) { | |||
if (i != 0) { | |||
putchar(' '); | |||
} | |||
struct l2_vm_value *val = &vm->values[args->data[i]]; | |||
print_val(vm, val); | |||
} | |||
putchar('\n'); | |||
return 0; | |||
} |
@@ -226,6 +226,7 @@ void l2_vm_print_op(l2_word *ops, size_t opcount, size_t *ptr) { | |||
void l2_vm_print_bytecode(l2_word *ops, size_t opcount) { | |||
size_t ptr = 0; | |||
while (ptr < opcount) { | |||
printf("%04zu ", ptr); | |||
l2_vm_print_op(ops, opcount, &ptr); | |||
} | |||
} |
@@ -12,7 +12,7 @@ static l2_word alloc_val(struct l2_vm *vm) { | |||
vm->valuessize = 16; | |||
} | |||
while (id > vm->valuessize) { | |||
while (id >= vm->valuessize) { | |||
vm->valuessize *= 2; | |||
} | |||
@@ -164,6 +164,13 @@ void l2_vm_init(struct l2_vm *vm, l2_word *ops, size_t opcount) { | |||
#undef X | |||
} | |||
l2_word l2_vm_alloc(struct l2_vm *vm, enum l2_value_type typ, enum l2_value_flags flags) { | |||
l2_word id = alloc_val(vm); | |||
memset(&vm->values[id], 0, sizeof(vm->values[id])); | |||
vm->values[id].flags = typ | flags; | |||
return id; | |||
} | |||
void l2_vm_free(struct l2_vm *vm) { | |||
// Skip ID 0, because that's always NONE | |||
for (size_t i = 1; i < vm->valuessize; ++i) { | |||
@@ -266,7 +273,7 @@ void l2_vm_step(struct l2_vm *vm) { | |||
vm->stack[vm->sptr++] = arr_id; | |||
l2_word ns_id = alloc_val(vm); | |||
vm->values[ns_id].extra.ns_parent = ns_id; | |||
vm->values[ns_id].extra.ns_parent = func->func.namespace; | |||
vm->values[ns_id].ns = NULL; | |||
vm->values[ns_id].flags = L2_VAL_TYPE_NAMESPACE; | |||
vm->nstack[vm->nsptr++] = ns_id; |