#ifndef L2_BYTECODE_H | |||||
#define L2_BYTECODE_H | |||||
#include <stdint.h> | |||||
typedef uint32_t l2_word; | |||||
enum l2_opcode { | |||||
L2_OP_PUSH, | |||||
L2_OP_ADD, | |||||
L2_OP_JUMP, | |||||
L2_OP_CALL, | |||||
L2_OP_ALLOC_STRING, | |||||
L2_OP_ALLOC_ARRAY, | |||||
L2_OP_HALT, | |||||
}; | |||||
struct l2_op { | |||||
enum l2_opcode code; | |||||
l2_word val; | |||||
}; | |||||
#endif |
#ifndef L2_PARSE_H | |||||
#define L2_PARSE_H | |||||
#include "lex.h" | |||||
void l2_parse(); | |||||
#endif |
#ifndef L2_VM_H | |||||
#define L2_VM_H | |||||
#include <stdlib.h> | |||||
#include "../bytecode.h" | |||||
enum { | |||||
L2_VAL_TYPE_STRING = (1 << 30) + 0, | |||||
L2_VAL_TYPE_ARRAY = (1 << 30) + 1, | |||||
L2_VAL_MARKED = 1 << 29, | |||||
}; | |||||
struct l2_vm_value { | |||||
l2_word flags; | |||||
}; | |||||
struct l2_vm_string { | |||||
struct l2_vm_value val; | |||||
char *mem; | |||||
size_t len; | |||||
}; | |||||
struct l2_vm_array { | |||||
struct l2_vm_value val; | |||||
l2_word *data; | |||||
size_t len; | |||||
size_t size; | |||||
}; | |||||
struct l2_vm { | |||||
struct l2_op *ops; | |||||
size_t opcount; | |||||
struct l2_vm_value *allocs[1024]; | |||||
size_t allocslen; | |||||
l2_word stack[1024]; | |||||
l2_word iptr; | |||||
l2_word sptr; | |||||
}; | |||||
void l2_vm_init(struct l2_vm *vm, struct l2_op *ops, size_t opcount); | |||||
void l2_vm_step(struct l2_vm *vm); | |||||
#endif |
#include "io.h" | |||||
#include "parse/lex.h" | |||||
#include "vm/vm.h" | |||||
#include "bitmap.h" | |||||
#include <stdio.h> | |||||
#include <assert.h> | |||||
int main() { | int main() { | ||||
struct l2_io_mem_reader r = { l2_io_mem_read }; | |||||
r.mem = " \"Hello\", [], {}."; | |||||
r.len = strlen(r.mem); | |||||
struct l2_lexer lexer; | |||||
l2_lexer_init(&lexer, &r.r); | |||||
while (1) { | |||||
struct l2_token *tok = l2_lexer_get(&lexer); | |||||
printf("%s\n", l2_token_kind_name(tok->kind)); | |||||
if (tok->kind == L2_TOK_EOF) { | |||||
break; | |||||
struct l2_bitmap bm; | |||||
l2_bitmap_init(&bm); | |||||
for (size_t i = 0; i < 8191; ++i) { | |||||
size_t id = l2_bitmap_set_next(&bm); | |||||
assert(id == i); | |||||
assert(l2_bitmap_get(&bm, i)); | |||||
} | |||||
for (size_t i = 0; i < 10000; ++i) { | |||||
if (i < 8191) { | |||||
assert(l2_bitmap_get(&bm, i)); | |||||
} else { | |||||
assert(!l2_bitmap_get(&bm, i)); | |||||
} | } | ||||
} | } | ||||
l2_bitmap_unset(&bm, 100); | |||||
assert(l2_bitmap_set_next(&bm) == 8191); | |||||
assert(l2_bitmap_set_next(&bm) == 100); | |||||
l2_bitmap_free(&bm); | |||||
} | |||||
/* | |||||
int main() { | |||||
struct l2_op ops[] = { | |||||
{ L2_OP_PUSH, 100 }, | |||||
{ L2_OP_PUSH, 100 }, | |||||
{ L2_OP_ADD }, | |||||
{ L2_OP_HALT }, | |||||
}; | |||||
struct l2_vm vm; | |||||
l2_vm_init(&vm, ops, sizeof(ops) / sizeof(*ops)); | |||||
while (vm.ops[vm.iptr].code != L2_OP_HALT) { | |||||
printf("Exec %i\n", vm.ops[vm.iptr].code); | |||||
l2_vm_step(&vm); | |||||
} | |||||
printf("Done. Stack:\n"); | |||||
for (l2_word i = 0; i < vm.sptr; ++i) { | |||||
printf(" %i: %i\n", i, vm.stack[i]); | |||||
} | |||||
} | } | ||||
*/ |
#include "vm/vm.h" | |||||
void l2_vm_init(struct l2_vm *vm, struct l2_op *ops, size_t opcount) { | |||||
vm->ops = ops; | |||||
vm->opcount = opcount; | |||||
vm->iptr = 0; | |||||
vm->sptr = 0; | |||||
} | |||||
static l2_word alloc(struct l2_vm *vm, size_t size) { | |||||
l2_word id = vm->allocslen++; | |||||
vm->allocs[id] = malloc(size); | |||||
return id | 1 << 31; | |||||
} | |||||
void l2_vm_step(struct l2_vm *vm) { | |||||
struct l2_op op = vm->ops[vm->iptr++]; | |||||
switch (op.code) { | |||||
case L2_OP_PUSH: | |||||
vm->stack[vm->sptr++] = op.val; | |||||
break; | |||||
case L2_OP_ADD: | |||||
vm->sptr -= 1; | |||||
vm->stack[vm->sptr - 1] += vm->stack[vm->sptr]; | |||||
break; | |||||
case L2_OP_JUMP: | |||||
vm->iptr = vm->stack[--vm->sptr]; | |||||
break; | |||||
case L2_OP_HALT: | |||||
break; | |||||
} | |||||
} |