semmacrosanity.nim 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  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. else:
  66. globalError(conf, n.info, "() must have a tuple type")
  67. of nkBracket:
  68. if x.kind in {tyArray, tySequence, tyOpenArray}:
  69. n.typ = t
  70. for m in n: annotateType(m, x.elemType, conf)
  71. else:
  72. globalError(conf, n.info, "[] must have some form of array type")
  73. of nkCurly:
  74. if x.kind in {tySet}:
  75. n.typ = t
  76. for m in n: annotateType(m, x.elemType, conf)
  77. else:
  78. globalError(conf, n.info, "{} must have the set type")
  79. of nkFloatLit..nkFloat128Lit:
  80. if x.kind in {tyFloat..tyFloat128}:
  81. n.typ = t
  82. else:
  83. globalError(conf, n.info, "float literal must have some float type")
  84. of nkCharLit..nkUInt64Lit:
  85. if x.kind in {tyInt..tyUInt64, tyBool, tyChar, tyEnum}:
  86. n.typ = t
  87. else:
  88. globalError(conf, n.info, "integer literal must have some int type")
  89. of nkStrLit..nkTripleStrLit:
  90. if x.kind in {tyString, tyCString}:
  91. n.typ = t
  92. else:
  93. globalError(conf, n.info, "string literal must be of some string type")
  94. of nkNilLit:
  95. if x.kind in NilableTypes+{tyString, tySequence}:
  96. n.typ = t
  97. else:
  98. globalError(conf, n.info, "nil literal must be of some pointer type")
  99. else: discard