Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inline generic structural/alias types #350

Merged
merged 6 commits into from
Jan 11, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/nimony/decls.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
21 changes: 16 additions & 5 deletions src/nimony/sem.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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
Expand Down
128 changes: 128 additions & 0 deletions tests/nimony/basics/tgenericbinarytree.nif
Original file line number Diff line number Diff line change
@@ -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) .))))
21 changes: 21 additions & 0 deletions tests/nimony/basics/tgenericbinarytree.nim
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion tests/nimony/generics/trecursiveobj.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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]
7 changes: 3 additions & 4 deletions tests/nimony/sysbasics/tdefault.nif
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
Loading