nir.nim 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2023 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. ## Nim Intermediate Representation, designed to capture all of Nim's semantics without losing too much
  10. ## precious information. Can easily be translated into C. And to JavaScript, hopefully.
  11. from std/os import addFileExt, `/`, createDir
  12. import std / assertions
  13. import ".." / [ast, modulegraphs, renderer, transf, options, msgs, lineinfos]
  14. import nirtypes, nirinsts, ast2ir, nirlineinfos, nirfiles, nirvm
  15. import ".." / ic / [rodfiles, bitabs]
  16. type
  17. PCtx* = ref object of TPassContext
  18. m: ModuleCon
  19. c: ProcCon
  20. oldErrorCount: int
  21. bytecode: Bytecode
  22. proc newCtx*(module: PSym; g: ModuleGraph; idgen: IdGenerator): PCtx =
  23. var lit = Literals()
  24. var nirm = (ref NirModule)(types: initTypeGraph(lit), lit: lit)
  25. var m = initModuleCon(g, g.config, idgen, module, nirm)
  26. m.noModularity = true
  27. PCtx(m: m, c: initProcCon(m, nil, g.config), idgen: idgen, bytecode: initBytecode(nirm))
  28. proc refresh*(c: PCtx; module: PSym; idgen: IdGenerator) =
  29. #c.m = initModuleCon(c.m.graph, c.m.graph.config, idgen, module, c.m.nirm)
  30. #c.m.noModularity = true
  31. c.c = initProcCon(c.m, nil, c.m.graph.config)
  32. c.idgen = idgen
  33. proc setupGlobalCtx*(module: PSym; graph: ModuleGraph; idgen: IdGenerator) =
  34. if graph.repl.isNil:
  35. graph.repl = newCtx(module, graph, idgen)
  36. #registerAdditionalOps(PCtx graph.repl)
  37. else:
  38. refresh(PCtx graph.repl, module, idgen)
  39. proc setupNirReplGen*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
  40. setupGlobalCtx(module, graph, idgen)
  41. result = PCtx graph.repl
  42. proc evalStmt(c: PCtx; n: PNode) =
  43. let n = transformExpr(c.m.graph, c.idgen, c.m.module, n)
  44. let pc = genStmt(c.c, n)
  45. #var res = ""
  46. #toString c.m.nirm.code, NodePos(pc), c.m.nirm.lit.strings, c.m.nirm.lit.numbers, c.m.symnames, res
  47. #res.add "\n--------------------------\n"
  48. #toString res, c.m.types.g
  49. if pc.int < c.m.nirm.code.len:
  50. c.bytecode.interactive = c.m.graph.interactive
  51. execCode c.bytecode, c.m.nirm.code, pc
  52. #echo res
  53. proc runCode*(c: PPassContext; n: PNode): PNode =
  54. let c = PCtx(c)
  55. # don't eval errornous code:
  56. if c.oldErrorCount == c.m.graph.config.errorCounter:
  57. evalStmt(c, n)
  58. result = newNodeI(nkEmpty, n.info)
  59. else:
  60. result = n
  61. c.oldErrorCount = c.m.graph.config.errorCounter
  62. type
  63. NirPassContext* = ref object of TPassContext
  64. m: ModuleCon
  65. c: ProcCon
  66. proc openNirBackend*(g: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
  67. var lit = Literals()
  68. var nirm = (ref NirModule)(types: initTypeGraph(lit), lit: lit)
  69. let m = initModuleCon(g, g.config, idgen, module, nirm)
  70. NirPassContext(m: m, c: initProcCon(m, nil, g.config), idgen: idgen)
  71. proc gen(c: NirPassContext; n: PNode) =
  72. let n = transformExpr(c.m.graph, c.idgen, c.m.module, n)
  73. let pc = genStmt(c.c, n)
  74. proc nirBackend*(c: PPassContext; n: PNode): PNode =
  75. gen(NirPassContext(c), n)
  76. result = n
  77. proc closeNirBackend*(c: PPassContext; finalNode: PNode) =
  78. discard nirBackend(c, finalNode)
  79. let c = NirPassContext(c)
  80. let nimcache = getNimcacheDir(c.c.config).string
  81. createDir nimcache
  82. let outp = nimcache / c.m.module.name.s.addFileExt("nir")
  83. #c.m.nirm.code = move c.c.code
  84. try:
  85. store c.m.nirm[], outp
  86. echo "created: ", outp
  87. except IOError:
  88. rawMessage(c.c.config, errFatal, "serialization failed: " & outp)