mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-29 01:14:41 +00:00
284 lines
8.4 KiB
Nim
284 lines
8.4 KiB
Nim
#
|
|
#
|
|
# The Nim Compiler
|
|
# (c) Copyright 2015 Andreas Rumpf
|
|
#
|
|
# See the file "copying.txt", included in this
|
|
# distribution, for details about the copyright.
|
|
#
|
|
|
|
# implements the command dispatcher and several commands
|
|
|
|
import
|
|
llstream, strutils, ast, astalgo, lexer, syntaxes, renderer, options, msgs,
|
|
os, condsyms, rodread, rodwrite, times,
|
|
wordrecg, sem, semdata, idents, passes, docgen, extccomp,
|
|
cgen, jsgen, json, nversion,
|
|
platform, nimconf, importer, passaux, depends, vm, vmdef, types, idgen,
|
|
docgen2, service, parser, modules, ccgutils, sigmatch, ropes, lists,
|
|
modulegraphs
|
|
|
|
from magicsys import systemModule, resetSysTypes
|
|
|
|
proc rodPass =
|
|
if optSymbolFiles in gGlobalOptions:
|
|
registerPass(rodwritePass)
|
|
|
|
proc codegenPass =
|
|
registerPass cgenPass
|
|
|
|
proc semanticPasses =
|
|
registerPass verbosePass
|
|
registerPass semPass
|
|
|
|
proc commandGenDepend(graph: ModuleGraph; cache: IdentCache) =
|
|
semanticPasses()
|
|
registerPass(gendependPass)
|
|
registerPass(cleanupPass)
|
|
compileProject(graph, cache)
|
|
generateDot(gProjectFull)
|
|
execExternalProgram("dot -Tpng -o" & changeFileExt(gProjectFull, "png") &
|
|
' ' & changeFileExt(gProjectFull, "dot"))
|
|
|
|
proc commandCheck(graph: ModuleGraph; cache: IdentCache) =
|
|
msgs.gErrorMax = high(int) # do not stop after first error
|
|
defineSymbol("nimcheck")
|
|
semanticPasses() # use an empty backend for semantic checking only
|
|
rodPass()
|
|
compileProject(graph, cache)
|
|
|
|
proc commandDoc2(graph: ModuleGraph; cache: IdentCache; json: bool) =
|
|
msgs.gErrorMax = high(int) # do not stop after first error
|
|
semanticPasses()
|
|
if json: registerPass(docgen2JsonPass)
|
|
else: registerPass(docgen2Pass)
|
|
#registerPass(cleanupPass())
|
|
compileProject(graph, cache)
|
|
finishDoc2Pass(gProjectName)
|
|
|
|
proc commandCompileToC(graph: ModuleGraph; cache: IdentCache) =
|
|
extccomp.initVars()
|
|
semanticPasses()
|
|
registerPass(cgenPass)
|
|
rodPass()
|
|
#registerPass(cleanupPass())
|
|
|
|
compileProject(graph, cache)
|
|
cgenWriteModules(graph.backend)
|
|
if gCmd != cmdRun:
|
|
extccomp.callCCompiler(changeFileExt(gProjectFull, ""))
|
|
|
|
proc commandCompileToJS(graph: ModuleGraph; cache: IdentCache) =
|
|
#incl(gGlobalOptions, optSafeCode)
|
|
setTarget(osJS, cpuJS)
|
|
#initDefines()
|
|
defineSymbol("nimrod") # 'nimrod' is always defined
|
|
defineSymbol("ecmascript") # For backward compatibility
|
|
defineSymbol("js")
|
|
if gCmd == cmdCompileToPHP: defineSymbol("nimphp")
|
|
semanticPasses()
|
|
registerPass(JSgenPass)
|
|
compileProject(graph, cache)
|
|
|
|
proc interactivePasses(graph: ModuleGraph; cache: IdentCache) =
|
|
#incl(gGlobalOptions, optSafeCode)
|
|
#setTarget(osNimrodVM, cpuNimrodVM)
|
|
initDefines()
|
|
defineSymbol("nimscript")
|
|
when hasFFI: defineSymbol("nimffi")
|
|
registerPass(verbosePass)
|
|
registerPass(semPass)
|
|
registerPass(evalPass)
|
|
|
|
proc commandInteractive(graph: ModuleGraph; cache: IdentCache) =
|
|
msgs.gErrorMax = high(int) # do not stop after first error
|
|
interactivePasses(graph, cache)
|
|
compileSystemModule(graph, cache)
|
|
if commandArgs.len > 0:
|
|
discard graph.compileModule(fileInfoIdx(gProjectFull), cache, {})
|
|
else:
|
|
var m = graph.makeStdinModule()
|
|
incl(m.flags, sfMainModule)
|
|
processModule(graph, m, llStreamOpenStdIn(), nil, cache)
|
|
|
|
const evalPasses = [verbosePass, semPass, evalPass]
|
|
|
|
proc evalNim(graph: ModuleGraph; nodes: PNode, module: PSym; cache: IdentCache) =
|
|
carryPasses(graph, nodes, module, cache, evalPasses)
|
|
|
|
proc commandEval(graph: ModuleGraph; cache: IdentCache; exp: string) =
|
|
if systemModule == nil:
|
|
interactivePasses(graph, cache)
|
|
compileSystemModule(graph, cache)
|
|
let echoExp = "echo \"eval\\t\", " & "repr(" & exp & ")"
|
|
evalNim(graph, echoExp.parseString(cache), makeStdinModule(graph), cache)
|
|
|
|
proc commandScan(cache: IdentCache) =
|
|
var f = addFileExt(mainCommandArg(), NimExt)
|
|
var stream = llStreamOpen(f, fmRead)
|
|
if stream != nil:
|
|
var
|
|
L: TLexer
|
|
tok: TToken
|
|
initToken(tok)
|
|
openLexer(L, f, stream, cache)
|
|
while true:
|
|
rawGetTok(L, tok)
|
|
printTok(tok)
|
|
if tok.tokType == tkEof: break
|
|
closeLexer(L)
|
|
else:
|
|
rawMessage(errCannotOpenFile, f)
|
|
|
|
const
|
|
SimulateCaasMemReset = false
|
|
PrintRopeCacheStats = false
|
|
|
|
proc mainCommand*(graph: ModuleGraph; cache: IdentCache) =
|
|
when SimulateCaasMemReset:
|
|
gGlobalOptions.incl(optCaasEnabled)
|
|
|
|
# In "nim serve" scenario, each command must reset the registered passes
|
|
clearPasses()
|
|
gLastCmdTime = epochTime()
|
|
appendStr(searchPaths, options.libpath)
|
|
when false: # gProjectFull.len != 0:
|
|
# current path is always looked first for modules
|
|
prependStr(searchPaths, gProjectPath)
|
|
setId(100)
|
|
case command.normalize
|
|
of "c", "cc", "compile", "compiletoc":
|
|
# compile means compileToC currently
|
|
gCmd = cmdCompileToC
|
|
commandCompileToC(graph, cache)
|
|
of "cpp", "compiletocpp":
|
|
gCmd = cmdCompileToCpp
|
|
defineSymbol("cpp")
|
|
commandCompileToC(graph, cache)
|
|
of "objc", "compiletooc":
|
|
gCmd = cmdCompileToOC
|
|
defineSymbol("objc")
|
|
commandCompileToC(graph, cache)
|
|
of "run":
|
|
gCmd = cmdRun
|
|
when hasTinyCBackend:
|
|
extccomp.setCC("tcc")
|
|
commandCompileToC(graph, cache)
|
|
else:
|
|
rawMessage(errInvalidCommandX, command)
|
|
of "js", "compiletojs":
|
|
gCmd = cmdCompileToJS
|
|
commandCompileToJS(graph, cache)
|
|
of "php":
|
|
gCmd = cmdCompileToPHP
|
|
commandCompileToJS(graph, cache)
|
|
of "doc":
|
|
wantMainModule()
|
|
gCmd = cmdDoc
|
|
loadConfigs(DocConfig, cache)
|
|
commandDoc()
|
|
of "doc2":
|
|
gCmd = cmdDoc
|
|
loadConfigs(DocConfig, cache)
|
|
defineSymbol("nimdoc")
|
|
commandDoc2(graph, cache, false)
|
|
of "rst2html":
|
|
gCmd = cmdRst2html
|
|
loadConfigs(DocConfig, cache)
|
|
commandRst2Html()
|
|
of "rst2tex":
|
|
gCmd = cmdRst2tex
|
|
loadConfigs(DocTexConfig, cache)
|
|
commandRst2TeX()
|
|
of "jsondoc":
|
|
wantMainModule()
|
|
gCmd = cmdDoc
|
|
loadConfigs(DocConfig, cache)
|
|
wantMainModule()
|
|
defineSymbol("nimdoc")
|
|
commandJson()
|
|
of "jsondoc2":
|
|
gCmd = cmdDoc
|
|
loadConfigs(DocConfig, cache)
|
|
wantMainModule()
|
|
defineSymbol("nimdoc")
|
|
commandDoc2(graph, cache, true)
|
|
of "buildindex":
|
|
gCmd = cmdDoc
|
|
loadConfigs(DocConfig, cache)
|
|
commandBuildIndex()
|
|
of "gendepend":
|
|
gCmd = cmdGenDepend
|
|
commandGenDepend(graph, cache)
|
|
of "dump":
|
|
gCmd = cmdDump
|
|
if getConfigVar("dump.format") == "json":
|
|
wantMainModule()
|
|
|
|
var definedSymbols = newJArray()
|
|
for s in definedSymbolNames(): definedSymbols.elems.add(%s)
|
|
|
|
var libpaths = newJArray()
|
|
for dir in iterSearchPath(searchPaths): libpaths.elems.add(%dir)
|
|
|
|
var dumpdata = % [
|
|
(key: "version", val: %VersionAsString),
|
|
(key: "project_path", val: %gProjectFull),
|
|
(key: "defined_symbols", val: definedSymbols),
|
|
(key: "lib_paths", val: libpaths)
|
|
]
|
|
|
|
msgWriteln($dumpdata, {msgStdout, msgSkipHook})
|
|
else:
|
|
msgWriteln("-- list of currently defined symbols --",
|
|
{msgStdout, msgSkipHook})
|
|
for s in definedSymbolNames(): msgWriteln(s, {msgStdout, msgSkipHook})
|
|
msgWriteln("-- end of list --", {msgStdout, msgSkipHook})
|
|
|
|
for it in iterSearchPath(searchPaths): msgWriteln(it)
|
|
of "check":
|
|
gCmd = cmdCheck
|
|
commandCheck(graph, cache)
|
|
of "parse":
|
|
gCmd = cmdParse
|
|
wantMainModule()
|
|
discard parseFile(gProjectMainIdx, cache)
|
|
of "scan":
|
|
gCmd = cmdScan
|
|
wantMainModule()
|
|
commandScan(cache)
|
|
msgWriteln("Beware: Indentation tokens depend on the parser's state!")
|
|
of "secret":
|
|
gCmd = cmdInteractive
|
|
commandInteractive(graph, cache)
|
|
of "e":
|
|
commandEval(graph, cache, mainCommandArg())
|
|
of "nop", "help":
|
|
# prevent the "success" message:
|
|
gCmd = cmdDump
|
|
else:
|
|
rawMessage(errInvalidCommandX, command)
|
|
|
|
if msgs.gErrorCounter == 0 and
|
|
gCmd notin {cmdInterpret, cmdRun, cmdDump}:
|
|
rawMessage(hintSuccessX, [$gLinesCompiled,
|
|
formatFloat(epochTime() - gLastCmdTime, ffDecimal, 3),
|
|
formatSize(getTotalMem()),
|
|
if condSyms.isDefined("release"): "Release Build"
|
|
else: "Debug Build"])
|
|
|
|
when PrintRopeCacheStats:
|
|
echo "rope cache stats: "
|
|
echo " tries : ", gCacheTries
|
|
echo " misses: ", gCacheMisses
|
|
echo " int tries: ", gCacheIntTries
|
|
echo " efficiency: ", formatFloat(1-(gCacheMisses.float/gCacheTries.float),
|
|
ffDecimal, 3)
|
|
|
|
when SimulateCaasMemReset:
|
|
resetMemory()
|
|
|
|
resetAttributes()
|
|
|
|
proc mainCommand*() = mainCommand(newModuleGraph(), newIdentCache())
|