diff --git a/src/builtins/builtins.zig b/src/builtins/builtins.zig index 96a24811c..a9a651dd9 100644 --- a/src/builtins/builtins.zig +++ b/src/builtins/builtins.zig @@ -533,21 +533,13 @@ const ParseCyberState = struct { node: cy.Node, }; -fn genTypeSpecString(vm: *cy.VM, ast: cy.ast.AstView, headId: cy.NodeId) !cy.Value { - if (headId != cy.NullNode) { +fn genTypeSpecString(vm: *cy.VM, ast: cy.ast.AstView, exprId: cy.NodeId) !cy.Value { + if (exprId != cy.NullNode) { var sb: std.ArrayListUnmanaged(u8) = .{}; defer sb.deinit(vm.alloc); - var name = ast.nodeStringById(headId); - try sb.appendSlice(vm.alloc, name); - - var curId = ast.node(headId).next(); - while (curId != cy.NullNode) { - try sb.append(vm.alloc, '.'); - name = ast.nodeStringById(curId); - try sb.appendSlice(vm.alloc, name); - curId = ast.node(curId).next(); - } + var enc = cy.ast.Encoder{ .ast = ast }; + try enc.writeNode(sb.writer(vm.alloc), exprId); return try vm.retainOrAllocAstring(sb.items); } else { diff --git a/src/cte.zig b/src/cte.zig index b87740566..6bc3124e2 100644 --- a/src/cte.zig +++ b/src/cte.zig @@ -96,16 +96,17 @@ fn execTemplateCtNodes(c: *cy.Chunk, template: *cy.sym.TypeTemplate, params: []c try paramMap.put(c.alloc, param.name, params[i]); } + const tchunk = template.chunk(); const res = try c.alloc.alloc(cy.NodeId, template.ctNodes.len); for (template.ctNodes, 0..) |ctNodeId, i| { - const node = c.ast.node(ctNodeId); + const node = tchunk.ast.node(ctNodeId); // Check for simple template param replacement. - const child = c.ast.node(node.data.comptimeExpr.child); + const child = tchunk.ast.node(node.data.comptimeExpr.child); if (child.type() == .ident) { - const name = c.ast.nodeString(child); + const name = tchunk.ast.nodeString(child); if (paramMap.get(name)) |param| { - res[i] = try cte.genNodeFromValue(c, param, node.srcPos); + res[i] = try cte.genNodeFromValue(tchunk, param, node.srcPos); continue; } } @@ -113,7 +114,7 @@ fn execTemplateCtNodes(c: *cy.Chunk, template: *cy.sym.TypeTemplate, params: []c return error.TODO; } - c.updateAstView(c.parser.ast.view()); + tchunk.updateAstView(tchunk.parser.ast.view()); return res; } diff --git a/src/sema.zig b/src/sema.zig index 08047d0b8..0547a514f 100644 --- a/src/sema.zig +++ b/src/sema.zig @@ -968,16 +968,17 @@ pub fn declareHostObject(c: *cy.Chunk, nodeId: cy.NodeId) !*cy.sym.HostObjectTyp } pub fn declareTemplateVariant(c: *cy.Chunk, template: *cy.sym.TypeTemplate, variantId: u32) !*cy.sym.Sym { + const tchunk = template.chunk(); + const template_n = tchunk.ast.node(template.declId); switch (template.kind) { .object_t => { const sym = try c.declareObjectVariantType(template, variantId); // Set variant in context chunk so sema ops know to swap nodes. const variant = template.variants.items[variantId]; - c.patchTemplateNodes = variant.patchNodes; + tchunk.patchTemplateNodes = variant.patchNodes; - const template_n = c.ast.node(template.declId); - try declareObjectMembers(c, @ptrCast(sym), template_n.data.typeTemplate.typeDecl); + try declareObjectMembers(tchunk, @ptrCast(sym), template_n.data.typeTemplate.typeDecl); // Defer method sema. const mod = sym.getMod(); @@ -985,16 +986,15 @@ pub fn declareTemplateVariant(c: *cy.Chunk, template: *cy.sym.TypeTemplate, vari return @ptrCast(sym); }, .enum_t => { - const template_n = c.ast.node(template.declId); - const enum_n = c.ast.node(template_n.data.typeTemplate.typeDecl); + const enum_n = tchunk.ast.node(template_n.data.typeTemplate.typeDecl); const isChoiceType = enum_n.data.enumDecl.isChoiceType; const sym = try c.declareEnumVariantType(template, isChoiceType, variantId); // Set variant in context chunk so sema ops know to swap nodes. const variant = template.variants.items[variantId]; - c.patchTemplateNodes = variant.patchNodes; + tchunk.patchTemplateNodes = variant.patchNodes; - try declareEnumMembers(c, sym, template_n.data.typeTemplate.typeDecl); + try declareEnumMembers(tchunk, sym, template_n.data.typeTemplate.typeDecl); return @ptrCast(sym); }, } diff --git a/src/sym.zig b/src/sym.zig index 2b3b3e28a..847acd65d 100644 --- a/src/sym.zig +++ b/src/sym.zig @@ -415,6 +415,10 @@ pub const TypeTemplate = struct { /// This array allows each variant to build their replacement AST /// without scanning the entire template again for compile-time expressions. ctNodes: []const cy.NodeId, + + pub fn chunk(self: *const TypeTemplate) *cy.Chunk { + return self.head.parent.?.getMod().?.chunk; + } }; pub const TemplateParam = struct { diff --git a/test/modules/import.cy b/test/modules/import.cy index c69faa35f..f8b7e67ff 100644 --- a/test/modules/import.cy +++ b/test/modules/import.cy @@ -60,4 +60,8 @@ my v = a.Vec2.new(3, 4) t.eq(v.x, 3.0) t.eq(v.y, 4.0) +-- Templates from another module. +var b a.TFoo#int = [a: 123] +t.eq(b.a, 123) + --cytest: pass \ No newline at end of file diff --git a/test/modules/test_mods/a.cy b/test/modules/test_mods/a.cy index 8953c1238..8f8e3e78b 100644 --- a/test/modules/test_mods/a.cy +++ b/test/modules/test_mods/a.cy @@ -53,4 +53,8 @@ func Vec2.new(x float, y float): type Vec2Alias Vec2 type Bar: - var a float \ No newline at end of file + var a float + +template(T type) +type TFoo: + var a #T \ No newline at end of file