This commit is contained in:
Araq 2014-03-05 02:14:53 +01:00
commit aa92669d92
5 changed files with 47 additions and 6 deletions

View file

@ -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)

View file

@ -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

View file

@ -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
View 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"

View file

@ -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