diff options
author | Araq <rumpf_a@web.de> | 2012-10-03 20:49:43 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-10-03 20:49:43 +0200 |
commit | 9fbee85cc9dd95c1f99e5b55a3d382196eabb7fc (patch) | |
tree | 5b38a0d41d876a4c35d979d09a4d3ba8ecd30722 /compiler | |
parent | b28fcdfa93ccf132b878e7dcd26e36d48f107212 (diff) | |
download | Nim-9fbee85cc9dd95c1f99e5b55a3d382196eabb7fc.tar.gz |
first steps for compiler as a service
Diffstat (limited to 'compiler')
-rwxr-xr-x | compiler/main.nim | 13 | ||||
-rw-r--r-- | compiler/service.nim | 71 | ||||
-rwxr-xr-x | compiler/suggest.nim | 21 |
3 files changed, 96 insertions, 9 deletions
diff --git a/compiler/main.nim b/compiler/main.nim index 37feabd17..dec393c50 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 + tables, docgen2, service const has_LLVM_Backend = false @@ -292,5 +292,16 @@ proc MainCommand = gCmd = cmdIdeTools 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 = gProjectFull + discard CompileModule(projectFile, {sfMainModule}) + ) else: rawMessage(errInvalidCommandX, command) diff --git a/compiler/service.nim b/compiler/service.nim new file mode 100644 index 000000000..95fb11022 --- /dev/null +++ b/compiler/service.nim @@ -0,0 +1,71 @@ +# +# +# The Nimrod Compiler +# (c) Copyright 2012 Andreas Rumpf +# +# See the file "copying.txt", included in this +# distribution, for details about the copyright. +# + +## Implements the "compiler as a service" feature. + +import + sockets, + times, commands, options, msgs, nimconf, + extccomp, strutils, os, platform, main, parseopt + +# We cache modules and the dependency graph. However, we don't check for +# file changes but expect the client to tell us about them, otherwise the +# repeated CRC calculations may turn out to be too slow. + +var + arguments: string = "" # the arguments to be passed to the program that + # should be run + +proc ProcessCmdLine(pass: TCmdLinePass, cmd: string) = + # XXX remove duplication with nimrod.nim + var p = parseopt.initOptParser(cmd) + var argsCount = 0 + while true: + parseopt.next(p) + case p.kind + of cmdEnd: break + of cmdLongOption, cmdShortOption: + # hint[X]:off is parsed as (p.key = "hint[X]", p.val = "off") + # we fix this here + var bracketLe = strutils.find(p.key, '[') + if bracketLe >= 0: + var key = substr(p.key, 0, bracketLe - 1) + var val = substr(p.key, bracketLe + 1) & ':' & p.val + ProcessSwitch(key, val, pass, gCmdLineInfo) + else: + ProcessSwitch(p.key, p.val, pass, gCmdLineInfo) + of cmdArgument: + if argsCount == 0: + options.command = p.key + else: + if pass == passCmd1: options.commandArgs.add p.key + if argsCount == 1: + # support UNIX style filenames anywhere for portable build scripts: + options.gProjectName = unixToNativePath(p.key) + arguments = cmdLineRest(p) + break + inc argsCount + + if pass == passCmd2: + if optRun notin gGlobalOptions and arguments != "": + 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() + while true: + var client = InvalidSocket + accept(server, client) + discard client.recvLine(inp) + processCmdLine(passCmd2, inp.string) + action() diff --git a/compiler/suggest.nim b/compiler/suggest.nim index daecf44b8..d33f9a7bd 100755 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -18,6 +18,11 @@ const sectionContext = "con" sectionUsage = "use" +proc SuggestWriteln(s: string) = + if gSilence == 0: + Writeln(stdout, s) + + proc SymToStr(s: PSym, isLocal: bool, section: string, li: TLineInfo): string = result = section result.add(sep) @@ -51,7 +56,7 @@ proc fieldVisible*(c: PContext, f: PSym): bool {.inline.} = proc suggestField(c: PContext, s: PSym, outputs: var int) = if filterSym(s) and fieldVisible(c, s): - OutWriteln(SymToStr(s, isLocal=true, sectionSuggest)) + SuggestWriteln(SymToStr(s, isLocal=true, sectionSuggest)) inc outputs when not defined(nimhygiene): @@ -62,7 +67,7 @@ template wholeSymTab(cond, section: expr) {.immediate.} = for item in items(c.tab.stack[i]): let it {.inject.} = item if cond: - OutWriteln(SymToStr(it, isLocal = i > ModuleTablePos, section)) + SuggestWriteln(SymToStr(it, isLocal = i > ModuleTablePos, section)) inc outputs proc suggestSymList(c: PContext, list: PNode, outputs: var int) = @@ -120,7 +125,7 @@ proc suggestEverything(c: PContext, n: PNode, outputs: var int) = for i in countdown(c.tab.tos-1, 1): for it in items(c.tab.stack[i]): if filterSym(it): - OutWriteln(SymToStr(it, isLocal = i > ModuleTablePos, sectionSuggest)) + SuggestWriteln(SymToStr(it, isLocal = i > ModuleTablePos, sectionSuggest)) inc outputs proc suggestFieldAccess(c: PContext, n: PNode, outputs: var int) = @@ -134,12 +139,12 @@ proc suggestFieldAccess(c: PContext, n: PNode, outputs: var int) = # all symbols accessible, because we are in the current module: for it in items(c.tab.stack[ModuleTablePos]): if filterSym(it): - OutWriteln(SymToStr(it, isLocal=false, sectionSuggest)) + SuggestWriteln(SymToStr(it, isLocal=false, sectionSuggest)) inc outputs else: for it in items(n.sym.tab): if filterSym(it): - OutWriteln(SymToStr(it, isLocal=false, sectionSuggest)) + SuggestWriteln(SymToStr(it, isLocal=false, sectionSuggest)) inc outputs else: # fallback: @@ -224,15 +229,15 @@ var proc findUsages(node: PNode, s: PSym) = if usageSym == nil and isTracked(node.info, s.name.s.len): usageSym = s - OutWriteln(SymToStr(s, isLocal=false, sectionUsage)) + SuggestWriteln(SymToStr(s, isLocal=false, sectionUsage)) elif s == usageSym: if lastLineInfo != node.info: - OutWriteln(SymToStr(s, isLocal=false, sectionUsage, node.info)) + SuggestWriteln(SymToStr(s, isLocal=false, sectionUsage, node.info)) lastLineInfo = node.info proc findDefinition(node: PNode, s: PSym) = if isTracked(node.info, s.name.s.len): - OutWriteln(SymToStr(s, isLocal=false, sectionDef)) + SuggestWriteln(SymToStr(s, isLocal=false, sectionDef)) quit(0) proc suggestSym*(n: PNode, s: PSym) {.inline.} = |