// X macro: Define a macro named X, then include this file, then undef X. | // X macro: Define a macro named X, then include this file, then undef X. | ||||
#ifdef X | #ifdef X | ||||
X("+", l2_builtin_add); | |||||
X("-", l2_builtin_sub); | |||||
X("*", l2_builtin_mul); | |||||
X("/", l2_builtin_div); | |||||
X("print", l2_builtin_print); | X("print", l2_builtin_print); | ||||
#endif | #endif |
}; | }; | ||||
void l2_vm_init(struct l2_vm *vm, l2_word *ops, size_t opcount); | 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_free(struct l2_vm *vm); | ||||
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); |
void l2_gen_free(struct l2_generator *gen) { | void l2_gen_free(struct l2_generator *gen) { | ||||
l2_strset_free(&gen->atomset); | l2_strset_free(&gen->atomset); | ||||
l2_strset_free(&gen->stringset); | l2_strset_free(&gen->stringset); | ||||
free(gen->strings); | |||||
} | } | ||||
void l2_gen_halt(struct l2_generator *gen) { | void l2_gen_halt(struct l2_generator *gen) { | ||||
put(gen, L2_OP_RJMP); | put(gen, L2_OP_RJMP); | ||||
l2_word pos = gen->pos; | l2_word pos = gen->pos; | ||||
gen->pos += aligned / sizeof(l2_word); | |||||
l2_bufio_put_n(&gen->writer, *str, len); | l2_bufio_put_n(&gen->writer, *str, len); | ||||
for (size_t i = len; i < aligned; ++i) { | for (size_t i = len; i < aligned; ++i) { | ||||
l2_bufio_put(&gen->writer, '\0'); | l2_bufio_put(&gen->writer, '\0'); |
while (1) { | while (1) { | ||||
int ch = read_ch(lexer); | int ch = read_ch(lexer); | ||||
if (ch == '"') { | if (ch == '"') { | ||||
tok->v.str[idx] = '\0'; | |||||
return; | return; | ||||
} else if (ch == EOF) { | } else if (ch == EOF) { | ||||
tok->kind = L2_TOK_EOF; | tok->kind = L2_TOK_EOF; |
#include "strset.h" | #include "strset.h" | ||||
#include <string.h> | #include <string.h> | ||||
#include <stdio.h> | |||||
// sdbm from http://www.cse.yorku.ca/~oz/hash.html; | // sdbm from http://www.cse.yorku.ca/~oz/hash.html; | ||||
// there are probably better algorithms out there | // there are probably better algorithms out there |
#include <stdio.h> | #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) { | 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; | return 0; | ||||
} | } |
void l2_vm_print_bytecode(l2_word *ops, size_t opcount) { | void l2_vm_print_bytecode(l2_word *ops, size_t opcount) { | ||||
size_t ptr = 0; | size_t ptr = 0; | ||||
while (ptr < opcount) { | while (ptr < opcount) { | ||||
printf("%04zu ", ptr); | |||||
l2_vm_print_op(ops, opcount, &ptr); | l2_vm_print_op(ops, opcount, &ptr); | ||||
} | } | ||||
} | } |
vm->valuessize = 16; | vm->valuessize = 16; | ||||
} | } | ||||
while (id > vm->valuessize) { | |||||
while (id >= vm->valuessize) { | |||||
vm->valuessize *= 2; | vm->valuessize *= 2; | ||||
} | } | ||||
#undef X | #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) { | void l2_vm_free(struct l2_vm *vm) { | ||||
// Skip ID 0, because that's always NONE | // Skip ID 0, because that's always NONE | ||||
for (size_t i = 1; i < vm->valuessize; ++i) { | for (size_t i = 1; i < vm->valuessize; ++i) { | ||||
vm->stack[vm->sptr++] = arr_id; | vm->stack[vm->sptr++] = arr_id; | ||||
l2_word ns_id = alloc_val(vm); | 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].ns = NULL; | ||||
vm->values[ns_id].flags = L2_VAL_TYPE_NAMESPACE; | vm->values[ns_id].flags = L2_VAL_TYPE_NAMESPACE; | ||||
vm->nstack[vm->nsptr++] = ns_id; | vm->nstack[vm->nsptr++] = ns_id; |