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

make var, let work in static, const sections (v2): without intermediate proc #795

Draft
wants to merge 8 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
6 changes: 6 additions & 0 deletions compiler/astalgo.nim
Original file line number Diff line number Diff line change
Expand Up @@ -527,6 +527,12 @@ proc value(this: var DebugPrinter; value: PSym) =
this.value(value.name.s)
this.key("id")
this.value(value.id)
if value.owner != nil:
this.key "ownerName"
this.value($value.owner) # PRTEMP
# this.key "owner"
# this.value(value.owner) # PRTEMP

if value.kind in {skField, skEnumField, skParam}:
this.key("position")
this.value(value.position)
Expand Down
2 changes: 2 additions & 0 deletions compiler/debugutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,5 @@ proc isCompilerDebug*(): bool =
{.undef(nimCompilerDebug).}
echo 'x'
conf0.isDefined("nimCompilerDebug")

include timn/exp/nim_compiler_debugutils
26 changes: 25 additions & 1 deletion compiler/semstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,7 @@ proc semIdentDef(c: PContext, n: PNode, kind: TSymKind): PSym =
else:
result = semIdentWithPragma(c, kind, n, {})
if result.owner.kind == skModule:
# if result.owner.kind in {skModule, skLabel}:
incl(result.flags, sfGlobal)
result.options = c.config.options

Expand Down Expand Up @@ -655,6 +656,17 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
if v.flags * {sfGlobal, sfThread} == {sfGlobal}:
message(c.config, v.info, hintGlobalVar)

proc pushStaticContext(c: PContext, n: PNode): PSym =
let s2 = newSym(skLabel, c.cache.idAnon, nextSymId c.idgen, c.graph.owners[^1], n.info)
s2.flags.incl sfUsed
result = c.p.owner
c.p.owner = s2
pushOwner(c, s2)

proc popStaticContext(c: PContext, ownerOld: PSym) =
c.p.owner = ownerOld
popOwner(c)

proc semConst(c: PContext, n: PNode): PNode =
result = copyNode(n)
inc c.inStaticContext
Expand All @@ -672,8 +684,8 @@ proc semConst(c: PContext, n: PNode): PNode =
var typFlags: TTypeAllowedFlags

# don't evaluate here since the type compatibility check below may add a converter
let ownerOld = pushStaticContext(c, a[^1])
var def = semExprWithType(c, a[^1])

if def.kind == nkSym and def.sym.kind in {skTemplate, skMacro}:
typFlags.incl taIsTemplateOrMacro
elif def.typ.kind == tyTypeDesc and c.p.owner.kind != skMacro:
Expand Down Expand Up @@ -731,6 +743,7 @@ proc semConst(c: PContext, n: PNode): PNode =
else: def[j][1]
b[j] = newSymNode(v)
result.add b
popStaticContext(c, ownerOld)
dec c.inStaticContext

include semfields
Expand Down Expand Up @@ -2227,11 +2240,22 @@ proc semStaticStmt(c: PContext, n: PNode): PNode =
#writeStackTrace()
inc c.inStaticContext
openScope(c)
# var ownerOld: PSym = nil
# if c.config.isDefined("nim_pushStaticContext"):
# ownerOld = pushStaticContext(c, n)
let ownerOld = pushStaticContext(c, n)
let ownerNew = c.p.owner
let a = semStmt(c, n[0], {})
# if c.config.isDefined("nim_pushStaticContext"):
# popStaticContext(c, ownerOld)
popStaticContext(c, ownerOld)
closeScope(c)
dec c.inStaticContext
n[0] = a
dbgIf c.p.owner, ownerOld, ownerNew
evalStaticStmt(c.module, c.idgen, c.graph, a, c.p.owner)
dbgIf "after"
# popStaticContext(c, ownerOld)
when false:
# for incremental replays, keep the AST as required for replays:
result = n
Expand Down
7 changes: 7 additions & 0 deletions compiler/vm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2201,6 +2201,11 @@ proc evalConstExprAux(module: PSym; idgen: IdGenerator;
var c = PCtx g.vm
let oldMode = c.mode
c.mode = mode

# PRTEMP1
# let oldPrc = c.prc
# c.prc = PProc(sym: prc)

let start = genExpr(c, n, requiresValue = mode!=emStaticStmt)
if c.code[start].opcode == opcEof: return newNodeI(nkEmpty, n.info)
assert c.code[start].opcode != opcEof
Expand All @@ -2212,6 +2217,8 @@ proc evalConstExprAux(module: PSym; idgen: IdGenerator;
if result.info.col < 0: result.info = n.info
c.mode = oldMode

# c.prc = oldPrc

proc evalConstExpr*(module: PSym; idgen: IdGenerator; g: ModuleGraph; e: PNode): PNode =
result = evalConstExprAux(module, idgen, g, nil, e, emConst)

Expand Down
25 changes: 21 additions & 4 deletions compiler/vmgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,9 @@ proc genCall(c: PCtx; n: PNode; dest: var TDest) =
c.gABC(n, opcIndCallAsgn, dest, x, n.len)
c.freeTempRange(x, n.len)

template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar
template isGlobal(s: PSym): bool =
# (sfGlobal in s.flags and s.kind != skForVar) or (s.owner != nil and s.owner.kind == skLabel)
(sfGlobal in s.flags and s.kind != skForVar)
proc isGlobal(n: PNode): bool = n.kind == nkSym and isGlobal(n.sym)

proc needsAsgnPatch(n: PNode): bool =
Expand Down Expand Up @@ -986,7 +988,8 @@ proc genBindSym(c: PCtx; n: PNode; dest: var TDest) =
proc fitsRegister*(t: PType): bool =
assert t != nil
t.skipTypes(abstractInst + {tyStatic} - {tyTypeDesc}).kind in {
tyRange, tyEnum, tyBool, tyInt..tyUInt64, tyChar}
# tyRange, tyEnum, tyBool, tyInt..tyUInt64, tyChar}
tyRange, tyEnum, tyBool, tyInt..tyUInt64, tyChar, tyPtr} # PRTEMP

proc ldNullOpcode(t: PType): TOpcode =
assert t != nil
Expand Down Expand Up @@ -1495,11 +1498,13 @@ proc checkCanEval(c: PCtx; n: PNode) =
if {sfCompileTime, sfGlobal} <= s.flags: return
if s.importcCondVar: return
if s.kind in {skVar, skTemp, skLet, skParam, skResult} and
not s.isOwnedBy(c.prc.sym) and s.owner != c.module and c.mode != emRepl:
not s.isOwnedBy(c.prc.sym) and s.owner != c.module and c.mode != emRepl and not (s.owner.kind == skLabel): # PRTEMP
# little hack ahead for bug #12612: assume gensym'ed variables
# are in the right scope:
if sfGenSym in s.flags and c.prc.sym == nil: discard
else: cannotEval(c, n)
else:
# dbg s, s.kind, s.isOwnedBy(c.prc.sym), s.owner, s.owner.kind, c.mode, c.prc.sym, s.flags
cannotEval(c, n)
elif s.kind in {skProc, skFunc, skConverter, skMethod,
skIterator} and sfForward in s.flags:
cannotEval(c, n)
Expand Down Expand Up @@ -1632,6 +1637,8 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
# gfNodeAddr and gfNode are mutually exclusive
assert card(flags * {gfNodeAddr, gfNode}) < 2
let s = n.sym
dbgIf s, c.config$n.info, n, s.isGlobal, s.kind, s.owner, flags, s.position, dest
dbgIf getStacktrace()
if s.isGlobal:
let isImportcVar = importcCondVar(s)
if sfCompileTime in s.flags or c.mode == emRepl or isImportcVar:
Expand Down Expand Up @@ -1664,7 +1671,9 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
s.kind in {skParam, skResult}):
if dest < 0:
dest = s.position + ord(s.kind == skParam)
dbgIf c.prc.regInfo, dest, c.prc.regInfo.len, c.prc.sym
internalAssert(c.config, c.prc.regInfo[dest].kind < slotSomeTemp)
# discard
else:
# we need to generate an assignment:
let requiresCopy = c.prc.regInfo[dest].kind >= slotSomeTemp and
Expand Down Expand Up @@ -1851,6 +1860,7 @@ proc getNullValue(typ: PType, info: TLineInfo; conf: ConfigRef): PNode =
result = newNodeI(nkEmpty, info)

proc genVarSection(c: PCtx; n: PNode) =
dbgIf c.config$n.info, n
for a in n:
if a.kind == nkCommentStmt: continue
#assert(a[0].kind == nkSym) can happen for transformed vars
Expand All @@ -1863,6 +1873,7 @@ proc genVarSection(c: PCtx; n: PNode) =
elif a[0].kind == nkSym:
let s = a[0].sym
checkCanEval(c, a[0])
dbgIf s, s.kind, s.isGlobal, s.position, a[2].kind
if s.isGlobal:
if s.position == 0:
if importcCond(c, s): c.importcSym(a.info, s)
Expand All @@ -1874,8 +1885,10 @@ proc genVarSection(c: PCtx; n: PNode) =
c.globals.add(sa)
s.position = c.globals.len
if a[2].kind != nkEmpty:
dbgIf "gfNodeAddr"
let tmp = c.genx(a[0], {gfNodeAddr})
let val = c.genx(a[2])
dbgIf tmp, val
c.genAdditionalCopy(a[2], opcWrDeref, tmp, 0, val)
c.freeTemp(val)
c.freeTemp(tmp)
Expand All @@ -1885,16 +1898,20 @@ proc genVarSection(c: PCtx; n: PNode) =
c.gABx(a, ldNullOpcode(s.typ), s.position, c.genType(s.typ))
else:
assert s.typ != nil
dbgIf fitsRegister(s.typ), s.typ
if not fitsRegister(s.typ):
c.gABx(a, ldNullOpcode(s.typ), s.position, c.genType(s.typ))
let le = a[0]
assert le.typ != nil
dbgIf fitsRegister(le.typ), le.typ
if not fitsRegister(le.typ) and s.kind in {skResult, skVar, skParam}:
dbgIf "not fitsRegister"
var cc = c.getTemp(le.typ)
gen(c, a[2], cc)
c.gABC(le, whichAsgnOpc(le), s.position.TRegister, cc)
c.freeTemp(cc)
else:
dbgIf "fitsRegister"
gen(c, a[2], s.position.TRegister)
else:
# assign to a[0]; happens for closures
Expand Down
Loading