semmacrosanity.nim 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2015 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## Implements type sanity checking for ASTs resulting from macros. Lots of
  10. ## room for improvement here.
  11. import ast, msgs, types, options
  12. proc ithField(n: PNode, field: var int): PSym =
  13. result = nil
  14. case n.kind
  15. of nkRecList:
  16. for i in 0..<n.len:
  17. result = ithField(n[i], field)
  18. if result != nil: return
  19. of nkRecCase:
  20. if n[0].kind != nkSym: return
  21. result = ithField(n[0], field)
  22. if result != nil: return
  23. for i in 1..<n.len:
  24. case n[i].kind
  25. of nkOfBranch, nkElse:
  26. result = ithField(lastSon(n[i]), field)
  27. if result != nil: return
  28. else: discard
  29. of nkSym:
  30. if field == 0: result = n.sym
  31. else: dec(field)
  32. else: discard
  33. proc ithField(t: PType, field: var int): PSym =
  34. var base = t.baseClass
  35. while base != nil:
  36. let b = skipTypes(base, skipPtrs)
  37. result = ithField(b.n, field)
  38. if result != nil: return result
  39. base = b.baseClass
  40. result = ithField(t.n, field)
  41. proc annotateType*(n: PNode, t: PType; conf: ConfigRef) =
  42. let x = t.skipTypes(abstractInst+{tyRange})
  43. # Note: x can be unequal to t and we need to be careful to use 't'
  44. # to not to skip tyGenericInst
  45. case n.kind
  46. of nkObjConstr:
  47. let x = t.skipTypes(abstractPtrs)
  48. n.typ() = t
  49. n[0].typ() = t
  50. for i in 1..<n.len:
  51. var j = i-1
  52. let field = x.ithField(j)
  53. if field.isNil:
  54. globalError conf, n.info, "invalid field at index " & $i
  55. else:
  56. internalAssert(conf, n[i].kind == nkExprColonExpr)
  57. annotateType(n[i][1], field.typ, conf)
  58. of nkPar, nkTupleConstr:
  59. if x.kind == tyTuple:
  60. n.typ() = t
  61. for i in 0..<n.len:
  62. if i >= x.kidsLen: globalError conf, n.info, "invalid field at index " & $i
  63. else: annotateType(n[i], x[i], conf)
  64. elif x.kind == tyProc and x.callConv == ccClosure:
  65. n.typ() = t
  66. elif x.kind == tyOpenArray: # `opcSlice` transforms slices into tuples
  67. if n.kind == nkTupleConstr:
  68. let
  69. bracketExpr = newNodeI(nkBracket, n.info)
  70. left = int n[1].intVal
  71. right = int n[2].intVal
  72. bracketExpr.flags = n.flags
  73. case n[0].kind # is this a string slice or a array slice
  74. of nkStrKinds:
  75. for i in left..right:
  76. bracketExpr.add newIntNode(nkCharLit, BiggestInt n[0].strVal[i])
  77. annotateType(bracketExpr[^1], x.elementType, conf)
  78. of nkBracket:
  79. for i in left..right:
  80. bracketExpr.add n[0][i]
  81. annotateType(bracketExpr[^1], x.elementType, conf)
  82. else:
  83. globalError(conf, n.info, "Incorrectly generated tuple constr")
  84. n[] = bracketExpr[]
  85. n.typ() = t
  86. else:
  87. globalError(conf, n.info, "() must have a tuple type")
  88. of nkBracket:
  89. if x.kind in {tyArray, tySequence, tyOpenArray}:
  90. n.typ() = t
  91. for m in n: annotateType(m, x.elemType, conf)
  92. else:
  93. globalError(conf, n.info, "[] must have some form of array type")
  94. of nkCurly:
  95. if x.kind in {tySet}:
  96. n.typ() = t
  97. for m in n: annotateType(m, x.elemType, conf)
  98. else:
  99. globalError(conf, n.info, "{} must have the set type")
  100. of nkFloatLit..nkFloat128Lit:
  101. if x.kind in {tyFloat..tyFloat128}:
  102. n.typ() = t
  103. else:
  104. globalError(conf, n.info, "float literal must have some float type")
  105. of nkCharLit..nkUInt64Lit:
  106. if x.kind in {tyInt..tyUInt64, tyBool, tyChar, tyEnum}:
  107. n.typ() = t
  108. else:
  109. globalError(conf, n.info, "integer literal must have some int type")
  110. of nkStrLit..nkTripleStrLit:
  111. if x.kind in {tyString, tyCstring}:
  112. n.typ() = t
  113. else:
  114. globalError(conf, n.info, "string literal must be of some string type")
  115. of nkNilLit:
  116. if x.kind in NilableTypes+{tyString, tySequence}:
  117. n.typ() = t
  118. else:
  119. globalError(conf, n.info, "nil literal must be of some pointer type")
  120. else: discard