123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- # author: Ethosa
- ## It provides runtime scripts loader.
- import
- compiler / [
- astalgo, ast, vmdef, vm, options,
- modulegraphs, idents, modules,
- pathutils, llstream, passes, sem,
- condsyms
- ],
- exceptions,
- os
- type
- CompiledScript = ref object
- pctx*: PCtx
- graph*: ModuleGraph
- module*: PSym
- filename*: string
- var
- ident_cache = newIdentCache()
- cfg = newConfigRef()
- once:
- # Search .nimble/lib folder 👀
- cfg.libpath = AbsoluteDir(getHomeDir() / ".nimble" / "lib")
- cfg.searchPaths.add(cfg.libpath)
- cfg.searchPaths.add(AbsoluteDir($cfg.libpath / "pure"))
- # --- Convert default Nim types to PNode --- #
- converter toNode*(x: float): PNode = newFloatNode(nkFloatLit, x)
- converter toNode*(x: int): PNode = newIntNode(nkIntLit, x)
- converter toNode*(x: string): PNode = newStrNode(nkStrLit, x)
- converter toNode*(x: bool): PNode = x.ord.toNode()
- converter toNode*(x: enum): PNode = x.ord.toNode()
- converter toNode*(x: openarray[int|float|string|bool|enum]): PNode =
- result = newNode(nkBracket)
- result.sons.initialize(x.len)
- for i in x.low..x.high:
- result[i] = x[i].toNode()
- converter toNode*(x: tuple | object): PNode =
- result = newTree(nkPar)
- for field in x.fields:
- result.sons.add(field.toNode())
- converter toNode*(x: ref tuple | ref object): PNode =
- result = newTree(nkPar)
- if x.isNil():
- return result
- for field in x.fields:
- result.sons.add(field.toNode())
- proc setupModule(self: CompiledScript) =
- self.graph.connectCallbacks()
- initDefines(cfg.symbols)
- defineSymbol(cfg.symbols, "nimscript")
- defineSymbol(cfg.symbols, "nimconfig")
- self.graph.registerPass(semPass)
- self.graph.registerPass(evalPass)
- proc cleanupModule(self: CompiledScript) =
- initDefines(cfg.symbols)
- undefSymbol(cfg.symbols, "nimscript")
- undefSymbol(cfg.symbols, "nimconfig")
- clearPasses(self.graph)
- proc compileScript*(file: string): CompiledScript =
- ## Compiles script with std module.
- new result
- result.filename = file
- result.graph = newModuleGraph(ident_cache, cfg)
- result.setupModule()
- result.module = makeModule(result.graph, file)
- # Create context
- incl(result.module.flags, sfMainModule)
- result.pctx = newCtx(result.module, identCache, result.graph)
- result.pctx.mode = emRepl
- # Setup context
- setupGlobalCtx(result.module, result.graph)
- registerAdditionalOps(result.pctx)
- # Compile std
- compileSystemModule(result.graph)
- # Compile module
- if not processModule(result.graph, result.module, llStreamOpen(AbsoluteFile(file), fmRead)):
- raise newException(VMError, "Failed to process `" & file & "`")
- # Cleanup
- setupGlobalCtx(nil, result.graph)
- result.cleanupModule()
- proc getProc*(self: CompiledScript, routine: string): PSym =
- strTableGet(self.module.tab, getIdent(identCache, routine))
- proc hasProc*(self: CompiledScript, routine: string): bool =
- ## Returns true, if `routine` available.
- not self.getProc(routine).isNil()
- proc call*(self: CompiledScript, routine: string,
- args: varargs[PNode]): PNode {.discardable.} =
- ## Calls routine by name
- # Setup context
- setupGlobalCtx(self.module, self.graph)
- # Find routine
- let prc = self.getProc(routine)
- if prc.isNil():
- raise newException(VMError, "\nUnable to locate proc `" & routine & "` in `" & self.filename & "`")
- # Call routine
- result = execProc(self.pctx, prc, args)
|