diff options
Diffstat (limited to 'tests/pragmas/tcustom_pragma.nim')
-rw-r--r-- | tests/pragmas/tcustom_pragma.nim | 192 |
1 files changed, 176 insertions, 16 deletions
diff --git a/tests/pragmas/tcustom_pragma.nim b/tests/pragmas/tcustom_pragma.nim index e9dac753d..11a6df813 100644 --- a/tests/pragmas/tcustom_pragma.nim +++ b/tests/pragmas/tcustom_pragma.nim @@ -17,10 +17,26 @@ block: MyObj = object myField1, myField2 {.myAttr: "hi".}: int + MyGenericObj[T] = object + myField1, myField2 {.myAttr: "hi".}: int + + MyOtherObj = MyObj + + var o: MyObj static: doAssert o.myField2.hasCustomPragma(myAttr) doAssert(not o.myField1.hasCustomPragma(myAttr)) + doAssert(not o.myField1.hasCustomPragma(MyObj)) + doAssert(not o.myField1.hasCustomPragma(MyOtherObj)) + + var ogen: MyGenericObj[int] + static: + doAssert ogen.myField2.hasCustomPragma(myAttr) + doAssert(not ogen.myField1.hasCustomPragma(myAttr)) + doAssert(not ogen.myField1.hasCustomPragma(MyGenericObj)) + doAssert(not ogen.myField1.hasCustomPragma(MyGenericObj)) + import custom_pragma block: # A bit more advanced case @@ -156,13 +172,23 @@ block: proc generic_proc[T]() = doAssert Annotated.hasCustomPragma(simpleAttr) - #-------------------------------------------------------------------------- # Pragma on proc type -let a: proc(x: int) {.defaultValue(5).} = nil +type + MyAnnotatedProcType {.defaultValue(4).} = proc(x: int) + +let a {.defaultValue(4).}: proc(x: int) = nil +var b: MyAnnotatedProcType = nil +var c: proc(x: int): void {.defaultValue(5).} = nil +var d {.defaultValue(44).}: MyAnnotatedProcType = nil static: - doAssert hasCustomPragma(a.type, defaultValue) + doAssert hasCustomPragma(a, defaultValue) + doAssert hasCustomPragma(MyAnnotatedProcType, defaultValue) + doAssert hasCustomPragma(b, defaultValue) + doAssert hasCustomPragma(typeof(c), defaultValue) + doAssert getCustomPragmaVal(d, defaultValue) == 44 + doAssert getCustomPragmaVal(typeof(d), defaultValue) == 4 # bug #8371 template thingy {.pragma.} @@ -255,6 +281,10 @@ block: doAssert input.treeRepr & "\n" == expectedRepr return input + macro expectedAstRepr(expectedRepr: static[string], input: untyped): untyped = + doAssert input.repr == expectedRepr + return input + const procTypeAst = """ ProcTy FormalParams @@ -273,20 +303,10 @@ ProcTy static: doAssert Foo is proc(x: int): Future[void] const asyncProcTypeAst = """ -ProcTy - FormalParams - BracketExpr - Ident "Future" - Ident "void" - IdentDefs - Ident "s" - Ident "string" - Empty - Pragma -""" - +proc (s: string): Future[void] {..}""" + # using expectedAst would show `OpenSymChoice` for Future[void], which is fragile. type - Bar = proc (s: string) {.async, expectedAst(asyncProcTypeAst).} + Bar = proc (s: string) {.async, expectedAstRepr(asyncProcTypeAst).} static: doAssert Bar is proc(x: string): Future[void] @@ -378,3 +398,143 @@ block: b {.world.}: int discard Hello(a: 1.0, b: 12) + +# test routines +block: + template prag {.pragma.} + proc hello {.prag.} = discard + iterator hello2: int {.prag.} = discard + template hello3(x: int): int {.prag.} = x + macro hello4(x: int): int {.prag.} = x + func hello5(x: int): int {.prag.} = x + doAssert hello.hasCustomPragma(prag) + doAssert hello2.hasCustomPragma(prag) + doAssert hello3.hasCustomPragma(prag) + doAssert hello4.hasCustomPragma(prag) + doAssert hello5.hasCustomPragma(prag) + +# test push doesn't break +block: + template prag {.pragma.} + {.push prag.} + proc hello = discard + iterator hello2: int = discard + template hello3(x: int): int = x + macro hello4(x: int): int = x + func hello5(x: int): int = x + type + Foo = enum a + Bar[T] = ref object of RootObj + x: T + case y: bool + of false: discard + else: + when true: discard + for a in [1]: discard a + {.pop.} + +# issue #11511 +when false: + template myAttr {.pragma.} + + type TObj = object + a {.myAttr.}: int + + macro hasMyAttr(t: typedesc): untyped = + let objTy = t.getType[1].getType + let recList = objTy[2] + let sym = recList[0] + assert sym.kind == nnkSym and sym.eqIdent("a") + let hasAttr = sym.hasCustomPragma(myAttr) + newLit(hasAttr) + + doAssert hasMyAttr(TObj) + + +# bug #11415 +template noserialize() {.pragma.} + +type + Point[T] = object + x, y: T + + ReplayEventKind = enum + FoodAppeared, FoodEaten, DirectionChanged + + ReplayEvent = object + case kind: ReplayEventKind + of FoodEaten, FoodAppeared: # foodPos is in multiple branches + foodPos {.noserialize.}: Point[float] + of DirectionChanged: + playerPos: float +let ev = ReplayEvent( + kind: FoodEaten, + foodPos: Point[float](x: 5.0, y: 1.0) + ) + +doAssert ev.foodPos.hasCustomPragma(noserialize) + + +when false: + # misc + {.pragma: haha.} + {.pragma: hoho.} + template hehe(key, val: string, haha) {.pragma.} + + type A {.haha, hoho, haha, hehe("hi", "hu", "he").} = int + + assert A.getCustomPragmaVal(hehe) == (key: "hi", val: "hu", haha: "he") + + template hehe(key, val: int) {.pragma.} + + var bb {.haha, hoho, hehe(1, 2), haha, hehe("hi", "hu", "he").} = 3 + + # left-to-right priority/override order for getCustomPragmaVal + assert bb.getCustomPragmaVal(hehe) == (key: "hi", val: "hu", haha: "he") + +{.experimental: "dynamicBindSym".} + +# const +block: + template myAttr() {.pragma.} + template myAttr2(x: int) {.pragma.} + template myAttr3(x: string) {.pragma.} + + type + MyObj2 = ref object + + const a {.myAttr,myAttr2(2),myAttr3:"test".}: int = 0 + const b {.myAttr,myAttr2(2),myAttr3:"test".} = 0 + + macro forceHasCustomPragma(x: untyped, y: typed): untyped = + var x = bindSym(x.repr) + for c in x: + if c.symKind == nskConst: + x = c + break + result = getAst(hasCustomPragma(x, y)) + + macro forceGetCustomPragmaVal(x: untyped, y: typed): untyped = + var x = bindSym(x.repr) + for c in x: + if c.symKind == nskConst: + x = c + break + result = getAst(getCustomPragmaVal(x, y)) + + template check(s: untyped) = + doAssert forceHasCustomPragma(s, myAttr) + doAssert forceHasCustomPragma(s, myAttr2) + doAssert forceGetCustomPragmaVal(s, myAttr2) == 2 + doAssert forceHasCustomPragma(s, myAttr3) + doAssert forceGetCustomPragmaVal(s, myAttr3) == "test" + + check(a) + check(b) + +block: # https://forum.nim-lang.org/t/12522, backticks + template `mypragma`() {.pragma.} + # Error: invalid pragma: `mypragma` + type Test = object + field {.`mypragma`.}: int + doAssert Test().field.hasCustomPragma(mypragma) |