diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2019-08-23 16:15:02 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-08-23 16:15:02 +0200 |
commit | b07694cd90ab7c6eb4660971ddb818b461d4eed8 (patch) | |
tree | a158993297748d4c55b6e069a6636eefcacd9865 /compiler | |
parent | f28a47ea7b9c579b172653c15dc2cc054adf599a (diff) | |
download | Nim-b07694cd90ab7c6eb4660971ddb818b461d4eed8.tar.gz |
new gensym handling (#11985)
* new .gensym implementation * make astspec test green again * introduce a --useVersion switch to group compatibility switches * fixes #10180 * fixes #11494 * fixes #11483 * object constructor fields and named parameters are also not gensym'ed * disabled broken package
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/commands.nim | 9 | ||||
-rw-r--r-- | compiler/evaltempl.nim | 14 | ||||
-rw-r--r-- | compiler/main.nim | 2 | ||||
-rw-r--r-- | compiler/options.nim | 1 | ||||
-rw-r--r-- | compiler/semexprs.nim | 3 | ||||
-rw-r--r-- | compiler/semtempl.nim | 62 | ||||
-rw-r--r-- | compiler/suggest.nim | 6 | ||||
-rw-r--r-- | compiler/vm.nim | 2 |
8 files changed, 71 insertions, 28 deletions
diff --git a/compiler/commands.nim b/compiler/commands.nim index 3874ea38f..662df9c84 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -788,6 +788,15 @@ proc processSwitch*(switch, arg: string, pass: TCmdLinePass, info: TLineInfo; of "expandmacro": expectArg(conf, switch, arg, pass, info) conf.macrosToExpand[arg] = "T" + of "useversion": + expectArg(conf, switch, arg, pass, info) + case arg + of "0.19": + conf.globalOptions.incl optNimV019 + of "1.0": + discard "the default" + else: + localError(conf, info, "unknown Nim version; currently supported values are: {0.19, 1.0}") of "": conf.projectName = "-" else: diff --git a/compiler/evaltempl.nim b/compiler/evaltempl.nim index d3d3e5f77..d941f6c46 100644 --- a/compiler/evaltempl.nim +++ b/compiler/evaltempl.nim @@ -10,7 +10,7 @@ ## Template evaluation engine. Now hygienic. import - strutils, options, ast, astalgo, msgs, renderer, lineinfos + strutils, options, ast, astalgo, msgs, renderer, lineinfos, idents type TemplCtx = object @@ -20,6 +20,7 @@ type mapping: TIdTable # every gensym'ed symbol needs to be mapped to some # new symbol config: ConfigRef + ic: IdentCache proc copyNode(ctx: TemplCtx, a, b: PNode): PNode = result = copyNode(a) @@ -52,7 +53,11 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) = #if x.kind == skParam and x.owner.kind == skModule: # internalAssert c.config, false idTablePut(c.mapping, s, x) - result.add newSymNode(x, if c.instLines: actual.info else: templ.info) + if sfGenSym in s.flags and optNimV019 notin c.config.globalOptions: + result.add newIdentNode(getIdent(c.ic, x.name.s & "`gensym" & $x.id), + if c.instLines: actual.info else: templ.info) + else: + result.add newSymNode(x, if c.instLines: actual.info else: templ.info) else: result.add copyNode(c, templ, actual) of nkNone..nkIdent, nkType..nkNilLit: # atom @@ -160,7 +165,9 @@ proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode = result.typ = res.typ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym; - conf: ConfigRef; fromHlo=false): PNode = + conf: ConfigRef; + ic: IdentCache; + fromHlo=false): PNode = inc(conf.evalTemplateCounter) if conf.evalTemplateCounter > evalTemplateLimit: globalError(conf, n.info, errTemplateInstantiationTooNested) @@ -172,6 +179,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym; ctx.owner = tmpl ctx.genSymOwner = genSymOwner ctx.config = conf + ctx.ic = ic initIdTable(ctx.mapping) let body = tmpl.getBody diff --git a/compiler/main.nim b/compiler/main.nim index 8cd8a52d4..877b82dd9 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -18,7 +18,7 @@ import sem, idents, passes, extccomp, cgen, json, nversion, platform, nimconf, passaux, depends, vm, idgen, - parser, modules, + modules, modulegraphs, tables, rod, lineinfos, pathutils when not defined(leanCompiler): diff --git a/compiler/options.nim b/compiler/options.nim index 75eec4756..52ecd61bc 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -84,6 +84,7 @@ type # please make sure we have under 32 options optDynlibOverrideAll optNimV2 optMultiMethods + optNimV019 TGlobalOptions* = set[TGlobalOption] diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 8048111cd..57d9aae4b 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -30,7 +30,7 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym, # Note: This is n.info on purpose. It prevents template from creating an info # context when called from an another template pushInfoContext(c.config, n.info, s.detailedInfo) - result = evalTemplate(n, s, getCurrOwner(c), c.config, efFromHlo in flags) + result = evalTemplate(n, s, getCurrOwner(c), c.config, c.cache, efFromHlo in flags) if efNoSemCheck notin flags: result = semAfterMacroCall(c, n, result, s, flags) popInfoContext(c.config) @@ -1236,6 +1236,7 @@ proc semSym(c: PContext, n: PNode, sym: PSym, flags: TExprFlags): PNode = result = newSymNode(s, n.info) else: let info = getCallLineInfo(n) + #if efInCall notin flags: markUsed(c, info, s) onUse(info, s) result = newSymNode(s, info) diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index ddc0667e4..907d2174e 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -47,7 +47,8 @@ type TSymChoiceRule = enum scClosed, scOpen, scForceOpen -proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule): PNode = +proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule; + isField = false): PNode = var a: PSym o: TOverloadIter @@ -63,9 +64,12 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule): PNode = # XXX this makes more sense but breaks bootstrapping for now: # (s.kind notin routineKinds or s.magic != mNone): # for instance 'nextTry' is both in tables.nim and astalgo.nim ... - result = newSymNode(s, info) - markUsed(c, info, s) - onUse(info, s) + if not isField or sfGenSym notin s.flags: + result = newSymNode(s, info) + markUsed(c, info, s) + onUse(info, s) + else: + result = n else: # semantic checking requires a type; ``fitNode`` deals with it # appropriately @@ -74,7 +78,7 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule): PNode = result = newNodeIT(kind, info, newTypeS(tyNone, c)) a = initOverloadIter(o, c, n) while a != nil: - if a.kind != skModule: + if a.kind != skModule and (not isField or sfGenSym notin s.flags): incl(a.flags, sfUsed) addSon(result, newSymNode(a, info)) onUse(info, a) @@ -119,6 +123,7 @@ type owner: PSym cursorInBody: bool # only for nimsuggest scopeN: int + noGenSym: int template withBracketExpr(ctx, x, body: untyped) = body @@ -228,7 +233,7 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) = else: replaceIdentBySym(c.c, n, ident) -proc semTemplSymbol(c: PContext, n: PNode, s: PSym): PNode = +proc semTemplSymbol(c: PContext, n: PNode, s: PSym; isField: bool): PNode = incl(s.flags, sfUsed) # we do not call onUse here, as the identifier is not really # resolved here. We will fixup the used identifiers later. @@ -237,15 +242,18 @@ proc semTemplSymbol(c: PContext, n: PNode, s: PSym): PNode = # Introduced in this pass! Leave it as an identifier. result = n of OverloadableSyms: - result = symChoice(c, n, s, scOpen) + result = symChoice(c, n, s, scOpen, isField) of skGenericParam: - result = newSymNodeTypeDesc(s, n.info) + if isField: result = n + else: result = newSymNodeTypeDesc(s, n.info) of skParam: result = n of skType: - result = newSymNodeTypeDesc(s, n.info) + if isField: result = n + else: result = newSymNodeTypeDesc(s, n.info) else: - result = newSymNode(s, n.info) + if isField: result = n + else: result = newSymNode(s, n.info) proc semRoutineInTemplName(c: var TemplCtx, n: PNode): PNode = result = n @@ -322,22 +330,23 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode = if n.ident.id in c.toInject: return n let s = qualifiedLookUp(c.c, n, {}) if s != nil: - if s.owner == c.owner and s.kind == skParam: + if s.owner == c.owner and s.kind == skParam and + (sfGenSym notin s.flags or c.noGenSym == 0): incl(s.flags, sfUsed) result = newSymNode(s, n.info) onUse(n.info, s) elif contains(c.toBind, s.id): - result = symChoice(c.c, n, s, scClosed) + result = symChoice(c.c, n, s, scClosed, c.noGenSym > 0) elif contains(c.toMixin, s.name.id): - result = symChoice(c.c, n, s, scForceOpen) - elif s.owner == c.owner and sfGenSym in s.flags: + result = symChoice(c.c, n, s, scForceOpen, c.noGenSym > 0) + elif s.owner == c.owner and sfGenSym in s.flags and c.noGenSym == 0: # template tmp[T](x: var seq[T]) = # var yz: T incl(s.flags, sfUsed) result = newSymNode(s, n.info) onUse(n.info, s) else: - result = semTemplSymbol(c.c, n, s) + result = semTemplSymbol(c.c, n, s, c.noGenSym > 0) of nkBind: result = semTemplBody(c, n.sons[0]) of nkBindStmt: @@ -524,12 +533,27 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode = onUse(n.info, s) return newSymNode(s, n.info) elif contains(c.toBind, s.id): - return symChoice(c.c, n, s, scClosed) + return symChoice(c.c, n, s, scClosed, c.noGenSym > 0) elif contains(c.toMixin, s.name.id): - return symChoice(c.c, n, s, scForceOpen) + return symChoice(c.c, n, s, scForceOpen, c.noGenSym > 0) else: - return symChoice(c.c, n, s, scOpen) - result = semTemplBodySons(c, n) + return symChoice(c.c, n, s, scOpen, c.noGenSym > 0) + if n.kind == nkDotExpr: + result = n + result.sons[0] = semTemplBody(c, n.sons[0]) + inc c.noGenSym + result.sons[1] = semTemplBody(c, n.sons[1]) + dec c.noGenSym + else: + result = semTemplBodySons(c, n) + of nkExprColonExpr, nkExprEqExpr: + if n.len == 2: + inc c.noGenSym + result.sons[0] = semTemplBody(c, n.sons[0]) + dec c.noGenSym + result.sons[1] = semTemplBody(c, n.sons[1]) + else: + result = semTemplBodySons(c, n) else: result = semTemplBodySons(c, n) diff --git a/compiler/suggest.nim b/compiler/suggest.nim index dc01916d1..9680bc846 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -261,15 +261,15 @@ proc getQuality(s: PSym): range[0..100] = if exp.kind in {tyUntyped, tyTyped, tyGenericParam, tyAnything}: return 50 return 100 -template wholeSymTab(cond, section: untyped) = +template wholeSymTab(cond, section: untyped) {.dirty.} = var isLocal = true var scopeN = 0 for scope in walkScopes(c.currentScope): if scope == c.topLevelScope: isLocal = false dec scopeN for item in scope.symbols: - let it {.inject.} = item - var pm {.inject.}: PrefixMatch + let it = item + var pm: PrefixMatch if cond: outputs.add(symToSuggest(c.config, it, isLocal = isLocal, section, info, getQuality(it), pm, c.inTypeContext > 0, scopeN)) diff --git a/compiler/vm.nim b/compiler/vm.nim index 75f6cc1c3..31dec418f 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -1137,7 +1137,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = let node = regs[rb+i].regToNode node.info = c.debug[pc] macroCall.add(node) - var a = evalTemplate(macroCall, prc, genSymOwner, c.config) + var a = evalTemplate(macroCall, prc, genSymOwner, c.config, c.cache) if a.kind == nkStmtList and a.len == 1: a = a[0] a.recSetFlagIsRef ensureKind(rkNode) |