@@ -0,0 +1,23 @@ | |||
#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 |
@@ -0,0 +1,8 @@ | |||
#ifndef L2_PARSE_H | |||
#define L2_PARSE_H | |||
#include "lex.h" | |||
void l2_parse(); | |||
#endif |
@@ -0,0 +1,45 @@ | |||
#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 |
@@ -1,19 +1,53 @@ | |||
#include "io.h" | |||
#include "parse/lex.h" | |||
#include "vm/vm.h" | |||
#include "bitmap.h" | |||
#include <stdio.h> | |||
#include <assert.h> | |||
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]); | |||
} | |||
} | |||
*/ |
@@ -0,0 +1,36 @@ | |||
#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; | |||
} | |||
} |