semfold.nim 28 KB

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