Skip to content

Commit f005a36

Browse files
committed
feat: implement initial bytecode compiler for expressions and VM infrastructure
1 parent 6022377 commit f005a36

3 files changed

Lines changed: 20 additions & 4 deletions

File tree

src/compiler/bytecode_gen.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,10 @@ static int resolveLocal(BytecodeGen* gen, const char* name) {
115115
}
116116

117117
static void addLocal(BytecodeGen* gen, const char* name) {
118+
if (gen->hadError) return;
118119
if (gen->compiler->localCount == 256) {
119120
fprintf(stderr, "Too many local variables.\n");
121+
gen->hadError = true;
120122
return;
121123
}
122124
Local* local = &gen->compiler->locals[gen->compiler->localCount++];
@@ -125,10 +127,12 @@ static void addLocal(BytecodeGen* gen, const char* name) {
125127
}
126128

127129
static void emitConstant(BytecodeGen* gen, Value value, int line) {
130+
if (gen->hadError) return;
128131
int constant = addConstant(gen->chunk, value);
129132
if (constant > 255) {
130133
writeChunk(gen->chunk, OP_CONSTANT, line);
131134
fprintf(stderr, "Too many constants.\n");
135+
gen->hadError = true;
132136
} else {
133137
writeChunk(gen->chunk, OP_CONSTANT, line);
134138
writeChunk(gen->chunk, (uint8_t)constant, line);
@@ -768,18 +772,19 @@ static void genStmt(BytecodeGen* gen, Stmt* stmt) {
768772
}
769773
}
770774

771-
void generateBytecode(StmtList* statements, Chunk* chunk) {
775+
bool generateBytecode(StmtList* statements, Chunk* chunk) {
772776
BytecodeGen gen;
773777
Compiler compiler;
774778

775779
gen.compiler = &compiler;
776780
gen.chunk = chunk;
781+
gen.hadError = false;
777782

778783
compiler.enclosing = NULL;
779784
compiler.function = newFunction();
780785
compiler.function->chunk = *chunk;
781786

782-
compiler.type = COMP_SCRIPT;
787+
compiler.type = COMP_SCRIPT;
783788
compiler.localCount = 0;
784789
compiler.scopeDepth = 0;
785790
compiler.loop = NULL;
@@ -790,9 +795,12 @@ void generateBytecode(StmtList* statements, Chunk* chunk) {
790795
if (statements) {
791796
for (int i = 0; i < statements->count; i++) {
792797
genStmt(&gen, statements->items[i]);
798+
if (gen.hadError) break;
793799
}
794800
}
795801

796802
writeChunk(gen.chunk, OP_NIL, 0);
797803
writeChunk(gen.chunk, OP_RETURN, 0);
804+
805+
return !gen.hadError;
798806
}

src/main.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,12 @@ static void repl() {
9393
// --- Pipeline: AST -> Bytecode -> VM ---
9494
Chunk chunk;
9595
initChunk(&chunk);
96-
generateBytecode(statements, &chunk);
96+
if (!generateBytecode(statements, &chunk)) {
97+
fprintf(stderr, "Compilation error\n");
98+
freeChunk(&chunk);
99+
freeStmtList(statements);
100+
continue;
101+
}
97102

98103
interpretChunk(&vm, &chunk);
99104

src/runtime/vm.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -934,7 +934,10 @@ InterpretResult interpretAST(VM* pvm, StmtList* statements) {
934934
ObjFunction* function = newFunction();
935935

936936
// Connect the AST-based bytecode generator
937-
generateBytecode(statements, &function->chunk);
937+
if (!generateBytecode(statements, &function->chunk)) {
938+
pvm->nextGC = oldNextGC;
939+
return INTERPRET_COMPILE_ERROR;
940+
}
938941

939942
// Setup for execution
940943
push(pvm, OBJ_VAL(function));

0 commit comments

Comments
 (0)