better tester
This commit is contained in:
parent
12247b3f56
commit
383fbca27e
21 changed files with 39 additions and 31 deletions
23
tests/macros/tmacro1.nim
Normal file
23
tests/macros/tmacro1.nim
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import macros
|
||||
|
||||
from uri import `/`
|
||||
|
||||
macro test*(a: stmt): stmt {.immediate.} =
|
||||
var nodes: tuple[a, b: int]
|
||||
nodes.a = 4
|
||||
nodes[1] = 45
|
||||
|
||||
type
|
||||
TTypeEx = object
|
||||
x, y: int
|
||||
case b: bool
|
||||
of false: nil
|
||||
of true: z: float
|
||||
|
||||
var t: TTypeEx
|
||||
t.b = true
|
||||
t.z = 4.5
|
||||
|
||||
test:
|
||||
"hi"
|
||||
|
||||
28
tests/macros/tmacro2.nim
Normal file
28
tests/macros/tmacro2.nim
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
discard """
|
||||
output: "ta-da Your value sir: 'HE!!!!o Wor!!d'"
|
||||
"""
|
||||
|
||||
import macros, strutils
|
||||
|
||||
proc testBlock(): string {.compileTime.} =
|
||||
block myBlock:
|
||||
while true:
|
||||
echo "inner block"
|
||||
break myBlock
|
||||
echo "outer block"
|
||||
result = "ta-da"
|
||||
|
||||
macro mac(n: expr): expr =
|
||||
let n = callsite()
|
||||
expectKind(n, nnkCall)
|
||||
expectLen(n, 2)
|
||||
expectKind(n[1], nnkStrLit)
|
||||
var s: string = n[1].strVal
|
||||
s = s.replace("l", "!!")
|
||||
result = newStrLitNode("Your value sir: '$#'" % [s])
|
||||
|
||||
const s = testBlock()
|
||||
const t = mac("HEllo World")
|
||||
echo s, " ", t
|
||||
|
||||
|
||||
31
tests/macros/tmacro3.nim
Normal file
31
tests/macros/tmacro3.nim
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
discard """
|
||||
output: ""
|
||||
"""
|
||||
|
||||
import macros
|
||||
|
||||
type
|
||||
TA = tuple[a: int]
|
||||
PA = ref TA
|
||||
|
||||
macro test*(a: stmt): stmt {.immediate.} =
|
||||
var val: PA
|
||||
new(val)
|
||||
val.a = 4
|
||||
|
||||
test:
|
||||
"hi"
|
||||
|
||||
macro test2*(a: stmt): stmt {.immediate.} =
|
||||
proc testproc(recurse: int) =
|
||||
echo "Thats weird"
|
||||
var o : PNimrodNode = nil
|
||||
echo " no its not!"
|
||||
o = newNimNode(nnkNone)
|
||||
if recurse > 0:
|
||||
testproc(recurse - 1)
|
||||
testproc(5)
|
||||
|
||||
test2:
|
||||
"hi"
|
||||
|
||||
19
tests/macros/tmacro4.nim
Normal file
19
tests/macros/tmacro4.nim
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
discard """
|
||||
output: "after"
|
||||
"""
|
||||
|
||||
import
|
||||
macros, strutils
|
||||
|
||||
macro test_macro*(n: stmt): stmt {.immediate.} =
|
||||
result = newNimNode(nnkStmtList)
|
||||
var ass : PNimrodNode = newNimNode(nnkAsgn)
|
||||
add(ass, newIdentNode("str"))
|
||||
add(ass, newStrLitNode("after"))
|
||||
add(result, ass)
|
||||
when isMainModule:
|
||||
var str: string = "before"
|
||||
test_macro(str):
|
||||
var i : integer = 123
|
||||
echo str
|
||||
|
||||
59
tests/macros/tmacro5.nim
Normal file
59
tests/macros/tmacro5.nim
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
import macros,json
|
||||
|
||||
var decls{.compileTime.}: seq[PNimrodNode] = @[]
|
||||
var impls{.compileTime.}: seq[PNimrodNode] = @[]
|
||||
|
||||
macro importImpl_forward(name, returns): stmt {.immediate.} =
|
||||
result = newNimNode(nnkEmpty)
|
||||
var func_name = newNimNode(nnkAccQuoted)
|
||||
func_name.add newIdentNode("import")
|
||||
func_name.add name
|
||||
|
||||
var res = newNimNode(nnkProcDef)
|
||||
res.add newNimNode(nnkPostfix)
|
||||
res[0].add newIdentNode("*")
|
||||
res[0].add func_name
|
||||
res.add newNimNode(nnkEmpty)
|
||||
res.add newNimNode(nnkEmpty)
|
||||
res.add newNimNode(nnkFormalParams)
|
||||
res[3].add returns
|
||||
var p1 = newNimNode(nnkIdentDefs)
|
||||
p1.add newIdentNode("dat")
|
||||
p1.add newIdentNOde("PJsonNode")
|
||||
p1.add newNimNode(nnkEmpty)
|
||||
res[3].add p1
|
||||
var p2 = newNimNode(nnkIdentDefs)
|
||||
p2.add newIdentNode("errors")
|
||||
p2.add newNimNode(nnkVarTy)
|
||||
p2.add newNimNode(nnkEmpty)
|
||||
p2[1].add newNimNode(nnkBracketExpr)
|
||||
p2[1][0].add newIdentNode("seq")
|
||||
p2[1][0].add newIdentNode("string")
|
||||
res[3].add p2
|
||||
|
||||
res.add newNimNode(nnkEmpty)
|
||||
res.add newNimNode(nnkEmpty)
|
||||
res.add newNimNode(nnkEmpty)
|
||||
|
||||
decls.add res
|
||||
echo(repr(res))
|
||||
|
||||
macro importImpl(name, returns: expr, body: stmt): stmt {.immediate.} =
|
||||
#var res = getAST(importImpl_forward(name, returns))
|
||||
discard getAST(importImpl_forward(name, returns))
|
||||
var res = copyNimTree(decls[decls.high])
|
||||
res[6] = body
|
||||
echo repr(res)
|
||||
impls.add res
|
||||
|
||||
macro okayy:stmt =
|
||||
result = newNimNode(nnkStmtList)
|
||||
for node in decls: result.add node
|
||||
for node in impls: result.add node
|
||||
|
||||
importimpl(Item, int):
|
||||
echo 42
|
||||
importImpl(Foo, int16):
|
||||
echo 77
|
||||
|
||||
okayy
|
||||
8
tests/macros/tmacroaspragma.nim
Normal file
8
tests/macros/tmacroaspragma.nim
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import macros
|
||||
|
||||
macro foo(x: stmt): stmt =
|
||||
echo treerepr(callsite())
|
||||
result = newNimNode(nnkStmtList)
|
||||
|
||||
proc zoo() {.foo.} = echo "hi"
|
||||
|
||||
39
tests/macros/tmacrogenerics.nim
Normal file
39
tests/macros/tmacrogenerics.nim
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
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
|
||||
'''
|
||||
output: "int\nfloat\nint\nstring"
|
||||
"""
|
||||
|
||||
import typetraits, macros
|
||||
|
||||
var counter {.compileTime.} = 0
|
||||
|
||||
macro makeBar(A, B: typedesc): typedesc =
|
||||
inc counter
|
||||
echo "instantiation ", counter, " with ", A.name, " and ", B.name
|
||||
result = A
|
||||
|
||||
type
|
||||
Bar[T, U] = makeBar(T, U)
|
||||
|
||||
var bb1: Bar[int, float]
|
||||
var bb2: Bar[float, string]
|
||||
var bb3: Bar[int, float]
|
||||
var bb4: Bar[string, string]
|
||||
|
||||
proc match(a: int) = echo "int"
|
||||
proc match(a: string) = echo "string"
|
||||
proc match(a: float) = echo "float"
|
||||
|
||||
match(bb1)
|
||||
match(bb2)
|
||||
match(bb3)
|
||||
match(bb4)
|
||||
|
||||
static:
|
||||
echo "counter: ", counter
|
||||
31
tests/macros/tmacros1.nim
Normal file
31
tests/macros/tmacros1.nim
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
discard """
|
||||
output: "Got: 'nnkCall' hi"
|
||||
"""
|
||||
|
||||
import
|
||||
macros, strutils
|
||||
|
||||
macro outterMacro*(n: stmt): stmt {.immediate.} =
|
||||
let n = callsite()
|
||||
var j : string = "hi"
|
||||
proc innerProc(i: int): string =
|
||||
echo "Using arg ! " & n.repr
|
||||
result = "Got: '" & $n.kind & "' " & $j
|
||||
var callNode = n[0]
|
||||
expectKind(n, TNimrodNodeKind.nnkCall)
|
||||
if n.len != 3 or n[1].kind != TNimrodNodeKind.nnkIdent:
|
||||
error("Macro " & callNode.repr &
|
||||
" requires the ident passed as parameter (eg: " & callNode.repr &
|
||||
"(the_name_you_want)): statements.")
|
||||
result = newNimNode(TNimrodNodeKind.nnkStmtList)
|
||||
var ass : PNimrodNode = newNimNode(nnkAsgn)
|
||||
ass.add(newIdentNode(n[1].ident))
|
||||
ass.add(newStrLitNode(innerProc(4)))
|
||||
result.add(ass)
|
||||
|
||||
var str: string
|
||||
outterMacro(str):
|
||||
"hellow"
|
||||
echo str
|
||||
|
||||
|
||||
26
tests/macros/tmacrostmt.nim
Normal file
26
tests/macros/tmacrostmt.nim
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
import macros
|
||||
macro case_token(n: stmt): stmt {.immediate.} =
|
||||
# creates a lexical analyzer from regular expressions
|
||||
# ... (implementation is an exercise for the reader :-)
|
||||
nil
|
||||
|
||||
case_token: # this colon tells the parser it is a macro statement
|
||||
of r"[A-Za-z_]+[A-Za-z_0-9]*":
|
||||
return tkIdentifier
|
||||
of r"0-9+":
|
||||
return tkInteger
|
||||
of r"[\+\-\*\?]+":
|
||||
return tkOperator
|
||||
else:
|
||||
return tkUnknown
|
||||
|
||||
case_token: inc i
|
||||
|
||||
#bug #488
|
||||
|
||||
macro foo: stmt =
|
||||
var exp = newCall("whatwhat", newIntLitNode(1))
|
||||
if compiles(getAst(exp)): return exp
|
||||
else: echo "Does not compute!"
|
||||
|
||||
foo()
|
||||
12
tests/macros/tmacrotypes.nim
Normal file
12
tests/macros/tmacrotypes.nim
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import macros, typetraits
|
||||
|
||||
macro checkType(ex, expected: expr): stmt {.immediate.} =
|
||||
var t = ex.typ
|
||||
assert t.name == expected.strVal
|
||||
|
||||
proc voidProc = echo "hello"
|
||||
proc intProc(a, b): int = 10
|
||||
|
||||
checkType(voidProc(), "void")
|
||||
checkType(intProc(10, 20.0), "int")
|
||||
checkType(noproc(10, 20.0), "Error Type")
|
||||
13
tests/macros/tnimrodnode_for_runtime.nim
Normal file
13
tests/macros/tnimrodnode_for_runtime.nim
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
discard """
|
||||
output: "bla"
|
||||
disabled: true
|
||||
"""
|
||||
|
||||
import macros
|
||||
proc makeMacro: PNimrodNode =
|
||||
result = nil
|
||||
|
||||
var p = makeMacro()
|
||||
|
||||
echo "bla"
|
||||
|
||||
16
tests/macros/tprintf.nim
Normal file
16
tests/macros/tprintf.nim
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
discard """
|
||||
file: "tprintf.nim"
|
||||
output: "Andreas Rumpf"
|
||||
"""
|
||||
# Test a printf proc
|
||||
|
||||
proc printf(file: TFile, args: openarray[string]) =
|
||||
var i = 0
|
||||
while i < args.len:
|
||||
write(file, args[i])
|
||||
inc(i)
|
||||
|
||||
printf(stdout, ["Andreas ", "Rumpf\n"])
|
||||
#OUT Andreas Rumpf
|
||||
|
||||
|
||||
26
tests/macros/tquotewords.nim
Normal file
26
tests/macros/tquotewords.nim
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
discard """
|
||||
file: "tquotewords.nim"
|
||||
output: "thisanexample"
|
||||
"""
|
||||
# Test an idea I recently had:
|
||||
|
||||
import macros
|
||||
|
||||
macro quoteWords(n: expr): expr {.immediate.} =
|
||||
let n = callsite()
|
||||
result = newNimNode(nnkBracket, n)
|
||||
for i in 1..n.len-1:
|
||||
expectKind(n[i], nnkIdent)
|
||||
result.add(toStrLit(n[i]))
|
||||
|
||||
const
|
||||
myWordList = quoteWords(this, an, example)
|
||||
|
||||
var s = ""
|
||||
for w in items(myWordList):
|
||||
s.add(w)
|
||||
|
||||
echo s #OUT thisanexample
|
||||
|
||||
|
||||
|
||||
14
tests/macros/trecmacro.nim
Normal file
14
tests/macros/trecmacro.nim
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
discard """
|
||||
file: "trecmacro.nim"
|
||||
line: 8
|
||||
errormsg: "recursive dependency: 'dump'"
|
||||
"""
|
||||
|
||||
macro dump(n: stmt): stmt =
|
||||
dump(n)
|
||||
if kind(n) == nnkNone:
|
||||
nil
|
||||
else:
|
||||
hint($kind(n))
|
||||
for i in countUp(0, len(n)-1):
|
||||
nil
|
||||
74
tests/macros/tstringinterp.nim
Normal file
74
tests/macros/tstringinterp.nim
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
discard """
|
||||
file: "tstringinterp.nim"
|
||||
output: "Hello Alice, 64 | Hello Bob, 10$"
|
||||
"""
|
||||
|
||||
import macros, parseutils, strutils
|
||||
|
||||
proc concat(strings: varargs[string]): string =
|
||||
result = newString(0)
|
||||
for s in items(strings): result.add(s)
|
||||
|
||||
template ProcessInterpolations(e: expr) =
|
||||
var s = e[1].strVal
|
||||
for f in interpolatedFragments(s):
|
||||
case f.kind
|
||||
of ikStr: addString(f.value)
|
||||
of ikDollar: addDollar()
|
||||
of ikVar, ikExpr: addExpr(newCall("$", parseExpr(f.value)))
|
||||
|
||||
macro formatStyleInterpolation(e: expr): expr =
|
||||
let e = callsite()
|
||||
var
|
||||
formatString = ""
|
||||
arrayNode = newNimNode(nnkBracket)
|
||||
idx = 1
|
||||
|
||||
proc addString(s: string) =
|
||||
formatString.add(s)
|
||||
|
||||
proc addExpr(e: PNimrodNode) =
|
||||
arrayNode.add(e)
|
||||
formatString.add("$" & $(idx))
|
||||
inc idx
|
||||
|
||||
proc addDollar() =
|
||||
formatString.add("$$")
|
||||
|
||||
ProcessInterpolations(e)
|
||||
|
||||
result = parseExpr("\"x\" % [y]")
|
||||
result[1].strVal = formatString
|
||||
result[2] = arrayNode
|
||||
|
||||
macro concatStyleInterpolation(e: expr): expr =
|
||||
let e = callsite()
|
||||
var args: seq[PNimrodNode]
|
||||
newSeq(args, 0)
|
||||
|
||||
proc addString(s: string) = args.add(newStrLitNode(s))
|
||||
proc addExpr(e: PNimrodNode) = args.add(e)
|
||||
proc addDollar() = args.add(newStrLitNode"$")
|
||||
|
||||
ProcessInterpolations(e)
|
||||
|
||||
result = newCall("concat", args)
|
||||
|
||||
###
|
||||
|
||||
proc sum(a, b, c: int): int =
|
||||
return (a + b + c)
|
||||
|
||||
var
|
||||
alice = "Alice"
|
||||
bob = "Bob"
|
||||
a = 10
|
||||
b = 20
|
||||
c = 34
|
||||
|
||||
var
|
||||
s1 = concatStyleInterpolation"Hello ${alice}, ${sum(a, b, c)}"
|
||||
s2 = formatStyleInterpolation"Hello ${bob}, ${sum(alice.len, bob.len, 2)}$$"
|
||||
|
||||
write(stdout, s1 & " | " & s2)
|
||||
|
||||
74
tests/macros/tvtable.nim
Normal file
74
tests/macros/tvtable.nim
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
discard """
|
||||
output: '''
|
||||
OBJ 1 foo
|
||||
10
|
||||
OBJ 1 bar
|
||||
OBJ 2 foo
|
||||
5
|
||||
OBJ 2 bar
|
||||
'''
|
||||
"""
|
||||
|
||||
type
|
||||
# these are the signatures of the virtual procs for each type
|
||||
fooProc[T] = proc (o: var T): int
|
||||
barProc[T] = proc (o: var T)
|
||||
|
||||
# an untyped table to store the proc pointers
|
||||
# it's also possible to use a strongly typed tuple here
|
||||
VTable = array[0..1, pointer]
|
||||
|
||||
TBase = object {.inheritable.}
|
||||
vtbl: ptr VTable
|
||||
|
||||
TUserObject1 = object of TBase
|
||||
x: int
|
||||
|
||||
TUserObject2 = object of TBase
|
||||
y: int
|
||||
|
||||
proc foo(o: var TUserObject1): int =
|
||||
echo "OBJ 1 foo"
|
||||
return 10
|
||||
|
||||
proc bar(o: var TUserObject1) =
|
||||
echo "OBJ 1 bar"
|
||||
|
||||
proc foo(o: var TUserObject2): int =
|
||||
echo "OBJ 2 foo"
|
||||
return 5
|
||||
|
||||
proc bar(o: var TUserObject2) =
|
||||
echo "OBJ 2 bar"
|
||||
|
||||
proc getVTable(T: typedesc): ptr VTable =
|
||||
# pay attention to what's going on here
|
||||
# this will initialize the vtable for each type at program start-up
|
||||
#
|
||||
# fooProc[T](foo) is a type coercion - it looks for a proc named foo
|
||||
# matching the signature fooProc[T] (e.g. proc (o: var TUserObject1): int)
|
||||
var vtbl {.global.} = [
|
||||
cast[pointer](fooProc[T](foo)),
|
||||
cast[pointer](barProc[T](bar))
|
||||
]
|
||||
|
||||
return vtbl.addr
|
||||
|
||||
proc create(T: typedesc): T =
|
||||
result.vtbl = getVTable(T)
|
||||
|
||||
proc baseFoo(o: var TBase): int =
|
||||
return cast[fooProc[TBase]](o.vtbl[0]) (o)
|
||||
|
||||
proc baseBar(o: var TBase) =
|
||||
cast[barProc[TBase]](o.vtbl[1]) (o)
|
||||
|
||||
var a = TUserObject1.create
|
||||
var b = TUserObject2.create
|
||||
|
||||
echo a.baseFoo
|
||||
a.baseBar
|
||||
|
||||
echo b.baseFoo
|
||||
b.baseBar
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue