aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBad Diode <bd@badd10de.dev>2021-12-22 16:30:23 +0100
committerBad Diode <bd@badd10de.dev>2021-12-22 16:30:23 +0100
commit7963d9ab628d03c5004f32899aa6b21663a78007 (patch)
tree5c04bc7fe6c93823372f3468498575c641baf3a2
parent9c5fb457fe6063b7545515397aa45cecb7af66bf (diff)
downloadbdl-7963d9ab628d03c5004f32899aa6b21663a78007.tar.gz
bdl-7963d9ab628d03c5004f32899aa6b21663a78007.zip
Start refactoring of compiler to stack-ir
-rw-r--r--Makefile7
-rw-r--r--src/ir.h155
-rw-r--r--src/main.c6
3 files changed, 161 insertions, 7 deletions
diff --git a/Makefile b/Makefile
index cdb8c93..4e31a67 100644
--- a/Makefile
+++ b/Makefile
@@ -20,7 +20,7 @@ CFLAGS += $(INC_FLAGS)
20NASM_FLAGS ?= -felf64 20NASM_FLAGS ?= -felf64
21LDFLAGS := 21LDFLAGS :=
22LDLIBS := 22LDLIBS :=
23RELEASE_CFLAGS := -DNDEBUG -O2 -static 23RELEASE_CFLAGS := -DNDEBUG -O2
24DEBUG_CFLAGS := -DDEBUG -O0 -g 24DEBUG_CFLAGS := -DDEBUG -O0 -g
25 25
26.PHONY: build tests clean 26.PHONY: build tests clean
@@ -56,10 +56,7 @@ tests: $(BIN)
56 # ./$(BIN) examples/variables.bdl | diff tests/variables_expected.txt - 56 # ./$(BIN) examples/variables.bdl | diff tests/variables_expected.txt -
57 57
58run: $(BIN) 58run: $(BIN)
59 $(BIN) example.bdl > build/example.asm 59 $(BIN) example.bdl
60 nasm $(NASM_FLAGS) build/example.asm -o build/example.o
61 ld build/example.o -o build/example
62 @./build/example
63 60
64# Remove build directory. 61# Remove build directory.
65clean: 62clean:
diff --git a/src/ir.h b/src/ir.h
new file mode 100644
index 0000000..10f48fd
--- /dev/null
+++ b/src/ir.h
@@ -0,0 +1,155 @@
1#ifndef BDL_IR_H
2#define BDL_IR_H
3
4typedef struct LineInfo {
5 size_t line;
6 size_t col;
7} LineInfo;
8
9typedef enum Op {
10 // Arithmetic ops.
11 // - Binary operations.
12 // - Arguments are passed via the stack.
13 OP_ADD,
14 OP_SUB,
15 OP_MUL,
16 OP_DIV,
17 OP_MOD,
18 // Stack ops.
19 // - Requires an Object to push into the stack.
20 OP_PUSH,
21 // - Discards the last value in the stack.
22 OP_DROP,
23 // Jump/conditional ops.
24 // - Take a label as argument.
25 // - For conditional jumps, the last value in the stack is used.
26 OP_JUMP,
27 OP_JUMP_IF_FALSE,
28 // Primitive complex commands.
29 // - Prints the last object in the stack.
30 OP_PRINT,
31 // Procedures.
32 // - Requires a function name as parameter.
33 OP_CALL,
34 // - Return position is on a know location of the stack based on the offset
35 // of locals, parameters, etc.
36 OP_RETURN,
37 // TODO: add remaining ops.
38} Op;
39
40static const char* ops_str[] = {
41 [OP_ADD] = "OP_ADD",
42 [OP_SUB] = "OP_SUB",
43 [OP_MUL] = "OP_MUL",
44 [OP_DIV] = "OP_DIV",
45 [OP_MOD] = "OP_MOD",
46 [OP_PUSH] = "OP_PUSH",
47 [OP_DROP] = "OP_DROP",
48 [OP_JUMP] = "OP_JUMP",
49 [OP_JUMP_IF_FALSE] = "OP_JUMP_IF_FALSE",
50 [OP_PRINT] = "OP_PRINT",
51 [OP_CALL] = "OP_CALL",
52 [OP_RETURN] = "OP_RETURN",
53};
54
55typedef struct Instruction {
56 Op op;
57 Object *argument;
58
59 // Original line/column for debugging purposes.
60 size_t line;
61 size_t col;
62} Instruction;
63
64typedef struct Procedure {
65 // Procedure name.
66 char *name;
67
68 // Program code.
69 Instruction *instructions;
70
71 // Number of locals and parameters.
72 size_t n_params;
73 size_t n_locals;
74} Procedure;
75
76typedef struct ProgramIr {
77 Procedure **procedures;
78 Object **constants;
79} ProgramIr;
80
81void
82print_instruction(Instruction *instruction) {
83 printf("%4ld:%-4ld ", instruction->line, instruction->col);
84 Op op = instruction->op;
85 switch (op) {
86 case OP_PUSH: {
87 printf("%-16s -> ", ops_str[op]);
88 OBJ_PRINT(instruction->argument);
89 } break;
90 default: {
91 printf("%s\n", ops_str[op]);
92 } break;
93 }
94}
95
96void
97print_procedure(Procedure *proc) {
98 printf("===== %.*s =====\n", (int)array_size(proc->name), proc->name);
99 printf("code:\n");
100 for (size_t i = 0; i < array_size(proc->instructions); ++i) {
101 print_instruction(&proc->instructions[i]);
102 }
103}
104
105Procedure *
106proc_alloc(ProgramIr *program, StringView name) {
107 Procedure *proc = calloc(1, sizeof(Procedure));
108 array_init(proc->name, name.n);
109 array_insert(proc->name, name.start, name.n);
110 array_init(proc->instructions, 0);
111 array_push(program->procedures, proc);
112 return proc;
113}
114
115void
116compile_object(ProgramIr *program, Procedure *proc, Object *obj) {
117 switch (obj->type) {
118 case OBJ_TYPE_NIL:
119 case OBJ_TYPE_TRUE:
120 case OBJ_TYPE_FALSE:
121 case OBJ_TYPE_STRING:
122 case OBJ_TYPE_FIXNUM: {
123 Instruction inst = (Instruction){OP_PUSH, obj, obj->line, obj->col};
124 array_push(proc->instructions, inst);
125 } break;
126 // case OBJ_TYPE_PAIR: { compile_proc_call(obj); } break;
127 // case OBJ_TYPE_IF: { compile_if(obj); } break;
128 // case OBJ_TYPE_LAMBDA: { compile_lambda(obj); } break;
129 // case OBJ_TYPE_DEF: { compile_def(obj); } break;
130 // case OBJ_TYPE_SYMBOL: { compile_symbol(obj); } break;
131 default: break;
132 }
133}
134
135ProgramIr
136compile(Program program) {
137 ProgramIr program_ir = {0};
138 array_init(program_ir.procedures, 0);
139 array_init(program_ir.constants, 0);
140 Procedure *main = proc_alloc(&program_ir, STRING("main"));
141
142 for (size_t i = 0; i < array_size(program.roots); i++) {
143 Object *root = program.roots[i];
144 compile_object(&program_ir, main, root);
145 }
146
147 // DEBUG:...
148 for (size_t i = 0; i < array_size(program_ir.procedures); ++i) {
149 print_procedure(program_ir.procedures[i]);
150 }
151
152 return program_ir;
153}
154
155#endif // BDL_IR_H
diff --git a/src/main.c b/src/main.c
index d006d2d..30eab2b 100644
--- a/src/main.c
+++ b/src/main.c
@@ -8,7 +8,8 @@
8#include "errors.c" 8#include "errors.c"
9#include "lexer.c" 9#include "lexer.c"
10#include "parser.c" 10#include "parser.c"
11#include "compiler.h" 11#include "ir.h"
12// #include "compiler.h"
12 13
13void 14void
14init(void) { 15init(void) {
@@ -45,7 +46,8 @@ process_source(const StringView *source, const char *file_name) {
45 // TODO: Optimization. 46 // TODO: Optimization.
46 47
47 // Compilation. 48 // Compilation.
48 compile(program); 49 ProgramIr program_ir = compile(program);
50 (void)program_ir;
49 51
50 // Free resources. 52 // Free resources.
51 free_objects(); 53 free_objects();