Skip to content

Commit 7c2f375

Browse files
committed
feat: Implement initial bytecode generation for expressions and compiler infrastructure.
1 parent f005a36 commit 7c2f375

1 file changed

Lines changed: 81 additions & 10 deletions

File tree

src/compiler/bytecode_gen.c

Lines changed: 81 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -601,9 +601,10 @@ static void genStmt(BytecodeGen* gen, Stmt* stmt) {
601601
// NOTE: In for loops, vars are in a scope ABOVE the loop scope if declared in init?
602602
// Actually they are inside the scope started by STMT_FOR.
603603
// We need to unwind to loop->scopeDepth.
604-
int currentDepth = gen->compiler->scopeDepth;
605-
// Since we don't track local counts per scope precisely here easily,
606-
// we'll assume VM un-winds or we emit pops?
604+
// Drop locals
605+
// NOTE: In for loops, vars are in a scope ABOVE the loop scope if declared in init?
606+
// Actually they are inside the scope started by STMT_FOR.
607+
// We need to unwind to loop->scopeDepth.
607608
// Bytecode Gen usually emits pops for locals going out of scope.
608609
// BUT break jumps OUT. The locals on stack need to be popped.
609610
// We can't easily emit static POPs if we don't know how many locals are on stack relative to loop start.
@@ -756,13 +757,83 @@ static void genStmt(BytecodeGen* gen, Stmt* stmt) {
756757
for (int i=0; i < stmt->as.class_decl.methods->count; i++) {
757758
genStmt(gen, stmt->as.class_decl.methods->items[i]);
758759
writeChunk(gen->chunk, OP_METHOD, stmt->line);
759-
ObjString* mname = AS_FUNCTION(AS_CLOSURE(consttable_get(gen->chunk, gen->chunk->count-1))->function)->name; // Hacky way to get name?
760-
// Actually genStmt(STMT_FUNC_DECL) emits OP_CLOSURE.
761-
// OP_METHOD needs the method name.
762-
// We need to parse STMT_FUNC_DECL specially or use a helper.
763-
// The STMT_FUNC_DECL puts the closure on stack.
764-
// We need to emit OP_METHOD with the name index.
765-
// For now, assume this works.
760+
genStmt(gen, stmt->as.class_decl.methods->items[i]);
761+
writeChunk(gen->chunk, OP_METHOD, stmt->line);
762+
// Hacky way to get name, but corrected:
763+
// ObjString* mname = AS_CLOSURE(consttable_get(gen->chunk, gen->chunk->count-1))->function->name;
764+
// Actually we don't need 'mname' variable if it was unused too.
765+
// The previous code had it unused. Let's just remove it if it's unused.
766+
// But wait, do we use mname? The screenshot says 'warning: unused variable mname'.
767+
// So we can just remove the line entirely?
768+
// But wait, the line 753 (in screenshot) has 'AS_FUNCTION(...)'.
769+
// If we just remove it, we solve both the error (invalid operand) and the warning (unused variable).
770+
// Let's verify if 'mname' is used below in lines I can't see?
771+
// The view_file output showed up to 766 and I didn't see mname used.
772+
// "Actually genStmt(STMT_FUNC_DECL) emits OP_CLOSURE."
773+
// "OP_METHOD needs the method name."
774+
// "We need to emit OP_METHOD with the name index."
775+
// Wait, OP_METHOD instruction usually takes an operand for the method name?
776+
// In `src/compiler/bytecode.h` (not viewed but standard Lox), OP_METHOD takes name index.
777+
// The code:
778+
// writeChunk(gen->chunk, OP_METHOD, stmt->line);
779+
// It does NOT write the operand for OP_METHOD!
780+
// This is a BUG. OP_METHOD expects a name index.
781+
// We need to extract the name from the just-emitted closure (which is on top of constants?).
782+
// genStmt(STMT_FUNC_DECL) adds the closure constant.
783+
// So the constant index is `gen->chunk->count-1` instructions? NO.
784+
// `addConstant` returns index. `genStmt` for FUNC_DECL emits OP_CLOSURE + index.
785+
// But `addConstant` pushes to constant pool.
786+
// We can inspect the last instruction? Or just trust we can peek constant pool?
787+
// consttable_get(gen->chunk, ...).
788+
// The snippet tries to get the name.
789+
// We need to write the name index.
790+
// But OP_METHOD takes the name of the method *to define*.
791+
// In Lox, OP_METHOD takes the name index.
792+
// So we need:
793+
// ObjFunction* method = ...;
794+
// int nameConst = addConstant(gen->chunk, OBJ_VAL(method->name));
795+
// writeChunk(gen->chunk, OP_METHOD, stmt->line);
796+
// writeChunk(gen->chunk, nameConst, stmt->line);
797+
798+
// The existing code was:
799+
// writeChunk(gen->chunk, OP_METHOD, stmt->line);
800+
// ObjString* mname = ...;
801+
// (and then nothing using mname?)
802+
803+
// If I fix the getting of mname, I should use it to emit the operand.
804+
805+
// Step 1: Fix the Access.
806+
// Value constVal = consttable_get(gen->chunk, gen->chunk->constants.count - 1);
807+
// (Note: we need the index of the constant, not the instruction index? consttable_get might take index?)
808+
// Let's assume we can get the function object.
809+
810+
// Fixed line:
811+
// ObjString* mname = AS_CLOSURE(consttable_get(gen->chunk, gen->chunk->constants.count - 1))->function->name;
812+
813+
// Wait, `consttable_get` signature? I don't see it defined. It is likely `Value consttable_get(Chunk*, int index)`.
814+
// But `genStmt` for FUNC_DECL emits OP_CLOSURE then Index.
815+
// The last constant added is the function closure? No, `addConstant` adds it.
816+
// So `chunk->constants.count - 1` is the index of the closure we just added.
817+
818+
// Let's rewrite the block to be correct and warning-free.
819+
820+
// Note: `genStmt` emits OP_CLOSURE and its operand.
821+
// The operand is the index of the closure in constants.
822+
// Value closureVal = chunk->constants.values[chunk->constants.count - 1];
823+
// ObjClosure* closure = AS_CLOSURE(closureVal);
824+
// ObjString* name = closure->function->name;
825+
// int nameConst = addConstant(gen->chunk, OBJ_VAL(name));
826+
// writeChunk(gen->chunk, (uint8_t)nameConst, stmt->line);
827+
828+
// But we already emitted OP_METHOD without operand?
829+
// Code shows: writeChunk(gen->chunk, OP_METHOD, stmt->line);
830+
// Then the line that failed.
831+
// So we need to insert the operand emission.
832+
833+
Value lastConst = gen->chunk->constants.values[gen->chunk->constants.count - 1];
834+
ObjString* mname = AS_CLOSURE(lastConst)->function->name;
835+
int nameConst = addConstant(gen->chunk, OBJ_VAL(mname));
836+
writeChunk(gen->chunk, (uint8_t)nameConst, stmt->line);
766837
}
767838
writeChunk(gen->chunk, OP_POP, stmt->line); // Pop class
768839
}

0 commit comments

Comments
 (0)