mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-19 14:00:35 +00:00
new VM is getting stable
This commit is contained in:
@@ -67,7 +67,7 @@ type
|
||||
errAmbiguousCallXYZ, errWrongNumberOfArguments,
|
||||
errXCannotBePassedToProcVar,
|
||||
errXCannotBeInParamDecl, errPragmaOnlyInHeaderOfProc, errImplOfXNotAllowed,
|
||||
errImplOfXexpected, errNoSymbolToBorrowFromFound, errDiscardValue,
|
||||
errImplOfXexpected, errNoSymbolToBorrowFromFound, errDiscardValueX,
|
||||
errInvalidDiscard, errIllegalConvFromXtoY, errCannotBindXTwice,
|
||||
errInvalidOrderInArrayConstructor,
|
||||
errInvalidOrderInEnumX, errEnumXHasHoles, errExceptExpected, errInvalidTry,
|
||||
@@ -264,7 +264,7 @@ const
|
||||
errImplOfXNotAllowed: "implementation of \'$1\' is not allowed",
|
||||
errImplOfXexpected: "implementation of \'$1\' expected",
|
||||
errNoSymbolToBorrowFromFound: "no symbol to borrow from found",
|
||||
errDiscardValue: "value returned by statement has to be discarded",
|
||||
errDiscardValueX: "value of type '$1' has to be discarded",
|
||||
errInvalidDiscard: "statement returns no value that can be discarded",
|
||||
errIllegalConvFromXtoY: "conversion from $1 to $2 is invalid",
|
||||
errCannotBindXTwice: "cannot bind parameter \'$1\' twice",
|
||||
|
||||
@@ -890,7 +890,7 @@ proc loadStub*(s: PSym) =
|
||||
|
||||
# deactivate the GC here because we do a deep recursion and generate no
|
||||
# garbage when restoring parts of the object graph anyway.
|
||||
# Since we die with internal errors if this fails, so no try-finally is
|
||||
# Since we die with internal errors if this fails, no try-finally is
|
||||
# necessary.
|
||||
GC_disable()
|
||||
rawLoadStub(s)
|
||||
|
||||
@@ -220,7 +220,7 @@ proc tryConstExpr(c: PContext, n: PNode): PNode =
|
||||
return nil
|
||||
|
||||
result = fixupTypeAfterEval(c, result, e)
|
||||
except:
|
||||
except ERecoverableError:
|
||||
return nil
|
||||
|
||||
proc semConstExpr(c: PContext, n: PNode): PNode =
|
||||
|
||||
@@ -641,9 +641,11 @@ proc evalAtCompileTime(c: PContext, n: PNode): PNode =
|
||||
result = evalStaticExpr(c.module, call, c.p.owner)
|
||||
if result.isNil:
|
||||
localError(n.info, errCannotInterpretNodeX, renderTree(call))
|
||||
else: result = fixupTypeAfterEval(c, result, n)
|
||||
else:
|
||||
result = evalConstExpr(c.module, call)
|
||||
if result.isNil: result = n
|
||||
else: result = fixupTypeAfterEval(c, result, n)
|
||||
#if result != n:
|
||||
# echo "SUCCESS evaluated at compile time: ", call.renderTree
|
||||
|
||||
@@ -653,6 +655,8 @@ proc semStaticExpr(c: PContext, n: PNode): PNode =
|
||||
if result.isNil:
|
||||
localError(n.info, errCannotInterpretNodeX, renderTree(n))
|
||||
result = emptyNode
|
||||
else:
|
||||
result = fixupTypeAfterEval(c, result, a)
|
||||
|
||||
proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
|
||||
flags: TExprFlags): PNode =
|
||||
|
||||
@@ -126,7 +126,7 @@ proc implicitlyDiscardable(n: PNode): bool =
|
||||
proc fixNilType(n: PNode) =
|
||||
if isAtom(n):
|
||||
if n.kind != nkNilLit and n.typ != nil:
|
||||
localError(n.info, errDiscardValue)
|
||||
localError(n.info, errDiscardValueX, n.typ.typeToString)
|
||||
elif n.kind in {nkStmtList, nkStmtListExpr}:
|
||||
n.kind = nkStmtList
|
||||
for it in n: fixNilType(it)
|
||||
@@ -154,7 +154,7 @@ proc discardCheck(c: PContext, result: PNode) =
|
||||
else:
|
||||
var n = result
|
||||
while n.kind in skipForDiscardable: n = n.lastSon
|
||||
localError(n.info, errDiscardValue)
|
||||
localError(n.info, errDiscardValueX, result.typ.typeToString)
|
||||
|
||||
proc semIf(c: PContext, n: PNode): PNode =
|
||||
result = n
|
||||
@@ -331,6 +331,7 @@ proc checkNilable(v: PSym) =
|
||||
proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
var b: PNode
|
||||
result = copyNode(n)
|
||||
var hasCompileTime = false
|
||||
for i in countup(0, sonsLen(n)-1):
|
||||
var a = n.sons[i]
|
||||
if gCmd == cmdIdeTools: suggestStmt(c, a)
|
||||
@@ -405,7 +406,9 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
|
||||
v.typ = tup.sons[j]
|
||||
b.sons[j] = newSymNode(v)
|
||||
checkNilable(v)
|
||||
|
||||
if sfCompileTime in v.flags: hasCompileTime = true
|
||||
if hasCompileTime: vm.setupCompileTimeVar(c.module, result)
|
||||
|
||||
proc semConst(c: PContext, n: PNode): PNode =
|
||||
result = copyNode(n)
|
||||
for i in countup(0, sonsLen(n) - 1):
|
||||
|
||||
@@ -109,11 +109,17 @@ template decodeBx(k: expr) {.immediate, dirty.} =
|
||||
template move(a, b: expr) {.immediate, dirty.} = system.shallowCopy(a, b)
|
||||
# XXX fix minor 'shallowCopy' overloading bug in compiler
|
||||
|
||||
template createStr(x) =
|
||||
if x.node.isNil: x.node = newNode(nkStrLit)
|
||||
template createStrKeepNode(x) =
|
||||
if x.node.isNil:
|
||||
x.node = newNode(nkStrLit)
|
||||
elif x.node.kind == nkNilLit:
|
||||
system.reset(x.node[])
|
||||
x.node.kind = nkStrLit
|
||||
else:
|
||||
assert x.node.kind in {nkStrLit..nkTripleStrLit}
|
||||
|
||||
template createStr(x) =
|
||||
x.node = newNode(nkStrLit)
|
||||
|
||||
proc moveConst(x: var TRegister, y: TRegister) =
|
||||
if x.kind != y.kind:
|
||||
@@ -254,7 +260,7 @@ proc opConv*(dest: var TRegister, src: TRegister, desttyp, srctyp: PType): bool
|
||||
if dest.kind != rkNode:
|
||||
myreset(dest)
|
||||
dest.kind = rkNode
|
||||
dest.node = newNode(nkStrLit)
|
||||
dest.node = newNode(nkStrLit)
|
||||
let styp = srctyp.skipTypes(abstractRange)
|
||||
case styp.kind
|
||||
of tyEnum:
|
||||
@@ -329,8 +335,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TRegister =
|
||||
#{.computedGoto.}
|
||||
let instr = c.code[pc]
|
||||
let ra = instr.regA
|
||||
#echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra
|
||||
#message(c.debug[pc], warnUser, "gah")
|
||||
#if c.traceActive:
|
||||
# echo "PC ", pc, " ", c.code[pc].opcode, " ra ", ra
|
||||
# message(c.debug[pc], warnUser, "Trace")
|
||||
case instr.opcode
|
||||
of opcEof: return regs[ra]
|
||||
of opcRet:
|
||||
@@ -354,7 +361,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TRegister =
|
||||
regs[ra].intVal = regs[rb].intVal
|
||||
of opcAsgnStr:
|
||||
decodeB(rkNode)
|
||||
createStr regs[ra]
|
||||
createStrKeepNode regs[ra]
|
||||
regs[ra].node.strVal = regs[rb].node.strVal
|
||||
of opcAsgnFloat:
|
||||
decodeB(rkFloat)
|
||||
@@ -454,7 +461,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TRegister =
|
||||
of opcWrDeref:
|
||||
# a[] = b
|
||||
decodeBC(rkNode)
|
||||
putIntoNode(regs[ra].node, regs[rc])
|
||||
putIntoNode(regs[ra].node, regs[rb])
|
||||
of opcAddInt:
|
||||
decodeBC(rkInt)
|
||||
regs[ra].intVal = regs[rb].intVal + regs[rc].intVal
|
||||
@@ -484,8 +491,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TRegister =
|
||||
of opcInclRange:
|
||||
decodeBC(rkNode)
|
||||
var r = newNode(nkRange)
|
||||
r.add regs[rb].node
|
||||
r.add regs[rc].node
|
||||
r.add regs[rb].regToNode
|
||||
r.add regs[rc].regToNode
|
||||
addSon(regs[ra].node, r.copyTree)
|
||||
of opcExcl:
|
||||
decodeB(rkNode)
|
||||
@@ -643,15 +650,18 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TRegister =
|
||||
regs[ra].node.strVal.add getstr(regs[i])
|
||||
of opcAddStrCh:
|
||||
decodeB(rkNode)
|
||||
createStr regs[ra]
|
||||
createStrKeepNode regs[ra]
|
||||
regs[ra].node.strVal.add(regs[rb].intVal.chr)
|
||||
of opcAddStrStr:
|
||||
decodeB(rkNode)
|
||||
createStr regs[ra]
|
||||
createStrKeepNode regs[ra]
|
||||
regs[ra].node.strVal.add(regs[rb].node.strVal)
|
||||
of opcAddSeqElem:
|
||||
decodeB(rkNode)
|
||||
regs[ra].node.add(copyTree(regs[rb].node))
|
||||
if regs[ra].node.kind == nkBracket:
|
||||
regs[ra].node.add(copyTree(regs[rb].regToNode))
|
||||
else:
|
||||
stackTrace(c, tos, pc, errNilAccess)
|
||||
of opcEcho:
|
||||
let rb = instr.regB
|
||||
for i in ra..ra+rb-1:
|
||||
@@ -660,7 +670,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TRegister =
|
||||
writeln(stdout, "")
|
||||
of opcContainsSet:
|
||||
decodeBC(rkInt)
|
||||
regs[ra].intVal = ord(inSet(regs[rb].node, regs[rc].node))
|
||||
regs[ra].intVal = ord(inSet(regs[rb].node, regs[rc].regToNode))
|
||||
of opcSubStr:
|
||||
decodeBC(rkNode)
|
||||
inc pc
|
||||
@@ -815,8 +825,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TRegister =
|
||||
ensureKind(rkNode)
|
||||
let typ = c.types[instr.regBx - wordExcess]
|
||||
regs[ra].node = getNullValue(typ, c.debug[pc])
|
||||
if regs[ra].node.kind in {nkStrLit..nkTripleStrLit}:
|
||||
regs[ra].kind = rkNode
|
||||
# opcLdNull really is the gist of the VM's problems: should it load
|
||||
# a fresh null to regs[ra].node or to regs[ra].node[]? This really
|
||||
# depends on whether regs[ra] represents the variable itself or wether
|
||||
# it holds the indirection! Due to the way registers are re-used we cannot
|
||||
# say for sure here! --> The codegen has to deal with it
|
||||
# via 'genAsgnPatch'.
|
||||
of opcLdNullReg:
|
||||
let typ = c.types[instr.regBx - wordExcess]
|
||||
if typ.skipTypes(abstractInst+{tyRange}-{tyTypeDesc}).kind in {
|
||||
@@ -858,7 +872,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TRegister =
|
||||
return TRegister(kind: rkNone)
|
||||
of opcSetLenStr:
|
||||
decodeB(rkNode)
|
||||
createStr regs[ra]
|
||||
createStrKeepNode regs[ra]
|
||||
regs[ra].node.strVal.setLen(regs[rb].intVal.int)
|
||||
of opcOf:
|
||||
decodeBC(rkInt)
|
||||
@@ -1209,6 +1223,9 @@ proc evalStaticExpr*(module: PSym, e: PNode, prc: PSym): PNode =
|
||||
proc evalStaticStmt*(module: PSym, e: PNode, prc: PSym) =
|
||||
discard evalConstExprAux(module, prc, e, emStaticStmt)
|
||||
|
||||
proc setupCompileTimeVar*(module: PSym, n: PNode) =
|
||||
discard evalConstExprAux(module, nil, n, emStaticStmt)
|
||||
|
||||
proc setupMacroParam(x: PNode): PNode =
|
||||
result = x
|
||||
if result.kind in {nkHiddenSubConv, nkHiddenStdConv}: result = result.sons[1]
|
||||
@@ -1250,3 +1267,4 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
|
||||
if cyclicTree(result): globalError(n.info, errCyclicTree)
|
||||
dec(evalMacroCounter)
|
||||
c.callsite = nil
|
||||
#debug result
|
||||
|
||||
@@ -163,8 +163,6 @@ type
|
||||
blocks*: seq[TBlock] # blocks; temp data structure
|
||||
slots*: array[TRegister, tuple[inUse: bool, kind: TSlotKind]]
|
||||
maxSlots*: int
|
||||
globals*: array[TRegister, int] # hack: to support passing globals byref
|
||||
# we map a slot persistently to a global
|
||||
|
||||
PCtx* = ref TCtx
|
||||
TCtx* = object of passes.TPassContext # code gen context
|
||||
@@ -181,6 +179,7 @@ type
|
||||
callsite*: PNode
|
||||
mode*: TEvalMode
|
||||
features*: TSandboxFlags
|
||||
traceActive*: bool
|
||||
|
||||
TPosition* = distinct int
|
||||
|
||||
|
||||
@@ -451,9 +451,11 @@ 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
|
||||
|
||||
proc needsAsgnPatch(n: PNode): bool =
|
||||
n.kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr,
|
||||
nkDerefExpr, nkHiddenDeref}
|
||||
nkDerefExpr, nkHiddenDeref} or (n.kind == nkSym and n.sym.isGlobal)
|
||||
|
||||
proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
|
||||
case le.kind
|
||||
@@ -461,15 +463,25 @@ proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
|
||||
let dest = c.genx(le.sons[0], {gfAddrOf})
|
||||
let idx = c.genx(le.sons[1])
|
||||
c.gABC(le, opcWrArr, dest, idx, value)
|
||||
c.freeTemp(dest)
|
||||
c.freeTemp(idx)
|
||||
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], {gfAddrOf})
|
||||
let idx = c.genx(left.sons[1])
|
||||
c.gABC(left, opcWrObj, dest, idx, value)
|
||||
c.freeTemp(dest)
|
||||
c.freeTemp(idx)
|
||||
of nkDerefExpr, nkHiddenDeref:
|
||||
let dest = c.genx(le.sons[0], {gfAddrOf})
|
||||
c.gABC(le, opcWrDeref, dest, value)
|
||||
c.freeTemp(dest)
|
||||
of nkSym:
|
||||
if le.sym.isGlobal:
|
||||
let dest = c.genx(le, {gfAddrOf})
|
||||
c.gABC(le, opcWrDeref, dest, value)
|
||||
c.freeTemp(dest)
|
||||
else:
|
||||
discard
|
||||
|
||||
@@ -608,6 +620,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||
c.genAddSubInt(n, dest, opcAddInt)
|
||||
of mInc, mDec:
|
||||
unused(n, dest)
|
||||
# XXX generates inefficient code for globals
|
||||
var d = c.genx(n.sons[1]).TDest
|
||||
c.genAddSubInt(n, d, if m == mInc: opcAddInt else: opcSubInt)
|
||||
c.genAsgnPatch(n.sons[1], d)
|
||||
@@ -621,6 +634,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||
c.genNewSeq(n)
|
||||
of mNewString:
|
||||
genUnaryABC(c, n, dest, opcNewStr)
|
||||
# XXX buggy
|
||||
of mNewStringOfCap:
|
||||
# we ignore the 'cap' argument and translate it as 'newString(0)'.
|
||||
# eval n.sons[1] for possible side effects:
|
||||
@@ -629,6 +643,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||
if dest < 0: dest = c.getTemp(n.typ)
|
||||
c.gABC(n, opcNewStr, dest, tmp)
|
||||
c.freeTemp(tmp)
|
||||
# XXX buggy
|
||||
of mLengthOpenArray, mLengthArray, mLengthSeq:
|
||||
genUnaryABI(c, n, dest, opcLenSeq)
|
||||
of mLengthStr:
|
||||
@@ -955,8 +970,6 @@ proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) =
|
||||
gABC(c, ri, whichAsgnOpc(ri), dest, tmp)
|
||||
c.freeTemp(tmp)
|
||||
|
||||
template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar
|
||||
|
||||
proc setSlot(c: PCtx; v: PSym) =
|
||||
# XXX generate type initialization here?
|
||||
if v.position == 0:
|
||||
@@ -1035,14 +1048,22 @@ proc cannotEval(n: PNode) {.noinline.} =
|
||||
globalError(n.info, errGenerated, "cannot evaluate at compile time: " &
|
||||
n.renderTree)
|
||||
|
||||
proc getNullValue*(typ: PType, info: TLineInfo): PNode
|
||||
|
||||
proc genGlobalInit(c: PCtx; n: PNode; s: PSym) =
|
||||
c.globals.add(emptyNode.copyNode)
|
||||
c.globals.add(getNullValue(s.typ, n.info))
|
||||
s.position = c.globals.len
|
||||
# This is rather hard to support, due to the laziness of the VM code
|
||||
# generator. See tests/compile/tmacro2 for why this is necesary:
|
||||
# var decls{.compileTime.}: seq[PNimrodNode] = @[]
|
||||
let dest = c.getTemp(s.typ)
|
||||
c.gABx(n, opcLdGlobal, dest, s.position)
|
||||
let tmp = c.genx(s.ast)
|
||||
c.gABC(n, opcWrDeref, dest, tmp)
|
||||
c.freeTemp(dest)
|
||||
c.freeTemp(tmp)
|
||||
|
||||
proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
|
||||
proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
||||
let s = n.sym
|
||||
if s.isGlobal:
|
||||
if sfCompileTime in s.flags or c.mode == emRepl:
|
||||
@@ -1052,7 +1073,14 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
|
||||
if s.position == 0:
|
||||
if sfImportc in s.flags: c.importcSym(n.info, s)
|
||||
else: genGlobalInit(c, n, s)
|
||||
c.gABx(n, opcLdGlobal, dest, s.position)
|
||||
if dest < 0: dest = c.getTemp(n.typ)
|
||||
if gfAddrOf notin flags and fitsRegister(s.typ):
|
||||
var cc = c.getTemp(n.typ)
|
||||
c.gABx(n, opcLdGlobal, cc, s.position)
|
||||
c.gABC(n, opcNodeToReg, dest, cc)
|
||||
c.freeTemp(cc)
|
||||
else:
|
||||
c.gABx(n, opcLdGlobal, dest, s.position)
|
||||
else:
|
||||
if s.kind == skForVar and c.mode == emRepl: c.setSlot s
|
||||
if s.position > 0 or (s.position == 0 and
|
||||
@@ -1095,7 +1123,6 @@ proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
||||
else:
|
||||
genAccess(c, n, dest, opcLdArr, flags)
|
||||
|
||||
proc getNullValue*(typ: PType, info: TLineInfo): PNode
|
||||
proc getNullValueAux(obj: PNode, result: PNode) =
|
||||
case obj.kind
|
||||
of nkRecList:
|
||||
@@ -1161,7 +1188,7 @@ proc genVarSection(c: PCtx; n: PNode) =
|
||||
setSlot(c, a[i].sym)
|
||||
# v = t[i]
|
||||
var v: TDest = -1
|
||||
genRdVar(c, a[i], v)
|
||||
genRdVar(c, a[i], v, {gfAddrOf})
|
||||
c.gABC(n, opcWrObj, v, tmp, i)
|
||||
# XXX globals?
|
||||
c.freeTemp(tmp)
|
||||
@@ -1184,6 +1211,7 @@ proc genVarSection(c: PCtx; n: PNode) =
|
||||
let val = c.genx(a.sons[2])
|
||||
c.gABC(a, opcWrDeref, tmp, val)
|
||||
c.freeTemp(val)
|
||||
c.freeTemp(tmp)
|
||||
else:
|
||||
setSlot(c, s)
|
||||
if a.sons[2].kind == nkEmpty:
|
||||
@@ -1202,8 +1230,17 @@ proc genVarSection(c: PCtx; n: PNode) =
|
||||
proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) =
|
||||
if dest < 0: dest = c.getTemp(n.typ)
|
||||
c.gABx(n, opcLdNull, dest, c.genType(n.typ))
|
||||
|
||||
let intType = getSysType(tyInt)
|
||||
let seqType = n.typ.skipTypes(abstractVar-{tyTypeDesc})
|
||||
if seqType.kind == tySequence:
|
||||
var tmp = c.getTemp(intType)
|
||||
c.gABx(n, opcLdImmInt, tmp, n.len)
|
||||
c.gABx(n, opcNewSeq, dest, c.genType(seqType))
|
||||
c.gABx(n, opcNewSeq, tmp, 0)
|
||||
c.freeTemp(tmp)
|
||||
|
||||
if n.len > 0:
|
||||
let intType = getSysType(tyInt)
|
||||
var tmp = getTemp(c, intType)
|
||||
c.gABx(n, opcLdNullReg, tmp, c.genType(intType))
|
||||
for x in n:
|
||||
@@ -1271,7 +1308,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
let s = n.sym
|
||||
case s.kind
|
||||
of skVar, skForVar, skTemp, skLet, skParam, skResult:
|
||||
genRdVar(c, n, dest)
|
||||
genRdVar(c, n, dest, flags)
|
||||
of skProc, skConverter, skMacro, skTemplate, skMethod, skIterator:
|
||||
# 'skTemplate' is only allowed for 'getAst' support:
|
||||
if sfImportc in s.flags: c.importcSym(n.info, s)
|
||||
@@ -1503,7 +1540,7 @@ proc genProc(c: PCtx; s: PSym): int =
|
||||
c.gABC(body, opcEof, eofInstr.regA)
|
||||
c.optimizeJumps(result)
|
||||
s.offset = c.prc.maxSlots
|
||||
#if s.name.s == "traverse":
|
||||
#if s.name.s == "importImpl_forward" or s.name.s == "importImpl":
|
||||
# c.echoCode(result)
|
||||
# echo renderTree(body)
|
||||
c.prc = oldPrc
|
||||
|
||||
@@ -51,7 +51,7 @@ macro okayy:stmt =
|
||||
for node in decls: result.add node
|
||||
for node in impls: result.add node
|
||||
|
||||
importimpl(Item, int):
|
||||
importImpl(Item, int):
|
||||
echo 42
|
||||
importImpl(Foo, int16):
|
||||
echo 77
|
||||
|
||||
2
todo.txt
2
todo.txt
@@ -1,7 +1,6 @@
|
||||
version 0.9.4
|
||||
=============
|
||||
|
||||
- fix macros\tstringinterp.nim
|
||||
- fix GC issues
|
||||
- test and fix showoff
|
||||
|
||||
@@ -24,7 +23,6 @@ version 0.9.x
|
||||
|
||||
- implement 'union' and 'bits' pragmas
|
||||
- fix closures
|
||||
- test and fix exception handling
|
||||
- ensure (ref T)(a, b) works as a type conversion and type constructor
|
||||
- optimize 'genericReset'; 'newException' leads to code bloat
|
||||
- stack-less GC
|
||||
|
||||
Reference in New Issue
Block a user