You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(chunk): add OP_SWAP opcode to swap top two stack elements for better stack manipulation
feat(compiler): implement logic for handling reference type assignments and updates for global variables
feat(vm): add support for OP_SWAP in the virtual machine to facilitate stack operations
docs(ref_example): create examples demonstrating reference updates and rebindings in the language
docs(test_global_ref): add test case for verifying reference updates on global variables
returnnil, nil, fmt.Errorf("[line %d] type mismatch in rebind to global '%s': expected %s, got %s", c.currentLine, ident.Value, globalType.String(), valType.String())
returnnil, nil, fmt.Errorf("[line %d] type mismatch in update to global '%s': expected %s (rebind) or %s (update), got %s", c.currentLine, ident.Value, refType.String(), refType.ElementType.String(), valType.String())
// But we have [val, ref]. We need to emit differently.
266
+
// Actually, we compiled Value first, then GET_GLOBAL.
267
+
// Stack: [val, ref]
268
+
// OP_STORE_REF expects: pop val, pop ref. So [ref, val] order.
269
+
// We have [val, ref]. We need OP_STORE_REF_SWAPPED or different approach.
270
+
// Alternative: Emit GET_GLOBAL first, then compile value.
271
+
// But we already compiled value. Can't undo.
272
+
// Use OP_STORE_REF with swapped logic? Or add OP_SWAP?
273
+
// For now, let's just emit the global name and use a new opcode.
274
+
// Actually, I'll recompile: emit GET first, then value.
275
+
// NO - value already compiled.
276
+
// HACK: pop both, swap, push back? No such ops.
277
+
// Simplest: Just do the store in VM with swapped operands.
278
+
// I'll create OP_STORE_GLOBAL_DEREF which takes name as operand.
279
+
// Stack: [val] -> reads global ref, writes val to it.
280
+
// That's cleaner. Let's use that.
281
+
// Actually, I don't have that opcode. Let me improvise.
282
+
// Emit: swap then store_ref? No swap opcode.
283
+
// For now, just error and require wrapping in function.
284
+
// TODO: Add proper support later.
285
+
// Actually, simpler: just use existing logic but different stack order.
286
+
// Re-emit: POP val (save in temp), GET_GLOBAL, push val back, STORE_REF
287
+
// No temp storage in VM.
288
+
// Let's just emit correct order by recompiling:
289
+
// This is hacky but works: emit a synthetic sequence.
290
+
// GET_GLOBAL pushes ref. Then we need val on top.
291
+
// We already have val on stack. GET_GLOBAL added ref.
292
+
// Stack: [val, ref]. STORE_REF wants [ref, val].
293
+
// I'll add a simple OP_SWAP.
294
+
c.emitByte(byte(chunk.OP_SWAP))
295
+
c.emitByte(byte(chunk.OP_STORE_REF))
296
+
// No OP_POP needed - STORE_REF consumes both values
297
+
}
298
+
returnc.currentChunk, nil, nil
299
+
}
300
+
// Standard type check for non-ref globals
242
301
if!c.areTypesCompatible(globalType, valType) {
243
302
returnnil, nil, fmt.Errorf("[line %d] type mismatch in assignment to global '%s': expected %s, got %s", c.currentLine, ident.Value, globalType.String(), valType.String())
0 commit comments