| @@ -17,6 +17,13 @@ enum l2_opcode { | |||
| */ | |||
| L2_OP_PUSH, | |||
| /* | |||
| * Push a value to the stack. | |||
| * Push <word1> | |||
| * Push <word2> | |||
| */ | |||
| L2_OP_PUSH_2, | |||
| /* | |||
| * Discard the top element from the stack. | |||
| * Pop <word> | |||
| @@ -14,5 +14,6 @@ void l2_gen_init(struct l2_generator *gen); | |||
| void l2_gen_free(struct l2_generator *gen); | |||
| void l2_gen_stack_frame(struct l2_generator *gen); | |||
| void l2_gen_assignment(struct l2_generator *gen, char **ident); | |||
| void l2_gen_number(struct l2_generator *gen, double num); | |||
| #endif | |||
| @@ -4,6 +4,6 @@ | |||
| #include "lex.h" | |||
| #include "gen/gen.h" | |||
| void l2_parse_program(struct l2_lexer *lexer, struct l2_generator *gen); | |||
| int l2_parse_program(struct l2_lexer *lexer, struct l2_generator *gen); | |||
| #endif | |||
| @@ -26,3 +26,12 @@ void l2_gen_assignment(struct l2_generator *gen, char **ident) { | |||
| put(gen, atom_id); | |||
| put(gen, L2_OP_NAMESPACE_SET); | |||
| } | |||
| void l2_gen_number(struct l2_generator *gen, double num) { | |||
| uint64_t n; | |||
| memcpy(&n, &num, sizeof(num)); | |||
| put(gen, L2_OP_PUSH_2); | |||
| put(gen, n >> 32); | |||
| put(gen, n); | |||
| put(gen, L2_OP_ALLOC_REAL_64); | |||
| } | |||
| @@ -2,17 +2,23 @@ | |||
| #include "gen/gen.h" | |||
| static void parse_expression(struct l2_lexer *lexer, struct l2_generator *gen) { | |||
| static int parse_expression(struct l2_lexer *lexer, struct l2_generator *gen) { | |||
| struct l2_token *tok = l2_lexer_peek(lexer, 1); | |||
| struct l2_token *tok2 = l2_lexer_peek(lexer, 2); | |||
| if (tok->kind == L2_TOK_IDENT && tok2->kind == L2_TOK_COLON_EQ) { | |||
| parse_expression(lexer, gen); | |||
| l2_gen_assignment(gen, &tok->v.str); | |||
| return 0; | |||
| } else if (tok->kind == L2_TOK_NUMBER) { | |||
| l2_gen_number(gen, tok->v.num); | |||
| return 0; | |||
| } | |||
| return -1; | |||
| } | |||
| void l2_parse_program(struct l2_lexer *lexer, struct l2_generator *gen) { | |||
| int l2_parse_program(struct l2_lexer *lexer, struct l2_generator *gen) { | |||
| l2_gen_stack_frame(gen); | |||
| while (1) { | |||
| @@ -21,6 +27,10 @@ void l2_parse_program(struct l2_lexer *lexer, struct l2_generator *gen) { | |||
| break; | |||
| } | |||
| parse_expression(lexer, gen); | |||
| if (parse_expression(lexer, gen) < 0) { | |||
| return -1; | |||
| } | |||
| } | |||
| return 0; | |||
| } | |||
| @@ -159,6 +159,15 @@ void l2_vm_step(struct l2_vm *vm) { | |||
| vm->iptr += 1; | |||
| break; | |||
| case L2_OP_PUSH_2: | |||
| vm->stack[vm->sptr] = vm->ops[vm->iptr]; | |||
| vm->stack[vm->sptr + 1] = vm->ops[vm->iptr + 1]; | |||
| vm->stackflags[vm->sptr] = 0; | |||
| vm->stackflags[vm->sptr + 1] = 0; | |||
| vm->sptr += 2; | |||
| vm->iptr += 2; | |||
| break; | |||
| case L2_OP_POP: | |||
| vm->sptr -= 1; | |||
| break; | |||
| @@ -255,6 +264,7 @@ void l2_vm_step(struct l2_vm *vm) { | |||
| vm->stackflags[vm->sptr] = 1; | |||
| vm->sptr += 1; | |||
| } | |||
| break; | |||
| case L2_OP_ALLOC_ARRAY: | |||
| word = alloc_val(vm); | |||
| @@ -274,6 +284,16 @@ void l2_vm_step(struct l2_vm *vm) { | |||
| vm->sptr += 1; | |||
| break; | |||
| case L2_OP_NAMESPACE_SET: | |||
| { | |||
| l2_word key = vm->stack[vm->sptr - 1]; | |||
| l2_word val = vm->stack[vm->sptr - 2]; | |||
| l2_word ns = vm->stack[vm->sptr - 3]; | |||
| l2_vm_namespace_set(&vm->values[ns], key, val); | |||
| vm->sptr -= 1; | |||
| } | |||
| break; | |||
| case L2_OP_HALT: | |||
| break; | |||
| } | |||