| @@ -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; | |||