Skip to content

Commit

Permalink
Fix objectTypeCheck.
Browse files Browse the repository at this point in the history
  • Loading branch information
fubark committed Oct 4, 2023
1 parent 961b0c7 commit bf73c50
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 7 deletions.
21 changes: 14 additions & 7 deletions src/codegen.zig
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,8 @@ fn objectInit(self: *Chunk, nodeId: cy.NodeId, req: RegisterCstr) !GenValue {
entryId = entry.next;
}

var hasDynamicInit = false;
const dynamicInitIdxStart = self.stackData.items.len;
var reqTypeCheck = false;
const typeCheckIdxStart = self.stackData.items.len;
for (fieldsData, 0..) |item, fidx| {
if (item.nodeId == cy.NullId) {
if (mod.fields[fidx].typeId == bt.Dynamic) {
Expand All @@ -298,17 +298,18 @@ fn objectInit(self: *Chunk, nodeId: cy.NodeId, req: RegisterCstr) !GenValue {
} else {
const entry = self.nodes[item.nodeId];
const exprv = try expression(self, entry.head.mapEntry.right, RegisterCstr.tempMustRetain);
if (exprv.vtype == bt.Dynamic) {
hasDynamicInit = true;
if (mod.fields[fidx].typeId != bt.Dynamic and exprv.vtype == bt.Dynamic) {
reqTypeCheck = true;
try self.stackData.append(self.alloc, .{ .idx = @intCast(fidx) });
}
}
}

if (hasDynamicInit) {
if (reqTypeCheck) {
try self.pushFailableDebugSym(nodeId);
try self.buf.pushOp2(.objectTypeCheck, tempStart, @intCast(mod.fields.len));
for (self.stackData.items[dynamicInitIdxStart..]) |fidx| {
const typeCheckIdxes = self.stackData.items[typeCheckIdxStart..];
try self.buf.pushOp2(.objectTypeCheck, tempStart, @intCast(typeCheckIdxes.len));
for (typeCheckIdxes) |fidx| {
const start = self.buf.ops.items.len;
try self.buf.pushOperands(&.{ @as(u8, @intCast(fidx.idx)), 0, 0, 0, 0 });
self.buf.setOpArgU32(start + 1, mod.fields[fidx.idx].typeId);
Expand Down Expand Up @@ -3325,6 +3326,9 @@ fn genMethodDecl(self: *Chunk, typeId: rt.TypeId, node: cy.Node, func: sema.Func
const jumpPc = try self.pushEmptyJump();

try self.pushSemaBlock(func.semaBlockId);
if (self.compiler.config.genDebugFuncMarkers) {
try self.compiler.buf.pushDebugFuncStart(node.head.func.semaDeclId, self.id);
}

const opStart: u32 = @intCast(self.buf.ops.items.len);
try self.reserveFuncParams(func.numParams);
Expand All @@ -3335,6 +3339,9 @@ fn genMethodDecl(self: *Chunk, typeId: rt.TypeId, node: cy.Node, func: sema.Func

const stackSize = self.getMaxUsedRegisters();
self.popSemaBlock();
if (self.compiler.config.genDebugFuncMarkers) {
try self.compiler.buf.pushDebugFuncEnd(node.head.func.semaDeclId, self.id);
}

self.patchJumpToCurPc(jumpPc);

Expand Down
1 change: 1 addition & 0 deletions src/vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -1516,6 +1516,7 @@ ResultCode execBytecode(VM* vm) {
}
dataPtr += 5;
}
pc = dataPtr;
NEXT();
}
CASE(ObjectSmall): {
Expand Down
40 changes: 40 additions & 0 deletions test/behavior_test.zig
Original file line number Diff line number Diff line change
Expand Up @@ -1322,6 +1322,46 @@ test "Objects." {
}}.func);
}

test "Object fields." {
// Initialize field with dynamic value does not gen `objectTypeCheck`.
try eval(.{ .silent = true },
\\type S object:
\\ a
\\func foo():
\\ return 123
\\var s = S{a: foo()}
, struct { fn func(run: *VMrunner, res: EvalResult) !void {
_ = try res;

const ops = run.vm.internal().ops;
var pc: u32 = 0;
while (pc < ops.len) {
if (@as(cy.OpCode, @enumFromInt(ops[pc].val)) == .objectTypeCheck) {
return error.Failed;
}
pc += cy.bytecode.getInstLenAt(ops.ptr + pc);
}
}}.func);

// Initialize field with typed value does not gen `objectTypeCheck`.
try eval(.{ .silent = true },
\\type S object:
\\ a
\\var s = S{a: 123}
, struct { fn func(run: *VMrunner, res: EvalResult) !void {
_ = try res;

const ops = run.vm.internal().ops;
var pc: u32 = 0;
while (pc < ops.len) {
if (@as(cy.OpCode, @enumFromInt(ops[pc].val)) == .objectTypeCheck) {
return error.Failed;
}
pc += cy.bytecode.getInstLenAt(ops.ptr + pc);
}
}}.func);
}

test "Typed object fields." {
// Field declaration ends the file without parser error.
try evalPass(.{},
Expand Down

0 comments on commit bf73c50

Please sign in to comment.