diff --git a/src/nimony/decls.nim b/src/nimony/decls.nim index 0af905cd..f5174e20 100644 --- a/src/nimony/decls.nim +++ b/src/nimony/decls.nim @@ -14,6 +14,10 @@ proc isRoutine*(t: SymKind): bool {.inline.} = proc isLocal*(t: SymKind): bool {.inline.} = t in {LetY, VarY, ResultY, ConstY, ParamY, TypevarY, CursorY, FldY, EfldY} +proc isNominal*(t: TypeKind): bool {.inline.} = + ## type kinds that should stay as symbols, see sigmatch.matchSymbol + t in {ObjectT, EnumT, HoleyEnumT, DistinctT, ConceptT} + const LocalTypePos* = 3 LocalValuePos* = 4 diff --git a/src/nimony/sem.nim b/src/nimony/sem.nim index 27ec4f85..02653f10 100644 --- a/src/nimony/sem.nim +++ b/src/nimony/sem.nim @@ -1777,9 +1777,9 @@ proc semTypeSym(c: var SemContext; s: Sym; info: PackedLineInfo; start: int; con typeclassBuf.addParRi() typeclassBuf.addParRi() replace(c.dest, cursorAt(typeclassBuf, 0), start) - else: + elif res.status == LacksNothing: let typ = asTypeDecl(res.decl) - if isGeneric(typ) or typ.body.typeKind in {ObjectT, EnumT, HoleyEnumT, DistinctT, ConceptT}: + if isGeneric(typ) or isNominal(typ.body.typeKind): # types that should stay as symbols, see sigmatch.matchSymbol discard else: @@ -2055,7 +2055,12 @@ proc semInvoke(c: var SemContext; n: var Cursor) = semLocalTypeImpl c, n, AllowValues swap c.usedTypevars, genericArgs wantParRi c, n - if (genericArgs == 0 or magicKind != NoType) and ok: + if ok and (genericArgs == 0 or magicKind != NoType or + # structural types are inlined even with generic arguments + # XXX does not instantiate properly if structural type is forward declared + # because typevar syms are not created in the SemcheckTopLevelSyms phase + # maybe they could be declared and captured in the body with an untyped prepass + not isNominal(decl.body.typeKind)): # we have to be eager in generic type instantiations so that type-checking # can do its job properly: let key = typeToCanon(c.dest, typeStart) @@ -2113,7 +2118,8 @@ proc semInvoke(c: var SemContext; n: var Cursor) = semLocalTypeImpl c, m, InLocalDecl return let targetSym = newSymId(c, headId) - c.instantiatedTypes[key] = targetSym + if genericArgs == 0: + c.instantiatedTypes[key] = targetSym var sub = createTokenBuf(30) subsGenericTypeFromArgs c, sub, info, headId, targetSym, decl, args c.dest.endRead() @@ -3691,6 +3697,7 @@ proc semObjConstr(c: var SemContext, it: var Item) = c.dest.shrink exprStart var decl = default(TypeDecl) var objType = it.typ + let isGenericObj = containsGenericParams(objType) if objType.typeKind in {RefT, PtrT}: inc objType if objType.typeKind == InvokeT: @@ -3738,7 +3745,11 @@ proc semObjConstr(c: var SemContext, it: var Item) = skip it.n else: setFieldPositions[field.sym] = fieldStart - fieldBuf.add symToken(field.sym, info) + if isGenericObj: + # do not save generic field sym + fieldBuf.add identToken(fieldName, info) + else: + fieldBuf.add symToken(field.sym, info) # maybe add inheritance depth too somehow? var val = Item(n: it.n, typ: field.typ) swap c.dest, fieldBuf diff --git a/tests/nimony/basics/tgenericbinarytree.nif b/tests/nimony/basics/tgenericbinarytree.nif new file mode 100644 index 00000000..926f1d61 --- /dev/null +++ b/tests/nimony/basics/tgenericbinarytree.nif @@ -0,0 +1,128 @@ +(.nif24) +,1,tests/nimony/basics/tgenericbinarytree.nim(stmts 5 + (type :int.0.tge0lah6v + (i -1) . 5 + (pragmas 2 + (magic 7 Int)) .) 10,3 + (type ~8 :Node.0.tge0lah6v . ~4 + (typevars 1 + (typevar :T.0.tge0lah6v . . . .)) . 2 + (ref 11 + (at ~7 NodeObj.0.tge0lah6v 1 T.0.tge0lah6v))) 13,4 + (type ~11 :NodeObj.0.tge0lah6v . ~4 + (typevars 1 + (typevar :T.1.tge0lah6v . . . .)) . 2 + (object . ~11,1 + (fld :data.0.tge0lah6v . . 6 T.1.tge0lah6v .) ~11,2 + (fld :left.0.tge0lah6v . . 8,~3 + (ref 11 + (at ~7 NodeObj.0.tge0lah6v ~1,3 T.1.tge0lah6v)) .) ~5,2 + (fld :right.0.tge0lah6v . . 2,~3 + (ref 11 + (at ~7 NodeObj.0.tge0lah6v ~1,3 T.1.tge0lah6v)) .))) 4,8 + (var :x.0.tge0lah6v . . 8,~5 + (ref 11 NodeObj.1.tge0lah6v) 13 + (obj ~5,~5 + (ref 11 NodeObj.1.tge0lah6v) 5 + (kv ~5 data.1.tge0lah6v 2 +123) 16 + (kv ~16 left.1.tge0lah6v 2 + (nil)) 28 + (kv ~28 right.1.tge0lah6v 2 + (nil)))) 7,9 + (asgn ~6 + (dot ~1 x.0.tge0lah6v data.1.tge0lah6v +0) 2 +456) 7,10 + (asgn ~6 + (dot ~1 x.0.tge0lah6v left.1.tge0lah6v +0) 11 + (obj ~6,~7 + (ref 11 NodeObj.1.tge0lah6v) 5 + (kv ~5 data.1.tge0lah6v 2 +123) 16 + (kv ~16 left.1.tge0lah6v 2 + (nil)) 28 + (kv ~28 right.1.tge0lah6v 2 + (nil)))) 8,11 + (asgn ~7 + (dot ~1 x.0.tge0lah6v right.1.tge0lah6v +0) 2 + (nil)) 13,12 + (asgn ~7 + (dot ~5 + (dot ~1 x.0.tge0lah6v left.1.tge0lah6v +0) right.1.tge0lah6v +0) 2 + (nil)) 4,13 + (var :y.0.tge0lah6v . . 8,~10 + (ref 11 NodeObj.1.tge0lah6v) 13 + (obj ~5,~10 + (ref 11 NodeObj.1.tge0lah6v) 5 + (kv ~5 data.1.tge0lah6v 2 +987) 16 + (kv ~16 left.1.tge0lah6v 2 + (nil)) 28 + (kv ~28 right.1.tge0lah6v 2 + (nil)))) 12,14 + (asgn ~6 + (dot ~5 + (dot ~1 x.0.tge0lah6v left.1.tge0lah6v +0) left.1.tge0lah6v +0) 11 + (obj ~11,~11 + (ref 11 NodeObj.1.tge0lah6v) 5 + (kv ~5 data.1.tge0lah6v 2 -123) 17 + (kv ~17 left.1.tge0lah6v 2 y.0.tge0lah6v) 27 + (kv ~27 right.1.tge0lah6v 2 y.0.tge0lah6v))) ,16 + (proc 5 :foo.0.tge0lah6v . . 8 + (typevars 1 + (typevar :T.2.tge0lah6v . . . .)) 11 + (params 1 + (param :data.0 . . 6 T.2.tge0lah6v .)) 12,~13 + (ref 11 + (at ~7 NodeObj.0.tge0lah6v ~7,13 T.2.tge0lah6v)) . . 2,1 + (stmts 7 + (result :result.0 . . 3,~14 + (ref 11 + (at ~7 NodeObj.0.tge0lah6v ~7,13 T.2.tge0lah6v)) .) 7 + (asgn ~7 result.0 9 + (obj ~6,~14 + (ref 11 + (at ~7 NodeObj.0.tge0lah6v ~7,13 T.2.tge0lah6v)) 5 + (kv ~5 data 2 data.0) 17 + (kv ~17 left 2 + (nil)) 29 + (kv ~29 right 2 + (nil)))) 12,1 + (asgn ~6 + (dot ~6 result.0 data.0.tge0lah6v +0) 2 data.0) ~2,~1 + (ret result.0))) 4,19 + (let :a.0.tge0lah6v . . 8,~16 + (ref 11 NodeObj.1.tge0lah6v) 7 + (call ~3 foo.1.tge0lah6v 1 +123)) 2,20 + (asgn ~2 x.0.tge0lah6v 2 a.0.tge0lah6v) 11,19 + (proc :foo.1.tge0lah6v . ~11,~3 . + (at foo.0.tge0lah6v + (i -1)) ,~3 + (params 1 + (param :data.2 . . + (i -1) .)) 1,~16 + (ref 11 NodeObj.1.tge0lah6v) ~11,~3 . ~11,~3 . ~9,~2 + (stmts 7 + (result :result.1 . . 3,~14 + (ref 11 NodeObj.1.tge0lah6v) .) 7 + (asgn ~7 result.1 9 + (obj ~6,~14 + (ref 11 NodeObj.1.tge0lah6v) 5 + (kv ~5 data.1.tge0lah6v 2 data.2) 17 + (kv ~17 left.1.tge0lah6v 2 + (nil)) 29 + (kv ~29 right.1.tge0lah6v 2 + (nil)))) 12,1 + (asgn ~6 + (dot ~6 result.1 data.1.tge0lah6v +0) 2 data.2) ~2,~1 + (ret result.1))) 12,8 + (type :Node.4.tge0lah6v . + (at Node.0.tge0lah6v ~7,~8 + (i -1)) ~2,~5 . ,~5 + (ref 11 NodeObj.1.tge0lah6v)) 23,3 + (type :NodeObj.1.tge0lah6v . + (at NodeObj.0.tge0lah6v ~18,~3 + (i -1)) ~10,1 . ~8,1 + (object . ~11,1 + (fld :data.1.tge0lah6v . . 1,~5 + (i -1) .) ~11,2 + (fld :left.1.tge0lah6v . . 8,~3 + (ref 11 NodeObj.1.tge0lah6v) .) ~5,2 + (fld :right.1.tge0lah6v . . 2,~3 + (ref 11 NodeObj.1.tge0lah6v) .)))) \ No newline at end of file diff --git a/tests/nimony/basics/tgenericbinarytree.nim b/tests/nimony/basics/tgenericbinarytree.nim new file mode 100644 index 00000000..1b50e90f --- /dev/null +++ b/tests/nimony/basics/tgenericbinarytree.nim @@ -0,0 +1,21 @@ +type int* {.magic: Int.} + +type + Node[T] = ref NodeObj[T] + NodeObj[T] = object + data: T + left, right: Node[T] + +var x = Node[int](data: 123, left: nil, right: nil) +x.data = 456 +x.left = Node[int](data: 123, left: nil, right: nil) +x.right = nil +x.left.right = nil +var y = Node[int](data: 987, left: nil, right: nil) +x.left.left = Node[int](data: -123, left: y, right: y) + +proc foo[T](data: T): Node[T] = + result = Node[T](data: data, left: nil, right: nil) + result.data = data +let a = foo(123) +x = a diff --git a/tests/nimony/generics/trecursiveobj.nim b/tests/nimony/generics/trecursiveobj.nim index ca89898c..84ff8951 100644 --- a/tests/nimony/generics/trecursiveobj.nim +++ b/tests/nimony/generics/trecursiveobj.nim @@ -5,9 +5,9 @@ type var foo: Foo[int] type + Node[T] = ref NodeObj[T] NodeObj[T] = object val: T left, right: Node[T] - Node[T] = ref NodeObj[T] var node: Node[int] diff --git a/tests/nimony/sysbasics/tdefault.nif b/tests/nimony/sysbasics/tdefault.nif index 3c7519da..d74e99df 100644 --- a/tests/nimony/sysbasics/tdefault.nif +++ b/tests/nimony/sysbasics/tdefault.nif @@ -158,7 +158,7 @@ (asgn ~7 result.2 15 (obj ~6,~1 (at ~10 GenericObj.0.tde837gue 1 T.1.tde837gue) 2 - (kv ~2 x.2.tde837gue 2 x.1))) 9,1 + (kv ~2 x 2 x.1))) 9,1 (asgn ~3 (dot ~6 result.2 x.2.tde837gue +0) 2 x.1) ~2,~1 (ret result.2))) 8,44 @@ -173,9 +173,8 @@ (stmts 7 (result :result.3 . . 9,~1 GenericObj.1.tde837gue .) 7 (asgn ~7 result.3 15 - (obj ~1,~4 GenericObj.1.tde837gue - (kv x.3.tde837gue 28,646,lib/std/system.nim - (expr +0)))) 9,1 + (obj ~1,~4 GenericObj.1.tde837gue 2 + (kv ~2 x.3.tde837gue 2 x.4))) 9,1 (asgn ~3 (dot ~6 result.3 x.3.tde837gue +0) 2 x.4) ~2,~1 (ret result.3))) 23,38