semfold.nim 28 KB

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