123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392 |
- discard """
- nimout: '''
- Infix
- Ident "=>"
- Call
- Ident "name"
- Ident "a"
- ExprColonExpr
- Ident "b"
- Ident "cint"
- NilLit
- macrocache ok
- '''
- output: '''
- x = 10
- x + y = 30
- proc foo[T, N: static[int]]()
- proc foo[T; N: static[int]]()
- a[0]: 42
- a[1]: 45
- x: some string
- ([("key", "val"), ("keyB", "2")], [("val", "key"), ("2", "keyB")])
- ([("key", "val"), ("keyB", "2")], [("val", "key"), ("2", "keyB")])
- 0
- 0
- 0
- '''
- """
- import macros, sugar, macrocache
- block tdump:
- let
- x = 10
- y = 20
- dump x
- dump(x + y)
- block texprcolonexpr:
- macro def(x): untyped =
- echo treeRepr(x)
- def name(a, b:cint) => nil
- block tgenericparams:
- macro test():string =
- let expr0 = "proc foo[T, N: static[int]]()"
- let expr1 = "proc foo[T; N: static[int]]()"
- newLit($toStrLit(parseExpr(expr0)) & "\n" & $toStrLit(parseExpr(expr1)))
- echo test()
- block tidgen:
- # Test compile-time state in same module
- var gid {.compileTime.} = 3
- macro genId(): int =
- result = newIntLitNode(gid)
- inc gid
- proc Id1(): int {.compileTime.} = return genId()
- proc Id2(): int {.compileTime.} = return genId()
- doAssert Id1() == 3
- doAssert Id2() == 4
- block tlexerex:
- macro match(s: cstring|string; pos: int; sections: varargs[untyped]): untyped =
- for sec in sections:
- expectKind sec, nnkOfBranch
- expectLen sec, 2
- result = newStmtList()
- var input = "the input"
- var pos = 0
- match input, pos:
- of r"[a-zA-Z_]\w+": echo "an identifier"
- of r"\d+": echo "an integer"
- of r".": echo "something else"
- block tcopylineinfo:
- # issue #5617, feature request
- type Test = object
- macro mixer(n: typed): untyped =
- let x = newIdentNode("echo")
- x.copyLineInfo(n)
- result = newLit(x.lineInfo == n.lineInfo)
- var z = mixer(Test)
- doAssert z
- block tsetgetlineinfo:
- # issue #21098, feature request
- type Test = object
- macro mixer1(n: typed): untyped =
- let x = newIdentNode("echo")
- var lineInfo = n.lineInfoObj
- x.setLineInfo lineInfo
- result = newLit(x.lineInfo == n.lineInfo)
- macro mixer2(n: typed): untyped =
- let x = newIdentNode("echo")
- var lineInfo = n.lineInfoObj
- lineInfo.line += 1
- x.setLineInfo lineInfo
- result = newLit(x.lineInfo != n.lineInfo)
- doAssert mixer1(Test)
- doAssert mixer2(Test)
- block tdebugstmt:
- macro debug(n: varargs[untyped]): untyped =
- result = newNimNode(nnkStmtList, n)
- for i in 0..n.len-1:
- add(result, newCall("write", newIdentNode("stdout"), toStrLit(n[i])))
- add(result, newCall("write", newIdentNode("stdout"), newStrLitNode(": ")))
- add(result, newCall("writeLine", newIdentNode("stdout"), n[i]))
- var
- a: array[0..10, int]
- x = "some string"
- a[0] = 42
- a[1] = 45
- debug(a[0], a[1], x)
- const
- pairs = {"key": "val", "keyB": "2"}
- macro bilookups(arg: static[openArray[(string, string)]]): untyped =
- var a = newTree(nnkBracket)
- var b = newTree(nnkBracket)
- for (k, v) in items(arg):
- a.add(newTree(nnkTupleConstr, newLit k, newLit v))
- b.add(newTree(nnkTupleConstr, newLit v, newLit k))
- result = newTree(nnkTupleConstr, a, b)
- macro bilookups2(arg: untyped): untyped =
- var a = newTree(nnkBracket)
- var b = newTree(nnkBracket)
- arg.expectKind(nnkTableConstr)
- for x in items(arg):
- x.expectKind(nnkExprColonExpr)
- a.add(newTree(nnkTupleConstr, x[0], x[1]))
- b.add(newTree(nnkTupleConstr, x[1], x[0]))
- result = newTree(nnkTupleConstr, a, b)
- const cnst1 = bilookups(pairs)
- echo cnst1
- const cnst2 = bilookups2({"key": "val", "keyB": "2"})
- echo cnst2
- # macrocache #11404
- const
- mcTable = CacheTable"nimTest"
- mcSeq = CacheSeq"nimTest"
- mcCounter = CacheCounter"nimTest"
- static:
- doAssert(mcCounter.value == 0) # CacheCounter.value
- mcCounter.inc # CacheCounter.inc
- doAssert(mcCounter.value == 1) # CacheCounter.value
- let a = newLit(1)
- let b = newLit(2)
- let c = newLit(3)
- let d = newLit(4)
- mcSeq.add a # CacheSeq.add
- mcSeq.add b # CacheSeq.add
- mcSeq.add c # CacheSeq.add
- doAssert(mcSeq.len == 3) # CacheSeq.len
- #doAssert(c in mcSeq) # CacheSeq.contains
- #doAssert(d notin mcSeq) # CacheSeq.contains
- mcSeq.incl d # CacheSeq.incl
- doAssert(mcSeq.len == 4) # CacheSeq.len
- mcSeq.incl c # CacheSeq.incl
- doAssert(mcSeq.len == 4) # CacheSeq.len
- doAssert(mcSeq[3] == d) # CacheSeq.[]
- #doAssert(mcSeq.pop() == d)# CacheSeq.pop
- #doAssert(mcSeq.len == 3) # CacheSeq.len
- doAssert(mcTable.len == 0) # CacheTable.len
- mcTable["a"] = a # CacheTable.[]=
- doAssert(mcTable.len == 1) # CacheTable.len
- doAssert(mcTable["a"] == a) # CacheTable.[]
- #doAssert("a" in mcTable) # CacheTable.contains
- #doAssert(mcTable.hasKey("a"))# CacheTable.hasKey
- for k, v in mcTable: # CacheTable.items
- doAssert(k == "a")
- doAssert(v == a)
- echo "macrocache ok"
- block tupleNewLitTests:
- macro t(): untyped =
- result = newLit (1, "foo", (), (1,), (a1: 'x', a2: @["ba"]))
- doAssert $t() == """(1, "foo", (), (1,), (a1: 'x', a2: @["ba"]))"""
- # this `$` test is needed because tuple equality doesn't distinguish
- # between named vs unnamed tuples
- doAssert t() == (1, "foo", (), (1, ), (a1: 'x', a2: @["ba"]))
- from strutils import contains
- block getImplTransformed:
- macro bar(a: typed): string =
- # newLit a.getImpl.repr # this would be before code transformation
- let b = a.getImplTransformed
- newLit b.repr
- template toExpand() =
- for ai in 0..2: echo ai
- proc baz(a=1): int =
- defer: discard
- toExpand()
- 12
- const code = bar(baz)
- # sanity check:
- doAssert "finally" in code # `defer` is lowered to try/finally
- doAssert "while" in code # `for` is lowered to `while`
- doAssert "toExpand" notin code
- # template is expanded (but that would already be the case with
- # `a.getImpl.repr`, unlike the other transformations mentioned above
- # test macro resemming
- macro makeVar(): untyped =
- quote:
- var tensorY {.inject.}: int
- macro noop(a: typed): untyped =
- a
- noop:
- makeVar
- echo tensorY
- macro xbenchmark(body: typed): untyped =
- result = body
- xbenchmark:
- proc fastSHA(inputtest: string) =
- discard inputtest
- fastSHA("hey")
- block: # issue #4547
- macro lazy(stmtList : typed) : untyped =
- let decl = stmtList[0]
- decl.expectKind nnkLetSection
- let name = decl[0][0].strVal
- let call = decl[0][2].copy
- call.expectKind nnkCall
- let ident = newIdentNode("get" & name)
- result = quote do:
- var value : type(`call`)
- proc `ident`() : type(`call`) =
- if value.isNil:
- value = `call`
- value
- type MyObject = object
- a,b: int
- # this part, the macro call and it's result (written in the comment below) is important
- lazy:
- let y = new(MyObject)
- #[
- var value: type(new(MyObject))
- proc gety(): type(new(MyObject)) =
- if value.isNil:
- value = new(MyObject)
- value
- ]#
- doAssert gety().a == 0 # works and should work
- doAssert gety().b == 0 # works and should work
- doAssert not declared(y)
- doAssert not compiles(y.a) # identifier y should not exist anymore
- doAssert not compiles(y.b) # identifier y should not exist anymore
- block: # bug #13511
- type
- Builder = ref object
- components: seq[Component]
- Component = object
- proc add(builder: var Builder, component: Component) {.compileTime.} =
- builder.components.add(component)
- macro debugAst(arg: typed): untyped =
- ## just for debugging purpose.
- discard arg.treeRepr
- return arg
- static:
- var component = Component()
- var builder = Builder()
- template foo(): untyped =
- ## WAS: this doc comment causes compilation failure.
- builder
- debugAst:
- add(foo(), component)
- block: # bug #15118
- macro flop(name: static string) =
- let id = genSym(nskType, "env")
- let r =
- nnkStmtList.newTree(
- nnkTypeSection.newTree(
- nnkTypeDef.newTree(
- id,
- newEmptyNode(),
- nnkRefTy.newTree(
- nnkObjectTy.newTree(
- newEmptyNode(),
- newEmptyNode(),
- nnkRecList.newTree(
- nnkIdentDefs.newTree(
- newIdentNode(name),
- newIdentNode("int"),
- newEmptyNode()
- )
- )
- )
- )
- )
- ),
- # var f: T
-
- nnkVarSection.newTree(
- nnkIdentDefs.newTree(
- newIdentNode("f"),
- id,
- newEmptyNode()
- )
- ),
- # echo f.a
- nnkCommand.newTree(
- newIdentNode("new"),
- newIdentNode("f")
- ),
- nnkCommand.newTree(
- newIdentNode("echo"),
- nnkDotExpr.newTree(
- newIdentNode("f"),
- newIdentNode(name)
- )
- )
- )
- r
- block:
- flop("a")
- block:
- flop("b")
- static:
- block:
- const containsTable = CacheTable"containsTable"
- doAssert "foo" notin containsTable
- containsTable["foo"] = newLit 42
- doAssert "foo" in containsTable
|