semfold.nim 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  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. # this module folds constants; used by semantic checking phase
  10. # and evaluation phase
  11. import
  12. strutils, options, ast, trees, nimsets,
  13. platform, math, msgs, idents, renderer, types,
  14. commands, magicsys, modulegraphs, strtabs, lineinfos
  15. proc newIntNodeT*(intVal: BiggestInt, n: PNode; g: ModuleGraph): PNode =
  16. case skipTypes(n.typ, abstractVarRange).kind
  17. of tyInt:
  18. result = newIntNode(nkIntLit, intVal)
  19. # See bug #6989. 'pred' et al only produce an int literal type if the
  20. # original type was 'int', not a distinct int etc.
  21. if n.typ.kind == tyInt:
  22. result.typ = getIntLitType(g, result)
  23. else:
  24. result.typ = n.typ
  25. # hrm, this is not correct: 1 + high(int) shouldn't produce tyInt64 ...
  26. #setIntLitType(result)
  27. of tyChar:
  28. result = newIntNode(nkCharLit, intVal)
  29. result.typ = n.typ
  30. else:
  31. result = newIntNode(nkIntLit, intVal)
  32. result.typ = n.typ
  33. result.info = n.info
  34. proc newFloatNodeT*(floatVal: BiggestFloat, n: PNode; g: ModuleGraph): PNode =
  35. result = newFloatNode(nkFloatLit, floatVal)
  36. result.typ = n.typ
  37. result.info = n.info
  38. proc newStrNodeT*(strVal: string, n: PNode; g: ModuleGraph): PNode =
  39. result = newStrNode(nkStrLit, strVal)
  40. result.typ = n.typ
  41. result.info = n.info
  42. proc getConstExpr*(m: PSym, n: PNode; g: ModuleGraph): PNode
  43. # evaluates the constant expression or returns nil if it is no constant
  44. # expression
  45. proc evalOp*(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode
  46. proc checkInRange(conf: ConfigRef; n: PNode, res: BiggestInt): bool =
  47. if res in firstOrd(conf, n.typ)..lastOrd(conf, n.typ):
  48. result = true
  49. proc foldAdd(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
  50. let res = a +% b
  51. if ((res xor a) >= 0'i64 or (res xor b) >= 0'i64) and
  52. checkInRange(g.config, n, res):
  53. result = newIntNodeT(res, n, g)
  54. proc foldSub*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
  55. let res = a -% b
  56. if ((res xor a) >= 0'i64 or (res xor not b) >= 0'i64) and
  57. checkInRange(g.config, n, res):
  58. result = newIntNodeT(res, n, g)
  59. proc foldUnarySub(a: BiggestInt, n: PNode, g: ModuleGraph): PNode =
  60. if a != firstOrd(g.config, n.typ):
  61. result = newIntNodeT(-a, n, g)
  62. proc foldAbs*(a: BiggestInt, n: PNode; g: ModuleGraph): PNode =
  63. if a != firstOrd(g.config, n.typ):
  64. result = newIntNodeT(abs(a), n, g)
  65. proc foldMod*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
  66. if b != 0'i64:
  67. result = newIntNodeT(a mod b, n, g)
  68. proc foldModU*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
  69. if b != 0'i64:
  70. result = newIntNodeT(a %% b, n, g)
  71. proc foldDiv*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
  72. if b != 0'i64 and (a != firstOrd(g.config, n.typ) or b != -1'i64):
  73. result = newIntNodeT(a div b, n, g)
  74. proc foldDivU*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
  75. if b != 0'i64:
  76. result = newIntNodeT(a /% b, n, g)
  77. proc foldMul*(a, b: BiggestInt, n: PNode; g: ModuleGraph): PNode =
  78. let res = a *% b
  79. let floatProd = toBiggestFloat(a) * toBiggestFloat(b)
  80. let resAsFloat = toBiggestFloat(res)
  81. # Fast path for normal case: small multiplicands, and no info
  82. # is lost in either method.
  83. if resAsFloat == floatProd and checkInRange(g.config, n, res):
  84. return newIntNodeT(res, n, g)
  85. # Somebody somewhere lost info. Close enough, or way off? Note
  86. # that a != 0 and b != 0 (else resAsFloat == floatProd == 0).
  87. # The difference either is or isn't significant compared to the
  88. # true value (of which floatProd is a good approximation).
  89. # abs(diff)/abs(prod) <= 1/32 iff
  90. # 32 * abs(diff) <= abs(prod) -- 5 good bits is "close enough"
  91. if 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd) and
  92. checkInRange(g.config, n, res):
  93. return newIntNodeT(res, n, g)
  94. proc ordinalValToString*(a: PNode; g: ModuleGraph): string =
  95. # because $ has the param ordinal[T], `a` is not necessarily an enum, but an
  96. # ordinal
  97. var x = getInt(a)
  98. var t = skipTypes(a.typ, abstractRange)
  99. case t.kind
  100. of tyChar:
  101. result = $chr(int(x) and 0xff)
  102. of tyEnum:
  103. var n = t.n
  104. for i in 0 ..< sonsLen(n):
  105. if n.sons[i].kind != nkSym: internalError(g.config, a.info, "ordinalValToString")
  106. var field = n.sons[i].sym
  107. if field.position == x:
  108. if field.ast == nil:
  109. return field.name.s
  110. else:
  111. return field.ast.strVal
  112. localError(g.config, a.info,
  113. "Cannot convert int literal to $1. The value is invalid." %
  114. [typeToString(t)])
  115. else:
  116. result = $x
  117. proc isFloatRange(t: PType): bool {.inline.} =
  118. result = t.kind == tyRange and t.sons[0].kind in {tyFloat..tyFloat128}
  119. proc isIntRange(t: PType): bool {.inline.} =
  120. result = t.kind == tyRange and t.sons[0].kind in {
  121. tyInt..tyInt64, tyUInt8..tyUInt32}
  122. proc pickIntRange(a, b: PType): PType =
  123. if isIntRange(a): result = a
  124. elif isIntRange(b): result = b
  125. else: result = a
  126. proc isIntRangeOrLit(t: PType): bool =
  127. result = isIntRange(t) or isIntLit(t)
  128. proc makeRange(typ: PType, first, last: BiggestInt; g: ModuleGraph): PType =
  129. let minA = min(first, last)
  130. let maxA = max(first, last)
  131. let lowerNode = newIntNode(nkIntLit, minA)
  132. if typ.kind == tyInt and minA == maxA:
  133. result = getIntLitType(g, lowerNode)
  134. elif typ.kind in {tyUInt, tyUInt64}:
  135. # these are not ordinal types, so you get no subrange type for these:
  136. result = typ
  137. else:
  138. var n = newNode(nkRange)
  139. addSon(n, lowerNode)
  140. addSon(n, newIntNode(nkIntLit, maxA))
  141. result = newType(tyRange, typ.owner)
  142. result.n = n
  143. addSonSkipIntLit(result, skipTypes(typ, {tyRange}))
  144. proc makeRangeF(typ: PType, first, last: BiggestFloat; g: ModuleGraph): PType =
  145. var n = newNode(nkRange)
  146. addSon(n, newFloatNode(nkFloatLit, min(first.float, last.float)))
  147. addSon(n, newFloatNode(nkFloatLit, max(first.float, last.float)))
  148. result = newType(tyRange, typ.owner)
  149. result.n = n
  150. addSonSkipIntLit(result, skipTypes(typ, {tyRange}))
  151. proc fitLiteral(c: ConfigRef, n: PNode): PNode =
  152. # Trim the literal value in order to make it fit in the destination type
  153. if n == nil:
  154. # `n` may be nil if the overflow check kicks in
  155. return
  156. doAssert n.kind in {nkIntLit, nkCharLit}
  157. result = n
  158. let typ = n.typ.skipTypes(abstractRange)
  159. if typ.kind in tyUInt..tyUInt32:
  160. result.intVal = result.intVal and lastOrd(c, typ, fixedUnsigned=true)
  161. proc evalOp(m: TMagic, n, a, b, c: PNode; g: ModuleGraph): PNode =
  162. template doAndFit(op: untyped): untyped =
  163. # Implements wrap-around behaviour for unsigned types
  164. fitLiteral(g.config, op)
  165. # b and c may be nil
  166. result = nil
  167. case m
  168. of mOrd: result = newIntNodeT(getOrdValue(a), n, g)
  169. of mChr: result = newIntNodeT(getInt(a), n, g)
  170. of mUnaryMinusI, mUnaryMinusI64: result = foldUnarySub(getInt(a), n, g)
  171. of mUnaryMinusF64: result = newFloatNodeT(- getFloat(a), n, g)
  172. of mNot: result = newIntNodeT(1 - getInt(a), n, g)
  173. of mCard: result = newIntNodeT(nimsets.cardSet(g.config, a), n, g)
  174. of mBitnotI: result = doAndFit(newIntNodeT(not getInt(a), n, g))
  175. of mLengthArray: result = newIntNodeT(lengthOrd(g.config, a.typ), n, g)
  176. of mLengthSeq, mLengthOpenArray, mXLenSeq, mLengthStr, mXLenStr:
  177. if a.kind == nkNilLit:
  178. result = newIntNodeT(0, n, g)
  179. elif a.kind in {nkStrLit..nkTripleStrLit}:
  180. result = newIntNodeT(len a.strVal, n, g)
  181. else:
  182. result = newIntNodeT(sonsLen(a), n, g)
  183. of mUnaryPlusI, mUnaryPlusF64: result = a # throw `+` away
  184. of mToFloat, mToBiggestFloat:
  185. result = newFloatNodeT(toFloat(int(getInt(a))), n, g)
  186. # XXX: Hides overflow/underflow
  187. of mToInt, mToBiggestInt: result = newIntNodeT(system.toInt(getFloat(a)), n, g)
  188. of mAbsF64: result = newFloatNodeT(abs(getFloat(a)), n, g)
  189. of mAbsI: result = foldAbs(getInt(a), n, g)
  190. of mUnaryLt: result = doAndFit(foldSub(getOrdValue(a), 1, n, g))
  191. of mSucc: result = doAndFit(foldAdd(getOrdValue(a), getInt(b), n, g))
  192. of mPred: result = doAndFit(foldSub(getOrdValue(a), getInt(b), n, g))
  193. of mAddI: result = foldAdd(getInt(a), getInt(b), n, g)
  194. of mSubI: result = foldSub(getInt(a), getInt(b), n, g)
  195. of mMulI: result = foldMul(getInt(a), getInt(b), n, g)
  196. of mMinI:
  197. if getInt(a) > getInt(b): result = newIntNodeT(getInt(b), n, g)
  198. else: result = newIntNodeT(getInt(a), n, g)
  199. of mMaxI:
  200. if getInt(a) > getInt(b): result = newIntNodeT(getInt(a), n, g)
  201. else: result = newIntNodeT(getInt(b), n, g)
  202. of mShlI:
  203. case skipTypes(n.typ, abstractRange).kind
  204. of tyInt8: result = newIntNodeT(int8(getInt(a)) shl int8(getInt(b)), n, g)
  205. of tyInt16: result = newIntNodeT(int16(getInt(a)) shl int16(getInt(b)), n, g)
  206. of tyInt32: result = newIntNodeT(int32(getInt(a)) shl int32(getInt(b)), n, g)
  207. of tyInt64, tyInt:
  208. result = newIntNodeT(`shl`(getInt(a), getInt(b)), n, g)
  209. of tyUInt..tyUInt64:
  210. result = doAndFit(newIntNodeT(`shl`(getInt(a), getInt(b)), n, g))
  211. else: internalError(g.config, n.info, "constant folding for shl")
  212. of mShrI:
  213. var a = cast[uint64](getInt(a))
  214. let b = cast[uint64](getInt(b))
  215. # To support the ``-d:nimOldShiftRight`` flag, we need to mask the
  216. # signed integers to cut off the extended sign bit in the internal
  217. # representation.
  218. if 0'u64 < b: # do not cut off the sign extension, when there is
  219. # no bit shifting happening.
  220. case skipTypes(n.typ, abstractRange).kind
  221. of tyInt8: a = a and 0xff'u64
  222. of tyInt16: a = a and 0xffff'u64
  223. of tyInt32: a = a and 0xffffffff'u64
  224. of tyInt:
  225. if g.config.target.intSize == 4:
  226. a = a and 0xffffffff'u64
  227. else:
  228. # unsigned and 64 bit integers don't need masking
  229. discard
  230. let c = cast[BiggestInt](a shr b)
  231. result = newIntNodeT(c, n, g)
  232. of mAshrI:
  233. case skipTypes(n.typ, abstractRange).kind
  234. of tyInt8: result = newIntNodeT(ashr(int8(getInt(a)), int8(getInt(b))), n, g)
  235. of tyInt16: result = newIntNodeT(ashr(int16(getInt(a)), int16(getInt(b))), n, g)
  236. of tyInt32: result = newIntNodeT(ashr(int32(getInt(a)), int32(getInt(b))), n, g)
  237. of tyInt64, tyInt:
  238. result = newIntNodeT(ashr(getInt(a), getInt(b)), n, g)
  239. else: internalError(g.config, n.info, "constant folding for ashr")
  240. of mDivI: result = foldDiv(getInt(a), getInt(b), n, g)
  241. of mModI: result = foldMod(getInt(a), getInt(b), n, g)
  242. of mAddF64: result = newFloatNodeT(getFloat(a) + getFloat(b), n, g)
  243. of mSubF64: result = newFloatNodeT(getFloat(a) - getFloat(b), n, g)
  244. of mMulF64: result = newFloatNodeT(getFloat(a) * getFloat(b), n, g)
  245. of mDivF64:
  246. result = newFloatNodeT(getFloat(a) / getFloat(b), n, g)
  247. of mMaxF64:
  248. if getFloat(a) > getFloat(b): result = newFloatNodeT(getFloat(a), n, g)
  249. else: result = newFloatNodeT(getFloat(b), n, g)
  250. of mMinF64:
  251. if getFloat(a) > getFloat(b): result = newFloatNodeT(getFloat(b), n, g)
  252. else: result = newFloatNodeT(getFloat(a), n, g)
  253. of mIsNil: result = newIntNodeT(ord(a.kind == nkNilLit), n, g)
  254. of mLtI, mLtB, mLtEnum, mLtCh:
  255. result = newIntNodeT(ord(getOrdValue(a) < getOrdValue(b)), n, g)
  256. of mLeI, mLeB, mLeEnum, mLeCh:
  257. result = newIntNodeT(ord(getOrdValue(a) <= getOrdValue(b)), n, g)
  258. of mEqI, mEqB, mEqEnum, mEqCh:
  259. result = newIntNodeT(ord(getOrdValue(a) == getOrdValue(b)), n, g)
  260. of mLtF64: result = newIntNodeT(ord(getFloat(a) < getFloat(b)), n, g)
  261. of mLeF64: result = newIntNodeT(ord(getFloat(a) <= getFloat(b)), n, g)
  262. of mEqF64: result = newIntNodeT(ord(getFloat(a) == getFloat(b)), n, g)
  263. of mLtStr: result = newIntNodeT(ord(getStr(a) < getStr(b)), n, g)
  264. of mLeStr: result = newIntNodeT(ord(getStr(a) <= getStr(b)), n, g)
  265. of mEqStr: result = newIntNodeT(ord(getStr(a) == getStr(b)), n, g)
  266. of mLtU, mLtU64:
  267. result = newIntNodeT(ord(`<%`(getOrdValue(a), getOrdValue(b))), n, g)
  268. of mLeU, mLeU64:
  269. result = newIntNodeT(ord(`<=%`(getOrdValue(a), getOrdValue(b))), n, g)
  270. of mBitandI, mAnd: result = doAndFit(newIntNodeT(a.getInt and b.getInt, n, g))
  271. of mBitorI, mOr: result = doAndFit(newIntNodeT(getInt(a) or getInt(b), n, g))
  272. of mBitxorI, mXor: result = doAndFit(newIntNodeT(a.getInt xor b.getInt, n, g))
  273. of mAddU: result = doAndFit(newIntNodeT(`+%`(getInt(a), getInt(b)), n, g))
  274. of mSubU: result = doAndFit(newIntNodeT(`-%`(getInt(a), getInt(b)), n, g))
  275. of mMulU: result = doAndFit(newIntNodeT(`*%`(getInt(a), getInt(b)), n, g))
  276. of mModU: result = doAndFit(foldModU(getInt(a), getInt(b), n, g))
  277. of mDivU: result = doAndFit(foldDivU(getInt(a), getInt(b), n, g))
  278. of mLeSet: result = newIntNodeT(ord(containsSets(g.config, a, b)), n, g)
  279. of mEqSet: result = newIntNodeT(ord(equalSets(g.config, a, b)), n, g)
  280. of mLtSet:
  281. result = newIntNodeT(ord(containsSets(g.config, a, b) and not equalSets(g.config, a, b)), n, g)
  282. of mMulSet:
  283. result = nimsets.intersectSets(g.config, a, b)
  284. result.info = n.info
  285. of mPlusSet:
  286. result = nimsets.unionSets(g.config, a, b)
  287. result.info = n.info
  288. of mMinusSet:
  289. result = nimsets.diffSets(g.config, a, b)
  290. result.info = n.info
  291. of mSymDiffSet:
  292. result = nimsets.symdiffSets(g.config, a, b)
  293. result.info = n.info
  294. of mConStrStr: result = newStrNodeT(getStrOrChar(a) & getStrOrChar(b), n, g)
  295. of mInSet: result = newIntNodeT(ord(inSet(a, b)), n, g)
  296. of mRepr:
  297. # BUGFIX: we cannot eval mRepr here for reasons that I forgot.
  298. discard
  299. of mIntToStr, mInt64ToStr: result = newStrNodeT($(getOrdValue(a)), n, g)
  300. of mBoolToStr:
  301. if getOrdValue(a) == 0: result = newStrNodeT("false", n, g)
  302. else: result = newStrNodeT("true", n, g)
  303. of mCopyStr: result = newStrNodeT(substr(getStr(a), int(getOrdValue(b))), n, g)
  304. of mCopyStrLast:
  305. result = newStrNodeT(substr(getStr(a), int(getOrdValue(b)),
  306. int(getOrdValue(c))), n, g)
  307. of mFloatToStr: result = newStrNodeT($getFloat(a), n, g)
  308. of mCStrToStr, mCharToStr:
  309. if a.kind == nkBracket:
  310. var s = ""
  311. for b in a.sons:
  312. s.add b.getStrOrChar
  313. result = newStrNodeT(s, n, g)
  314. else:
  315. result = newStrNodeT(getStrOrChar(a), n, g)
  316. of mStrToStr: result = newStrNodeT(getStrOrChar(a), n, g)
  317. of mEnumToStr: result = newStrNodeT(ordinalValToString(a, g), n, g)
  318. of mArrToSeq:
  319. result = copyTree(a)
  320. result.typ = n.typ
  321. of mCompileOption:
  322. result = newIntNodeT(ord(commands.testCompileOption(g.config, a.getStr, n.info)), n, g)
  323. of mCompileOptionArg:
  324. result = newIntNodeT(ord(
  325. testCompileOptionArg(g.config, getStr(a), getStr(b), n.info)), n, g)
  326. of mEqProc:
  327. result = newIntNodeT(ord(
  328. exprStructuralEquivalent(a, b, strictSymEquality=true)), n, g)
  329. else: discard
  330. proc getConstIfExpr(c: PSym, n: PNode; g: ModuleGraph): PNode =
  331. result = nil
  332. for i in 0 ..< sonsLen(n):
  333. var it = n.sons[i]
  334. if it.len == 2:
  335. var e = getConstExpr(c, it.sons[0], g)
  336. if e == nil: return nil
  337. if getOrdValue(e) != 0:
  338. if result == nil:
  339. result = getConstExpr(c, it.sons[1], g)
  340. if result == nil: return
  341. elif it.len == 1:
  342. if result == nil: result = getConstExpr(c, it.sons[0], g)
  343. else: internalError(g.config, it.info, "getConstIfExpr()")
  344. proc leValueConv*(a, b: PNode): bool =
  345. result = false
  346. case a.kind
  347. of nkCharLit..nkUInt64Lit:
  348. case b.kind
  349. of nkCharLit..nkUInt64Lit: result = a.intVal <= b.intVal
  350. of nkFloatLit..nkFloat128Lit: result = a.intVal <= round(b.floatVal).int
  351. else: result = false #internalError(a.info, "leValueConv")
  352. of nkFloatLit..nkFloat128Lit:
  353. case b.kind
  354. of nkFloatLit..nkFloat128Lit: result = a.floatVal <= b.floatVal
  355. of nkCharLit..nkUInt64Lit: result = a.floatVal <= toFloat(int(b.intVal))
  356. else: result = false # internalError(a.info, "leValueConv")
  357. else: result = false # internalError(a.info, "leValueConv")
  358. proc magicCall(m: PSym, n: PNode; g: ModuleGraph): PNode =
  359. if sonsLen(n) <= 1: return
  360. var s = n.sons[0].sym
  361. var a = getConstExpr(m, n.sons[1], g)
  362. var b, c: PNode
  363. if a == nil: return
  364. if sonsLen(n) > 2:
  365. b = getConstExpr(m, n.sons[2], g)
  366. if b == nil: return
  367. if sonsLen(n) > 3:
  368. c = getConstExpr(m, n.sons[3], g)
  369. if c == nil: return
  370. result = evalOp(s.magic, n, a, b, c, g)
  371. proc getAppType(n: PNode; g: ModuleGraph): PNode =
  372. if g.config.globalOptions.contains(optGenDynLib):
  373. result = newStrNodeT("lib", n, g)
  374. elif g.config.globalOptions.contains(optGenStaticLib):
  375. result = newStrNodeT("staticlib", n, g)
  376. elif g.config.globalOptions.contains(optGenGuiApp):
  377. result = newStrNodeT("gui", n, g)
  378. else:
  379. result = newStrNodeT("console", n, g)
  380. proc rangeCheck(n: PNode, value: BiggestInt; g: ModuleGraph) =
  381. var err = false
  382. if n.typ.skipTypes({tyRange}).kind in {tyUInt..tyUInt64}:
  383. err = value <% firstOrd(g.config, n.typ) or value >% lastOrd(g.config, n.typ, fixedUnsigned=true)
  384. else:
  385. err = value < firstOrd(g.config, n.typ) or value > lastOrd(g.config, n.typ)
  386. if err:
  387. localError(g.config, n.info, "cannot convert " & $value &
  388. " to " & typeToString(n.typ))
  389. proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode =
  390. let dstTyp = skipTypes(n.typ, abstractRange)
  391. let srcTyp = skipTypes(a.typ, abstractRange)
  392. # XXX range checks?
  393. case dstTyp.kind
  394. of tyInt..tyInt64, tyUInt..tyUInt64:
  395. case srcTyp.kind
  396. of tyFloat..tyFloat64:
  397. result = newIntNodeT(int(getFloat(a)), n, g)
  398. of tyChar:
  399. result = newIntNodeT(getOrdValue(a), n, g)
  400. of tyUInt..tyUInt64, tyInt..tyInt64:
  401. let toSigned = dstTyp.kind in tyInt..tyInt64
  402. var val = a.getOrdValue
  403. if dstTyp.kind in {tyInt, tyInt64, tyUInt, tyUInt64}:
  404. # No narrowing needed
  405. discard
  406. elif dstTyp.kind in {tyInt..tyInt64}:
  407. # Signed type: Overflow check (if requested) and conversion
  408. if check: rangeCheck(n, val, g)
  409. let mask = (`shl`(1, getSize(g.config, dstTyp) * 8) - 1)
  410. let valSign = val < 0
  411. val = abs(val) and mask
  412. if valSign: val = -val
  413. else:
  414. # Unsigned type: Conversion
  415. let mask = (`shl`(1, getSize(g.config, dstTyp) * 8) - 1)
  416. val = val and mask
  417. result = newIntNodeT(val, n, g)
  418. else:
  419. result = a
  420. result.typ = n.typ
  421. if check and result.kind in {nkCharLit..nkUInt64Lit}:
  422. rangeCheck(n, result.intVal, g)
  423. of tyFloat..tyFloat64:
  424. case srcTyp.kind
  425. of tyInt..tyInt64, tyEnum, tyBool, tyChar:
  426. result = newFloatNodeT(toBiggestFloat(getOrdValue(a)), n, g)
  427. else:
  428. result = a
  429. result.typ = n.typ
  430. of tyOpenArray, tyVarargs, tyProc, tyPointer:
  431. discard
  432. else:
  433. result = a
  434. result.typ = n.typ
  435. proc getArrayConstr(m: PSym, n: PNode; g: ModuleGraph): PNode =
  436. if n.kind == nkBracket:
  437. result = n
  438. else:
  439. result = getConstExpr(m, n, g)
  440. if result == nil: result = n
  441. proc foldArrayAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
  442. var x = getConstExpr(m, n.sons[0], g)
  443. if x == nil or x.typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyTypeDesc:
  444. return
  445. var y = getConstExpr(m, n.sons[1], g)
  446. if y == nil: return
  447. var idx = getOrdValue(y)
  448. case x.kind
  449. of nkPar, nkTupleConstr:
  450. if idx >= 0 and idx < sonsLen(x):
  451. result = x.sons[int(idx)]
  452. if result.kind == nkExprColonExpr: result = result.sons[1]
  453. else:
  454. localError(g.config, n.info, formatErrorIndexBound(idx, sonsLen(x)-1) & $n)
  455. of nkBracket:
  456. idx = idx - firstOrd(g.config, x.typ)
  457. if idx >= 0 and idx < x.len: result = x.sons[int(idx)]
  458. else: localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n)
  459. of nkStrLit..nkTripleStrLit:
  460. result = newNodeIT(nkCharLit, x.info, n.typ)
  461. if idx >= 0 and idx < len(x.strVal):
  462. result.intVal = ord(x.strVal[int(idx)])
  463. elif idx == len(x.strVal) and optLaxStrings in g.config.options:
  464. discard
  465. else:
  466. localError(g.config, n.info, formatErrorIndexBound(idx, len(x.strVal)-1) & $n)
  467. else: discard
  468. proc foldFieldAccess(m: PSym, n: PNode; g: ModuleGraph): PNode =
  469. # a real field access; proc calls have already been transformed
  470. var x = getConstExpr(m, n.sons[0], g)
  471. if x == nil or x.kind notin {nkObjConstr, nkPar, nkTupleConstr}: return
  472. var field = n.sons[1].sym
  473. for i in ord(x.kind == nkObjConstr) ..< sonsLen(x):
  474. var it = x.sons[i]
  475. if it.kind != nkExprColonExpr:
  476. # lookup per index:
  477. result = x.sons[field.position]
  478. if result.kind == nkExprColonExpr: result = result.sons[1]
  479. return
  480. if it.sons[0].sym.name.id == field.name.id:
  481. result = x.sons[i].sons[1]
  482. return
  483. localError(g.config, n.info, "field not found: " & field.name.s)
  484. proc foldConStrStr(m: PSym, n: PNode; g: ModuleGraph): PNode =
  485. result = newNodeIT(nkStrLit, n.info, n.typ)
  486. result.strVal = ""
  487. for i in 1 ..< sonsLen(n):
  488. let a = getConstExpr(m, n.sons[i], g)
  489. if a == nil: return nil
  490. result.strVal.add(getStrOrChar(a))
  491. proc newSymNodeTypeDesc*(s: PSym; info: TLineInfo): PNode =
  492. result = newSymNode(s, info)
  493. if s.typ.kind != tyTypeDesc:
  494. result.typ = newType(tyTypeDesc, s.owner)
  495. result.typ.addSonSkipIntLit(s.typ)
  496. else:
  497. result.typ = s.typ
  498. proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode =
  499. result = nil
  500. case n.kind
  501. of nkSym:
  502. var s = n.sym
  503. case s.kind
  504. of skEnumField:
  505. result = newIntNodeT(s.position, n, g)
  506. of skConst:
  507. case s.magic
  508. of mIsMainModule: result = newIntNodeT(ord(sfMainModule in m.flags), n, g)
  509. of mCompileDate: result = newStrNodeT(getDateStr(), n, g)
  510. of mCompileTime: result = newStrNodeT(getClockStr(), n, g)
  511. of mCpuEndian: result = newIntNodeT(ord(CPU[g.config.target.targetCPU].endian), n, g)
  512. of mHostOS: result = newStrNodeT(toLowerAscii(platform.OS[g.config.target.targetOS].name), n, g)
  513. of mHostCPU: result = newStrNodeT(platform.CPU[g.config.target.targetCPU].name.toLowerAscii, n, g)
  514. of mBuildOS: result = newStrNodeT(toLowerAscii(platform.OS[g.config.target.hostOS].name), n, g)
  515. of mBuildCPU: result = newStrNodeT(platform.CPU[g.config.target.hostCPU].name.toLowerAscii, n, g)
  516. of mAppType: result = getAppType(n, g)
  517. of mIntDefine:
  518. if isDefined(g.config, s.name.s):
  519. try:
  520. result = newIntNodeT(g.config.symbols[s.name.s].parseInt, n, g)
  521. except ValueError:
  522. localError(g.config, s.info,
  523. "{.intdefine.} const was set to an invalid integer: '" &
  524. g.config.symbols[s.name.s] & "'")
  525. of mStrDefine:
  526. if isDefined(g.config, s.name.s):
  527. result = newStrNodeT(g.config.symbols[s.name.s], n, g)
  528. of mBoolDefine:
  529. if isDefined(g.config, s.name.s):
  530. try:
  531. result = newIntNodeT(g.config.symbols[s.name.s].parseBool.int, n, g)
  532. except ValueError:
  533. localError(g.config, s.info,
  534. "{.booldefine.} const was set to an invalid bool: '" &
  535. g.config.symbols[s.name.s] & "'")
  536. else:
  537. result = copyTree(s.ast)
  538. of skProc, skFunc, skMethod:
  539. result = n
  540. of skParam:
  541. if s.typ != nil and s.typ.kind == tyTypeDesc:
  542. result = newSymNodeTypeDesc(s, n.info)
  543. of skType:
  544. # XXX gensym'ed symbols can come here and cannot be resolved. This is
  545. # dirty, but correct.
  546. if s.typ != nil:
  547. result = newSymNodeTypeDesc(s, n.info)
  548. of skGenericParam:
  549. if s.typ.kind == tyStatic:
  550. if s.typ.n != nil and tfUnresolved notin s.typ.flags:
  551. result = s.typ.n
  552. result.typ = s.typ.base
  553. elif s.typ.isIntLit:
  554. result = s.typ.n
  555. else:
  556. result = newSymNodeTypeDesc(s, n.info)
  557. else: discard
  558. of nkCharLit..nkNilLit:
  559. result = copyNode(n)
  560. of nkIfExpr:
  561. result = getConstIfExpr(m, n, g)
  562. of nkCallKinds:
  563. if n.sons[0].kind != nkSym: return
  564. var s = n.sons[0].sym
  565. if s.kind != skProc and s.kind != skFunc: return
  566. try:
  567. case s.magic
  568. of mNone:
  569. # If it has no sideEffect, it should be evaluated. But not here.
  570. return
  571. of mLow:
  572. if skipTypes(n.sons[1].typ, abstractVarRange).kind in tyFloat..tyFloat64:
  573. result = newFloatNodeT(firstFloat(n.sons[1].typ), n, g)
  574. else:
  575. result = newIntNodeT(firstOrd(g.config, n.sons[1].typ), n, g)
  576. of mHigh:
  577. if skipTypes(n.sons[1].typ, abstractVar+{tyUserTypeClassInst}).kind notin
  578. {tySequence, tyString, tyCString, tyOpenArray, tyVarargs}:
  579. if skipTypes(n.sons[1].typ, abstractVarRange).kind in tyFloat..tyFloat64:
  580. result = newFloatNodeT(lastFloat(n.sons[1].typ), n, g)
  581. else:
  582. result = newIntNodeT(lastOrd(g.config, skipTypes(n[1].typ, abstractVar)), n, g)
  583. else:
  584. var a = getArrayConstr(m, n.sons[1], g)
  585. if a.kind == nkBracket:
  586. # we can optimize it away:
  587. result = newIntNodeT(sonsLen(a)-1, n, g)
  588. of mLengthOpenArray:
  589. var a = getArrayConstr(m, n.sons[1], g)
  590. if a.kind == nkBracket:
  591. # we can optimize it away! This fixes the bug ``len(134)``.
  592. result = newIntNodeT(sonsLen(a), n, g)
  593. else:
  594. result = magicCall(m, n, g)
  595. of mLengthArray:
  596. # It doesn't matter if the argument is const or not for mLengthArray.
  597. # This fixes bug #544.
  598. result = newIntNodeT(lengthOrd(g.config, n.sons[1].typ), n, g)
  599. of mSizeOf:
  600. result = foldSizeOf(g.config, n, nil)
  601. of mAlignOf:
  602. result = foldAlignOf(g.config, n, nil)
  603. of mOffsetOf:
  604. result = foldOffsetOf(g.config, n, nil)
  605. of mAstToStr:
  606. result = newStrNodeT(renderTree(n[1], {renderNoComments}), n, g)
  607. of mConStrStr:
  608. result = foldConStrStr(m, n, g)
  609. of mIs:
  610. # The only kind of mIs node that comes here is one depending on some
  611. # generic parameter and that's (hopefully) handled at instantiation time
  612. discard
  613. else:
  614. result = magicCall(m, n, g)
  615. except OverflowError:
  616. localError(g.config, n.info, "over- or underflow")
  617. except DivByZeroError:
  618. localError(g.config, n.info, "division by zero")
  619. of nkAddr:
  620. var a = getConstExpr(m, n.sons[0], g)
  621. if a != nil:
  622. result = n
  623. n.sons[0] = a
  624. of nkBracket, nkCurly:
  625. result = copyNode(n)
  626. for i, son in n.pairs:
  627. var a = getConstExpr(m, son, g)
  628. if a == nil: return nil
  629. result.add a
  630. incl(result.flags, nfAllConst)
  631. of nkRange:
  632. var a = getConstExpr(m, n.sons[0], g)
  633. if a == nil: return
  634. var b = getConstExpr(m, n.sons[1], g)
  635. if b == nil: return
  636. result = copyNode(n)
  637. addSon(result, a)
  638. addSon(result, b)
  639. #of nkObjConstr:
  640. # result = copyTree(n)
  641. # for i in 1 ..< sonsLen(n):
  642. # var a = getConstExpr(m, n.sons[i].sons[1])
  643. # if a == nil: return nil
  644. # result.sons[i].sons[1] = a
  645. # incl(result.flags, nfAllConst)
  646. of nkPar, nkTupleConstr:
  647. # tuple constructor
  648. result = copyNode(n)
  649. if (sonsLen(n) > 0) and (n.sons[0].kind == nkExprColonExpr):
  650. for i, expr in n.pairs:
  651. let exprNew = copyNode(expr) # nkExprColonExpr
  652. exprNew.add expr[0]
  653. let a = getConstExpr(m, expr[1], g)
  654. if a == nil: return nil
  655. exprNew.add a
  656. result.add exprNew
  657. else:
  658. for i, expr in n.pairs:
  659. let a = getConstExpr(m, expr, g)
  660. if a == nil: return nil
  661. result.add a
  662. incl(result.flags, nfAllConst)
  663. of nkChckRangeF, nkChckRange64, nkChckRange:
  664. var a = getConstExpr(m, n.sons[0], g)
  665. if a == nil: return
  666. if leValueConv(n.sons[1], a) and leValueConv(a, n.sons[2]):
  667. result = a # a <= x and x <= b
  668. result.typ = n.typ
  669. else:
  670. localError(g.config, n.info,
  671. "conversion from $1 to $2 is invalid" %
  672. [typeToString(n.sons[0].typ), typeToString(n.typ)])
  673. of nkStringToCString, nkCStringToString:
  674. var a = getConstExpr(m, n.sons[0], g)
  675. if a == nil: return
  676. result = a
  677. result.typ = n.typ
  678. of nkHiddenStdConv, nkHiddenSubConv, nkConv:
  679. var a = getConstExpr(m, n.sons[1], g)
  680. if a == nil: return
  681. # XXX: we should enable `check` for other conversion types too
  682. result = foldConv(n, a, g, check=n.kind == nkHiddenStdConv)
  683. of nkCast:
  684. var a = getConstExpr(m, n.sons[1], g)
  685. if a == nil: return
  686. if n.typ != nil and n.typ.kind in NilableTypes:
  687. # we allow compile-time 'cast' for pointer types:
  688. result = a
  689. result.typ = n.typ
  690. of nkBracketExpr: result = foldArrayAccess(m, n, g)
  691. of nkDotExpr: result = foldFieldAccess(m, n, g)
  692. of nkStmtListExpr:
  693. if n.len == 2 and n[0].kind == nkComesFrom:
  694. result = getConstExpr(m, n[1], g)
  695. else:
  696. discard