semfold.nim 31 KB

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