summary refs log blame commit diff stats
path: root/tests/pragmas/tcustom_pragma.nim
blob: e9dac753dddfa7a9eb299ab592334f664d00f8b8 (plain) (tree)
1
2
3
4
5
6
7
8
9
10

                          
                                       
 



                                  

                                                  
                       



                                       



                                              
              
         

                                                    
 
                    
                                 

                                                
                                            





                                                         
                                            
 
                                                                                        


             


                                                      
                                

                                                          
                                     

                                                                 
                                   

                                                                 
                                            
 
                                                           
 
                                                                    
                                                 
 

                       

                                                                   
 
                                                         
 
                                   
                                                               


        












                                                                            

                              





                                                               

                               






                                                                  

                                   


                         
                                                                     
         
                                  





                                                            

                                        
 
         
                                                                     
 























                                                                                                    


                                                               






                                        
                                                  







                                                                           



















                                              
 
                             





                           
                                   



                     
                                          




                                           







                                        



                                




                                                     
                                












                                                    








                                                                      






                                                                   


                                                                            
                                                  
















                                                           
                                                    
















                                                                   
                                                       




















                                         
                                  





















                                                        
                                  
 
                                                       
            







                                                                                           





















                                                      










                              
{.experimental: "notnil".}

import macros, asyncmacro, asyncfutures

block:
  template myAttr() {.pragma.}

  proc myProc():int {.myAttr.} = 2
  const hasMyAttr = myProc.hasCustomPragma(myAttr)
  static:
    doAssert(hasMyAttr)

block:
  template myAttr(a: string) {.pragma.}

  type
    MyObj = object
      myField1, myField2 {.myAttr: "hi".}: int

  var o: MyObj
  static:
    doAssert o.myField2.hasCustomPragma(myAttr)
    doAssert(not o.myField1.hasCustomPragma(myAttr))

import custom_pragma
block: # A bit more advanced case
  type
    Subfield {.defaultValue: "catman".} = object
      `c`* {.serializationKey: "cc".}: float

    MySerializable = object
      a {.serializationKey"asdf", defaultValue: 5.} : int
      b {.custom_pragma.defaultValue"hello".} : int
      field: Subfield
      d {.alternativeKey("df", 5).}: float
      e {.alternativeKey(V = 5).}: seq[bool]

  proc myproc(x: int, s: string) {.alternativeKey(V = 5), serializationKey"myprocSS".} =
    echo x, s


  var s: MySerializable

  const aDefVal = s.a.getCustomPragmaVal(defaultValue)
  static: doAssert(aDefVal == 5)

  const aSerKey = s.a.getCustomPragmaVal(serializationKey)
  static: doAssert(aSerKey == "asdf")

  const cSerKey = getCustomPragmaVal(s.field.c, serializationKey)
  static: doAssert(cSerKey == "cc")

  const procSerKey = getCustomPragmaVal(myproc, serializationKey)
  static: doAssert(procSerKey == "myprocSS")

  static: doAssert(hasCustomPragma(myproc, alternativeKey))

  const hasFieldCustomPragma = s.field.hasCustomPragma(defaultValue)
  static: doAssert(hasFieldCustomPragma == false)

  # pragma on an object
  static:
    doAssert Subfield.hasCustomPragma(defaultValue)
    doAssert(Subfield.getCustomPragmaVal(defaultValue) == "catman")

    doAssert hasCustomPragma(type(s.field), defaultValue)

  proc foo(s: var MySerializable) =
    static: doAssert(s.a.getCustomPragmaVal(defaultValue) == 5)

  foo(s)

block: # ref types
  type
    Node = object of RootObj
      left {.serializationKey:"l".}, right {.serializationKey:"r".}: NodeRef
    NodeRef = ref Node
    NodePtr = ptr Node

    SpecialNodeRef = ref object of NodeRef
      data {.defaultValue"none".}: string

    MyFile {.defaultValue: "closed".} = ref object
      path {.defaultValue: "invalid".}: string

    TypeWithoutPragma = object

  var s = NodeRef()

  const
    leftSerKey = getCustomPragmaVal(s.left, serializationKey)
    rightSerKey = getCustomPragmaVal(s.right, serializationKey)
  static:
    doAssert leftSerKey == "l"
    doAssert rightSerKey == "r"

  var specS = SpecialNodeRef()

  const
    dataDefVal = hasCustomPragma(specS.data, defaultValue)
    specLeftSerKey = hasCustomPragma(specS.left, serializationKey)
  static:
    doAssert dataDefVal == true
    doAssert specLeftSerKey == true

  var ptrS = NodePtr(nil)
  const
    ptrRightSerKey = getCustomPragmaVal(ptrS.right, serializationKey)
  static:
    doAssert ptrRightSerKey == "r"

  var f = MyFile()
  const
    fileDefVal = f.getCustomPragmaVal(defaultValue)
    filePathDefVal = f.path.getCustomPragmaVal(defaultValue)
  static:
    doAssert fileDefVal == "closed"
    doAssert filePathDefVal == "invalid"

  static:
    doAssert TypeWithoutPragma.hasCustomPragma(defaultValue) == false

block:
  type
    VariantKind = enum
      variInt,
      variFloat
      variString
      variNestedCase
    Variant = object
      case kind: VariantKind
      of variInt: integer {.serializationKey: "int".}: BiggestInt
      of variFloat: floatp: BiggestFloat
      of variString: str {.serializationKey: "string".}: string
      of variNestedCase:
        case nestedKind: VariantKind
        of variInt..variNestedCase: nestedItem {.defaultValue: "Nimmers of the world, unite!".}: int

  let vari = Variant(kind: variInt)

  const
    hasIntSerKey = vari.integer.hasCustomPragma(serializationKey)
    strSerKey = vari.str.getCustomPragmaVal(serializationKey)
    nestedItemDefVal = vari.nestedItem.getCustomPragmaVal(defaultValue)

  static:
    doAssert hasIntSerKey
    doAssert strSerKey == "string"
    doAssert nestedItemDefVal == "Nimmers of the world, unite!"

block:
  template simpleAttr {.pragma.}

  type Annotated {.simpleAttr.} = object

  proc generic_proc[T]() =
    doAssert Annotated.hasCustomPragma(simpleAttr)


#--------------------------------------------------------------------------
# Pragma on proc type

let a: proc(x: int) {.defaultValue(5).} = nil
static:
  doAssert hasCustomPragma(a.type, defaultValue)

# bug #8371
template thingy {.pragma.}

type
  Cardinal = enum
    north, east, south, west
  Something = object
    a: float32
    case cardinal: Cardinal
    of north:
      b {.thingy.}: int
    of east:
      c: int
    of south: discard
    else: discard

var foo: Something
foo.cardinal = north
doAssert foo.b.hasCustomPragma(thingy) == true

proc myproc(s: string): int =
  {.thingy.}:
    s.len

doAssert myproc("123") == 3

let xx = compiles:
  proc myproc_bad(s: string): int =
    {.not_exist.}:
      s.len
doAssert: xx == false

macro checkSym(s: typed{nkSym}): untyped =
  let body = s.getImpl.body
  doAssert body[1].kind == nnkPragmaBlock
  doAssert body[1][0].kind == nnkPragma
  doAssert body[1][0][0] == bindSym"thingy"

checkSym(myproc)

# var and let pragmas
block:
  template myAttr() {.pragma.}
  template myAttr2(x: int) {.pragma.}
  template myAttr3(x: string) {.pragma.}

  type
    MyObj2 = ref object
    MyObjNotNil = MyObj2 not nil

  let a {.myAttr,myAttr2(2),myAttr3:"test".}: int = 0
  let b {.myAttr,myAttr2(2),myAttr3:"test".} = 0
  var x {.myAttr,myAttr2(2),myAttr3:"test".}: int = 0
  var y {.myAttr,myAttr2(2),myAttr3:"test".}: int
  var z {.myAttr,myAttr2(2),myAttr3:"test".} = 0
  var z2 {.myAttr.}: MyObjNotNil

  template check(s: untyped) =
    doAssert s.hasCustomPragma(myAttr)
    doAssert s.hasCustomPragma(myAttr2)
    doAssert s.getCustomPragmaVal(myAttr2) == 2
    doAssert s.hasCustomPragma(myAttr3)
    doAssert s.getCustomPragmaVal(myAttr3) == "test"

  check(a)
  check(b)
  check(x)
  check(y)
  check(z)

# pragma with multiple fields
block:
  template myAttr(first: string, second: int, third: float) {.pragma.}
  let a {.myAttr("one", 2, 3.0).} = 0
  let ps = a.getCustomPragmaVal(myAttr)
  doAssert ps.first == ps[0] and ps.first == "one"
  doAssert ps.second == ps[1] and ps.second == 2
  doAssert ps.third == ps[2] and ps.third == 3.0

# pragma with implicit&explicit generic types
block:
  template fooBar[T](x: T; c: static[int] = 42; m: char) {.pragma.}
  var e {.fooBar("foo", 123, 'u').}: int
  doAssert(hasCustomPragma(e, fooBar))
  doAssert(getCustomPragmaVal(e, fooBar).c == 123)

block:
  macro expectedAst(expectedRepr: static[string], input: untyped): untyped =
    doAssert input.treeRepr & "\n" == expectedRepr
    return input

  const procTypeAst = """
ProcTy
  FormalParams
    Empty
    IdentDefs
      Ident "x"
      Ident "int"
      Empty
  Pragma
    Ident "async"
"""

  type
    Foo = proc (x: int) {.expectedAst(procTypeAst), async.}

  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
"""

  type
    Bar = proc (s: string) {.async, expectedAst(asyncProcTypeAst).}

  static: doAssert Bar is proc(x: string): Future[void]

  const typeAst = """
TypeDef
  PragmaExpr
    Ident "Baz"
    Pragma
  Empty
  ObjectTy
    Empty
    Empty
    RecList
      IdentDefs
        Ident "x"
        Ident "string"
        Empty
"""

  type
    Baz {.expectedAst(typeAst).} = object
      x: string

  static: doAssert Baz.x is string

  const procAst = """
ProcDef
  Ident "bar"
  Empty
  Empty
  FormalParams
    Ident "string"
    IdentDefs
      Ident "s"
      Ident "string"
      Empty
  Empty
  Empty
  StmtList
    ReturnStmt
      Ident "s"
"""

  proc bar(s: string): string {.expectedAst(procAst).} =
    return s

  static: doAssert bar("x") == "x"

#------------------------------------------------------
# bug #13909

template dependency*(id: string, weight = 0.0) {.pragma.}

type
  MyObject* = object
    provider*: proc(obj: string): pointer {.dependency("Data/" & obj, 16.1), noSideEffect.}

proc myproc(obj: string): string {.dependency("Data/" & obj, 16.1).} =
  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)