mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-06 03:44:14 +00:00
macro tests almost green
This commit is contained in:
@@ -972,6 +972,9 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
|
||||
else:
|
||||
s = n[namePos].sym
|
||||
typeIsDetermined = s.typ == nil
|
||||
s.ast = n
|
||||
s.scope = c.currentScope
|
||||
|
||||
# if typeIsDetermined: assert phase == stepCompileBody
|
||||
# else: assert phase == stepDetermineType
|
||||
# before compiling the proc body, set as current the scope
|
||||
|
||||
@@ -47,7 +47,8 @@ proc equalParams*(a, b: PNode): TParamsEquality
|
||||
# returns whether the parameter lists of the procs a, b are exactly the same
|
||||
proc isOrdinalType*(t: PType): bool
|
||||
proc enumHasHoles*(t: PType): bool
|
||||
const
|
||||
# XXX it is WRONG to include tyTypeDesc here as that might not have any child!
|
||||
const
|
||||
abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal,
|
||||
tyConst, tyMutable, tyTypeDesc}
|
||||
abstractVar* = {tyVar, tyGenericInst, tyDistinct, tyOrdinal,
|
||||
|
||||
@@ -1047,7 +1047,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): PNode =
|
||||
# XXX only supports 'name' for now; we can use regC to encode the
|
||||
# type trait operation
|
||||
decodeB(nkStrLit)
|
||||
let typ = regs[rb].sym.typ.skipTypes({tyTypeDesc})
|
||||
var typ = regs[rb].typ
|
||||
internalAssert typ != nil
|
||||
while typ.kind == tyTypeDesc and typ.len > 0: typ = typ.sons[0]
|
||||
regs[ra].strVal = typ.typeToString(preferExported)
|
||||
of opcGlobalOnce:
|
||||
let rb = instr.regBx
|
||||
@@ -1178,7 +1180,7 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
|
||||
# doesn't end up in the parameter:
|
||||
#InternalAssert tos.slots.len >= L
|
||||
# return value:
|
||||
tos.slots[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0])
|
||||
tos.slots[0] = newNodeIT(nkEmpty, n.info, sym.typ.sons[0])
|
||||
# setup parameters:
|
||||
for i in 1 .. < min(tos.slots.len, L):
|
||||
tos.slots[i] = setupMacroParam(n.sons[i])
|
||||
|
||||
@@ -109,7 +109,7 @@ proc patch(c: PCtx, p: TPosition) =
|
||||
uint32(diff+wordExcess) shl 16'u32).TInstr
|
||||
|
||||
proc getSlotKind(t: PType): TSlotKind =
|
||||
case t.skipTypes(abstractRange).kind
|
||||
case t.skipTypes(abstractRange-{tyTypeDesc}).kind
|
||||
of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64:
|
||||
slotTempInt
|
||||
of tyString, tyCString:
|
||||
@@ -409,7 +409,7 @@ proc genTry(c: PCtx; n: PNode; dest: var TDest) =
|
||||
let endExcept = c.xjmp(it, opcExcept, 0)
|
||||
for j in countup(0, blen - 2):
|
||||
assert(it.sons[j].kind == nkType)
|
||||
let typ = it.sons[j].typ.skipTypes(abstractPtrs)
|
||||
let typ = it.sons[j].typ.skipTypes(abstractPtrs-{tyTypeDesc})
|
||||
c.gABx(it, opcExcept, 0, c.genType(typ))
|
||||
if blen == 1:
|
||||
# general except section:
|
||||
@@ -479,7 +479,7 @@ proc genNew(c: PCtx; n: PNode) =
|
||||
# we use the ref's base type here as the VM conflates 'ref object'
|
||||
# and 'object' since internally we already have a pointer.
|
||||
c.gABx(n, opcNew, dest,
|
||||
c.genType(n.sons[1].typ.skipTypes(abstractVar).sons[0]))
|
||||
c.genType(n.sons[1].typ.skipTypes(abstractVar-{tyTypeDesc}).sons[0]))
|
||||
c.genAsgnPatch(n.sons[1], dest)
|
||||
c.freeTemp(dest)
|
||||
|
||||
@@ -487,7 +487,8 @@ proc genNewSeq(c: PCtx; n: PNode) =
|
||||
let dest = if needsAsgnPatch(n.sons[1]): c.getTemp(n.sons[1].typ)
|
||||
else: c.genx(n.sons[1])
|
||||
let tmp = c.genx(n.sons[2])
|
||||
c.gABx(n, opcNewSeq, dest, c.genType(n.sons[1].typ.skipTypes(abstractVar)))
|
||||
c.gABx(n, opcNewSeq, dest, c.genType(n.sons[1].typ.skipTypes(
|
||||
abstractVar-{tyTypeDesc})))
|
||||
c.gABx(n, opcNewSeq, tmp, 0)
|
||||
c.freeTemp(tmp)
|
||||
c.genAsgnPatch(n.sons[1], dest)
|
||||
@@ -515,7 +516,7 @@ proc genBinaryABC(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode) =
|
||||
c.freeTemp(tmp2)
|
||||
|
||||
proc genSetType(c: PCtx; n: PNode; dest: TRegister) =
|
||||
let t = skipTypes(n.typ, abstractInst)
|
||||
let t = skipTypes(n.typ, abstractInst-{tyTypeDesc})
|
||||
if t.kind == tySet:
|
||||
c.gABx(n, opcSetType, dest, c.genType(t))
|
||||
|
||||
@@ -746,7 +747,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||
var tmp = c.genx(n.sons[1])
|
||||
var idx = c.getTemp(getSysType(tyInt))
|
||||
var typ = n.sons[2].typ
|
||||
if m == mOf: typ = typ.skipTypes(abstractPtrs)
|
||||
if m == mOf: typ = typ.skipTypes(abstractPtrs-{tyTypeDesc})
|
||||
c.gABx(n, opcLdImmInt, idx, c.genType(typ))
|
||||
c.gABC(n, if m == mOf: opcOf else: opcIs, dest, tmp, idx)
|
||||
c.freeTemp(tmp)
|
||||
@@ -756,7 +757,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest) =
|
||||
of mHigh:
|
||||
if dest < 0: dest = c.getTemp(n.typ)
|
||||
let tmp = c.genx(n.sons[1])
|
||||
if n.sons[1].typ.skipTypes(abstractVar).kind == tyString:
|
||||
if n.sons[1].typ.skipTypes(abstractVar-{tyTypeDesc}).kind == tyString:
|
||||
c.gABI(n, opcLenStr, dest, tmp, 1)
|
||||
else:
|
||||
c.gABI(n, opcLenSeq, dest, tmp, 1)
|
||||
@@ -891,7 +892,7 @@ const
|
||||
tyUInt, tyUInt8, tyUInt16, tyUInt32, tyUInt64}
|
||||
|
||||
proc requiresCopy(n: PNode): bool =
|
||||
if n.typ.skipTypes(abstractInst).kind in atomicTypes:
|
||||
if n.typ.skipTypes(abstractInst-{tyTypeDesc}).kind in atomicTypes:
|
||||
result = false
|
||||
elif n.kind in ({nkCurly, nkBracket, nkPar, nkObjConstr}+nkCallKinds):
|
||||
result = false
|
||||
@@ -899,7 +900,7 @@ proc requiresCopy(n: PNode): bool =
|
||||
result = true
|
||||
|
||||
proc unneededIndirection(n: PNode): bool =
|
||||
n.typ.skipTypes(abstractInst).kind == tyRef
|
||||
n.typ.skipTypes(abstractInst-{tyTypeDesc}).kind == tyRef
|
||||
|
||||
proc skipDeref(n: PNode): PNode =
|
||||
if n.kind in {nkDerefExpr, nkHiddenDeref} and unneededIndirection(n.sons[0]):
|
||||
@@ -920,7 +921,7 @@ proc genAddrDeref(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
|
||||
c.freeTemp(tmp)
|
||||
|
||||
proc whichAsgnOpc(n: PNode): TOpcode =
|
||||
case n.typ.skipTypes(abstractRange).kind
|
||||
case n.typ.skipTypes(abstractRange-{tyTypeDesc}).kind
|
||||
of tyBool, tyChar, tyEnum, tyOrdinal, tyInt..tyInt64, tyUInt..tyUInt64:
|
||||
opcAsgnInt
|
||||
of tyString, tyCString:
|
||||
@@ -932,7 +933,7 @@ proc whichAsgnOpc(n: PNode): TOpcode =
|
||||
else:
|
||||
opcAsgnComplex
|
||||
|
||||
proc isRef(t: PType): bool = t.skipTypes(abstractRange).kind == tyRef
|
||||
proc isRef(t: PType): bool = t.skipTypes(abstractRange-{tyTypeDesc}).kind == tyRef
|
||||
|
||||
proc whichAsgnOpc(n: PNode; opc: TOpcode): TOpcode =
|
||||
if isRef(n.typ): succ(opc) else: opc
|
||||
@@ -951,7 +952,8 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||
let dest = c.genx(le.sons[0])
|
||||
let idx = c.genx(le.sons[1])
|
||||
let tmp = c.genx(ri)
|
||||
if le.sons[0].typ.skipTypes(abstractVarRange).kind in {tyString, tyCString}:
|
||||
if le.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
|
||||
tyString, tyCString}:
|
||||
c.gABC(le, opcWrStrIdx, dest, idx, tmp)
|
||||
else:
|
||||
c.gABC(le, whichAsgnOpc(le, opcWrArr), dest, idx, tmp)
|
||||
@@ -1062,7 +1064,8 @@ proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
||||
genAccess(c, n.sons[0], dest, opcLdObj, flags)
|
||||
|
||||
proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
||||
if n.sons[0].typ.skipTypes(abstractVarRange).kind in {tyString, tyCString}:
|
||||
if n.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
|
||||
tyString, tyCString}:
|
||||
genAccess(c, n, dest, opcLdStrIdx, {})
|
||||
else:
|
||||
genAccess(c, n, dest, opcLdArr, flags)
|
||||
@@ -1207,7 +1210,7 @@ proc genSetConstr(c: PCtx, n: PNode, dest: var TDest) =
|
||||
|
||||
proc genObjConstr(c: PCtx, n: PNode, dest: var TDest) =
|
||||
if dest < 0: dest = c.getTemp(n.typ)
|
||||
let t = n.typ.skipTypes(abstractRange)
|
||||
let t = n.typ.skipTypes(abstractRange-{tyTypeDesc})
|
||||
if t.kind == tyRef:
|
||||
c.gABx(n, opcNew, dest, c.genType(t.sons[0]))
|
||||
else:
|
||||
|
||||
@@ -294,19 +294,6 @@ proc quote*(bl: stmt, op = "``"): PNimrodNode {.magic: "QuoteAst".}
|
||||
## if not `ex`:
|
||||
## echo `info` & ": Check failed: " & `expString`
|
||||
|
||||
when not defined(booting):
|
||||
template emit*(e: static[string]): stmt =
|
||||
## accepts a single string argument and treats it as nimrod code
|
||||
## that should be inserted verbatim in the program
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
## emit("echo " & '"' & "hello world".toUpper & '"')
|
||||
##
|
||||
macro payload: stmt {.gensym.} =
|
||||
result = e.parseStmt
|
||||
payload()
|
||||
|
||||
proc expectKind*(n: PNimrodNode, k: TNimrodNodeKind) {.compileTime.} =
|
||||
## checks that `n` is of kind `k`. If this is not the case,
|
||||
## compilation aborts with an error message. This is useful for writing
|
||||
@@ -421,7 +408,8 @@ proc lispRepr*(n: PNimrodNode): string {.compileTime.} =
|
||||
of nnkFloatLit..nnkFloat64Lit: add(result, $n.floatVal)
|
||||
of nnkStrLit..nnkTripleStrLit: add(result, $n.strVal)
|
||||
of nnkIdent: add(result, "!\"" & $n.ident & '"')
|
||||
of nnkSym, nnkNone: assert false
|
||||
of nnkSym: add(result, $n.symbol)
|
||||
of nnkNone: assert false
|
||||
else:
|
||||
add(result, lispRepr(n[0]))
|
||||
for j in 1..n.len-1:
|
||||
@@ -745,3 +733,15 @@ proc addIdentIfAbsent*(dest: PNimrodNode, ident: string) {.compiletime.} =
|
||||
else: discard
|
||||
dest.add(ident(ident))
|
||||
|
||||
when not defined(booting):
|
||||
template emit*(e: static[string]): stmt =
|
||||
## accepts a single string argument and treats it as nimrod code
|
||||
## that should be inserted verbatim in the program
|
||||
## Example:
|
||||
##
|
||||
## .. code-block:: nimrod
|
||||
## emit("echo " & '"' & "hello world".toUpper & '"')
|
||||
##
|
||||
macro payload: stmt {.gensym.} =
|
||||
result = parseStmt(e)
|
||||
payload()
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import macros
|
||||
|
||||
template plus(a, b: expr): expr =
|
||||
template plus(a, b: expr): expr {.dirty} =
|
||||
a + b
|
||||
|
||||
macro call(e: expr): expr =
|
||||
|
||||
@@ -7,7 +7,7 @@ proc dumpit(n: PNimrodNode): string {.compileTime.} =
|
||||
result = $n.kind
|
||||
add(result, "(")
|
||||
case n.kind
|
||||
of nnkEmpty: nil # same as nil node in this representation
|
||||
of nnkEmpty: discard # same as nil node in this representation
|
||||
of nnkNilLit: add(result, "nil")
|
||||
of nnkCharLit..nnkInt64Lit: add(result, $n.intVal)
|
||||
of nnkFloatLit..nnkFloat64Lit: add(result, $n.floatVal)
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
discard """
|
||||
file: "tmacrogenerics.nim"
|
||||
msg: '''
|
||||
instantiation 1 with int and float
|
||||
instantiation 2 with float and string
|
||||
instantiation 3 with string and string
|
||||
counter: 3
|
||||
instantiation 1 with typedesc and typedesc
|
||||
counter: 1
|
||||
'''
|
||||
output: "int\nfloat\nint\nstring"
|
||||
"""
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
discard """
|
||||
disabled: true
|
||||
"""
|
||||
|
||||
import macros, typetraits
|
||||
|
||||
macro checkType(ex, expected: expr): stmt {.immediate.} =
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
discard """
|
||||
out: '''HELLO WORLD'''
|
||||
output: '''HELLO WORLD'''
|
||||
"""
|
||||
|
||||
import macros, strutils
|
||||
|
||||
9
todo.txt
9
todo.txt
@@ -1,11 +1,18 @@
|
||||
version 0.9.4
|
||||
=============
|
||||
|
||||
- fix macros\tstringinterp.nim
|
||||
- test and fix showoff; add debug example to showoff
|
||||
- test and fix stdlib
|
||||
- test and fix misc
|
||||
- fix GC issues
|
||||
- test C source code generation
|
||||
- test and fix closures
|
||||
- test and fix exception handling
|
||||
|
||||
Bugs
|
||||
====
|
||||
|
||||
- fix eval in macros.nim
|
||||
- new VM:
|
||||
- implement overflow checking
|
||||
- bug: 'type T = ref T' not recognized as illegal recursion
|
||||
|
||||
Reference in New Issue
Block a user