semmacrosanity.nim 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  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[0]
  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[0]
  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. for i in 1..<n.len:
  50. var j = i-1
  51. let field = x.ithField(j)
  52. if field.isNil:
  53. globalError conf, n.info, "invalid field at index " & $i
  54. else:
  55. internalAssert(conf, n[i].kind == nkExprColonExpr)
  56. annotateType(n[i][1], field.typ, conf)
  57. of nkPar, nkTupleConstr:
  58. if x.kind == tyTuple:
  59. n.typ = t
  60. for i in 0..<n.len:
  61. if i >= x.len: globalError conf, n.info, "invalid field at index " & $i
  62. else: annotateType(n[i], x[i], conf)
  63. elif x.kind == tyProc and x.callConv == ccClosure:
  64. n.typ = t
  65. elif x.kind == tyOpenArray: # `opcSlice` transforms slices into tuples
  66. if n.kind == nkTupleConstr:
  67. let
  68. bracketExpr = newNodeI(nkBracket, n.info)
  69. left = int n[1].intVal
  70. right = int n[2].intVal
  71. bracketExpr.flags = n.flags
  72. case n[0].kind # is this a string slice or a array slice
  73. of nkStrKinds:
  74. for i in left..right:
  75. bracketExpr.add newIntNode(nkCharLit, BiggestInt n[0].strVal[i])
  76. annotateType(bracketExpr[^1], t[0], conf)
  77. of nkBracket:
  78. for i in left..right:
  79. bracketExpr.add n[0][i]
  80. annotateType(bracketExpr[^1], t[0], conf)
  81. else:
  82. globalError(conf, n.info, "Incorrectly generated tuple constr")
  83. n[] = bracketExpr[]
  84. n.typ = t
  85. else:
  86. globalError(conf, n.info, "() must have a tuple type")
  87. of nkBracket:
  88. if x.kind in {tyArray, tySequence, tyOpenArray}:
  89. n.typ = t
  90. for m in n: annotateType(m, x.elemType, conf)
  91. else:
  92. globalError(conf, n.info, "[] must have some form of array type")
  93. of nkCurly:
  94. if x.kind in {tySet}:
  95. n.typ = t
  96. for m in n: annotateType(m, x.elemType, conf)
  97. else:
  98. globalError(conf, n.info, "{} must have the set type")
  99. of nkFloatLit..nkFloat128Lit:
  100. if x.kind in {tyFloat..tyFloat128}:
  101. n.typ = t
  102. else:
  103. globalError(conf, n.info, "float literal must have some float type")
  104. of nkCharLit..nkUInt64Lit:
  105. if x.kind in {tyInt..tyUInt64, tyBool, tyChar, tyEnum}:
  106. n.typ = t
  107. else:
  108. globalError(conf, n.info, "integer literal must have some int type")
  109. of nkStrLit..nkTripleStrLit:
  110. if x.kind in {tyString, tyCstring}:
  111. n.typ = t
  112. else:
  113. globalError(conf, n.info, "string literal must be of some string type")
  114. of nkNilLit:
  115. if x.kind in NilableTypes+{tyString, tySequence}:
  116. n.typ = t
  117. else:
  118. globalError(conf, n.info, "nil literal must be of some pointer type")
  119. else: discard