aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/compiler.c209
-rw-r--r--src/main.c10
-rw-r--r--src/parser.c1
-rw-r--r--src/semantic.c9
-rw-r--r--src/vm.c136
-rw-r--r--tests/compilation.bad7
6 files changed, 246 insertions, 126 deletions
diff --git a/src/compiler.c b/src/compiler.c
index e303cee..04afd5d 100644
--- a/src/compiler.c
+++ b/src/compiler.c
@@ -5,6 +5,15 @@
5 5
6#include "parser.c" 6#include "parser.c"
7 7
8typedef struct Variable {
9 Str name;
10 Str type;
11 sz size;
12 sz offset;
13} Variable;
14
15MAPDEF(StrVarMap, varmap, Str, Variable, str_hash, str_eq)
16
8typedef struct Instruction { 17typedef struct Instruction {
9 u8 dst; 18 u8 dst;
10 u8 a; 19 u8 a;
@@ -33,6 +42,11 @@ typedef struct Chunk {
33 StrIntMap *strmap; 42 StrIntMap *strmap;
34 sz str_idx; 43 sz str_idx;
35 44
45 // Global/Local variables.
46 Variable *vars;
47 StrVarMap *varmap;
48 sz var_off;
49
36 // Number of registers currently used in this chunk. 50 // Number of registers currently used in this chunk.
37 sz reg_idx; 51 sz reg_idx;
38 52
@@ -46,7 +60,9 @@ typedef enum OpCode {
46 // OP DST A B 60 // OP DST A B
47 // --------------------------------------------------------------- 61 // ---------------------------------------------------------------
48 // VM/high level instructions. 62 // VM/high level instructions.
49 OP_HALT, // halt 63 OP_HALT, // halt
64 OP_STVARI, // stvari vx, ca
65 OP_STVAR, // stvar vx, ra
50 // Load/Store instructions. 66 // Load/Store instructions.
51 OP_LD8K, // ld8k rx, ca -> u8 rx = ca 67 OP_LD8K, // ld8k rx, ca -> u8 rx = ca
52 OP_LD16K, // ld16k rx, ca -> u16 rx = ca 68 OP_LD16K, // ld16k rx, ca -> u16 rx = ca
@@ -129,6 +145,8 @@ typedef enum OpCode {
129 145
130Str op_str[] = { 146Str op_str[] = {
131 [OP_HALT] = cstr("HALT "), 147 [OP_HALT] = cstr("HALT "),
148 [OP_STVAR] = cstr("STVAR "),
149 [OP_STVARI] = cstr("STVARI "),
132 // Load ops. 150 // Load ops.
133 [OP_LD8K] = cstr("LD8K "), 151 [OP_LD8K] = cstr("LD8K "),
134 [OP_LD16K] = cstr("LD16K "), 152 [OP_LD16K] = cstr("LD16K "),
@@ -210,6 +228,7 @@ Str op_str[] = {
210}; 228};
211 229
212typedef enum { 230typedef enum {
231 COMP_NIL,
213 COMP_CONST, 232 COMP_CONST,
214 COMP_STRING, 233 COMP_STRING,
215 COMP_REG, 234 COMP_REG,
@@ -464,6 +483,54 @@ compile_expr(Chunk *chunk, Node *node) {
464 .idx = map->val, 483 .idx = map->val,
465 }; 484 };
466 } break; 485 } break;
486 case NODE_LET: {
487 sz idx = array_size(chunk->vars);
488 Str name = node->unique_name;
489 Str type = node->var_name->type;
490 sz size = 8;
491 // TODO: get type storage from a table to consider all the basic
492 // types as well as user defined ones.
493 if (str_eq(type, cstr("str"))) {
494 size = 16;
495 }
496 Variable var = (Variable){
497 .name = name,
498 .type = type,
499 .size = size,
500 .offset = chunk->var_off,
501 };
502 varmap_insert(&chunk->varmap, name, var, chunk->storage);
503 array_push(chunk->vars, var, chunk->storage);
504 chunk->var_off += size;
505
506 // Value.
507 if (node->var_val) {
508 CompResult res = compile_expr(chunk, node->var_val);
509 switch (res.type) {
510 case COMP_CONST: {
511 EMIT_OP(OP_STVARI, idx, res.idx, 0, node->var_val,
512 chunk);
513 } break;
514 case COMP_REG: {
515 EMIT_OP(OP_STVAR, idx, res.idx, 0, node->var_val,
516 chunk);
517 } break;
518 default: {
519 return (CompResult){.type = COMP_ERR};
520 } break;
521 }
522 }
523
524 return (CompResult){.type = COMP_NIL};
525 } break;
526 case NODE_BLOCK: {
527 CompResult res;
528 for (sz i = 0; i < array_size(node->elements); i++) {
529 Node *root = node->elements[i];
530 res = compile_expr(chunk, root);
531 }
532 return res;
533 } break;
467 default: { 534 default: {
468 eprintln("error: compilation not implemented for node %s", 535 eprintln("error: compilation not implemented for node %s",
469 node_str[node->kind]); 536 node_str[node->kind]);
@@ -473,4 +540,144 @@ compile_expr(Chunk *chunk, Node *node) {
473 return (CompResult){.type = COMP_ERR}; 540 return (CompResult){.type = COMP_ERR};
474} 541}
475 542
543void
544disassemble_instruction(Instruction instruction) {
545 switch (instruction.op) {
546 case OP_MOV8:
547 case OP_MOV16:
548 case OP_MOV32:
549 case OP_MOV64:
550 println("%s r%d, r%d", op_str[instruction.op], instruction.dst,
551 instruction.a, instruction.b);
552 break;
553 case OP_LD8K:
554 case OP_LD16K:
555 case OP_LD32K:
556 case OP_LD64K:
557 println("%s r%d, c%d", op_str[instruction.op], instruction.dst,
558 instruction.a, instruction.b);
559 break;
560 case OP_LD8I:
561 case OP_LD16I:
562 case OP_LD32I:
563 case OP_LD64I:
564 case OP_ST8I:
565 case OP_ST16I:
566 case OP_ST32I:
567 case OP_ST64I:
568 case OP_ADDI:
569 case OP_SUBI:
570 case OP_MULI:
571 case OP_DIVI:
572 case OP_MODI:
573 case OP_ADDFI:
574 case OP_SUBFI:
575 case OP_MULFI:
576 case OP_DIVFI:
577 case OP_MODFI:
578 case OP_EQI:
579 case OP_NEQI:
580 case OP_LTI:
581 case OP_GTI:
582 case OP_LEI:
583 case OP_GEI:
584 case OP_ANDI:
585 case OP_ORI:
586 case OP_BITLSHIFTI:
587 case OP_BITRSHIFTI:
588 case OP_BITANDI:
589 case OP_BITORI:
590 println("%s r%d, r%d, c%d", op_str[instruction.op], instruction.dst,
591 instruction.a, instruction.b);
592 break;
593 case OP_LD8:
594 case OP_LD16:
595 case OP_LD32:
596 case OP_LD64:
597 case OP_ST8:
598 case OP_ST16:
599 case OP_ST32:
600 case OP_ST64:
601 case OP_ADD:
602 case OP_SUB:
603 case OP_MUL:
604 case OP_DIV:
605 case OP_MOD:
606 case OP_ADDF:
607 case OP_SUBF:
608 case OP_MULF:
609 case OP_DIVF:
610 case OP_MODF:
611 case OP_EQ:
612 case OP_NEQ:
613 case OP_LT:
614 case OP_GT:
615 case OP_LE:
616 case OP_GE:
617 case OP_AND:
618 case OP_OR:
619 case OP_BITLSHIFT:
620 case OP_BITRSHIFT:
621 case OP_BITAND:
622 case OP_BITOR:
623 println("%s r%d, r%d, r%d", op_str[instruction.op], instruction.dst,
624 instruction.a, instruction.b);
625 break;
626 case OP_STVAR:
627 println("%s v%d, r%d", op_str[instruction.op], instruction.dst,
628 instruction.a, instruction.b);
629 break;
630 case OP_STVARI:
631 println("%s v%d, c%d", op_str[instruction.op], instruction.dst,
632 instruction.a, instruction.b);
633 break;
634 case OP_BITNOTI:
635 case OP_NOTI:
636 println("%s r%d, c%d", op_str[instruction.op], instruction.dst,
637 instruction.a, instruction.b);
638 break;
639 case OP_BITNOT:
640 case OP_NOT:
641 println("%s r%d, r%d", op_str[instruction.op], instruction.dst,
642 instruction.a, instruction.b);
643 break;
644 case OP_HALT: println("%s", op_str[instruction.op]); break;
645 default: println("Unknown opcode %d", instruction.op); break;
646 }
647}
648
649void
650disassemble_chunk(Chunk chunk) {
651 println("%s: =========== code ===========", chunk.file_name);
652 for (sz i = 0; i < array_size(chunk.code); i++) {
653 print("%s: %x{4}: ", chunk.file_name, i);
654 disassemble_instruction(chunk.code[i]);
655 }
656 if (array_size(chunk.constants) > 0) {
657 println("%s: ========= constants ========", chunk.file_name);
658 for (sz i = 0; i < array_size(chunk.constants); i++) {
659 println("%s: %x{2}: %x{8}", chunk.file_name, i,
660 chunk.constants[i]);
661 }
662 }
663 if (array_size(chunk.strings) > 0) {
664 println("%s: ========== strings =========", chunk.file_name);
665 for (sz i = 0; i < array_size(chunk.strings); i++) {
666 println("%s: %x{2}: %s", chunk.file_name, i, chunk.strings[i]);
667 }
668 }
669 if (array_size(chunk.vars) > 0) {
670 println("%s: ========= variables ========", chunk.file_name);
671 for (sz i = 0; i < array_size(chunk.vars); i++) {
672 println("%s: %x{2}: [%x{4}:%x{4}] %s: %s", chunk.file_name, i,
673 chunk.vars[i].offset,
674 chunk.vars[i].offset + chunk.vars[i].size,
675 chunk.vars[i].name, chunk.vars[i].type);
676 }
677 }
678 println("n_regs: %d, n_vars: %d, n_strings: %d, n_consts: %d",
679 chunk.reg_idx, array_size(chunk.vars), chunk.str_idx,
680 chunk.const_idx);
681}
682
476#endif // COMPILER_C 683#endif // COMPILER_C
diff --git a/src/main.c b/src/main.c
index 60122b9..618d325 100644
--- a/src/main.c
+++ b/src/main.c
@@ -176,6 +176,10 @@ process_file(Str path) {
176 // The parser stores the root nodes as a stack. 176 // The parser stores the root nodes as a stack.
177 Node *root = parser.nodes[i]; 177 Node *root = parser.nodes[i];
178 res = compile_expr(&chunk, root); 178 res = compile_expr(&chunk, root);
179 if (res.type == COMP_ERR) {
180 eprintln("compilation error...");
181 exit(EXIT_FAILURE);
182 }
179 } 183 }
180 sz res_reg = 0; 184 sz res_reg = 0;
181 switch (res.type) { 185 switch (res.type) {
@@ -215,8 +219,10 @@ process_file(Str path) {
215 // println("VM REGISTERS BEFORE:\n%{Mem}", 219 // println("VM REGISTERS BEFORE:\n%{Mem}",
216 // &(Array){.mem = (u8 *)&vm.regs, sizeof(vm.regs)}); 220 // &(Array){.mem = (u8 *)&vm.regs, sizeof(vm.regs)});
217 vm_run(&vm); 221 vm_run(&vm);
218 // println("VM REGISTERS AFTER:\n%{Mem}", 222 println("VM REGISTERS AFTER:\n%{Mem}",
219 // &(Array){.mem = (u8 *)&vm.regs, sizeof(vm.regs)}); 223 &(Array){.mem = (u8 *)&vm.regs, sizeof(vm.regs)});
224 println("VM MEMORY AFTER:\n%{Mem}",
225 &(Array){.mem = (u8 *)&vm.stack, sizeof(vm.stack)});
220 226
221#if DEBUG == 1 227#if DEBUG == 1
222 println("Space used: %{Arena}", &lexer_arena); 228 println("Space used: %{Arena}", &lexer_arena);
diff --git a/src/parser.c b/src/parser.c
index f7d0d41..90adaf3 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -197,6 +197,7 @@ typedef struct Node {
197 Str type; 197 Str type;
198 Str fun_params; 198 Str fun_params;
199 Str fun_return; 199 Str fun_return;
200 Str unique_name;
200} Node; 201} Node;
201 202
202// 203//
diff --git a/src/semantic.c b/src/semantic.c
index 7158052..1b40723 100644
--- a/src/semantic.c
+++ b/src/semantic.c
@@ -2,6 +2,7 @@
2#define SEMANTIC_C 2#define SEMANTIC_C
3 3
4#include "badlib.h" 4#include "badlib.h"
5#include "parser.c"
5 6
6typedef enum { 7typedef enum {
7 SYM_UNKNOWN, 8 SYM_UNKNOWN,
@@ -514,6 +515,10 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
514 a->storage); 515 a->storage);
515 node->var_name->type = type; 516 node->var_name->type = type;
516 } 517 }
518 symbol = str_concat(cstr("."), symbol, a->storage);
519 symbol = str_concat(symbol, str_from_int(scope->id, a->storage),
520 a->storage);
521 node->unique_name = symbol;
517 return node->type; 522 return node->type;
518 } break; 523 } break;
519 case NODE_SET: { 524 case NODE_SET: {
@@ -843,7 +848,7 @@ type_inference(Analyzer *a, Node *node, Scope *scope) {
843 node->type = cstr("str"); 848 node->type = cstr("str");
844 return node->type; 849 return node->type;
845 } break; 850 } break;
846 case NODE_ARR_TYPE: 851 case NODE_ARR_TYPE:
847 case NODE_TYPE: { 852 case NODE_TYPE: {
848 SymbolMap *type = find_type(scope, node->value.str); 853 SymbolMap *type = find_type(scope, node->value.str);
849 if (!type) { 854 if (!type) {
@@ -1235,4 +1240,4 @@ symbolic_analysis(Analyzer *a, Parser *parser) {
1235 } 1240 }
1236} 1241}
1237 1242
1238#endif // SEMANTIC_C 1243#endif // SEMANTIC_C
diff --git a/src/vm.c b/src/vm.c
index 2771d07..556fbe9 100644
--- a/src/vm.c
+++ b/src/vm.c
@@ -4,130 +4,12 @@
4#include "badlib.h" 4#include "badlib.h"
5#include "compiler.c" 5#include "compiler.c"
6 6
7void
8disassemble_instruction(Instruction instruction) {
9 switch (instruction.op) {
10 case OP_MOV8:
11 case OP_MOV16:
12 case OP_MOV32:
13 case OP_MOV64:
14 println("%s r%d, r%d", op_str[instruction.op], instruction.dst,
15 instruction.a, instruction.b);
16 break;
17 case OP_LD8K:
18 case OP_LD16K:
19 case OP_LD32K:
20 case OP_LD64K:
21 println("%s r%d, c%d", op_str[instruction.op], instruction.dst,
22 instruction.a, instruction.b);
23 break;
24 case OP_LD8I:
25 case OP_LD16I:
26 case OP_LD32I:
27 case OP_LD64I:
28 case OP_ST8I:
29 case OP_ST16I:
30 case OP_ST32I:
31 case OP_ST64I:
32 case OP_ADDI:
33 case OP_SUBI:
34 case OP_MULI:
35 case OP_DIVI:
36 case OP_MODI:
37 case OP_ADDFI:
38 case OP_SUBFI:
39 case OP_MULFI:
40 case OP_DIVFI:
41 case OP_MODFI:
42 case OP_EQI:
43 case OP_NEQI:
44 case OP_LTI:
45 case OP_GTI:
46 case OP_LEI:
47 case OP_GEI:
48 case OP_ANDI:
49 case OP_ORI:
50 case OP_BITLSHIFTI:
51 case OP_BITRSHIFTI:
52 case OP_BITANDI:
53 case OP_BITORI:
54 println("%s r%d, r%d, c%d", op_str[instruction.op], instruction.dst,
55 instruction.a, instruction.b);
56 break;
57 case OP_LD8:
58 case OP_LD16:
59 case OP_LD32:
60 case OP_LD64:
61 case OP_ST8:
62 case OP_ST16:
63 case OP_ST32:
64 case OP_ST64:
65 case OP_ADD:
66 case OP_SUB:
67 case OP_MUL:
68 case OP_DIV:
69 case OP_MOD:
70 case OP_ADDF:
71 case OP_SUBF:
72 case OP_MULF:
73 case OP_DIVF:
74 case OP_MODF:
75 case OP_EQ:
76 case OP_NEQ:
77 case OP_LT:
78 case OP_GT:
79 case OP_LE:
80 case OP_GE:
81 case OP_AND:
82 case OP_OR:
83 case OP_BITLSHIFT:
84 case OP_BITRSHIFT:
85 case OP_BITAND:
86 case OP_BITOR:
87 println("%s r%d, r%d, r%d", op_str[instruction.op], instruction.dst,
88 instruction.a, instruction.b);
89 break;
90 case OP_BITNOTI:
91 case OP_NOTI:
92 println("%s r%d, c%d", op_str[instruction.op], instruction.dst,
93 instruction.a, instruction.b);
94 break;
95 case OP_BITNOT:
96 case OP_NOT:
97 println("%s r%d, r%d", op_str[instruction.op], instruction.dst,
98 instruction.a, instruction.b);
99 break;
100 case OP_HALT: println("%s", op_str[instruction.op]); break;
101 default: println("Unknown opcode %d", instruction.op); break;
102 }
103}
104
105void
106disassemble_chunk(Chunk chunk) {
107 println("%s: =========== code ===========", chunk.file_name);
108 for (sz i = 0; i < array_size(chunk.code); i++) {
109 print("%s: %x{4}: ", chunk.file_name, i);
110 disassemble_instruction(chunk.code[i]);
111 }
112 if (array_size(chunk.constants) > 0) {
113 println("%s: ========= constants ========", chunk.file_name);
114 for (sz i = 0; i < array_size(chunk.constants); i++) {
115 println("%s: %x{2}: %x{8}", chunk.file_name, i,
116 chunk.constants[i]);
117 }
118 }
119 if (array_size(chunk.strings) > 0) {
120 println("%s: ========== strings =========", chunk.file_name);
121 for (sz i = 0; i < array_size(chunk.strings); i++) {
122 println("%s: %x{2}: %s", chunk.file_name, i, chunk.strings[i]);
123 }
124 }
125}
126
127#define N_CONST 256 7#define N_CONST 256
8#define STACK_SIZE KB(64)
128typedef struct VM { 9typedef struct VM {
129 Chunk *chunk; 10 Chunk *chunk;
130 Constant regs[N_CONST]; 11 Constant regs[N_CONST];
12 u8 stack[STACK_SIZE];
131 Instruction *ip; 13 Instruction *ip;
132} VM; 14} VM;
133 15
@@ -252,6 +134,20 @@ vm_run(VM *vm) {
252 vm->regs[dst].f = 134 vm->regs[dst].f =
253 fmod(vm->regs[src_a].f, vm->chunk->constants[src_b].f); 135 fmod(vm->regs[src_a].f, vm->chunk->constants[src_b].f);
254 } break; 136 } break;
137 case OP_STVAR: {
138 u8 dst = instruction.dst;
139 u8 src = instruction.a;
140 Variable var = vm->chunk->vars[dst];
141 s64 *stack = (s64*)&vm->stack[var.offset];
142 *stack = vm->regs[src].i;
143 } break;
144 case OP_STVARI: {
145 u8 dst = instruction.dst;
146 u8 src = instruction.a;
147 Variable var = vm->chunk->vars[dst];
148 s64 *stack = (s64*)&vm->stack[var.offset];
149 *stack = vm->chunk->constants[src].i;
150 } break;
255 case OP_HALT: { 151 case OP_HALT: {
256 println("VM HALT (int) -> %d", vm->regs[instruction.dst]); 152 println("VM HALT (int) -> %d", vm->regs[instruction.dst]);
257 println("VM HALT (float) -> %f", vm->regs[instruction.dst]); 153 println("VM HALT (float) -> %f", vm->regs[instruction.dst]);
diff --git a/tests/compilation.bad b/tests/compilation.bad
index 9042242..120c020 100644
--- a/tests/compilation.bad
+++ b/tests/compilation.bad
@@ -1,8 +1,13 @@
1let a = 8
2{
3 let a = 1 + 2 * 4
4 let b = 3.0
5}
1; 0xf | 0xf0 6; 0xf | 0xf0
2; 0xf & 0xff 7; 0xf & 0xff
3; 0x1 << 2 8; 0x1 << 2
4; 0x1 << 2 9; 0x1 << 2
5~0xf & 0xfff 10; (~0xf & 0xfff << 8) == 0xfff00
6; 0xf << 4 | 0xf 11; 0xf << 4 | 0xf
7; 1 + 2 12; 1 + 2
8; 1 < 2 13; 1 < 2