semfold.nim 28 KB

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