semfold.nim 29 KB

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