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 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
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
10 changes: 4 additions & 6 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,14 +307,14 @@ 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

proc hasSubnodeWith*(n: PNode, kind: TNodeKind): bool =
case n.kind
of nkEmpty..nkNilLit, nkFormalParams:
of nkEmpty..nkNilLit, nkFormalParams, nkSymChoices:
result = n.kind == kind
of nkError:
result = hasSubnodeWith(n.diag.wrongNode, kind)
Expand Down
14 changes: 11 additions & 3 deletions 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 @@ -1758,13 +1760,14 @@ type

const
nkWithoutSons* =
{nkNone, nkEmpty} +
{nkIdent} +
{nkSym} +
{nkCharLit..nkUInt64Lit} +
{nkFloatLit..nkFloat128Lit} +
{nkStrLit..nkTripleStrLit} +
{nkSym} +
{nkIdent} +
{nkError} +
{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
2 changes: 1 addition & 1 deletion compiler/ast/errorhandling.nim
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ proc buildErrorList(config: ConfigRef, n: PNode, errs: var seq[PNode]) =
## creates a list (`errs` seq) from most specific to least specific
## by traversing the the error tree in a depth-first-search.
case n.kind
of nkEmpty .. nkNilLit:
of nkEmpty..nkNilLit, nkSymChoices:
discard
of nkError:
buildErrorList(config, n.diag.wrongNode, errs)
Expand Down
30 changes: 15 additions & 15 deletions compiler/ast/renderer.nim
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,7 @@ proc lsub(g: TSrcGen; n: PNode): int =
if containsNL(n.strVal): result = MaxLineLen + 1
else: result = atom(g, n).len
of succ(nkEmpty)..pred(nkTripleStrLit), succ(nkTripleStrLit)..nkNilLit:
# xxx: _never_ write a condition like the above, ffs
result = atom(g, n).len
of nkCall, nkBracketExpr, nkCurlyExpr, nkConv, nkPattern, nkObjConstr:
result = lsub(g, n[0]) + lcomma(g, n, 1) + 2
Expand All @@ -412,7 +413,7 @@ proc lsub(g: TSrcGen; n: PNode): int =
of nkTableConstr:
result = if n.len > 0: lcomma(g, n) + 2 else: len("{:}")
of nkClosedSymChoice, nkOpenSymChoice:
if n.len > 0: result += lsub(g, n[0])
if n.choices.len > 0: result = n.choices[0].name.s.len
of nkTupleTy: result = lcomma(g, n) + len("tuple[]")
of nkTupleClassTy: result = len("tuple")
of nkDotExpr: result = lsons(g, n) + 1
Expand Down Expand Up @@ -898,7 +899,8 @@ proc bracketKind*(g: TSrcGen, n: PNode): BracketKind =
if renderIds notin g.flags:
case n.kind
of nkClosedSymChoice, nkOpenSymChoice:
if n.len > 0: result = bracketKind(g, n[0])
if n.choices.len > 0:
result = bracketKind(g, newSymNode(n.choices[0], n.info))
of nkSym:
result = case n.sym.name.s
of "[]": bkBracket
Expand Down Expand Up @@ -1143,19 +1145,16 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
of nkClosedSymChoice, nkOpenSymChoice:
if renderIds in g.flags:
put(g, tkParLe, "(")
for i in 0..<n.len:
for i in 0..<n.choices.len:
if i > 0: put(g, tkOpr, "|")
if n[i].kind == nkSym:
let s = n[i].sym
if s.owner != nil:
put g, tkSymbol, n[i].sym.owner.name.s
put g, tkOpr, "."
put g, tkSymbol, n[i].sym.name.s
else:
gsub(g, n[i], c)
let s = n.choices[i]
if s.owner != nil:
put g, tkSymbol, n.choices[i].owner.name.s
put g, tkOpr, "."
put g, tkSymbol, n.choices[i].name.s
put(g, tkParRi, if n.kind == nkOpenSymChoice: "|...)" else: ")")
else:
gsub(g, n, 0)
put(g, tkSymbol, n.choices[0].name.s)
of nkPar, nkClosure:
put(g, tkParLe, "(")
gcomma(g, n, c)
Expand Down Expand Up @@ -1249,9 +1248,10 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext, fromStmtList = false) =
of nkPrefix:
gsub(g, n, 0)
if n.len > 1:
let opr = if n[0].kind == nkIdent: n[0].ident
elif n[0].kind == nkSym: n[0].sym.name
elif n[0].kind in {nkOpenSymChoice, nkClosedSymChoice}: n[0][0].sym.name
let opr = case n[0].kind
of nkIdent: n[0].ident
of nkSym: n[0].sym.name
of nkSymChoices: n[0].choices[0].name
else: nil
let nNext = skipHiddenNodes(n[1])
if nNext.kind == nkPrefix or (opr != nil and lexer.isKeyword(opr)):
Expand Down
9 changes: 4 additions & 5 deletions compiler/ast/trees.nim
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ proc cyclicTreeAux(n: PNode, visited: var seq[PNode]): bool =
for v in visited:
if v == n: return true
case n.kind
of nkEmpty..nkNilLit:
of nkEmpty..nkNilLit, nkSymChoices:
discard
of nkError:
visited.add(n)
Expand Down Expand Up @@ -131,8 +131,8 @@ proc isRange*(n: PNode): bool {.inline.} =
let callee = n[0]
if (callee.kind == nkIdent and callee.ident.id == ord(wDotDot)) or
(callee.kind == nkSym and callee.sym.name.id == ord(wDotDot)) or
(callee.kind in {nkClosedSymChoice, nkOpenSymChoice} and
callee[1].sym.name.id == ord(wDotDot)):
(callee.kind in nkSymChoices and
callee.choices[1].name.id == ord(wDotDot)):
result = true

proc whichPragma*(n: PNode): TSpecialWord =
Expand All @@ -141,8 +141,7 @@ proc whichPragma*(n: PNode): TSpecialWord =
of nkIdent: result = whichKeyword(key.ident)
of nkSym: result = whichKeyword(key.sym.name)
of nkCast: result = wCast
of nkClosedSymChoice, nkOpenSymChoice:
result = whichPragma(key[0])
of nkSymChoices: result = whichKeyword(key.choices[0].name)
else: result = wInvalid

proc isNoSideEffectPragma*(n: PNode): bool =
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
5 changes: 4 additions & 1 deletion compiler/sem/evaltempl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import
msgs
],
compiler/utils/[
debugutils
debugutils,
astrepr,
]

# xxx: reports are a code smell meaning data types are misplaced
Expand Down Expand Up @@ -84,6 +85,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
23 changes: 22 additions & 1 deletion compiler/sem/lambdalifting.nim
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ import
liftdestructors,
transf,
lowerings
]
],
compiler/utils/astrepr

# xxx: reports are a code smell meaning data types are misplaced
from compiler/ast/reports_sem import SemReport,
Expand Down Expand Up @@ -305,6 +306,7 @@ type
somethingToDo: bool
graph: ModuleGraph
idgen: IdGenerator
poop: bool

proc initDetectionPass(g: ModuleGraph; fn: PSym; idgen: IdGenerator): DetectionPass =
result.processed = initIntSet()
Expand Down Expand Up @@ -414,6 +416,19 @@ proc addClosureParam(c: var DetectionPass; fn: PSym; info: TLineInfo) =

proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
case n.kind
of nkSymChoices:
c.poop = n.choices.len > 1
if n.choices.len == 1:
detectCapturedVars(newSymNode(n.choices[0], n.info), owner, c)
if c.poop:
for i, c in n.choices.pairs:
if n.typ == c.typ:
echo "found matching type"
break
echo c.graph.config.`$`(n.info), " n:"
debug n
# doAssert n.choices.len == 1, "choices: " & $n.choices.len
# TODO: figure out why we're ending up with 8 choices here during bootstrap
of nkSym:
let
s = n.sym
Expand Down Expand Up @@ -490,6 +505,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
detectCapturedVars(n[namePos], owner, c)
of nkReturnStmt:
detectCapturedVars(n[0], owner, c)
of nkNimNodeLit:
discard "skip nim node literals as they're data not code"
else:
for i in 0..<n.len:
detectCapturedVars(n[i], owner, c)
Expand Down Expand Up @@ -795,6 +812,10 @@ proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool;
else:
var d = initDetectionPass(g, fn, idgen)
detectCapturedVars(body, fn, d)
if d.poop:
echo "the body:"
debug body
doAssert false, "we dun pooped"
if not d.somethingToDo and fn.isIterator:
# the "lift captures" pass needs to always run either directly or
# indirectly for closure iterators, as it's also responsible for
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
Loading