vmops.nim 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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. # Unfortunately this cannot be a module yet:
  10. #import vmdeps, vm
  11. from math import sqrt, ln, log10, log2, exp, round, arccos, arcsin,
  12. arctan, arctan2, cos, cosh, hypot, sinh, sin, tan, tanh, pow, trunc,
  13. floor, ceil, `mod`
  14. from os import getEnv, existsEnv, dirExists, fileExists, putEnv, walkDir, getAppFilename
  15. from md5 import getMD5
  16. from sighashes import symBodyDigest
  17. from times import cpuTime
  18. from hashes import hash
  19. template mathop(op) {.dirty.} =
  20. registerCallback(c, "stdlib.math." & astToStr(op), `op Wrapper`)
  21. template osop(op) {.dirty.} =
  22. registerCallback(c, "stdlib.os." & astToStr(op), `op Wrapper`)
  23. template timesop(op) {.dirty.} =
  24. registerCallback(c, "stdlib.times." & astToStr(op), `op Wrapper`)
  25. template systemop(op) {.dirty.} =
  26. registerCallback(c, "stdlib.system." & astToStr(op), `op Wrapper`)
  27. template ioop(op) {.dirty.} =
  28. registerCallback(c, "stdlib.io." & astToStr(op), `op Wrapper`)
  29. template macrosop(op) {.dirty.} =
  30. registerCallback(c, "stdlib.macros." & astToStr(op), `op Wrapper`)
  31. template md5op(op) {.dirty.} =
  32. registerCallback(c, "stdlib.md5." & astToStr(op), `op Wrapper`)
  33. template wrap1f_math(op) {.dirty.} =
  34. proc `op Wrapper`(a: VmArgs) {.nimcall.} =
  35. setResult(a, op(getFloat(a, 0)))
  36. mathop op
  37. template wrap2f_math(op) {.dirty.} =
  38. proc `op Wrapper`(a: VmArgs) {.nimcall.} =
  39. setResult(a, op(getFloat(a, 0), getFloat(a, 1)))
  40. mathop op
  41. template wrap0(op, modop) {.dirty.} =
  42. proc `op Wrapper`(a: VmArgs) {.nimcall.} =
  43. setResult(a, op())
  44. modop op
  45. template wrap1s(op, modop) {.dirty.} =
  46. proc `op Wrapper`(a: VmArgs) {.nimcall.} =
  47. setResult(a, op(getString(a, 0)))
  48. modop op
  49. template wrap2s(op, modop) {.dirty.} =
  50. proc `op Wrapper`(a: VmArgs) {.nimcall.} =
  51. setResult(a, op(getString(a, 0), getString(a, 1)))
  52. modop op
  53. template wrap2si(op, modop) {.dirty.} =
  54. proc `op Wrapper`(a: VmArgs) {.nimcall.} =
  55. setResult(a, op(getString(a, 0), getInt(a, 1)))
  56. modop op
  57. template wrap1svoid(op, modop) {.dirty.} =
  58. proc `op Wrapper`(a: VmArgs) {.nimcall.} =
  59. op(getString(a, 0))
  60. modop op
  61. template wrap2svoid(op, modop) {.dirty.} =
  62. proc `op Wrapper`(a: VmArgs) {.nimcall.} =
  63. op(getString(a, 0), getString(a, 1))
  64. modop op
  65. template wrapDangerous(op, modop) {.dirty.} =
  66. proc `op Wrapper`(a: VmArgs) {.nimcall.} =
  67. if defined(nimsuggest) or c.config.cmd == cmdCheck:
  68. discard
  69. else:
  70. op(getString(a, 0), getString(a, 1))
  71. modop op
  72. proc getCurrentExceptionMsgWrapper(a: VmArgs) {.nimcall.} =
  73. setResult(a, if a.currentException.isNil: ""
  74. else: a.currentException[3].skipColon.strVal)
  75. proc getCurrentExceptionWrapper(a: VmArgs) {.nimcall.} =
  76. setResult(a, a.currentException)
  77. proc staticWalkDirImpl(path: string, relative: bool): PNode =
  78. result = newNode(nkBracket)
  79. for k, f in walkDir(path, relative):
  80. result.add newTree(nkTupleConstr, newIntNode(nkIntLit, k.ord),
  81. newStrNode(nkStrLit, f))
  82. when defined(nimHasInvariant):
  83. from std / compilesettings import SingleValueSetting, MultipleValueSetting
  84. proc querySettingImpl(a: VmArgs, conf: ConfigRef, switch: BiggestInt): string =
  85. case SingleValueSetting(switch)
  86. of arguments: result = conf.arguments
  87. of outFile: result = conf.outFile.string
  88. of outDir: result = conf.outDir.string
  89. of nimcacheDir: result = conf.getNimcacheDir().string
  90. of projectName: result = conf.projectName
  91. of projectPath: result = conf.projectPath.string
  92. of projectFull: result = conf.projectFull.string
  93. of command: result = conf.command
  94. of commandLine: result = conf.commandLine
  95. of linkOptions: result = conf.linkOptions
  96. of compileOptions: result = conf.compileOptions
  97. of ccompilerPath: result = conf.cCompilerPath
  98. proc querySettingSeqImpl(a: VmArgs, conf: ConfigRef, switch: BiggestInt): seq[string] =
  99. template copySeq(field: untyped): untyped =
  100. for i in field: result.add i.string
  101. case MultipleValueSetting(switch)
  102. of nimblePaths: copySeq(conf.nimblePaths)
  103. of searchPaths: copySeq(conf.searchPaths)
  104. of lazyPaths: copySeq(conf.lazyPaths)
  105. of commandArgs: result = conf.commandArgs
  106. of cincludes: copySeq(conf.cIncludes)
  107. of clibs: copySeq(conf.cLibs)
  108. proc registerAdditionalOps*(c: PCtx) =
  109. proc gorgeExWrapper(a: VmArgs) =
  110. let (s, e) = opGorge(getString(a, 0), getString(a, 1), getString(a, 2),
  111. a.currentLineInfo, c.config)
  112. setResult a, newTree(nkTupleConstr, newStrNode(nkStrLit, s), newIntNode(nkIntLit, e))
  113. proc getProjectPathWrapper(a: VmArgs) =
  114. setResult a, c.config.projectPath.string
  115. wrap1f_math(sqrt)
  116. wrap1f_math(ln)
  117. wrap1f_math(log10)
  118. wrap1f_math(log2)
  119. wrap1f_math(exp)
  120. wrap1f_math(round)
  121. wrap1f_math(arccos)
  122. wrap1f_math(arcsin)
  123. wrap1f_math(arctan)
  124. wrap2f_math(arctan2)
  125. wrap1f_math(cos)
  126. wrap1f_math(cosh)
  127. wrap2f_math(hypot)
  128. wrap1f_math(sinh)
  129. wrap1f_math(sin)
  130. wrap1f_math(tan)
  131. wrap1f_math(tanh)
  132. wrap2f_math(pow)
  133. wrap1f_math(trunc)
  134. wrap1f_math(floor)
  135. wrap1f_math(ceil)
  136. wrap1s(getMD5, md5op)
  137. proc `mod Wrapper`(a: VmArgs) {.nimcall.} =
  138. setResult(a, `mod`(getFloat(a, 0), getFloat(a, 1)))
  139. registerCallback(c, "stdlib.math.mod", `mod Wrapper`)
  140. when defined(nimcore):
  141. wrap2s(getEnv, osop)
  142. wrap1s(existsEnv, osop)
  143. wrap2svoid(putEnv, osop)
  144. wrap1s(dirExists, osop)
  145. wrap1s(fileExists, osop)
  146. wrapDangerous(writeFile, ioop)
  147. wrap1s(readFile, ioop)
  148. wrap2si(readLines, ioop)
  149. systemop getCurrentExceptionMsg
  150. systemop getCurrentException
  151. registerCallback c, "stdlib.*.staticWalkDir", proc (a: VmArgs) {.nimcall.} =
  152. setResult(a, staticWalkDirImpl(getString(a, 0), getBool(a, 1)))
  153. when defined(nimHasInvariant):
  154. registerCallback c, "stdlib.compilesettings.querySetting", proc (a: VmArgs) {.nimcall.} =
  155. setResult(a, querySettingImpl(a, c.config, getInt(a, 0)))
  156. registerCallback c, "stdlib.compilesettings.querySettingSeq", proc (a: VmArgs) {.nimcall.} =
  157. setResult(a, querySettingSeqImpl(a, c.config, getInt(a, 0)))
  158. if defined(nimsuggest) or c.config.cmd == cmdCheck:
  159. discard "don't run staticExec for 'nim suggest'"
  160. else:
  161. systemop gorgeEx
  162. macrosop getProjectPath
  163. registerCallback c, "stdlib.os.getCurrentCompilerExe", proc (a: VmArgs) {.nimcall.} =
  164. setResult(a, getAppFilename())
  165. registerCallback c, "stdlib.macros.symBodyHash", proc (a: VmArgs) {.nimcall.} =
  166. let n = getNode(a, 0)
  167. if n.kind != nkSym:
  168. stackTrace(c, PStackFrame(prc: c.prc.sym, comesFrom: 0, next: nil), c.exceptionInstr,
  169. "symBodyHash() requires a symbol. '" & $n & "' is of kind '" & $n.kind & "'", n.info)
  170. setResult(a, $symBodyDigest(c.graph, n.sym))
  171. registerCallback c, "stdlib.macros.isExported", proc(a: VmArgs) {.nimcall.} =
  172. let n = getNode(a, 0)
  173. if n.kind != nkSym:
  174. stackTrace(c, PStackFrame(prc: c.prc.sym, comesFrom: 0, next: nil), c.exceptionInstr,
  175. "isExported() requires a symbol. '" & $n & "' is of kind '" & $n.kind & "'", n.info)
  176. setResult(a, sfExported in n.sym.flags)
  177. proc hashVmImpl(a: VmArgs) =
  178. var res = hashes.hash(a.getString(0), a.getInt(1).int, a.getInt(2).int)
  179. if c.config.cmd == cmdCompileToJS:
  180. # emulate JS's terrible integers:
  181. res = cast[int32](res)
  182. setResult(a, res)
  183. registerCallback c, "stdlib.hashes.hashVmImpl", hashVmImpl
  184. proc hashVmImplByte(a: VmArgs) =
  185. # nkBracket[...]
  186. let sPos = a.getInt(1).int
  187. let ePos = a.getInt(2).int
  188. let arr = a.getNode(0)
  189. var bytes = newSeq[byte](arr.len)
  190. for i in 0..<arr.len:
  191. bytes[i] = byte(arr[i].intVal and 0xff)
  192. var res = hashes.hash(bytes, sPos, ePos)
  193. if c.config.cmd == cmdCompileToJS:
  194. # emulate JS's terrible integers:
  195. res = cast[int32](res)
  196. setResult(a, res)
  197. registerCallback c, "stdlib.hashes.hashVmImplByte", hashVmImplByte
  198. registerCallback c, "stdlib.hashes.hashVmImplChar", hashVmImplByte
  199. if optBenchmarkVM in c.config.globalOptions:
  200. wrap0(cpuTime, timesop)
  201. else:
  202. proc cpuTime(): float = 5.391245e-44 # Randomly chosen
  203. wrap0(cpuTime, timesop)