mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-04 10:54:42 +00:00
some complex macros work
This commit is contained in:
@@ -96,19 +96,24 @@ template decodeBx(k: expr) {.immediate, dirty.} =
|
||||
template move(a, b: expr) = system.shallowCopy(a, b)
|
||||
# XXX fix minor 'shallowCopy' overloading bug in compiler
|
||||
|
||||
proc asgnRef(x, y: PNode) =
|
||||
myreset(x)
|
||||
x.kind = y.kind
|
||||
x.typ = y.typ
|
||||
case x.kind
|
||||
of nkCharLit..nkInt64Lit: x.intVal = y.intVal
|
||||
of nkFloatLit..nkFloat64Lit: x.floatVal = y.floatVal
|
||||
of nkStrLit..nkTripleStrLit: x.strVal = y.strVal
|
||||
of nkIdent: x.ident = y.ident
|
||||
of nkSym: x.sym = y.sym
|
||||
else:
|
||||
if x.kind notin {nkEmpty..nkNilLit}:
|
||||
move(x.sons, y.sons)
|
||||
when false:
|
||||
proc asgnRef(x, y: PNode) =
|
||||
myreset(x)
|
||||
x.kind = y.kind
|
||||
x.typ = y.typ
|
||||
case x.kind
|
||||
of nkCharLit..nkInt64Lit: x.intVal = y.intVal
|
||||
of nkFloatLit..nkFloat64Lit: x.floatVal = y.floatVal
|
||||
of nkStrLit..nkTripleStrLit: x.strVal = y.strVal
|
||||
of nkIdent: x.ident = y.ident
|
||||
of nkSym: x.sym = y.sym
|
||||
else:
|
||||
if x.kind notin {nkEmpty..nkNilLit}:
|
||||
move(x.sons, y.sons)
|
||||
else:
|
||||
# this seems to be the best way to model the reference semantics
|
||||
# of PNimrodNode:
|
||||
template asgnRef(x, y: expr) = x = y
|
||||
|
||||
proc asgnComplex(x, y: PNode) =
|
||||
myreset(x)
|
||||
@@ -279,7 +284,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
|
||||
of opcAsgnRef:
|
||||
asgnRef(regs[ra], regs[instr.regB])
|
||||
of opcWrGlobalRef:
|
||||
asgnRef(c.globals[instr.regBx-wordExcess-1], regs[ra])
|
||||
asgnRef(c.globals.sons[instr.regBx-wordExcess-1], regs[ra])
|
||||
of opcWrGlobal:
|
||||
asgnComplex(c.globals.sons[instr.regBx-wordExcess-1], regs[ra])
|
||||
of opcLdArr:
|
||||
@@ -470,24 +475,24 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
|
||||
regs[ra].intVal = not regs[rb].intVal
|
||||
of opcEqStr:
|
||||
decodeBC(nkIntLit)
|
||||
regs[ra].intVal = Ord(regs[rb].strVal == regs[rc].strVal)
|
||||
regs[ra].intVal = ord(regs[rb].strVal == regs[rc].strVal)
|
||||
of opcLeStr:
|
||||
decodeBC(nkIntLit)
|
||||
regs[ra].intVal = Ord(regs[rb].strVal <= regs[rc].strVal)
|
||||
regs[ra].intVal = ord(regs[rb].strVal <= regs[rc].strVal)
|
||||
of opcLtStr:
|
||||
decodeBC(nkIntLit)
|
||||
regs[ra].intVal = Ord(regs[rb].strVal < regs[rc].strVal)
|
||||
regs[ra].intVal = ord(regs[rb].strVal < regs[rc].strVal)
|
||||
of opcLeSet:
|
||||
decodeBC(nkIntLit)
|
||||
regs[ra].intVal = Ord(containsSets(regs[rb], regs[rc]))
|
||||
regs[ra].intVal = ord(containsSets(regs[rb], regs[rc]))
|
||||
of opcEqSet:
|
||||
decodeBC(nkIntLit)
|
||||
regs[ra].intVal = Ord(equalSets(regs[rb], regs[rc]))
|
||||
regs[ra].intVal = ord(equalSets(regs[rb], regs[rc]))
|
||||
of opcLtSet:
|
||||
decodeBC(nkIntLit)
|
||||
let a = regs[rb]
|
||||
let b = regs[rc]
|
||||
regs[ra].intVal = Ord(containsSets(a, b) and not equalSets(a, b))
|
||||
regs[ra].intVal = ord(containsSets(a, b) and not equalSets(a, b))
|
||||
of opcMulSet:
|
||||
decodeBC(nkCurly)
|
||||
move(regs[ra].sons, nimsets.intersectSets(regs[rb], regs[rc]).sons)
|
||||
@@ -652,9 +657,21 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
|
||||
regs[ra] = copyTree(c.globals.sons[rb])
|
||||
else:
|
||||
asgnComplex(regs[ra], c.globals.sons[rb])
|
||||
of opcRepr, opcSetLenStr, opcSetLenSeq,
|
||||
of opcRepr:
|
||||
decodeB(nkStrLit)
|
||||
regs[ra].strVal = renderTree(regs[rb], {renderNoComments})
|
||||
of opcQuit:
|
||||
if c.mode in {emRepl, emStatic}:
|
||||
Message(c.debug[pc], hintQuitCalled)
|
||||
quit(int(getOrdValue(regs[ra])))
|
||||
else:
|
||||
return nil
|
||||
of opcSetLenStr:
|
||||
decodeB(nkStrLit)
|
||||
regs[ra].strVal.setLen(regs[rb].getOrdValue.int)
|
||||
of opcSetLenSeq,
|
||||
opcSwap, opcIsNil, opcOf,
|
||||
opcCast, opcQuit, opcReset:
|
||||
opcCast, opcReset:
|
||||
internalError(c.debug[pc], "too implement")
|
||||
of opcNBindSym:
|
||||
# trivial implementation:
|
||||
@@ -670,7 +687,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
|
||||
regs[ra].sons[regs[rb].intVal.int] = regs[rc]
|
||||
of opcNAdd:
|
||||
declBC()
|
||||
regs[rb].add(regs[rb])
|
||||
regs[rb].add(regs[rc])
|
||||
regs[ra] = regs[rb]
|
||||
of opcNAddMultiple:
|
||||
declBC()
|
||||
@@ -904,6 +921,7 @@ const evalPass* = makePass(myOpen, nil, myProcess, myProcess)
|
||||
proc evalConstExprAux(module, prc: PSym, n: PNode, mode: TEvalMode): PNode =
|
||||
setupGlobalCtx(module)
|
||||
var c = globalCtx
|
||||
c.mode = mode
|
||||
let start = genExpr(c, n)
|
||||
assert c.code[start].opcode != opcEof
|
||||
var tos = PStackFrame(prc: prc, comesFrom: 0, next: nil)
|
||||
@@ -935,7 +953,8 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
|
||||
let start = genProc(c, sym)
|
||||
|
||||
var tos = PStackFrame(prc: sym, comesFrom: 0, next: nil)
|
||||
newSeq(tos.slots, c.prc.maxSlots)
|
||||
let maxSlots = sym.position
|
||||
newSeq(tos.slots, maxSlots)
|
||||
# setup arguments:
|
||||
var L = n.safeLen
|
||||
if L == 0: L = 1
|
||||
@@ -945,7 +964,7 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
|
||||
# setup parameters:
|
||||
for i in 1 .. < L: tos.slots[i] = setupMacroParam(n.sons[i])
|
||||
# temporary storage:
|
||||
for i in L .. <c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
|
||||
for i in L .. <maxSlots: tos.slots[i] = newNode(nkEmpty)
|
||||
result = rawExecute(c, start, tos)
|
||||
if cyclicTree(result): GlobalError(n.info, errCyclicTree)
|
||||
dec(evalMacroCounter)
|
||||
|
||||
@@ -129,6 +129,20 @@ type
|
||||
label*: PSym
|
||||
fixups*: seq[TPosition]
|
||||
|
||||
TEvalMode* = enum ## reason for evaluation
|
||||
emRepl, ## evaluate because in REPL mode
|
||||
emConst, ## evaluate for 'const' according to spec
|
||||
emOptimize, ## evaluate for optimization purposes (same as
|
||||
## emConst?)
|
||||
emStatic ## evaluate for enforced compile time eval
|
||||
## ('static' context)
|
||||
|
||||
TSandboxFlag* = enum ## what the evaluation engine should allow
|
||||
allowCast, ## allow unsafe language feature: 'cast'
|
||||
allowFFI, ## allow the FFI
|
||||
allowInfiniteLoops ## allow endless loops
|
||||
TSandboxFlags* = set[TSandboxFlag]
|
||||
|
||||
TSlotKind* = enum # We try to re-use slots in a smart way to
|
||||
# minimize allocations; however the VM supports arbitrary
|
||||
# temporary slot usage. This is required for the parameter
|
||||
@@ -160,25 +174,11 @@ type
|
||||
prc*: PProc
|
||||
module*: PSym
|
||||
callsite*: PNode
|
||||
mode*: TEvalMode
|
||||
|
||||
TPosition* = distinct int
|
||||
|
||||
PEvalContext* = PCtx
|
||||
|
||||
TEvalMode* = enum ## reason for evaluation
|
||||
emRepl, ## evaluate because in REPL mode
|
||||
emConst, ## evaluate for 'const' according to spec
|
||||
emOptimize, ## evaluate for optimization purposes (same as
|
||||
## emConst?)
|
||||
emStatic ## evaluate for enforced compile time eval
|
||||
## ('static' context)
|
||||
|
||||
TSandboxFlag* = enum ## what the evaluation engine should allow
|
||||
allowCast, ## allow unsafe language feature: 'cast'
|
||||
allowFFI, ## allow the FFI
|
||||
allowInfiniteLoops ## allow endless loops
|
||||
TSandboxFlags* = set[TSandboxFlag]
|
||||
|
||||
|
||||
proc newCtx*(module: PSym): PCtx =
|
||||
PCtx(code: @[], debug: @[],
|
||||
|
||||
@@ -112,8 +112,10 @@ const
|
||||
|
||||
proc getTemp(c: PCtx; typ: PType): TRegister =
|
||||
let c = c.prc
|
||||
# we prefer the same slot kind here for efficiency:
|
||||
let k = typ.getSlotKind
|
||||
# we prefer the same slot kind here for efficiency. Unfortunately for
|
||||
# discardable return types we may not know the desired type. This can happen
|
||||
# for e.g. mNAdd[Multiple]:
|
||||
let k = if typ.isNil: slotTempComplex else: typ.getSlotKind
|
||||
for i in 0 .. c.maxSlots-1:
|
||||
if c.slots[i].kind == k and not c.slots[i].inUse:
|
||||
c.slots[i].inUse = true
|
||||
@@ -179,7 +181,7 @@ proc gen(c: PCtx; n: PNode; dest: TRegister) =
|
||||
proc gen(c: PCtx; n: PNode) =
|
||||
var tmp: TDest = -1
|
||||
gen(c, n, tmp)
|
||||
InternalAssert tmp < 0
|
||||
#if n.typ.isEmptyType: InternalAssert tmp < 0
|
||||
|
||||
proc genx(c: PCtx; n: PNode): TRegister =
|
||||
var tmp: TDest = -1
|
||||
@@ -463,7 +465,7 @@ proc genBinaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
|
||||
c.freeTemp(tmp)
|
||||
|
||||
proc genUnaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
|
||||
let tmp = c.genx(n.sons[2])
|
||||
let tmp = c.genx(n.sons[1])
|
||||
c.gABC(n, opc, tmp, 0, 0)
|
||||
c.freeTemp(tmp)
|
||||
|
||||
@@ -852,11 +854,13 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||
else:
|
||||
c.gABC(le, whichAsgnOpc(le, opcWrArr), dest, idx, tmp)
|
||||
c.freeTemp(tmp)
|
||||
of nkDotExpr:
|
||||
let dest = c.genx(le.sons[0])
|
||||
let idx = c.genx(le.sons[1])
|
||||
of nkDotExpr, nkCheckedFieldExpr:
|
||||
# XXX field checks here
|
||||
let left = if le.kind == nkDotExpr: le else: le.sons[0]
|
||||
let dest = c.genx(left.sons[0])
|
||||
let idx = c.genx(left.sons[1])
|
||||
let tmp = c.genx(ri)
|
||||
c.gABC(le, whichAsgnOpc(le, opcWrObj), dest, idx, tmp)
|
||||
c.gABC(left, whichAsgnOpc(left, opcWrObj), dest, idx, tmp)
|
||||
c.freeTemp(tmp)
|
||||
of nkSym:
|
||||
let s = le.sym
|
||||
@@ -910,6 +914,10 @@ proc genAccess(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
|
||||
proc genObjAccess(c: PCtx; n: PNode; dest: var TDest) =
|
||||
genAccess(c, n, dest, opcLdObj)
|
||||
|
||||
proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest) =
|
||||
# XXX implement field checks!
|
||||
genAccess(c, n.sons[0], dest, opcLdObj)
|
||||
|
||||
proc genArrAccess(c: PCtx; n: PNode; dest: var TDest) =
|
||||
if n.sons[0].typ.skipTypes(abstractVarRange).kind in {tyString, tyCString}:
|
||||
genAccess(c, n, dest, opcLdStrIdx)
|
||||
@@ -1023,7 +1031,7 @@ proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) =
|
||||
c.gABx(n, opcLdNull, tmp, c.genType(intType))
|
||||
for x in n:
|
||||
let a = c.genx(x)
|
||||
c.gABC(n, opcWrArr, dest, a, tmp)
|
||||
c.gABC(n, whichAsgnOpc(x, opcWrArr), dest, tmp, a)
|
||||
c.gABI(n, opcAddImmInt, tmp, tmp, 1)
|
||||
c.freeTemp(a)
|
||||
c.freeTemp(tmp)
|
||||
@@ -1116,6 +1124,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest) =
|
||||
unused(n, dest)
|
||||
genAsgn(c, n.sons[0], n.sons[1], n.kind == nkAsgn)
|
||||
of nkDotExpr: genObjAccess(c, n, dest)
|
||||
of nkCheckedFieldExpr: genCheckedObjAccess(c, n, dest)
|
||||
of nkBracketExpr: genArrAccess(c, n, dest)
|
||||
of nkDerefExpr, nkHiddenDeref: genAddrDeref(c, n, dest, opcDeref)
|
||||
of nkAddr, nkHiddenAddr: genAddrDeref(c, n, dest, opcAddr)
|
||||
@@ -1288,5 +1297,8 @@ proc genProc(c: PCtx; s: PSym): int =
|
||||
c.gABC(body, opcEof, eofInstr.regA)
|
||||
s.position = c.prc.maxSlots
|
||||
c.prc = oldPrc
|
||||
#if s.name.s == "xmlConstructor":
|
||||
# echoCode(c)
|
||||
else:
|
||||
c.prc.maxSlots = s.position
|
||||
result = x.intVal.int
|
||||
|
||||
Reference in New Issue
Block a user