semfold.nim 28 KB

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