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

initial cut of the change #691

Draft
wants to merge 6 commits into
base: devel
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
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
11 changes: 10 additions & 1 deletion compiler/ast/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -473,12 +473,13 @@ template copyNodeImpl(dst, src, processSonsStmt) =
of nkCharLit..nkUInt64Lit: dst.intVal = src.intVal
of nkFloatLiterals: dst.floatVal = src.floatVal
of nkSym: dst.sym = src.sym
of nkSymChoices: dst.choices = src.choices
of nkIdent: dst.ident = src.ident
of nkStrLit..nkTripleStrLit: dst.strVal = src.strVal
of nkEmpty, nkNone: discard # no children, nothing to do
of nkError:
dst.diag = src.diag # do cheap copies
else: processSonsStmt
of nkWithSons: processSonsStmt

proc copyNode*(src: PNode): PNode =
# does not copy its sons!
Expand All @@ -495,6 +496,14 @@ template transitionNodeKindCommon(k: TNodeKind) =
flags: obj.flags)
# n.comment = obj.comment # shouldn't be needed, the address doesnt' change

proc transitionOpenToClosed*(n: PNode) =
## transitions an `nkOpenSymChoice` to `nkClosedSymChoice`, if it's already
## closed then nothing happens.
assert n.kind in nkSymChoices
if n.kind == nkOpenSymChoice:
transitionNodeKindCommon(nkClosedSymChoice)
n.choices = obj.choices

proc transitionSonsKind*(n: PNode, kind: range[nkDotCall..nkTupleConstr]) =
transitionNodeKindCommon(kind)
n.sons = obj.sons
Expand Down
8 changes: 3 additions & 5 deletions compiler/ast/ast_query.nim
Original file line number Diff line number Diff line change
Expand Up @@ -184,18 +184,16 @@ proc `$`*(s: PSym): string =
else:
result = "<nil>"


proc getnimblePkgId*(a: PSym): int =
let b = a.getnimblePkg
result = if b == nil: -1 else: b.id


proc isCallExpr*(n: PNode): bool =
result = n.kind in nkCallKinds

proc safeLen*(n: PNode): int {.inline.} =
## works even for leaves.
if n.kind in {nkNone..nkNilLit}: result = 0
if n.kind in {nkNone..nkNilLit} + nkSymChoices: result = 0
else: result = n.len

proc getDeclPragma*(n: PNode): PNode =
Expand Down Expand Up @@ -309,8 +307,8 @@ proc hasNilSon*(n: PNode): bool =
proc containsNode*(n: PNode, kinds: TNodeKinds): bool =
if n == nil: return
case n.kind
of nkEmpty..nkNilLit: result = n.kind in kinds
else:
of nkWithoutSons: result = n.kind in kinds
of nkWithSons:
for i in 0..<n.len:
if n.kind in kinds or containsNode(n[i], kinds): return true

Expand Down
10 changes: 9 additions & 1 deletion compiler/ast/ast_types.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1530,6 +1530,8 @@ type
discard
of nkError:
diag*: PAstDiag
of nkClosedSymChoice, nkOpenSymChoice:
choices*: seq[PSym]
else:
sons*: TNodeSeq

Expand Down Expand Up @@ -1764,7 +1766,8 @@ const
{nkSym} +
{nkIdent} +
{nkError} +
{nkEmpty, nkNone}
{nkEmpty, nkNone} +
{nkClosedSymChoice, nkOpenSymChoice}

nkWithSons* = {low(TNodeKind) .. high(TNodeKind)} - nkWithoutSons

Expand Down Expand Up @@ -1835,6 +1838,11 @@ proc add*(father, son: Indexable) =
assert son != nil
father.sons.add(son)

proc add*(choice: PNode, sym: PSym) =
## add a symbol to a sym choice node
assert choice.kind in {nkClosedSymChoice, nkOpenSymChoice}
choice.choices.add sym

template `[]`*(n: Indexable, i: int): Indexable = n.sons[i]
template `[]=`*(n: Indexable, i: int; x: Indexable) = n.sons[i] = x

Expand Down
23 changes: 12 additions & 11 deletions compiler/front/sexp_reporter.nim
Original file line number Diff line number Diff line change
Expand Up @@ -116,17 +116,18 @@ proc sexp*(node: PNode): SexpNode =

result = newSList()
result.add newSSymbol(($node.kind)[2 ..^ 1])
case node.kind:
of nkNone, nkEmpty: discard
of nkCharLit..nkUInt64Lit: result.add sexp(node.intVal)
of nkFloatLit..nkFloat128Lit: result.add sexp(node.floatVal)
of nkStrLit..nkTripleStrLit: result.add sexp(node.strVal)
of nkSym: result.add newSSymbol(node.sym.name.s)
of nkIdent: result.add newSSymbol(node.ident.s)
of nkError: result.add sexp(node.diag.wrongNode)
of nkWithSons:
for node in node.sons:
result.add sexp(node)
case node.kind
of nkNone, nkEmpty: discard
of nkCharLit..nkUInt64Lit: result.add sexp(node.intVal)
of nkFloatLit..nkFloat128Lit: result.add sexp(node.floatVal)
of nkStrLit..nkTripleStrLit: result.add sexp(node.strVal)
of nkSym: result.add newSSymbol(node.sym.name.s)
of nkIdent: result.add newSSymbol(node.ident.s)
of nkError: result.add sexp(node.diag.wrongNode)
of nkSymChoices: result.add newSSymbol(node.choices[0].name.s)
of nkWithSons:
for node in node.sons:
result.add sexp(node)

proc sexp*(t: PSym): SexpNode =
convertSexp([
Expand Down
2 changes: 2 additions & 0 deletions compiler/sem/evaltempl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,8 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
result.add newSymNode(x, if c.instLines: actual.info else: templ.info)
else:
result.add copyNode(c, templ, actual)
of nkSymChoices:
result.add copyNode(c, templ, actual)
of nkNone..nkIdent, nkType..nkNilLit: # atom
result.add copyNode(c, templ, actual)
of nkCommentStmt:
Expand Down
21 changes: 11 additions & 10 deletions compiler/sem/lookups.nim
Original file line number Diff line number Diff line change
Expand Up @@ -211,8 +211,8 @@ proc considerQuotedIdent*(c: PContext; n: PNode): PIdentResult =
of nkIdent, nkSym:
ident = extractAtomicIdent(currN)
of nkOpenSymChoice, nkClosedSymChoice:
assert currN.len > 0 and currN[0].kind == nkSym
currN = currN[0]
assert currN.choices.len > 0
currN = newSymNode(currN.choices[0], currN.info)
of nkAccQuoted:
case currN.len
of 0: ident = notFoundIdent
Expand Down Expand Up @@ -1037,10 +1037,11 @@ proc initOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
c.config.wrapError(errDotExpr))

of nkClosedSymChoice, nkOpenSymChoice:
case n[0].kind
of nkSym:
# xxx: this code doesn't really make sense, likely some caller specific
# quirks are being accommodated here.
if n.choices.len > 0:
o.mode = oimSymChoice
result = n[0].sym
result = n.choices[0]

o.currentScope = c.currentScope # already remember the start scope
o.symChoiceIndex = 1
Expand Down Expand Up @@ -1129,21 +1130,21 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
of oimOtherModule:
result = nextModuleIter(o.mit, c.graph)
of oimSymChoice:
if o.symChoiceIndex < n.len:
result = n[o.symChoiceIndex].sym
if o.symChoiceIndex < n.choices.len:
result = n.choices[o.symChoiceIndex]
incl(o.marked, result.id)
inc o.symChoiceIndex
elif n.kind == nkOpenSymChoice:
# try 'local' symbols too for Koenig's lookup:
o.mode = oimSymChoiceLocalLookup
# the `currentScope` was already initialized by ``initOverloadIter``
result = firstIdentExcluding(o.it, o.currentScope.symbols,
n[0].sym.name, o.marked)
n.choices[0].name, o.marked)
while result == nil:
o.currentScope = o.currentScope.parent
if o.currentScope != nil:
result = firstIdentExcluding(o.it, o.currentScope.symbols,
n[0].sym.name, o.marked)
n.choices[0].name, o.marked)
else:
o.importIdx = 0
result = symChoiceExtension(o, c, n)
Expand All @@ -1157,7 +1158,7 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
o.currentScope = o.currentScope.parent
if o.currentScope != nil:
result = firstIdentExcluding(o.it, o.currentScope.symbols,
n[0].sym.name, o.marked)
n.choices[0].name, o.marked)
else:
o.importIdx = 0
result = symChoiceExtension(o, c, n)
Expand Down
2 changes: 2 additions & 0 deletions compiler/sem/semfields.nim
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ proc instFieldLoopBody(c: TFieldInstCtx, n: PNode, forLoop: PNode): PNode =
result.add(tupl)
result.add(newSymNode(c.field, n.info))
break
of nkSymChoices:
result = instFieldLoopBody(c, newSymNode(n.choices[0], n.info), forLoop)
saem marked this conversation as resolved.
Show resolved Hide resolved
else:
if n.kind == nkContinueStmt:
localReport(c.c.config, n, reportSem rsemFieldsIteratorCannotContinue)
Expand Down
7 changes: 6 additions & 1 deletion compiler/sem/semgnrc.nim
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags,
let syms = semGenericStmtSymbol(c, n, s, ctx, flags, fromDotExpr=true)
if syms.kind == nkSym:
let choice = symChoice(c, n, s, scForceOpen)
choice.transitionSonsKind(nkClosedSymChoice)
transitionOpenToClosed(choice)
result = newDot(result, choice)
else:
result = newDot(result, syms)
Expand Down Expand Up @@ -570,6 +570,11 @@ proc semGenericStmt(c: PContext, n: PNode,
result[1] = semGenericStmt(c, n[1], flags, ctx)
if result[1].isError:
result = c.config.wrapError(result)
of nkSymChoices:
for i, s in n.choices.pairs:
let b = getGenSym(c, s)
if s != b:
result.choices[i] = b
else:
captureError c.config, result:
for i in 0..<n.len:
Expand Down
6 changes: 4 additions & 2 deletions compiler/sem/semtempl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule;
if a.kind != skModule and not(isField and sfGenSym in s.flags):
incl(a.flags, sfUsed)
markOwnerModuleAsUsed(c, a)
result.add newSymNode(a, info)
result.add a
elif a.isError:
localReport(c.config, a.ast)
a = nextOverloadIter(o, c, n)
Expand Down Expand Up @@ -183,7 +183,7 @@ proc semMixinStmt(c: PContext, n: PNode, toMixin: var IntSet): PNode =
if err.isNil:
toMixin.incl(ident.id)
let x = symChoice(c, it, nil, scForceOpen)
inc count, x.len
inc count, x.choices.len
result.add x
else:
result.add err
Expand Down Expand Up @@ -599,6 +599,8 @@ proc semTemplBodySons(c: var TemplCtx, n: PNode): PNode =
case n.kind
of nkError:
discard # return the error in result
of nkSymChoices:
discard
else:
for i in 0..<n.len:
result[i] = semTemplBody(c, n[i])
Expand Down
4 changes: 2 additions & 2 deletions compiler/sem/semtypinst.nim
Original file line number Diff line number Diff line change
Expand Up @@ -201,14 +201,14 @@ proc prepareNode*(cl: var TReplTypeVars, n: PNode): PNode =
# call would traverse into types not depending on any of the type
# variables we're replacing here
result = n
of nkWithoutSons - {nkSym}:
of nkWithoutSons - {nkSym} - nkSymChoices:
resolveStatic()
result = copyNode(n)
result.typ = t
of nkSymChoices:
# a symbol choice is itself similiar to a symbol
result = n
of nkWithSons - nkSymChoices:
of nkWithSons:
resolveStatic()

result = shallowCopy(n)
Expand Down
25 changes: 23 additions & 2 deletions compiler/vm/packed_env.nim
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,9 @@ func storeNode(enc: var TypeInfoEncoder, ps: var PackedEnv, n: PNode): NodeId =
of nkIntKinds: ps.getLitId(n.intVal).int32
of nkFloatKinds: ps.getLitId(n.floatVal).int32
of nkStrKinds: ps.getLitId(n.strVal).int32
of nkSymChoices:
hasSons = true
n.choices.len.int32
of nkWithSons:
hasSons = true
n.sons.len.int32
Expand All @@ -617,8 +620,18 @@ func storeNode(enc: var TypeInfoEncoder, ps: var PackedEnv, n: PNode): NodeId =
typeId: storeTypeLater(enc, ps, n.typ)))

if hasSons:
for s in n.sons.items:
discard storeNode(enc, ps, s)
case n.kind
of nkSymChoices:
for s in n.choices:
let itemId = enc.storeSymLater(ps, n.sym).int32
ps.nimNodes.add(PackedNodeLite(kind: n.kind, flags: n.flags,
operand: itemId,
typeId: storeTypeLater(enc, ps, n.typ)))
of nkWithSons:
for s in n.sons.items:
discard storeNode(enc, ps, s)
else:
unreachable("no other nodes have children")

func storeSymAt(enc: var TypeInfoEncoder, ps: var PackedEnv, s: PSym, id: SymId) =
let p = PackedSymLite(kind: s.kind, magic: s.magic,
Expand Down Expand Up @@ -685,6 +698,14 @@ proc loadNode(dec: var TypeInfoDecoder, ps: PackedEnv, id: NodeId): (PNode, int3
r.sym = dec.loadSym(ps, n.operand.SymId)
of nkIdent:
r.ident = PIdent(s: ps.strings[n.operand.LitId])
of nkSymChoices:
r.choices.newSeq(n.operand)
for i in 1..n.operand:
let
nextId = id.int32 + i
(node, skip) = loadNode(dec, ps, nextId.NodeId)
assert skip == 1, "should be all consequtive sym nodes"
r.choices[i] = node.sym
of nkWithSons:
r.sons.newSeq(n.operand)
var nextId = id.int32 + 1
Expand Down