first steps for compiler as a service
This commit is contained in:
parent
b28fcdfa93
commit
9fbee85cc9
11 changed files with 142 additions and 40 deletions
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
71
compiler/service.nim
Normal file
71
compiler/service.nim
Normal file
|
|
@ -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()
|
||||
|
|
@ -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.} =
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue