diff options
Diffstat (limited to 'tests/pragmas/tcustom_pragma.nim')
-rw-r--r-- | tests/pragmas/tcustom_pragma.nim | 288 |
1 files changed, 240 insertions, 48 deletions
diff --git a/tests/pragmas/tcustom_pragma.nim b/tests/pragmas/tcustom_pragma.nim index b306045e0..11a6df813 100644 --- a/tests/pragmas/tcustom_pragma.nim +++ b/tests/pragmas/tcustom_pragma.nim @@ -8,7 +8,7 @@ block: proc myProc():int {.myAttr.} = 2 const hasMyAttr = myProc.hasCustomPragma(myAttr) static: - assert(hasMyAttr) + doAssert(hasMyAttr) block: template myAttr(a: string) {.pragma.} @@ -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: - assert o.myField2.hasCustomPragma(myAttr) - assert(not o.myField1.hasCustomPragma(myAttr)) + 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 @@ -42,31 +58,31 @@ block: # A bit more advanced case var s: MySerializable const aDefVal = s.a.getCustomPragmaVal(defaultValue) - static: assert(aDefVal == 5) + static: doAssert(aDefVal == 5) const aSerKey = s.a.getCustomPragmaVal(serializationKey) - static: assert(aSerKey == "asdf") + static: doAssert(aSerKey == "asdf") const cSerKey = getCustomPragmaVal(s.field.c, serializationKey) - static: assert(cSerKey == "cc") + static: doAssert(cSerKey == "cc") const procSerKey = getCustomPragmaVal(myproc, serializationKey) - static: assert(procSerKey == "myprocSS") + static: doAssert(procSerKey == "myprocSS") - static: assert(hasCustomPragma(myproc, alternativeKey)) + static: doAssert(hasCustomPragma(myproc, alternativeKey)) const hasFieldCustomPragma = s.field.hasCustomPragma(defaultValue) - static: assert(hasFieldCustomPragma == false) + static: doAssert(hasFieldCustomPragma == false) # pragma on an object static: - assert Subfield.hasCustomPragma(defaultValue) - assert(Subfield.getCustomPragmaVal(defaultValue) == "catman") + doAssert Subfield.hasCustomPragma(defaultValue) + doAssert(Subfield.getCustomPragmaVal(defaultValue) == "catman") - assert hasCustomPragma(type(s.field), defaultValue) + doAssert hasCustomPragma(type(s.field), defaultValue) proc foo(s: var MySerializable) = - static: assert(s.a.getCustomPragmaVal(defaultValue) == 5) + static: doAssert(s.a.getCustomPragmaVal(defaultValue) == 5) foo(s) @@ -91,8 +107,8 @@ block: # ref types leftSerKey = getCustomPragmaVal(s.left, serializationKey) rightSerKey = getCustomPragmaVal(s.right, serializationKey) static: - assert leftSerKey == "l" - assert rightSerKey == "r" + doAssert leftSerKey == "l" + doAssert rightSerKey == "r" var specS = SpecialNodeRef() @@ -100,25 +116,25 @@ block: # ref types dataDefVal = hasCustomPragma(specS.data, defaultValue) specLeftSerKey = hasCustomPragma(specS.left, serializationKey) static: - assert dataDefVal == true - assert specLeftSerKey == true + doAssert dataDefVal == true + doAssert specLeftSerKey == true var ptrS = NodePtr(nil) const ptrRightSerKey = getCustomPragmaVal(ptrS.right, serializationKey) static: - assert ptrRightSerKey == "r" + doAssert ptrRightSerKey == "r" var f = MyFile() const fileDefVal = f.getCustomPragmaVal(defaultValue) filePathDefVal = f.path.getCustomPragmaVal(defaultValue) static: - assert fileDefVal == "closed" - assert filePathDefVal == "invalid" + doAssert fileDefVal == "closed" + doAssert filePathDefVal == "invalid" static: - assert TypeWithoutPragma.hasCustomPragma(defaultValue) == false + doAssert TypeWithoutPragma.hasCustomPragma(defaultValue) == false block: type @@ -144,9 +160,9 @@ block: nestedItemDefVal = vari.nestedItem.getCustomPragmaVal(defaultValue) static: - assert hasIntSerKey - assert strSerKey == "string" - assert nestedItemDefVal == "Nimmers of the world, unite!" + doAssert hasIntSerKey + doAssert strSerKey == "string" + doAssert nestedItemDefVal == "Nimmers of the world, unite!" block: template simpleAttr {.pragma.} @@ -154,15 +170,25 @@ block: type Annotated {.simpleAttr.} = object proc generic_proc[T]() = - assert Annotated.hasCustomPragma(simpleAttr) - + 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.} @@ -252,7 +278,11 @@ block: block: macro expectedAst(expectedRepr: static[string], input: untyped): untyped = - assert input.treeRepr & "\n" == expectedRepr + doAssert input.treeRepr & "\n" == expectedRepr + return input + + macro expectedAstRepr(expectedRepr: static[string], input: untyped): untyped = + doAssert input.repr == expectedRepr return input const procTypeAst = """ @@ -270,25 +300,15 @@ ProcTy type Foo = proc (x: int) {.expectedAst(procTypeAst), async.} - static: assert Foo is proc(x: int): Future[void] + 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: assert Bar is proc(x: string): Future[void] + static: doAssert Bar is proc(x: string): Future[void] const typeAst = """ TypeDef @@ -310,7 +330,7 @@ TypeDef Baz {.expectedAst(typeAst).} = object x: string - static: assert Baz.x is string + static: doAssert Baz.x is string const procAst = """ ProcDef @@ -333,10 +353,10 @@ ProcDef proc bar(s: string): string {.expectedAst(procAst).} = return s - static: assert bar("x") == "x" + static: doAssert bar("x") == "x" #------------------------------------------------------ -# issue #13909 +# bug #13909 template dependency*(id: string, weight = 0.0) {.pragma.} @@ -345,4 +365,176 @@ type provider*: proc(obj: string): pointer {.dependency("Data/" & obj, 16.1), noSideEffect.} proc myproc(obj: string): string {.dependency("Data/" & obj, 16.1).} = - result = obj \ No newline at end of file + result = obj + +# bug 12523 +template myCustomPragma {.pragma.} + +type + RefType = ref object + field {.myCustomPragma.}: int + + ObjType = object + field {.myCustomPragma.}: int + RefType2 = ref ObjType + +block: + let x = RefType() + for fieldName, fieldSym in fieldPairs(x[]): + doAssert hasCustomPragma(fieldSym, myCustomPragma) + +block: + let x = RefType2() + for fieldName, fieldSym in fieldPairs(x[]): + doAssert hasCustomPragma(fieldSym, myCustomPragma) + +# bug 8457 +block: + template world {.pragma.} + + type + Hello = ref object + a: float32 + 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) |