mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
106 lines
3.4 KiB
Nim
106 lines
3.4 KiB
Nim
#
|
|
#
|
|
# The Nim Compiler
|
|
# (c) Copyright 2023 Andreas Rumpf
|
|
#
|
|
# See the file "copying.txt", included in this
|
|
# distribution, for details about the copyright.
|
|
#
|
|
|
|
## Nim Intermediate Representation, designed to capture all of Nim's semantics without losing too much
|
|
## precious information. Can easily be translated into C. And to JavaScript, hopefully.
|
|
|
|
from std/os import addFileExt, `/`, createDir
|
|
|
|
import std / assertions
|
|
import ".." / [ast, modulegraphs, renderer, transf, options, msgs, lineinfos]
|
|
import nirtypes, nirinsts, ast2ir, nirlineinfos, nirfiles, nirvm
|
|
|
|
import ".." / ic / [rodfiles, bitabs]
|
|
|
|
type
|
|
PCtx* = ref object of TPassContext
|
|
m: ModuleCon
|
|
c: ProcCon
|
|
oldErrorCount: int
|
|
bytecode: Bytecode
|
|
|
|
proc newCtx*(module: PSym; g: ModuleGraph; idgen: IdGenerator): PCtx =
|
|
var lit = Literals()
|
|
var nirm = (ref NirModule)(types: initTypeGraph(lit), lit: lit)
|
|
var m = initModuleCon(g, g.config, idgen, module, nirm)
|
|
m.noModularity = true
|
|
PCtx(m: m, c: initProcCon(m, nil, g.config), idgen: idgen, bytecode: initBytecode(nirm))
|
|
|
|
proc refresh*(c: PCtx; module: PSym; idgen: IdGenerator) =
|
|
#c.m = initModuleCon(c.m.graph, c.m.graph.config, idgen, module, c.m.nirm)
|
|
#c.m.noModularity = true
|
|
c.c = initProcCon(c.m, nil, c.m.graph.config)
|
|
c.idgen = idgen
|
|
|
|
proc setupGlobalCtx*(module: PSym; graph: ModuleGraph; idgen: IdGenerator) =
|
|
if graph.repl.isNil:
|
|
graph.repl = newCtx(module, graph, idgen)
|
|
#registerAdditionalOps(PCtx graph.repl)
|
|
else:
|
|
refresh(PCtx graph.repl, module, idgen)
|
|
|
|
proc setupNirReplGen*(graph: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
|
|
setupGlobalCtx(module, graph, idgen)
|
|
result = PCtx graph.repl
|
|
|
|
proc evalStmt(c: PCtx; n: PNode) =
|
|
let n = transformExpr(c.m.graph, c.idgen, c.m.module, n)
|
|
let pc = genStmt(c.c, n)
|
|
#var res = ""
|
|
#toString c.m.nirm.code, NodePos(pc), c.m.nirm.lit.strings, c.m.nirm.lit.numbers, c.m.symnames, res
|
|
#res.add "\n--------------------------\n"
|
|
#toString res, c.m.types.g
|
|
if pc.int < c.m.nirm.code.len:
|
|
c.bytecode.interactive = c.m.graph.interactive
|
|
execCode c.bytecode, c.m.nirm.code, pc
|
|
#echo res
|
|
|
|
proc runCode*(c: PPassContext; n: PNode): PNode =
|
|
let c = PCtx(c)
|
|
# don't eval errornous code:
|
|
if c.oldErrorCount == c.m.graph.config.errorCounter:
|
|
evalStmt(c, n)
|
|
result = newNodeI(nkEmpty, n.info)
|
|
else:
|
|
result = n
|
|
c.oldErrorCount = c.m.graph.config.errorCounter
|
|
|
|
type
|
|
NirPassContext* = ref object of TPassContext
|
|
m: ModuleCon
|
|
c: ProcCon
|
|
|
|
proc openNirBackend*(g: ModuleGraph; module: PSym; idgen: IdGenerator): PPassContext =
|
|
var lit = Literals()
|
|
var nirm = (ref NirModule)(types: initTypeGraph(lit), lit: lit)
|
|
let m = initModuleCon(g, g.config, idgen, module, nirm)
|
|
NirPassContext(m: m, c: initProcCon(m, nil, g.config), idgen: idgen)
|
|
|
|
proc gen(c: NirPassContext; n: PNode) =
|
|
let n = transformExpr(c.m.graph, c.idgen, c.m.module, n)
|
|
let pc = genStmt(c.c, n)
|
|
|
|
proc nirBackend*(c: PPassContext; n: PNode): PNode =
|
|
gen(NirPassContext(c), n)
|
|
result = n
|
|
|
|
proc closeNirBackend*(c: PPassContext; finalNode: PNode) =
|
|
discard nirBackend(c, finalNode)
|
|
|
|
let c = NirPassContext(c)
|
|
let nimcache = getNimcacheDir(c.c.config).string
|
|
createDir nimcache
|
|
let outp = nimcache / c.m.module.name.s.addFileExt("nir")
|
|
#c.m.nirm.code = move c.c.code
|
|
try:
|
|
store c.m.nirm[], outp
|
|
echo "created: ", outp
|
|
except IOError:
|
|
rawMessage(c.c.config, errFatal, "serialization failed: " & outp)
|