semfold.nim 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709
  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, trees, nimsets,
  13. platform, math, msgs, idents, renderer, types,
  14. commands, magicsys, modulegraphs, strtabs, lineinfos
  15. from system/memory import nimCStrLen
  16. when defined(nimPreviewSlimSystem):
  17. import std/[assertions, formatfloat]
  18. proc errorType*(g: ModuleGraph): PType =
  19. ## creates a type representing an error state
  20. result = newType(tyError, nextTypeId(g.idgen), g.owners[^1])
  21. result.flags.incl tfCheckedForDestructor
  22. proc getIntLitTypeG(g: ModuleGraph; literal: PNode; idgen: IdGenerator): PType =
  23. # we cache some common integer literal types for performance:
  24. let ti = getSysType(g, literal.info, tyInt)
  25. result = copyType(ti, nextTypeId(idgen), ti.owner)
  26. result.n = literal
  27. proc newIntNodeT*(intVal: Int128, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
  28. result = newIntTypeNode(intVal, n.typ)
  29. # See bug #6989. 'pred' et al only produce an int literal type if the
  30. # original type was 'int', not a distinct int etc.
  31. if n.typ.kind == tyInt:
  32. # access cache for the int lit type
  33. result.typ = getIntLitTypeG(g, result, idgen)
  34. result.info = n.info
  35. proc newFloatNodeT*(floatVal: BiggestFloat, n: PNode; g: ModuleGraph): PNode =
  36. if n.typ.skipTypes(abstractInst).kind == tyFloat32:
  37. result = newFloatNode(nkFloat32Lit, floatVal)
  38. else:
  39. result = newFloatNode(nkFloatLit, floatVal)
  40. result.typ = n.typ
  41. result.info = n.info
  42. proc newStrNodeT*(strVal: string, n: PNode; g: ModuleGraph): PNode =
  43. result = newStrNode(nkStrLit, strVal)
  44. result.typ = n.typ
  45. result.info = n.info
  46. proc getConstExpr*(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
  47. # evaluates the constant expression or returns nil if it is no constant
  48. # expression
  49. proc evalOp*(m: TMagic, n, a, b, c: PNode; idgen: IdGenerator; g: ModuleGraph): PNode
  50. proc checkInRange(conf: ConfigRef; n: PNode, res: Int128): bool =
  51. res in firstOrd(conf, n.typ)..lastOrd(conf, n.typ)
  52. proc foldAdd(a, b: Int128, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
  53. let res = a + b
  54. if checkInRange(g.config, n, res):
  55. result = newIntNodeT(res, n, idgen, g)
  56. proc foldSub(a, b: Int128, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
  57. let res = a - b
  58. if checkInRange(g.config, n, res):
  59. result = newIntNodeT(res, n, idgen, g)
  60. proc foldUnarySub(a: Int128, n: PNode; idgen: IdGenerator, g: ModuleGraph): PNode =
  61. if a != firstOrd(g.config, n.typ):
  62. result = newIntNodeT(-a, n, idgen, g)
  63. proc foldAbs(a: Int128, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
  64. if a != firstOrd(g.config, n.typ):
  65. result = newIntNodeT(abs(a), n, idgen, g)
  66. proc foldMul(a, b: Int128, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
  67. let res = a * b
  68. if checkInRange(g.config, n, res):
  69. return newIntNodeT(res, n, idgen, g)
  70. proc ordinalValToString*(a: PNode; g: ModuleGraph): string =
  71. # because $ has the param ordinal[T], `a` is not necessarily an enum, but an
  72. # ordinal
  73. var x = getInt(a)
  74. var t = skipTypes(a.typ, abstractRange)
  75. case t.kind
  76. of tyChar:
  77. result = $chr(toInt64(x) and 0xff)
  78. of tyEnum:
  79. var n = t.n
  80. for i in 0..<n.len:
  81. if n[i].kind != nkSym: internalError(g.config, a.info, "ordinalValToString")
  82. var field = n[i].sym
  83. if field.position == x:
  84. if field.ast == nil:
  85. return field.name.s
  86. else:
  87. return field.ast.strVal
  88. localError(g.config, a.info,
  89. "Cannot convert int literal to $1. The value is invalid." %
  90. [typeToString(t)])
  91. else:
  92. result = $x
  93. proc isFloatRange(t: PType): bool {.inline.} =
  94. result = t.kind == tyRange and t[0].kind in {tyFloat..tyFloat128}
  95. proc isIntRange(t: PType): bool {.inline.} =
  96. result = t.kind == tyRange and t[0].kind in {
  97. tyInt..tyInt64, tyUInt8..tyUInt32}
  98. proc pickIntRange(a, b: PType): PType =
  99. if isIntRange(a): result = a
  100. elif isIntRange(b): result = b
  101. else: result = a
  102. proc isIntRangeOrLit(t: PType): bool =
  103. result = isIntRange(t) or isIntLit(t)
  104. proc evalOp(m: TMagic, n, a, b, c: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
  105. # b and c may be nil
  106. result = nil
  107. case m
  108. of mOrd: result = newIntNodeT(getOrdValue(a), n, idgen, g)
  109. of mChr: result = newIntNodeT(getInt(a), n, idgen, g)
  110. of mUnaryMinusI, mUnaryMinusI64: result = foldUnarySub(getInt(a), n, idgen, g)
  111. of mUnaryMinusF64: result = newFloatNodeT(-getFloat(a), n, g)
  112. of mNot: result = newIntNodeT(One - getInt(a), n, idgen, g)
  113. of mCard: result = newIntNodeT(toInt128(nimsets.cardSet(g.config, a)), n, idgen, g)
  114. of mBitnotI:
  115. if n.typ.isUnsigned:
  116. result = newIntNodeT(bitnot(getInt(a)).maskBytes(int(getSize(g.config, n.typ))), n, idgen, g)
  117. else:
  118. result = newIntNodeT(bitnot(getInt(a)), n, idgen, g)
  119. of mLengthArray: result = newIntNodeT(lengthOrd(g.config, a.typ), n, idgen, g)
  120. of mLengthSeq, mLengthOpenArray, mLengthStr:
  121. if a.kind == nkNilLit:
  122. result = newIntNodeT(Zero, n, idgen, g)
  123. elif a.kind in {nkStrLit..nkTripleStrLit}:
  124. if a.typ.kind == tyString:
  125. result = newIntNodeT(toInt128(a.strVal.len), n, idgen, g)
  126. elif a.typ.kind == tyCstring:
  127. result = newIntNodeT(toInt128(nimCStrLen(a.strVal.cstring)), n, idgen, g)
  128. else:
  129. result = newIntNodeT(toInt128(a.len), n, idgen, g)
  130. of mUnaryPlusI, mUnaryPlusF64: result = a # throw `+` away
  131. # XXX: Hides overflow/underflow
  132. of mAbsI: result = foldAbs(getInt(a), n, idgen, g)
  133. of mSucc: result = foldAdd(getOrdValue(a), getInt(b), n, idgen, g)
  134. of mPred: result = foldSub(getOrdValue(a), getInt(b), n, idgen, g)
  135. of mAddI: result = foldAdd(getInt(a), getInt(b), n, idgen, g)
  136. of mSubI: result = foldSub(getInt(a), getInt(b), n, idgen, g)
  137. of mMulI: result = foldMul(getInt(a), getInt(b), n, idgen, g)
  138. of mMinI:
  139. let argA = getInt(a)
  140. let argB = getInt(b)
  141. result = newIntNodeT(if argA < argB: argA else: argB, n, idgen, g)
  142. of mMaxI:
  143. let argA = getInt(a)
  144. let argB = getInt(b)
  145. result = newIntNodeT(if argA > argB: argA else: argB, n, idgen, g)
  146. of mShlI:
  147. case skipTypes(n.typ, abstractRange).kind
  148. of tyInt8: result = newIntNodeT(toInt128(toInt8(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
  149. of tyInt16: result = newIntNodeT(toInt128(toInt16(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
  150. of tyInt32: result = newIntNodeT(toInt128(toInt32(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
  151. of tyInt64: result = newIntNodeT(toInt128(toInt64(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
  152. of tyInt:
  153. if g.config.target.intSize == 4:
  154. result = newIntNodeT(toInt128(toInt32(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
  155. else:
  156. result = newIntNodeT(toInt128(toInt64(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
  157. of tyUInt8: result = newIntNodeT(toInt128(toUInt8(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
  158. of tyUInt16: result = newIntNodeT(toInt128(toUInt16(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
  159. of tyUInt32: result = newIntNodeT(toInt128(toUInt32(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
  160. of tyUInt64: result = newIntNodeT(toInt128(toUInt64(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
  161. of tyUInt:
  162. if g.config.target.intSize == 4:
  163. result = newIntNodeT(toInt128(toUInt32(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
  164. else:
  165. result = newIntNodeT(toInt128(toUInt64(getInt(a)) shl toInt64(getInt(b))), n, idgen, g)
  166. else: internalError(g.config, n.info, "constant folding for shl")
  167. of mShrI:
  168. var a = cast[uint64](getInt(a))
  169. let b = cast[uint64](getInt(b))
  170. # To support the ``-d:nimOldShiftRight`` flag, we need to mask the
  171. # signed integers to cut off the extended sign bit in the internal
  172. # representation.
  173. if 0'u64 < b: # do not cut off the sign extension, when there is
  174. # no bit shifting happening.
  175. case skipTypes(n.typ, abstractRange).kind
  176. of tyInt8: a = a and 0xff'u64
  177. of tyInt16: a = a and 0xffff'u64
  178. of tyInt32: a = a and 0xffffffff'u64
  179. of tyInt:
  180. if g.config.target.intSize == 4:
  181. a = a and 0xffffffff'u64
  182. else:
  183. # unsigned and 64 bit integers don't need masking
  184. discard
  185. let c = cast[BiggestInt](a shr b)
  186. result = newIntNodeT(toInt128(c), n, idgen, g)
  187. of mAshrI:
  188. case skipTypes(n.typ, abstractRange).kind
  189. of tyInt8: result = newIntNodeT(toInt128(ashr(toInt8(getInt(a)), toInt8(getInt(b)))), n, idgen, g)
  190. of tyInt16: result = newIntNodeT(toInt128(ashr(toInt16(getInt(a)), toInt16(getInt(b)))), n, idgen, g)
  191. of tyInt32: result = newIntNodeT(toInt128(ashr(toInt32(getInt(a)), toInt32(getInt(b)))), n, idgen, g)
  192. of tyInt64, tyInt:
  193. result = newIntNodeT(toInt128(ashr(toInt64(getInt(a)), toInt64(getInt(b)))), n, idgen, g)
  194. else: internalError(g.config, n.info, "constant folding for ashr")
  195. of mDivI:
  196. let argA = getInt(a)
  197. let argB = getInt(b)
  198. if argB != Zero and (argA != firstOrd(g.config, n.typ) or argB != NegOne):
  199. result = newIntNodeT(argA div argB, n, idgen, g)
  200. of mModI:
  201. let argA = getInt(a)
  202. let argB = getInt(b)
  203. if argB != Zero and (argA != firstOrd(g.config, n.typ) or argB != NegOne):
  204. result = newIntNodeT(argA mod argB, n, idgen, g)
  205. of mAddF64: result = newFloatNodeT(getFloat(a) + getFloat(b), n, g)
  206. of mSubF64: result = newFloatNodeT(getFloat(a) - getFloat(b), n, g)
  207. of mMulF64: result = newFloatNodeT(getFloat(a) * getFloat(b), n, g)
  208. of mDivF64:
  209. result = newFloatNodeT(getFloat(a) / getFloat(b), n, g)
  210. of mIsNil: result = newIntNodeT(toInt128(ord(a.kind == nkNilLit)), n, idgen, g)
  211. of mLtI, mLtB, mLtEnum, mLtCh:
  212. result = newIntNodeT(toInt128(ord(getOrdValue(a) < getOrdValue(b))), n, idgen, g)
  213. of mLeI, mLeB, mLeEnum, mLeCh:
  214. result = newIntNodeT(toInt128(ord(getOrdValue(a) <= getOrdValue(b))), n, idgen, g)
  215. of mEqI, mEqB, mEqEnum, mEqCh:
  216. result = newIntNodeT(toInt128(ord(getOrdValue(a) == getOrdValue(b))), n, idgen, g)
  217. of mLtF64: result = newIntNodeT(toInt128(ord(getFloat(a) < getFloat(b))), n, idgen, g)
  218. of mLeF64: result = newIntNodeT(toInt128(ord(getFloat(a) <= getFloat(b))), n, idgen, g)
  219. of mEqF64: result = newIntNodeT(toInt128(ord(getFloat(a) == getFloat(b))), n, idgen, g)
  220. of mLtStr: result = newIntNodeT(toInt128(ord(getStr(a) < getStr(b))), n, idgen, g)
  221. of mLeStr: result = newIntNodeT(toInt128(ord(getStr(a) <= getStr(b))), n, idgen, g)
  222. of mEqStr: result = newIntNodeT(toInt128(ord(getStr(a) == getStr(b))), n, idgen, g)
  223. of mLtU:
  224. result = newIntNodeT(toInt128(ord(`<%`(toInt64(getOrdValue(a)), toInt64(getOrdValue(b))))), n, idgen, g)
  225. of mLeU:
  226. result = newIntNodeT(toInt128(ord(`<=%`(toInt64(getOrdValue(a)), toInt64(getOrdValue(b))))), n, idgen, g)
  227. of mBitandI, mAnd: result = newIntNodeT(bitand(a.getInt, b.getInt), n, idgen, g)
  228. of mBitorI, mOr: result = newIntNodeT(bitor(getInt(a), getInt(b)), n, idgen, g)
  229. of mBitxorI, mXor: result = newIntNodeT(bitxor(getInt(a), getInt(b)), n, idgen, g)
  230. of mAddU:
  231. let val = maskBytes(getInt(a) + getInt(b), int(getSize(g.config, n.typ)))
  232. result = newIntNodeT(val, n, idgen, g)
  233. of mSubU:
  234. let val = maskBytes(getInt(a) - getInt(b), int(getSize(g.config, n.typ)))
  235. result = newIntNodeT(val, n, idgen, g)
  236. # echo "subU: ", val, " n: ", n, " result: ", val
  237. of mMulU:
  238. let val = maskBytes(getInt(a) * getInt(b), int(getSize(g.config, n.typ)))
  239. result = newIntNodeT(val, n, idgen, g)
  240. of mModU:
  241. let argA = maskBytes(getInt(a), int(getSize(g.config, a.typ)))
  242. let argB = maskBytes(getInt(b), int(getSize(g.config, a.typ)))
  243. if argB != Zero:
  244. result = newIntNodeT(argA mod argB, n, idgen, g)
  245. of mDivU:
  246. let argA = maskBytes(getInt(a), int(getSize(g.config, a.typ)))
  247. let argB = maskBytes(getInt(b), int(getSize(g.config, a.typ)))
  248. if argB != Zero:
  249. result = newIntNodeT(argA div argB, n, idgen, g)
  250. of mLeSet: result = newIntNodeT(toInt128(ord(containsSets(g.config, a, b))), n, idgen, g)
  251. of mEqSet: result = newIntNodeT(toInt128(ord(equalSets(g.config, a, b))), n, idgen, g)
  252. of mLtSet:
  253. result = newIntNodeT(toInt128(ord(
  254. containsSets(g.config, a, b) and not equalSets(g.config, a, b))), n, idgen, g)
  255. of mMulSet:
  256. result = nimsets.intersectSets(g.config, a, b)
  257. result.info = n.info
  258. of mPlusSet:
  259. result = nimsets.unionSets(g.config, a, b)
  260. result.info = n.info
  261. of mMinusSet:
  262. result = nimsets.diffSets(g.config, a, b)
  263. result.info = n.info
  264. of mConStrStr: result = newStrNodeT(getStrOrChar(a) & getStrOrChar(b), n, g)
  265. of mInSet: result = newIntNodeT(toInt128(ord(inSet(a, b))), n, idgen, g)
  266. of mRepr:
  267. # BUGFIX: we cannot eval mRepr here for reasons that I forgot.
  268. discard
  269. of mIntToStr, mInt64ToStr: result = newStrNodeT($(getOrdValue(a)), n, g)
  270. of mBoolToStr:
  271. if getOrdValue(a) == 0: result = newStrNodeT("false", n, g)
  272. else: result = newStrNodeT("true", n, g)
  273. of mFloatToStr: result = newStrNodeT($getFloat(a), n, g)
  274. of mCStrToStr, mCharToStr:
  275. result = newStrNodeT(getStrOrChar(a), n, g)
  276. of mStrToStr: result = newStrNodeT(getStrOrChar(a), n, g)
  277. of mEnumToStr: result = newStrNodeT(ordinalValToString(a, g), n, g)
  278. of mArrToSeq:
  279. result = copyTree(a)
  280. result.typ = n.typ
  281. of mCompileOption:
  282. result = newIntNodeT(toInt128(ord(commands.testCompileOption(g.config, a.getStr, n.info))), n, idgen, g)
  283. of mCompileOptionArg:
  284. result = newIntNodeT(toInt128(ord(
  285. testCompileOptionArg(g.config, getStr(a), getStr(b), n.info))), n, idgen, g)
  286. of mEqProc:
  287. result = newIntNodeT(toInt128(ord(
  288. exprStructuralEquivalent(a, b, strictSymEquality=true))), n, idgen, g)
  289. else: discard
  290. proc getConstIfExpr(c: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
  291. result = nil
  292. for i in 0..<n.len:
  293. var it = n[i]
  294. if it.len == 2:
  295. var e = getConstExpr(c, it[0], idgen, g)
  296. if e == nil: return nil
  297. if getOrdValue(e) != 0:
  298. if result == nil:
  299. result = getConstExpr(c, it[1], idgen, g)
  300. if result == nil: return
  301. elif it.len == 1:
  302. if result == nil: result = getConstExpr(c, it[0], idgen, g)
  303. else: internalError(g.config, it.info, "getConstIfExpr()")
  304. proc leValueConv*(a, b: PNode): bool =
  305. result = false
  306. case a.kind
  307. of nkCharLit..nkUInt64Lit:
  308. case b.kind
  309. of nkCharLit..nkUInt64Lit: result = a.getInt <= b.getInt
  310. of nkFloatLit..nkFloat128Lit: result = a.intVal <= round(b.floatVal).int
  311. else: result = false #internalError(a.info, "leValueConv")
  312. of nkFloatLit..nkFloat128Lit:
  313. case b.kind
  314. of nkFloatLit..nkFloat128Lit: result = a.floatVal <= b.floatVal
  315. of nkCharLit..nkUInt64Lit: result = a.floatVal <= toFloat64(b.getInt)
  316. else: result = false # internalError(a.info, "leValueConv")
  317. else: result = false # internalError(a.info, "leValueConv")
  318. proc magicCall(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
  319. if n.len <= 1: return
  320. var s = n[0].sym
  321. var a = getConstExpr(m, n[1], idgen, g)
  322. var b, c: PNode
  323. if a == nil: return
  324. if n.len > 2:
  325. b = getConstExpr(m, n[2], idgen, g)
  326. if b == nil: return
  327. if n.len > 3:
  328. c = getConstExpr(m, n[3], idgen, g)
  329. if c == nil: return
  330. result = evalOp(s.magic, n, a, b, c, idgen, g)
  331. proc getAppType(n: PNode; g: ModuleGraph): PNode =
  332. if g.config.globalOptions.contains(optGenDynLib):
  333. result = newStrNodeT("lib", n, g)
  334. elif g.config.globalOptions.contains(optGenStaticLib):
  335. result = newStrNodeT("staticlib", n, g)
  336. elif g.config.globalOptions.contains(optGenGuiApp):
  337. result = newStrNodeT("gui", n, g)
  338. else:
  339. result = newStrNodeT("console", n, g)
  340. proc rangeCheck(n: PNode, value: Int128; g: ModuleGraph) =
  341. if value < firstOrd(g.config, n.typ) or value > lastOrd(g.config, n.typ):
  342. localError(g.config, n.info, "cannot convert " & $value &
  343. " to " & typeToString(n.typ))
  344. proc foldConv(n, a: PNode; idgen: IdGenerator; g: ModuleGraph; check = false): PNode =
  345. let dstTyp = skipTypes(n.typ, abstractRange - {tyTypeDesc})
  346. let srcTyp = skipTypes(a.typ, abstractRange - {tyTypeDesc})
  347. # if srcTyp.kind == tyUInt64 and "FFFFFF" in $n:
  348. # echo "n: ", n, " a: ", a
  349. # echo "from: ", srcTyp, " to: ", dstTyp, " check: ", check
  350. # echo getInt(a)
  351. # echo high(int64)
  352. # writeStackTrace()
  353. case dstTyp.kind
  354. of tyBool:
  355. case srcTyp.kind
  356. of tyFloat..tyFloat64:
  357. result = newIntNodeT(toInt128(getFloat(a) != 0.0), n, idgen, g)
  358. of tyChar, tyUInt..tyUInt64, tyInt..tyInt64:
  359. result = newIntNodeT(toInt128(a.getOrdValue != 0), n, idgen, g)
  360. of tyBool, tyEnum: # xxx shouldn't we disallow `tyEnum`?
  361. result = a
  362. result.typ = n.typ
  363. else: doAssert false, $srcTyp.kind
  364. of tyInt..tyInt64, tyUInt..tyUInt64:
  365. case srcTyp.kind
  366. of tyFloat..tyFloat64:
  367. result = newIntNodeT(toInt128(getFloat(a)), n, idgen, g)
  368. of tyChar, tyUInt..tyUInt64, tyInt..tyInt64:
  369. var val = a.getOrdValue
  370. if check: rangeCheck(n, val, g)
  371. result = newIntNodeT(val, n, idgen, g)
  372. if dstTyp.kind in {tyUInt..tyUInt64}:
  373. result.transitionIntKind(nkUIntLit)
  374. else:
  375. result = a
  376. result.typ = n.typ
  377. if check and result.kind in {nkCharLit..nkUInt64Lit}:
  378. rangeCheck(n, getInt(result), g)
  379. of tyFloat..tyFloat64:
  380. case srcTyp.kind
  381. of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyBool, tyChar:
  382. result = newFloatNodeT(toFloat64(getOrdValue(a)), n, g)
  383. else:
  384. result = a
  385. result.typ = n.typ
  386. of tyOpenArray, tyVarargs, tyProc, tyPointer:
  387. discard
  388. else:
  389. result = a
  390. result.typ = n.typ
  391. proc getArrayConstr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
  392. if n.kind == nkBracket:
  393. result = n
  394. else:
  395. result = getConstExpr(m, n, idgen, g)
  396. if result == nil: result = n
  397. proc foldArrayAccess(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
  398. var x = getConstExpr(m, n[0], idgen, g)
  399. if x == nil or x.typ.skipTypes({tyGenericInst, tyAlias, tySink}).kind == tyTypeDesc:
  400. return
  401. var y = getConstExpr(m, n[1], idgen, g)
  402. if y == nil: return
  403. var idx = toInt64(getOrdValue(y))
  404. case x.kind
  405. of nkPar, nkTupleConstr:
  406. if idx >= 0 and idx < x.len:
  407. result = x.sons[idx]
  408. if result.kind == nkExprColonExpr: result = result[1]
  409. else:
  410. localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n)
  411. of nkBracket:
  412. idx -= toInt64(firstOrd(g.config, x.typ))
  413. if idx >= 0 and idx < x.len: result = x[int(idx)]
  414. else: localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n)
  415. of nkStrLit..nkTripleStrLit:
  416. result = newNodeIT(nkCharLit, x.info, n.typ)
  417. if idx >= 0 and idx < x.strVal.len:
  418. result.intVal = ord(x.strVal[int(idx)])
  419. else:
  420. localError(g.config, n.info, formatErrorIndexBound(idx, x.strVal.len-1) & $n)
  421. else: discard
  422. proc foldFieldAccess(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
  423. # a real field access; proc calls have already been transformed
  424. if n[1].kind != nkSym: return nil
  425. var x = getConstExpr(m, n[0], idgen, g)
  426. if x == nil or x.kind notin {nkObjConstr, nkPar, nkTupleConstr}: return
  427. var field = n[1].sym
  428. for i in ord(x.kind == nkObjConstr)..<x.len:
  429. var it = x[i]
  430. if it.kind != nkExprColonExpr:
  431. # lookup per index:
  432. result = x[field.position]
  433. if result.kind == nkExprColonExpr: result = result[1]
  434. return
  435. if it[0].sym.name.id == field.name.id:
  436. result = x[i][1]
  437. return
  438. localError(g.config, n.info, "field not found: " & field.name.s)
  439. proc foldConStrStr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
  440. result = newNodeIT(nkStrLit, n.info, n.typ)
  441. result.strVal = ""
  442. for i in 1..<n.len:
  443. let a = getConstExpr(m, n[i], idgen, g)
  444. if a == nil: return nil
  445. result.strVal.add(getStrOrChar(a))
  446. proc newSymNodeTypeDesc*(s: PSym; idgen: IdGenerator; info: TLineInfo): PNode =
  447. result = newSymNode(s, info)
  448. if s.typ.kind != tyTypeDesc:
  449. result.typ = newType(tyTypeDesc, idgen.nextTypeId, s.owner)
  450. result.typ.addSonSkipIntLit(s.typ, idgen)
  451. else:
  452. result.typ = s.typ
  453. proc getConstExpr(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode =
  454. result = nil
  455. case n.kind
  456. of nkSym:
  457. var s = n.sym
  458. case s.kind
  459. of skEnumField:
  460. result = newIntNodeT(toInt128(s.position), n, idgen, g)
  461. of skConst:
  462. case s.magic
  463. of mIsMainModule: result = newIntNodeT(toInt128(ord(sfMainModule in m.flags)), n, idgen, g)
  464. of mCompileDate: result = newStrNodeT(getDateStr(), n, g)
  465. of mCompileTime: result = newStrNodeT(getClockStr(), n, g)
  466. of mCpuEndian: result = newIntNodeT(toInt128(ord(CPU[g.config.target.targetCPU].endian)), n, idgen, g)
  467. of mHostOS: result = newStrNodeT(toLowerAscii(platform.OS[g.config.target.targetOS].name), n, g)
  468. of mHostCPU: result = newStrNodeT(platform.CPU[g.config.target.targetCPU].name.toLowerAscii, n, g)
  469. of mBuildOS: result = newStrNodeT(toLowerAscii(platform.OS[g.config.target.hostOS].name), n, g)
  470. of mBuildCPU: result = newStrNodeT(platform.CPU[g.config.target.hostCPU].name.toLowerAscii, n, g)
  471. of mAppType: result = getAppType(n, g)
  472. of mIntDefine:
  473. if isDefined(g.config, s.name.s):
  474. try:
  475. result = newIntNodeT(toInt128(g.config.symbols[s.name.s].parseInt), n, idgen, g)
  476. except ValueError:
  477. localError(g.config, s.info,
  478. "{.intdefine.} const was set to an invalid integer: '" &
  479. g.config.symbols[s.name.s] & "'")
  480. else:
  481. result = copyTree(s.astdef)
  482. of mStrDefine:
  483. if isDefined(g.config, s.name.s):
  484. result = newStrNodeT(g.config.symbols[s.name.s], n, g)
  485. else:
  486. result = copyTree(s.astdef)
  487. of mBoolDefine:
  488. if isDefined(g.config, s.name.s):
  489. try:
  490. result = newIntNodeT(toInt128(g.config.symbols[s.name.s].parseBool.int), n, idgen, g)
  491. except ValueError:
  492. localError(g.config, s.info,
  493. "{.booldefine.} const was set to an invalid bool: '" &
  494. g.config.symbols[s.name.s] & "'")
  495. else:
  496. result = copyTree(s.astdef)
  497. else:
  498. result = copyTree(s.astdef)
  499. of skProc, skFunc, skMethod:
  500. result = n
  501. of skParam:
  502. if s.typ != nil and s.typ.kind == tyTypeDesc:
  503. result = newSymNodeTypeDesc(s, idgen, n.info)
  504. of skType:
  505. # XXX gensym'ed symbols can come here and cannot be resolved. This is
  506. # dirty, but correct.
  507. if s.typ != nil:
  508. result = newSymNodeTypeDesc(s, idgen, n.info)
  509. of skGenericParam:
  510. if s.typ.kind == tyStatic:
  511. if s.typ.n != nil and tfUnresolved notin s.typ.flags:
  512. result = s.typ.n
  513. result.typ = s.typ.base
  514. elif s.typ.isIntLit:
  515. result = s.typ.n
  516. else:
  517. result = newSymNodeTypeDesc(s, idgen, n.info)
  518. else: discard
  519. of nkCharLit..nkNilLit:
  520. result = copyNode(n)
  521. of nkIfExpr:
  522. result = getConstIfExpr(m, n, idgen, g)
  523. of nkCallKinds:
  524. if n[0].kind != nkSym: return
  525. var s = n[0].sym
  526. if s.kind != skProc and s.kind != skFunc: return
  527. try:
  528. case s.magic
  529. of mNone:
  530. # If it has no sideEffect, it should be evaluated. But not here.
  531. return
  532. of mLow:
  533. if skipTypes(n[1].typ, abstractVarRange).kind in tyFloat..tyFloat64:
  534. result = newFloatNodeT(firstFloat(n[1].typ), n, g)
  535. else:
  536. result = newIntNodeT(firstOrd(g.config, n[1].typ), n, idgen, g)
  537. of mHigh:
  538. if skipTypes(n[1].typ, abstractVar+{tyUserTypeClassInst}).kind notin
  539. {tySequence, tyString, tyCstring, tyOpenArray, tyVarargs}:
  540. if skipTypes(n[1].typ, abstractVarRange).kind in tyFloat..tyFloat64:
  541. result = newFloatNodeT(lastFloat(n[1].typ), n, g)
  542. else:
  543. result = newIntNodeT(lastOrd(g.config, skipTypes(n[1].typ, abstractVar)), n, idgen, g)
  544. else:
  545. var a = getArrayConstr(m, n[1], idgen, g)
  546. if a.kind == nkBracket:
  547. # we can optimize it away:
  548. result = newIntNodeT(toInt128(a.len-1), n, idgen, g)
  549. of mLengthOpenArray:
  550. var a = getArrayConstr(m, n[1], idgen, g)
  551. if a.kind == nkBracket:
  552. # we can optimize it away! This fixes the bug ``len(134)``.
  553. result = newIntNodeT(toInt128(a.len), n, idgen, g)
  554. else:
  555. result = magicCall(m, n, idgen, g)
  556. of mLengthArray:
  557. # It doesn't matter if the argument is const or not for mLengthArray.
  558. # This fixes bug #544.
  559. result = newIntNodeT(lengthOrd(g.config, n[1].typ), n, idgen, g)
  560. of mSizeOf:
  561. result = foldSizeOf(g.config, n, nil)
  562. of mAlignOf:
  563. result = foldAlignOf(g.config, n, nil)
  564. of mOffsetOf:
  565. result = foldOffsetOf(g.config, n, nil)
  566. of mAstToStr:
  567. result = newStrNodeT(renderTree(n[1], {renderNoComments}), n, g)
  568. of mConStrStr:
  569. result = foldConStrStr(m, n, idgen, g)
  570. of mIs:
  571. # The only kind of mIs node that comes here is one depending on some
  572. # generic parameter and that's (hopefully) handled at instantiation time
  573. discard
  574. else:
  575. result = magicCall(m, n, idgen, g)
  576. except OverflowDefect:
  577. localError(g.config, n.info, "over- or underflow")
  578. except DivByZeroDefect:
  579. localError(g.config, n.info, "division by zero")
  580. of nkAddr:
  581. var a = getConstExpr(m, n[0], idgen, g)
  582. if a != nil:
  583. result = n
  584. n[0] = a
  585. of nkBracket, nkCurly:
  586. result = copyNode(n)
  587. for i, son in n.pairs:
  588. var a = getConstExpr(m, son, idgen, g)
  589. if a == nil: return nil
  590. result.add a
  591. incl(result.flags, nfAllConst)
  592. of nkRange:
  593. var a = getConstExpr(m, n[0], idgen, g)
  594. if a == nil: return
  595. var b = getConstExpr(m, n[1], idgen, g)
  596. if b == nil: return
  597. result = copyNode(n)
  598. result.add a
  599. result.add b
  600. #of nkObjConstr:
  601. # result = copyTree(n)
  602. # for i in 1..<n.len:
  603. # var a = getConstExpr(m, n[i][1])
  604. # if a == nil: return nil
  605. # result[i][1] = a
  606. # incl(result.flags, nfAllConst)
  607. of nkPar, nkTupleConstr:
  608. # tuple constructor
  609. result = copyNode(n)
  610. if (n.len > 0) and (n[0].kind == nkExprColonExpr):
  611. for i, expr in n.pairs:
  612. let exprNew = copyNode(expr) # nkExprColonExpr
  613. exprNew.add expr[0]
  614. let a = getConstExpr(m, expr[1], idgen, g)
  615. if a == nil: return nil
  616. exprNew.add a
  617. result.add exprNew
  618. else:
  619. for i, expr in n.pairs:
  620. let a = getConstExpr(m, expr, idgen, g)
  621. if a == nil: return nil
  622. result.add a
  623. incl(result.flags, nfAllConst)
  624. of nkChckRangeF, nkChckRange64, nkChckRange:
  625. var a = getConstExpr(m, n[0], idgen, g)
  626. if a == nil: return
  627. if leValueConv(n[1], a) and leValueConv(a, n[2]):
  628. result = a # a <= x and x <= b
  629. result.typ = n.typ
  630. else:
  631. localError(g.config, n.info,
  632. "conversion from $1 to $2 is invalid" %
  633. [typeToString(n[0].typ), typeToString(n.typ)])
  634. of nkStringToCString, nkCStringToString:
  635. var a = getConstExpr(m, n[0], idgen, g)
  636. if a == nil: return
  637. result = a
  638. result.typ = n.typ
  639. of nkHiddenStdConv, nkHiddenSubConv, nkConv:
  640. var a = getConstExpr(m, n[1], idgen, g)
  641. if a == nil: return
  642. result = foldConv(n, a, idgen, g, check=true)
  643. of nkDerefExpr, nkHiddenDeref:
  644. let a = getConstExpr(m, n[0], idgen, g)
  645. if a != nil and a.kind == nkNilLit:
  646. result = nil
  647. #localError(g.config, n.info, "nil dereference is not allowed")
  648. of nkCast:
  649. var a = getConstExpr(m, n[1], idgen, g)
  650. if a == nil: return
  651. if n.typ != nil and n.typ.kind in NilableTypes:
  652. # we allow compile-time 'cast' for pointer types:
  653. result = a
  654. result.typ = n.typ
  655. of nkBracketExpr: result = foldArrayAccess(m, n, idgen, g)
  656. of nkDotExpr: result = foldFieldAccess(m, n, idgen, g)
  657. of nkCheckedFieldExpr:
  658. assert n[0].kind == nkDotExpr
  659. result = foldFieldAccess(m, n[0], idgen, g)
  660. of nkStmtListExpr:
  661. var i = 0
  662. while i <= n.len - 2:
  663. if n[i].kind in {nkComesFrom, nkCommentStmt, nkEmpty}: i.inc
  664. else: break
  665. if i == n.len - 1:
  666. result = getConstExpr(m, n[i], idgen, g)
  667. else:
  668. discard