diff --git a/compiler/ast.nim b/compiler/ast.nim index 085a243b3d..6302c21b98 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -293,6 +293,10 @@ const # the compiler will avoid printing such names # in user messages. + sfHoisted* = sfForward + # an expression was hoised to an anonymous variable. + # the flag is applied to the var/let symbol + sfNoForward* = sfRegister # forward declarations are not required (per module) sfReorder* = sfForward @@ -455,6 +459,8 @@ type nfBlockArg # this a stmtlist appearing in a call (e.g. a do block) nfFromTemplate # a top-level node returned from a template nfDefaultParam # an automatically inserter default parameter + nfDefaultRefsParam # a default param value references another parameter + # the flag is applied to proc default values and to calls TNodeFlags* = set[TNodeFlag] TTypeFlag* = enum # keep below 32 for efficiency reasons (now: beyond that) @@ -972,7 +978,7 @@ const PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16, nfDotSetter, nfDotField, nfIsRef, nfPreventCg, nfLL, - nfFromTemplate} + nfFromTemplate, nfDefaultRefsParam} namePos* = 0 patternPos* = 1 # empty except for term rewriting macros genericParamsPos* = 2 diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index a4a14405e5..290ac05ee9 100644 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -34,32 +34,36 @@ when declared(echo): template debug*(x: PSym|PType|PNode) {.deprecated.} = when compiles(c.config): debug(c.config, x) + elif compiles(c.graph.config): + debug(c.graph.config, x) else: error() template debug*(x: auto) {.deprecated.} = echo x -template mdbg*: bool {.dirty.} = - when compiles(c.module): - c.module.fileIdx == c.config.projectMainIdx - elif compiles(c.c.module): - c.c.module.fileIdx == c.c.config.projectMainIdx - elif compiles(m.c.module): - m.c.module.fileIdx == m.c.config.projectMainIdx - elif compiles(cl.c.module): - cl.c.module.fileIdx == cl.c.config.projectMainIdx - elif compiles(p): - when compiles(p.lex): - p.lex.fileIdx == p.lex.config.projectMainIdx + template mdbg*: bool {.deprecated.} = + when compiles(c.graph): + c.module.fileIdx == c.graph.config.projectMainIdx + elif compiles(c.module): + c.module.fileIdx == c.config.projectMainIdx + elif compiles(c.c.module): + c.c.module.fileIdx == c.c.config.projectMainIdx + elif compiles(m.c.module): + m.c.module.fileIdx == m.c.config.projectMainIdx + elif compiles(cl.c.module): + cl.c.module.fileIdx == cl.c.config.projectMainIdx + elif compiles(p): + when compiles(p.lex): + p.lex.fileIdx == p.lex.config.projectMainIdx + else: + p.module.module.fileIdx == p.config.projectMainIdx + elif compiles(m.module.fileIdx): + m.module.fileIdx == m.config.projectMainIdx + elif compiles(L.fileIdx): + L.fileIdx == L.config.projectMainIdx else: - p.module.module.fileIdx == p.config.projectMainIdx - elif compiles(m.module.fileIdx): - m.module.fileIdx == m.config.projectMainIdx - elif compiles(L.fileIdx): - L.fileIdx == L.config.projectMainIdx - else: - error() + error() # --------------------------- ident tables ---------------------------------- proc idTableGet*(t: TIdTable, key: PIdObj): RootRef diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index 24a4f186e7..1b17f620c8 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -336,6 +336,18 @@ proc typeNeedsNoDeepCopy(t: PType): bool = if t.kind in {tyVar, tyLent, tySequence}: t = t.lastSon result = not containsGarbageCollectedRef(t) +proc hoistExpr*(varSection, expr: PNode, name: PIdent, owner: PSym): PSym = + result = newSym(skLet, name, owner, varSection.info, owner.options) + result.flags.incl sfHoisted + result.typ = expr.typ + + var varDef = newNodeI(nkIdentDefs, varSection.info, 3) + varDef.sons[0] = newSymNode(result) + varDef.sons[1] = newNodeI(nkEmpty, varSection.info) + varDef.sons[2] = expr + + varSection.add varDef + proc addLocalVar(g: ModuleGraph; varSection, varInit: PNode; owner: PSym; typ: PType; v: PNode; useShallowCopy=false): PSym = result = newSym(skTemp, getIdent(g.cache, genPrefix), owner, varSection.info, diff --git a/compiler/sem.nim b/compiler/sem.nim index afc794a379..299286545e 100644 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -73,6 +73,16 @@ template semIdeForTemplateOrGeneric(c: PContext; n: PNode; # echo "passing to safeSemExpr: ", renderTree(n) discard safeSemExpr(c, n) +proc fitNodePostMatch(c: PContext, formal: PType, arg: PNode): PNode = + result = arg + let x = result.skipConv + if x.kind in {nkPar, nkTupleConstr} and formal.kind != tyExpr: + changeType(c, x, formal, check=true) + else: + result = skipHiddenSubConv(result) + #result.typ = takeType(formal, arg.typ) + #echo arg.info, " picked ", result.typ.typeToString + proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode = if arg.typ.isNil: localError(c.config, arg.info, "expression has no type: " & @@ -88,13 +98,7 @@ proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode = result = copyTree(arg) result.typ = formal else: - let x = result.skipConv - if x.kind in {nkPar, nkTupleConstr} and formal.kind != tyExpr: - changeType(c, x, formal, check=true) - else: - result = skipHiddenSubConv(result) - #result.typ = takeType(formal, arg.typ) - #echo arg.info, " picked ", result.typ.typeToString + result = fitNodePostMatch(c, formal, result) proc inferWithMetatype(c: PContext, formal: PType, arg: PNode, coerceDistincts = false): PNode diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 0de22cfb3d..67fe992321 100644 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -402,7 +402,9 @@ proc updateDefaultParams(call: PNode) = for i in countdown(call.len - 1, 1): if nfDefaultParam notin call[i].flags: return - call[i] = calleeParams[i].sym.ast + let def = calleeParams[i].sym.ast + if nfDefaultRefsParam in def.flags: call.flags.incl nfDefaultRefsParam + call[i] = def proc semResolvedCall(c: PContext, x: TCandidate, n: PNode, flags: TExprFlags): PNode = diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 0ad1fb8729..fac04e3a0b 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -220,6 +220,14 @@ proc instGenericContainer(c: PContext, info: TLineInfo, header: PType, result = replaceTypeVarsT(cl, header) closeScope(c) +proc referencesAnotherParam(n: PNode, p: PSym): bool = + if n.kind == nkSym: + return n.sym.kind == skParam and n.sym.owner == p + else: + for i in 0..