Skip to content

Commit

Permalink
inline generic structural/alias types (#350)
Browse files Browse the repository at this point in the history
* inline structural/alias invocations even with generic arguments, broken

* don't generate in output, could clean up later

* update comments

* fix generic object constructors

* update tdefault output

* update trecursiveobj
  • Loading branch information
metagn authored Jan 11, 2025
1 parent d2f9b48 commit 33a67cc
Show file tree
Hide file tree
Showing 6 changed files with 173 additions and 10 deletions.
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

0 comments on commit 33a67cc

Please sign in to comment.