diff options
author | Zahary Karadjov <zahary@gmail.com> | 2012-11-15 15:01:52 +0200 |
---|---|---|
committer | Zahary Karadjov <zahary@gmail.com> | 2012-11-28 01:15:13 +0200 |
commit | 091c1b30756a15c76ca09c0d95cfbb946aa9ea13 (patch) | |
tree | 18f876f9a6a5e998d08e9c6568c983747429c138 /compiler | |
parent | c43bf78000b21001726b31eb4259b90b3c91e03c (diff) | |
download | Nim-091c1b30756a15c76ca09c0d95cfbb946aa9ea13.tar.gz |
caas is now drivable through stdin
* added idetools --eval * streams.readLine recognises and applies the backspace character
Diffstat (limited to 'compiler')
-rwxr-xr-x | compiler/cgen.nim | 8 | ||||
-rwxr-xr-x | compiler/commands.nim | 3 | ||||
-rwxr-xr-x | compiler/depends.nim | 7 | ||||
-rw-r--r-- | compiler/docgen2.nim | 6 | ||||
-rwxr-xr-x | compiler/ecmasgen.nim | 8 | ||||
-rwxr-xr-x | compiler/evals.nim | 6 | ||||
-rwxr-xr-x | compiler/main.nim | 97 | ||||
-rwxr-xr-x | compiler/nimconf.nim | 19 | ||||
-rwxr-xr-x | compiler/nimrod.cfg | 13 | ||||
-rwxr-xr-x | compiler/options.nim | 2 | ||||
-rwxr-xr-x | compiler/passaux.nim | 11 | ||||
-rwxr-xr-x | compiler/passes.nim | 58 | ||||
-rwxr-xr-x | compiler/rodwrite.nim | 8 | ||||
-rwxr-xr-x | compiler/sem.nim | 9 | ||||
-rw-r--r-- | compiler/service.nim | 41 | ||||
-rwxr-xr-x | compiler/transf.nim | 8 |
16 files changed, 169 insertions, 135 deletions
diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 5bdbefde1..cf6af671e 100755 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -19,7 +19,6 @@ import when options.hasTinyCBackend: import tccgen -proc cgenPass*(): TPass # implementation var @@ -1157,10 +1156,5 @@ proc myClose(b: PPassContext, n: PNode): PNode = writeMapping(gMapping) if generatedHeader != nil: writeHeader(generatedHeader) -proc cgenPass(): TPass = - initPass(result) - result.open = myOpen - result.openCached = myOpenCached - result.process = myProcess - result.close = myClose +const cgenPass* = makePass(myOpen, myOpenCached, myProcess, myClose) diff --git a/compiler/commands.nim b/compiler/commands.nim index 50b4a1e6f..979da3db8 100755 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -458,6 +458,9 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) = of "def": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optDef) + of "eval": + expectArg(switch, arg, pass, info) + gEvalExpr = arg of "context": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optContext) diff --git a/compiler/depends.nim b/compiler/depends.nim index 4fde24ab4..f050c0993 100755 --- a/compiler/depends.nim +++ b/compiler/depends.nim @@ -12,7 +12,6 @@ import os, options, ast, astalgo, msgs, ropes, idents, passes, importer -proc genDependPass*(): TPass proc generateDot*(project: string) type @@ -55,7 +54,5 @@ proc myOpen(module: PSym, filename: string): PPassContext = g.filename = filename result = g -proc gendependPass(): TPass = - initPass(result) - result.open = myOpen - result.process = addDotDependency +const gendependPass* = makePass(open = myOpen, process = addDotDependency) + diff --git a/compiler/docgen2.nim b/compiler/docgen2.nim index 2d175adbf..6fa179e0f 100644 --- a/compiler/docgen2.nim +++ b/compiler/docgen2.nim @@ -45,11 +45,7 @@ proc myOpen(module: PSym, filename: string): PPassContext = g.doc = d result = g -proc docgen2Pass*(): TPass = - initPass(result) - result.open = myOpen - result.process = processNode - result.close = close +const docgen2Pass* = makePass(open = myOpen, process = processNode, close = close) proc finishDoc2Pass*(project: string) = nil diff --git a/compiler/ecmasgen.nim b/compiler/ecmasgen.nim index cff4cc1dd..d341a93be 100755 --- a/compiler/ecmasgen.nim +++ b/compiler/ecmasgen.nim @@ -17,7 +17,6 @@ import times, ropes, math, passes, ccgutils, wordrecg, renderer, rodread, rodutils, intsets, cgmeth -proc ecmasgenPass*(): TPass # implementation type @@ -1620,9 +1619,4 @@ proc myOpenCached(s: PSym, filename: string, rd: PRodReader): PPassContext = proc myOpen(s: PSym, filename: string): PPassContext = result = newModule(s, filename) -proc ecmasgenPass(): TPass = - InitPass(result) - result.open = myOpen - result.close = myClose - result.openCached = myOpenCached - result.process = myProcess +const ecmasgenPass* = makePass(myOpen, myOpenCached, myProcess, myClose) diff --git a/compiler/evals.nim b/compiler/evals.nim index 20d354aaf..f503922c2 100755 --- a/compiler/evals.nim +++ b/compiler/evals.nim @@ -1440,9 +1440,5 @@ proc myOpen(module: PSym, filename: string): PPassContext = proc myProcess(c: PPassContext, n: PNode): PNode = result = eval(PEvalContext(c), n) -proc evalPass*(): TPass = - initPass(result) - result.open = myOpen - result.close = myProcess - result.process = myProcess +const evalPass* = makePass(myOpen, nil, myProcess, myProcess) diff --git a/compiler/main.nim b/compiler/main.nim index dabd5309b..448efbd1d 100755 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -16,7 +16,7 @@ import wordrecg, sem, semdata, idents, passes, docgen, extccomp, cgen, ecmasgen, platform, nimconf, importer, passaux, depends, evals, types, idgen, - tables, docgen2, service + tables, docgen2, service, magicsys, parser const has_LLVM_Backend = false @@ -89,22 +89,30 @@ proc `==^`(a, b: string): bool = except EOS: result = false +proc compileSystemModule = + if magicsys.SystemModule == nil: + discard CompileModule(options.libpath /"system", {sfSystemModule}) + proc CompileProject(projectFile = gProjectFull) = let systemFile = options.libpath / "system" if projectFile.addFileExt(nimExt) ==^ systemFile.addFileExt(nimExt): discard CompileModule(projectFile, {sfMainModule, sfSystemModule}) else: - discard CompileModule(systemFile, {sfSystemModule}) + compileSystemModule() discard CompileModule(projectFile, {sfMainModule}) +proc rodPass = + if optSymbolFiles in gGlobalOptions: + registerPass(rodwritePass) + proc semanticPasses = - registerPass(verbosePass()) - registerPass(sem.semPass()) + registerPass verbosePass + registerPass semPass proc CommandGenDepend = semanticPasses() - registerPass(genDependPass()) - registerPass(cleanupPass()) + registerPass(genDependPass) + registerPass(cleanupPass) compileProject() generateDot(gProjectFull) execExternalProgram("dot -Tpng -o" & changeFileExt(gProjectFull, "png") & @@ -113,21 +121,21 @@ proc CommandGenDepend = proc CommandCheck = msgs.gErrorMax = high(int) # do not stop after first error semanticPasses() # use an empty backend for semantic checking only - registerPass(rodwrite.rodwritePass()) + rodPass() compileProject(mainCommandArg()) proc CommandDoc2 = msgs.gErrorMax = high(int) # do not stop after first error semanticPasses() - registerPass(docgen2Pass()) + registerPass(docgen2Pass) #registerPass(cleanupPass()) compileProject(mainCommandArg()) finishDoc2Pass(gProjectFull) proc CommandCompileToC = semanticPasses() - registerPass(cgen.cgenPass()) - registerPass(rodwrite.rodwritePass()) + registerPass(cgenPass) + rodPass() #registerPass(cleanupPass()) compileProject() if gCmd != cmdRun: @@ -137,7 +145,7 @@ when has_LLVM_Backend: proc CommandCompileToLLVM = semanticPasses() registerPass(llvmgen.llvmgenPass()) - registerPass(rodwrite.rodwritePass()) + rodPass() #registerPass(cleanupPass()) compileProject() @@ -148,27 +156,50 @@ proc CommandCompileToEcmaScript = DefineSymbol("nimrod") # 'nimrod' is always defined DefineSymbol("ecmascript") semanticPasses() - registerPass(ecmasgenPass()) + registerPass(ecmasgenPass) compileProject() -proc CommandInteractive = - msgs.gErrorMax = high(int) # do not stop after first error +proc InteractivePasses = incl(gGlobalOptions, optSafeCode) #setTarget(osNimrodVM, cpuNimrodVM) initDefines() DefineSymbol("nimrodvm") - registerPass(verbosePass()) - registerPass(sem.semPass()) - registerPass(evals.evalPass()) # load system module: - discard CompileModule(options.libpath /"system", {sfSystemModule}) + registerPass(verbosePass) + registerPass(semPass) + registerPass(evalPass) + +var stdinModule: PSym +proc makeStdinModule: PSym = + if stdinModule == nil: + stdinModule = newModule("stdin") + stdinModule.id = getID() + result = stdinModule + +proc CommandInteractive = + msgs.gErrorMax = high(int) # do not stop after first error + InteractivePasses() + compileSystemModule() if commandArgs.len > 0: discard CompileModule(mainCommandArg(), {}) else: - var m = newModule("stdin") - m.id = getID() + var m = makeStdinModule() incl(m.flags, sfMainModule) processModule(m, "stdin", LLStreamOpenStdIn(), nil) +const evalPasses = [verbosePass, semPass, evalPass] + +proc evalNim(nodes: PNode, module: PSym, filename: string) = + # we don't want to mess with gPasses here, because in nimrod serve + # scenario, it may be set up properly for normal cgenPass() compilation + carryPasses(nodes, module, filename, evalPasses) + +proc commandEval(exp: string) = + if SystemModule == nil: + InteractivePasses() + compileSystemModule() + var echoExp = "echo \"eval\\t\", " & "repr(" & exp & ")" + evalNim(echoExp.parseString, makeStdinModule(), "stdin") + proc CommandPretty = var module = parseFile(addFileExt(mainCommandArg(), NimExt)) if module != nil: @@ -194,7 +225,7 @@ proc CommandScan = proc CommandSuggest = msgs.gErrorMax = high(int) # do not stop after first error semanticPasses() - registerPass(rodwrite.rodwritePass()) + rodPass() compileProject() proc wantMainModule = @@ -202,6 +233,8 @@ proc wantMainModule = Fatal(gCmdLineInfo, errCommandExpectsFilename) proc MainCommand = + # In "nimrod serve" scenario, each command must reset the registered passes + clearPasses() appendStr(searchPaths, options.libpath) if gProjectFull.len != 0: # current path is always looked first for modules @@ -299,20 +332,20 @@ proc MainCommand = of "i": gCmd = cmdInteractive CommandInteractive() + of "e": + # XXX: temporary command for easier testing + commandEval(mainCommandArg()) of "idetools": gCmd = cmdIdeTools - wantMainModule() - CommandSuggest() + if gEvalExpr != "": + commandEval(gEvalExpr) + else: + wantMainModule() + CommandSuggest() of "serve": gCmd = cmdIdeTools - msgs.gErrorMax = high(int) # do not stop after first error - semanticPasses() - # no need to write rod files and would slow down things: - #registerPass(rodwrite.rodwritePass()) - discard CompileModule(options.libpath / "system", {sfSystemModule}) - service.serve(proc () = - let projectFile = mainCommandArg() - discard CompileModule(projectFile, {sfMainModule}) - ) + msgs.gErrorMax = high(int) # do not stop after first error + serve(MainCommand) + else: rawMessage(errInvalidCommandX, command) diff --git a/compiler/nimconf.nim b/compiler/nimconf.nim index f4f6d0a42..0f0b76827 100755 --- a/compiler/nimconf.nim +++ b/compiler/nimconf.nim @@ -235,15 +235,16 @@ proc LoadConfigs*(cfg: string) = if optSkipParentConfigFiles notin gGlobalOptions: for dir in parentDirs(pd, fromRoot=true, inclusive=false): readConfigFile(dir / cfg) - - if optSkipProjConfigFile notin gGlobalOptions and gProjectName.len != 0: + + if optSkipProjConfigFile notin gGlobalOptions: readConfigFile(pd / cfg) - var conffile = changeFileExt(gProjectFull, "cfg") - if conffile != pd / cfg and existsFile(conffile): - readConfigFile(conffile) - rawMessage(warnConfigDeprecated, conffile) - - # new project wide config file: - readConfigFile(changeFileExt(gProjectFull, "nimrod.cfg")) + if gProjectName.len != 0: + var conffile = changeFileExt(gProjectFull, "cfg") + if conffile != pd / cfg and existsFile(conffile): + readConfigFile(conffile) + rawMessage(warnConfigDeprecated, conffile) + + # new project wide config file: + readConfigFile(changeFileExt(gProjectFull, "nimrod.cfg")) diff --git a/compiler/nimrod.cfg b/compiler/nimrod.cfg index 42a5ed5f5..aa49729b9 100755 --- a/compiler/nimrod.cfg +++ b/compiler/nimrod.cfg @@ -1,9 +1,12 @@ # Special configuration file for the Nimrod project ---hint[XDeclaredButNotUsed]=off -path="llvm" -path="$projectPath/.." +mainModule:"nimrod.nim" -path="$nimrod/packages/docutils" +hint[XDeclaredButNotUsed]:off +path:"llvm" +path:"$projectPath/.." + +path:"$nimrod/packages/docutils" + +define:booting ---define:booting diff --git a/compiler/options.nim b/compiler/options.nim index 42fca1ad1..ba2a9eb41 100755 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -94,8 +94,8 @@ var gCmd*: TCommands = cmdNone # the command gVerbosity*: int # how verbose the compiler is gNumberOfProcessors*: int # number of processors - gWholeProject*: bool # for 'doc2': output any dependency + gEvalExpr*: string # expression for idetools --eval const genSubDir* = "nimcache" diff --git a/compiler/passaux.nim b/compiler/passaux.nim index 1ee6023c8..655b8ae68 100755 --- a/compiler/passaux.nim +++ b/compiler/passaux.nim @@ -26,10 +26,7 @@ proc verboseProcess(context: PPassContext, n: PNode): PNode = incl(msgs.gNotes, hintProcessing) Message(n.info, hintProcessing, $idgen.gBackendId) -proc verbosePass*(): TPass = - initPass(result) - result.open = verboseOpen - result.process = verboseProcess +const verbosePass* = makePass(open = verboseOpen, process = verboseProcess) proc cleanUp(c: PPassContext, n: PNode): PNode = result = n @@ -46,7 +43,5 @@ proc cleanUp(c: PPassContext, n: PNode): PNode = else: nil -proc cleanupPass*(): TPass = - initPass(result) - result.process = cleanUp - result.close = cleanUp +const cleanupPass* = makePass(process = cleanUp, close = cleanUp) + diff --git a/compiler/passes.nim b/compiler/passes.nim index 9b4a1b365..4941ac3b3 100755 --- a/compiler/passes.nim +++ b/compiler/passes.nim @@ -18,21 +18,34 @@ import type TPassContext* = object of TObject # the pass's context fromCache*: bool # true if created by "openCached" - + PPassContext* = ref TPassContext - TPass* = tuple[ - open: proc (module: PSym, filename: string): PPassContext {.nimcall.}, - openCached: proc (module: PSym, filename: string, - rd: PRodReader): PPassContext {.nimcall.}, - close: proc (p: PPassContext, n: PNode): PNode {.nimcall.}, - process: proc (p: PPassContext, topLevelStmt: PNode): PNode {.nimcall.}] - + + TPassOpen* = proc (module: PSym, filename: string): PPassContext {.nimcall.} + TPassOpenCached* = proc (module: PSym, filename: string, + rd: PRodReader): PPassContext {.nimcall.} + TPassClose* = proc (p: PPassContext, n: PNode): PNode {.nimcall.} + TPassProcess* = proc (p: PPassContext, topLevelStmt: PNode): PNode {.nimcall.} + + TPass* = tuple[open: TPassOpen, openCached: TPassOpenCached, + process: TPassProcess, close: TPassClose] + + TPassData* = tuple[input: PNode, closeOutput: Pnode] + TPasses* = openarray[TPass] + # a pass is a tuple of procedure vars ``TPass.close`` may produce additional # nodes. These are passed to the other close procedures. # This mechanism used to be used for the instantiation of generics. -proc registerPass*(p: TPass) -proc initPass*(p: var TPass) +proc makePass*(open: TPassOpen = nil, + openCached: TPassOpenCached = nil, + process: TPassProcess = nil, + close: TPassClose = nil): TPass = + result.open = open + result.openCached = openCached + result.close = close + result.process = process + # This implements a memory preserving scheme: Top level statements are # processed in a pipeline. The compiler never looks at a whole module # any longer. However, this is simple to change, as new passes may perform @@ -74,12 +87,28 @@ type var gPasses: array[0..maxPasses - 1, TPass] - gPassesLen: int + gPassesLen*: int + +proc clearPasses* = + gPassesLen = 0 -proc registerPass(p: TPass) = +proc registerPass*(p: TPass) = gPasses[gPassesLen] = p inc(gPassesLen) +proc carryPass*(p: TPass, module: PSym, filename: string, + m: TPassData): TPassData = + var c = p.open(module, filename) + result.input = p.process(c, m.input) + result.closeOutput = if p.close != nil: p.close(c, m.closeOutput) + else: m.closeOutput + +proc carryPasses*(nodes: PNode, module: PSym, file: string, passes: TPasses) = + var passdata: TPassData + passdata.input = nodes + for pass in passes: + passdata = carryPass(pass, module, file, passdata) + proc openPasses(a: var TPassContextArray, module: PSym, filename: string) = for i in countup(0, gPassesLen - 1): if not isNil(gPasses[i].open): @@ -175,8 +204,3 @@ proc processModule(module: PSym, filename: string, stream: PLLStream, for i in countup(0, sonsLen(n) - 1): processTopLevelStmtCached(n.sons[i], a) closePassesCached(a) -proc initPass(p: var TPass) = - p.open = nil - p.openCached = nil - p.close = nil - p.process = nil diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim index 5be9a2439..c89f06b37 100755 --- a/compiler/rodwrite.nim +++ b/compiler/rodwrite.nim @@ -15,7 +15,6 @@ import intsets, os, options, strutils, nversion, ast, astalgo, msgs, platform, condsyms, ropes, idents, crc, rodread, passes, importer, idgen, rodutils -proc rodwritePass*(): TPass # implementation type @@ -583,10 +582,5 @@ proc myClose(c: PPassContext, n: PNode): PNode = writeRod(w) idgen.saveMaxIds(options.gProjectPath / options.gProjectName) -proc rodwritePass(): TPass = - initPass(result) - if optSymbolFiles in gGlobalOptions: - result.open = myOpen - result.close = myClose - result.process = process +const rodwritePass* = makePass(open = myOpen, close = myClose, process = process) diff --git a/compiler/sem.nim b/compiler/sem.nim index 911eafb08..86d9bf872 100755 --- a/compiler/sem.nim +++ b/compiler/sem.nim @@ -17,7 +17,6 @@ import semthreads, intsets, transf, evals, idgen, aliases, cgmeth, lambdalifting, evaltempl, patterns, parampatterns, sempass2 -proc semPass*(): TPass # implementation type @@ -288,9 +287,5 @@ proc myClose(context: PPassContext, n: PNode): PNode = popOwner() popProcCon(c) -proc semPass(): TPass = - initPass(result) - result.open = myOpen - result.openCached = myOpenCached - result.close = myClose - result.process = myProcess +const semPass* = makePass(myOpen, myOpenCached, myProcess, myClose) + diff --git a/compiler/service.nim b/compiler/service.nim index b1741b7bd..2ed2b75f5 100644 --- a/compiler/service.nim +++ b/compiler/service.nim @@ -56,17 +56,30 @@ proc ProcessCmdLine*(pass: TCmdLinePass, cmd: string) = rawMessage(errArgsNeedRunOption, []) proc serve*(action: proc (){.nimcall.}) = - var server = Socket() - let p = getConfigVar("server.port") - let port = if p.len > 0: parseInt(p).TPort else: 6000.TPort - server.bindAddr(port, getConfigVar("server.address")) - var inp = "".TaintedString - server.listen() - new(stdoutSocket) - while true: - accept(server, stdoutSocket) - discard stdoutSocket.recvLine(inp) - processCmdLine(passCmd2, inp.string) - action() - stdoutSocket.send("\c\L") - stdoutSocket.close() + let typ = getConfigVar("server.type") + case typ + of "stdin": + while true: + var line = stdin.readLine.string + if line == "quit": quit() + processCmdLine(passCmd2, line) + action() + of "tcp", "": + var server = Socket() + let p = getConfigVar("server.port") + let port = if p.len > 0: parseInt(p).TPort else: 6000.TPort + server.bindAddr(port, getConfigVar("server.address")) + var inp = "".TaintedString + server.listen() + new(stdoutSocket) + while true: + accept(server, stdoutSocket) + discard stdoutSocket.recvLine(inp) + processCmdLine(passCmd2, inp.string) + action() + stdoutSocket.send("\c\L") + stdoutSocket.close() + else: + echo "Invalid server.type:", typ + quit 1 + diff --git a/compiler/transf.nim b/compiler/transf.nim index dfa4095b4..5ba997524 100755 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -696,12 +696,8 @@ when false: result = openTransf(module, filename) for m in items(rd.methods): methodDef(m, true) - proc transfPass(): TPass = - initPass(result) - result.open = openTransf - result.openCached = openTransfCached - result.process = processTransf - result.close = processTransf # we need to process generics too! + const transfPass* = makePass(openTransf, openTransfCached, + processTransf, processTransf) # we need to process generics too! proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode = if nfTransf in n.flags or prc.kind in {skTemplate, skMacro}: |