semmacrosanity.nim 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  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, astalgo, 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 countup(0, sonsLen(n) - 1):
  17. result = ithField(n.sons[i], field)
  18. if result != nil: return
  19. of nkRecCase:
  20. if n.sons[0].kind != nkSym: return
  21. result = ithField(n.sons[0], field)
  22. if result != nil: return
  23. for i in countup(1, sonsLen(n) - 1):
  24. case n.sons[i].kind
  25. of nkOfBranch, nkElse:
  26. result = ithField(lastSon(n.sons[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 annotateType*(n: PNode, t: PType; conf: ConfigRef) =
  34. let x = t.skipTypes(abstractInst+{tyRange})
  35. # Note: x can be unequal to t and we need to be careful to use 't'
  36. # to not to skip tyGenericInst
  37. case n.kind
  38. of nkObjConstr:
  39. let x = t.skipTypes(abstractPtrs)
  40. n.typ = t
  41. for i in 1 ..< n.len:
  42. var j = i-1
  43. let field = x.n.ithField(j)
  44. if field.isNil:
  45. globalError conf, n.info, "invalid field at index " & $i
  46. else:
  47. internalAssert(conf, n.sons[i].kind == nkExprColonExpr)
  48. annotateType(n.sons[i].sons[1], field.typ, conf)
  49. of nkPar, nkTupleConstr:
  50. if x.kind == tyTuple:
  51. n.typ = t
  52. for i in 0 ..< n.len:
  53. if i >= x.len: globalError conf, n.info, "invalid field at index " & $i
  54. else: annotateType(n.sons[i], x.sons[i], conf)
  55. elif x.kind == tyProc and x.callConv == ccClosure:
  56. n.typ = t
  57. else:
  58. globalError(conf, n.info, "() must have a tuple type")
  59. of nkBracket:
  60. if x.kind in {tyArray, tySequence, tyOpenArray}:
  61. n.typ = t
  62. for m in n: annotateType(m, x.elemType, conf)
  63. else:
  64. globalError(conf, n.info, "[] must have some form of array type")
  65. of nkCurly:
  66. if x.kind in {tySet}:
  67. n.typ = t
  68. for m in n: annotateType(m, x.elemType, conf)
  69. else:
  70. globalError(conf, n.info, "{} must have the set type")
  71. of nkFloatLit..nkFloat128Lit:
  72. if x.kind in {tyFloat..tyFloat128}:
  73. n.typ = t
  74. else:
  75. globalError(conf, n.info, "float literal must have some float type")
  76. of nkCharLit..nkUInt64Lit:
  77. if x.kind in {tyInt..tyUInt64, tyBool, tyChar, tyEnum}:
  78. n.typ = t
  79. else:
  80. globalError(conf, n.info, "integer literal must have some int type")
  81. of nkStrLit..nkTripleStrLit:
  82. if x.kind in {tyString, tyCString}:
  83. n.typ = t
  84. else:
  85. globalError(conf, n.info, "string literal must be of some string type")
  86. of nkNilLit:
  87. if x.kind in NilableTypes+{tyString, tySequence}:
  88. n.typ = t
  89. else:
  90. globalError(conf, n.info, "nil literal must be of some pointer type")
  91. else: discard