fixes #937
This commit is contained in:
parent
1ce30b9e10
commit
aa92669d92
5 changed files with 47 additions and 6 deletions
|
|
@ -161,6 +161,13 @@ proc hashType(c: var MD5Context, t: PType) =
|
||||||
if tfShared in t.flags: c &= "shared"
|
if tfShared in t.flags: c &= "shared"
|
||||||
if tfNotNil in t.flags: c &= "not nil"
|
if tfNotNil in t.flags: c &= "not nil"
|
||||||
|
|
||||||
|
proc canonConst(n: PNode): TUid =
|
||||||
|
var c: MD5Context
|
||||||
|
md5Init(c)
|
||||||
|
c.hashTree(n)
|
||||||
|
c.hashType(n.typ)
|
||||||
|
md5Final(c, MD5Digest(result))
|
||||||
|
|
||||||
proc canonSym(s: PSym): TUid
|
proc canonSym(s: PSym): TUid
|
||||||
var c: MD5Context
|
var c: MD5Context
|
||||||
md5Init(c)
|
md5Init(c)
|
||||||
|
|
|
||||||
|
|
@ -161,6 +161,7 @@ type
|
||||||
|
|
||||||
PProc* = ref object
|
PProc* = ref object
|
||||||
blocks*: seq[TBlock] # blocks; temp data structure
|
blocks*: seq[TBlock] # blocks; temp data structure
|
||||||
|
sym*: PSym
|
||||||
slots*: array[TRegister, tuple[inUse: bool, kind: TSlotKind]]
|
slots*: array[TRegister, tuple[inUse: bool, kind: TSlotKind]]
|
||||||
maxSlots*: int
|
maxSlots*: int
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -980,6 +980,25 @@ proc setSlot(c: PCtx; v: PSym) =
|
||||||
kind: if v.kind == skLet: slotFixedLet else: slotFixedVar)
|
kind: if v.kind == skLet: slotFixedLet else: slotFixedVar)
|
||||||
inc c.prc.maxSlots
|
inc c.prc.maxSlots
|
||||||
|
|
||||||
|
proc cannotEval(n: PNode) {.noinline.} =
|
||||||
|
globalError(n.info, errGenerated, "cannot evaluate at compile time: " &
|
||||||
|
n.renderTree)
|
||||||
|
|
||||||
|
proc isOwnedBy(a, b: PSym): bool =
|
||||||
|
var a = a.owner
|
||||||
|
while a != nil and a.kind != skModule:
|
||||||
|
if a == b: return true
|
||||||
|
a = a.owner
|
||||||
|
|
||||||
|
proc checkCanEval(c: PCtx; n: PNode) =
|
||||||
|
# we need to ensure that we don't evaluate 'x' here:
|
||||||
|
# proc foo() = var x ...
|
||||||
|
let s = n.sym
|
||||||
|
if s.position == 0:
|
||||||
|
if s.kind in {skVar, skTemp, skLet, skParam, skResult} and
|
||||||
|
not s.isOwnedBy(c.prc.sym) and s.owner != c.module:
|
||||||
|
cannotEval(n)
|
||||||
|
|
||||||
proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||||
case le.kind
|
case le.kind
|
||||||
of nkBracketExpr:
|
of nkBracketExpr:
|
||||||
|
|
@ -1007,6 +1026,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
of nkSym:
|
of nkSym:
|
||||||
let s = le.sym
|
let s = le.sym
|
||||||
|
checkCanEval(c, le)
|
||||||
if s.isGlobal:
|
if s.isGlobal:
|
||||||
withTemp(tmp, le.typ):
|
withTemp(tmp, le.typ):
|
||||||
c.gen(le, tmp, {gfAddrOf})
|
c.gen(le, tmp, {gfAddrOf})
|
||||||
|
|
@ -1014,7 +1034,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||||
c.gABC(le, opcWrDeref, tmp, val)
|
c.gABC(le, opcWrDeref, tmp, val)
|
||||||
c.freeTemp(val)
|
c.freeTemp(val)
|
||||||
else:
|
else:
|
||||||
if s.kind == skForVar and c.mode == emRepl: c.setSlot s
|
if s.kind == skForVar: c.setSlot s
|
||||||
internalAssert s.position > 0 or (s.position == 0 and
|
internalAssert s.position > 0 or (s.position == 0 and
|
||||||
s.kind in {skParam,skResult})
|
s.kind in {skParam,skResult})
|
||||||
var dest: TRegister = s.position + ord(s.kind == skParam)
|
var dest: TRegister = s.position + ord(s.kind == skParam)
|
||||||
|
|
@ -1046,10 +1066,6 @@ proc importcSym(c: PCtx; info: TLineInfo; s: PSym) =
|
||||||
localError(info, errGenerated,
|
localError(info, errGenerated,
|
||||||
"cannot 'importc' variable at compile time")
|
"cannot 'importc' variable at compile time")
|
||||||
|
|
||||||
proc cannotEval(n: PNode) {.noinline.} =
|
|
||||||
globalError(n.info, errGenerated, "cannot evaluate at compile time: " &
|
|
||||||
n.renderTree)
|
|
||||||
|
|
||||||
proc getNullValue*(typ: PType, info: TLineInfo): PNode
|
proc getNullValue*(typ: PType, info: TLineInfo): PNode
|
||||||
|
|
||||||
proc genGlobalInit(c: PCtx; n: PNode; s: PSym) =
|
proc genGlobalInit(c: PCtx; n: PNode; s: PSym) =
|
||||||
|
|
@ -1190,12 +1206,14 @@ proc genVarSection(c: PCtx; n: PNode) =
|
||||||
setSlot(c, a[i].sym)
|
setSlot(c, a[i].sym)
|
||||||
# v = t[i]
|
# v = t[i]
|
||||||
var v: TDest = -1
|
var v: TDest = -1
|
||||||
|
checkCanEval(c, a[i])
|
||||||
genRdVar(c, a[i], v, {gfAddrOf})
|
genRdVar(c, a[i], v, {gfAddrOf})
|
||||||
c.gABC(n, opcWrObj, v, tmp, i)
|
c.gABC(n, opcWrObj, v, tmp, i)
|
||||||
# XXX globals?
|
# XXX globals?
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
elif a.sons[0].kind == nkSym:
|
elif a.sons[0].kind == nkSym:
|
||||||
let s = a.sons[0].sym
|
let s = a.sons[0].sym
|
||||||
|
checkCanEval(c, a.sons[0])
|
||||||
if s.isGlobal:
|
if s.isGlobal:
|
||||||
if s.position == 0:
|
if s.position == 0:
|
||||||
if sfImportc in s.flags: c.importcSym(a.info, s)
|
if sfImportc in s.flags: c.importcSym(a.info, s)
|
||||||
|
|
@ -1308,6 +1326,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkSym:
|
of nkSym:
|
||||||
let s = n.sym
|
let s = n.sym
|
||||||
|
checkCanEval(c, n)
|
||||||
case s.kind
|
case s.kind
|
||||||
of skVar, skForVar, skTemp, skLet, skParam, skResult:
|
of skVar, skForVar, skTemp, skLet, skParam, skResult:
|
||||||
genRdVar(c, n, dest, flags)
|
genRdVar(c, n, dest, flags)
|
||||||
|
|
@ -1525,7 +1544,7 @@ proc genProc(c: PCtx; s: PSym): int =
|
||||||
# procs easily:
|
# procs easily:
|
||||||
let body = s.getBody
|
let body = s.getBody
|
||||||
let procStart = c.xjmp(body, opcJmp, 0)
|
let procStart = c.xjmp(body, opcJmp, 0)
|
||||||
var p = PProc(blocks: @[])
|
var p = PProc(blocks: @[], sym: s)
|
||||||
let oldPrc = c.prc
|
let oldPrc = c.prc
|
||||||
c.prc = p
|
c.prc = p
|
||||||
# iterate over the parameters and allocate space for them:
|
# iterate over the parameters and allocate space for them:
|
||||||
|
|
|
||||||
13
tests/vm/twrongwhen.nim
Normal file
13
tests/vm/twrongwhen.nim
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
discard """
|
||||||
|
output: "Error: cannot evaluate at compile time: x"
|
||||||
|
line: 7
|
||||||
|
"""
|
||||||
|
|
||||||
|
proc bla(x:int) =
|
||||||
|
when x == 0:
|
||||||
|
echo "oops"
|
||||||
|
else:
|
||||||
|
echo "good"
|
||||||
|
|
||||||
|
bla(2) # echos "oops"
|
||||||
|
|
||||||
1
todo.txt
1
todo.txt
|
|
@ -1,6 +1,7 @@
|
||||||
version 0.9.4
|
version 0.9.4
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
- implement unchecked arrays
|
||||||
- make testament produce full JSON information
|
- make testament produce full JSON information
|
||||||
- fix gensym capture bug
|
- fix gensym capture bug
|
||||||
- vm
|
- vm
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue