semfold.nim 29 KB

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