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

new gensym handling #11985

Merged
merged 14 commits into from
Aug 23, 2019
11 changes: 8 additions & 3 deletions compiler/evaltempl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -52,7 +53,8 @@ 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)
result.add newIdentNode(getIdent(c.ic, x.name.s & ":nim" & $x.id),
if c.instLines: actual.info else: templ.info)
else:
result.add copyNode(c, templ, actual)
of nkNone..nkIdent, nkType..nkNilLit: # atom
Expand Down Expand Up @@ -160,7 +162,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)
Expand All @@ -172,6 +176,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
Expand Down
2 changes: 1 addition & 1 deletion compiler/main.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
2 changes: 1 addition & 1 deletion compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
32 changes: 22 additions & 10 deletions compiler/semtempl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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)
Expand Down Expand Up @@ -119,6 +123,7 @@ type
owner: PSym
cursorInBody: bool # only for nimsuggest
scopeN: int
isDotField: int

template withBracketExpr(ctx, x, body: untyped) =
body
Expand Down Expand Up @@ -327,16 +332,16 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
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.isDotField > 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.isDotField > 0)
elif s.owner == c.owner and sfGenSym in s.flags and c.isDotField == 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:
elif c.isDotField == 0:
result = semTemplSymbol(c.c, n, s)
of nkBind:
result = semTemplBody(c, n.sons[0])
Expand Down Expand Up @@ -529,7 +534,14 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
return symChoice(c.c, n, s, scForceOpen)
else:
return symChoice(c.c, n, s, scOpen)
result = semTemplBodySons(c, n)
if n.kind == nkDotExpr:
result = n
result.sons[0] = semTemplBody(c, n.sons[0])
inc c.isDotField
result.sons[1] = semTemplBody(c, n.sons[1])
dec c.isDotField
else:
result = semTemplBodySons(c, n)
else:
result = semTemplBodySons(c, n)

Expand Down
6 changes: 3 additions & 3 deletions compiler/suggest.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
2 changes: 1 addition & 1 deletion compiler/vm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions doc/manual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4893,6 +4893,8 @@ no semantics outside of a template definition and cannot be abstracted over:
To get rid of hygiene in templates, one can use the `dirty`:idx: pragma for
a template. ``inject`` and ``gensym`` have no effect in ``dirty`` templates.

``gensym``'ed symbols cannot be used
Araq marked this conversation as resolved.
Show resolved Hide resolved



Limitations of the method call syntax
Expand Down
4 changes: 2 additions & 2 deletions lib/core/locks.nim
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,11 @@ template withLock*(a: Lock, body: untyped) =
## Acquires the given lock, executes the statements in body and
## releases the lock after the statements finish executing.
mixin acquire, release
a.acquire()
acquire(a)
{.locks: [a].}:
try:
body
finally:
a.release()
release(a)

{.pop.}
12 changes: 6 additions & 6 deletions lib/system/alloc.nim
Original file line number Diff line number Diff line change
Expand Up @@ -984,7 +984,7 @@ when defined(nimTypeNames):

# ---------------------- thread memory region -------------------------------

template instantiateForRegion(allocator: untyped) =
template instantiateForRegion(allocator: untyped) {.dirty.} =
{.push stackTrace: off.}

when defined(fulldebug):
Expand All @@ -1006,8 +1006,8 @@ template instantiateForRegion(allocator: untyped) =
proc dealloc(p: pointer) =
dealloc(allocator, p)

proc realloc(p: pointer, newsize: Natural): pointer =
result = realloc(allocator, p, newsize)
proc realloc(p: pointer, newSize: Natural): pointer =
result = realloc(allocator, p, newSize)

when false:
proc countFreeMem(): int =
Expand Down Expand Up @@ -1054,13 +1054,13 @@ template instantiateForRegion(allocator: untyped) =
else:
dealloc(p)

proc reallocShared(p: pointer, newsize: Natural): pointer =
proc reallocShared(p: pointer, newSize: Natural): pointer =
when hasThreadSupport:
acquireSys(heapLock)
result = realloc(sharedHeap, p, newsize)
result = realloc(sharedHeap, p, newSize)
releaseSys(heapLock)
else:
result = realloc(p, newsize)
result = realloc(p, newSize)

when hasThreadSupport:
template sharedMemStatsShared(v: int) =
Expand Down