diff options
author | Araq <rumpf_a@web.de> | 2013-05-07 18:44:24 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2013-05-07 18:44:24 +0200 |
commit | 9fc98cefda91d7199e46d271a466a07867354d91 (patch) | |
tree | 4e8abce285ad9f5c145ec9f660966f88604ab422 | |
parent | d97504d6ef7ad6c30adc5cd64872f600fd4ec14d (diff) | |
parent | f0be93bfa2cb49ab88595478efb4457391d49a31 (diff) | |
download | Nim-9fc98cefda91d7199e46d271a466a07867354d91.tar.gz |
Merge branch 'master' into newparser
-rw-r--r-- | compiler/ast.nim | 3 | ||||
-rw-r--r-- | compiler/cgen.nim | 34 | ||||
-rw-r--r-- | compiler/commands.nim | 22 | ||||
-rw-r--r-- | compiler/extccomp.nim | 2 | ||||
-rw-r--r-- | compiler/main.nim | 57 | ||||
-rw-r--r-- | compiler/msgs.nim | 15 | ||||
-rw-r--r-- | compiler/options.nim | 6 | ||||
-rw-r--r-- | compiler/rodread.nim | 6 | ||||
-rw-r--r-- | compiler/rodwrite.nim | 3 | ||||
-rw-r--r-- | compiler/semstmts.nim | 3 | ||||
-rw-r--r-- | compiler/semtypes.nim | 3 | ||||
-rw-r--r-- | compiler/service.nim | 3 | ||||
-rw-r--r-- | compiler/sigmatch.nim | 9 | ||||
-rw-r--r-- | compiler/suggest.nim | 61 | ||||
-rw-r--r-- | tests/caas/compile-suggest.txt | 7 | ||||
-rw-r--r-- | tests/caas/def-def-compile.txt | 10 | ||||
-rw-r--r-- | tests/caas/main_dirty.nim | 14 | ||||
-rw-r--r-- | tests/caas/suggest-compile.txt | 7 |
18 files changed, 196 insertions, 69 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 523831c04..eb12c977f 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -275,6 +275,7 @@ const sfDirty* = sfPure # template is not hygienic (old styled template) + # module, compiled from a dirty-buffer sfAnon* = sfDiscardable # symbol name that was generated by the compiler @@ -680,7 +681,6 @@ type size*: BiggestInt # the size of the type in bytes # -1 means that the size is unkwown align*: int # the type's alignment requirements - containerID*: int # used for type checking of generics loc*: TLoc TPair*{.final.} = object @@ -1020,7 +1020,6 @@ proc assignType(dest, src: PType) = dest.n = src.n dest.size = src.size dest.align = src.align - dest.containerID = src.containerID dest.destructor = src.destructor # this fixes 'type TLock = TSysLock': if src.sym != nil: diff --git a/compiler/cgen.nim b/compiler/cgen.nim index f09252b48..f034f6675 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -1279,10 +1279,6 @@ proc updateCachedModule(m: BModule) = addFileToLink(cfilenoext) -proc updateCachedModules* = - for m in cgenModules(): - if m.fromCache: m.updateCachedModule - proc myClose(b: PPassContext, n: PNode): PNode = result = n if b == nil or passes.skipCodegen(n): return @@ -1292,24 +1288,28 @@ proc myClose(b: PPassContext, n: PNode): PNode = genStmts(m.initProc, n) # cached modules need to registered too: registerModuleToMain(m.module) - + if sfMainModule in m.module.flags: var disp = generateMethodDispatchers() for i in 0..sonsLen(disp)-1: genProcAux(m, disp.sons[i].sym) - genMainProc(m) - # we need to process the transitive closure because recursive module - # deps are allowed (and the system module is processed in the wrong - # order anyway) - if generatedHeader != nil: finishModule(generatedHeader) - while gForwardedProcsCounter > 0: - for m in cgenModules(): - if not m.fromCache: - finishModule(m) + genMainProc(m) + +proc cgenWriteModules* = + # we need to process the transitive closure because recursive module + # deps are allowed (and the system module is processed in the wrong + # order anyway) + if generatedHeader != nil: finishModule(generatedHeader) + while gForwardedProcsCounter > 0: for m in cgenModules(): if not m.fromCache: - writeModule(m, pending=true) - writeMapping(gMapping) - if generatedHeader != nil: writeHeader(generatedHeader) + finishModule(m) + for m in cgenModules(): + if m.fromCache: + m.updateCachedModule + else: + m.writeModule(pending=true) + writeMapping(gMapping) + if generatedHeader != nil: writeHeader(generatedHeader) const cgenPass* = makePass(myOpen, myOpenCached, myProcess, myClose) diff --git a/compiler/commands.nim b/compiler/commands.nim index 27da03bbe..63704b328 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -207,6 +207,22 @@ proc processPath(path: string, notRelativeToProj = false): string = "projectname", options.gProjectName, "projectpath", options.gProjectPath]) +proc trackDirty(arg: string, info: TLineInfo) = + var a = arg.split(',') + if a.len != 4: LocalError(info, errTokenExpected, + "DIRTY_BUFFER,ORIGINAL_FILE,LINE,COLUMN") + var line, column: int + if parseUtils.parseInt(a[2], line) <= 0: + LocalError(info, errInvalidNumber, a[1]) + if parseUtils.parseInt(a[3], column) <= 0: + LocalError(info, errInvalidNumber, a[2]) + + gDirtyBufferIdx = a[0].fileInfoIdx + gDirtyOriginalIdx = a[1].fileInfoIdx + + optTrackPos = newLineInfo(gDirtyBufferIdx, line, column) + msgs.addCheckpoint(optTrackPos) + proc track(arg: string, info: TLineInfo) = var a = arg.split(',') if a.len != 3: LocalError(info, errTokenExpected, "FILE,LINE,COLUMN") @@ -215,7 +231,8 @@ proc track(arg: string, info: TLineInfo) = LocalError(info, errInvalidNumber, a[1]) if parseUtils.parseInt(a[2], column) <= 0: LocalError(info, errInvalidNumber, a[2]) - msgs.addCheckpoint(newLineInfo(a[0], line, column)) + optTrackPos = newLineInfo(a[0], line, column) + msgs.addCheckpoint(optTrackPos) proc dynlibOverride(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) = if pass in {passCmd2, passPP}: @@ -469,6 +486,9 @@ proc processSwitch(switch, arg: string, pass: TCmdlinePass, info: TLineInfo) = of "track": expectArg(switch, arg, pass, info) track(arg, info) + of "trackdirty": + expectArg(switch, arg, pass, info) + trackDirty(arg, info) of "suggest": expectNoArg(switch, arg, pass, info) incl(gGlobalOptions, optSuggest) diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index 8107fcd82..44396100b 100644 --- a/compiler/extccomp.nim +++ b/compiler/extccomp.nim @@ -579,7 +579,7 @@ proc CallCCompiler*(projectfile: string) = else: rawMessage(errGenerated, " execution of an external program failed; " & "rerun with --parallelBuild:1 to see the error message") - if optNoLinking notin gGlobalOptions: + if optNoLinking notin gGlobalOptions and cmds.len > 0: # call the linker: var it = PStrEntry(toLink.head) var objfiles = "" diff --git a/compiler/main.nim b/compiler/main.nim index 46ef65e81..2ff7691d8 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -16,7 +16,7 @@ import wordrecg, sem, semdata, idents, passes, docgen, extccomp, cgen, jsgen, cgendata, json, nversion, platform, nimconf, importer, passaux, depends, evals, types, idgen, - tables, docgen2, service, magicsys, parser, crc, ccgutils + tables, docgen2, service, magicsys, parser, crc, ccgutils, sigmatch const has_LLVM_Backend = false @@ -64,7 +64,7 @@ proc crcChanged(fileIdx: int32): bool = gMemCacheData[fileIdx].crcStatus = if result: crcHasChanged else: crcNotChanged # echo "TESTING CRC: ", fileIdx.toFilename, " ", result - + case gMemCacheData[fileIdx].crcStatus: of crcHasChanged: result = true @@ -89,38 +89,38 @@ proc addDep(x: Psym, dep: int32) = growCache gMemCacheData, dep gMemCacheData[x.position].deps.safeAdd(dep) -proc ResetModule(fileIdx: int32) = - echo "HARD RESETTING ", fileIdx.toFilename +proc resetModule(fileIdx: int32) = + # echo "HARD RESETTING ", fileIdx.toFilename gMemCacheData[fileIdx].needsRecompile = Yes gCompiledModules[fileIdx] = nil cgendata.gModules[fileIdx] = nil + resetSourceMap(fileIdx) -proc ResetAllModules = +proc resetAllModules = for i in 0..gCompiledModules.high: if gCompiledModules[i] != nil: - ResetModule(i.int32) + resetModule(i.int32) - for m in cgenModules(): - echo "CGEN MODULE FOUND" + # for m in cgenModules(): echo "CGEN MODULE FOUND" proc checkDepMem(fileIdx: int32): TNeedRecompile = template markDirty = - ResetModule(fileIdx) + resetModule(fileIdx) return Yes if gMemCacheData[fileIdx].needsRecompile != Maybe: return gMemCacheData[fileIdx].needsRecompile if optForceFullMake in gGlobalOptions or - curCaasCmd != lastCaasCmd or - crcChanged(fileIdx): markDirty + crcChanged(fileIdx): + markDirty if gMemCacheData[fileIdx].deps != nil: gMemCacheData[fileIdx].needsRecompile = Probing for dep in gMemCacheData[fileIdx].deps: let d = checkDepMem(dep) if d in { Yes, Recompiled }: - echo fileIdx.toFilename, " depends on ", dep.toFilename, " ", d + # echo fileIdx.toFilename, " depends on ", dep.toFilename, " ", d markDirty gMemCacheData[fileIdx].needsRecompile = No @@ -213,6 +213,9 @@ proc rodPass = if optSymbolFiles in gGlobalOptions: registerPass(rodwritePass) +proc codegenPass = + registerPass cgenPass + proc semanticPasses = registerPass verbosePass registerPass semPass @@ -251,14 +254,11 @@ proc CommandCompileToC = # echo "CHECK DEP COMPLETE" compileProject() - - if compilationCachePresent: - updateCachedModules() - + cgenWriteModules() if gCmd != cmdRun: extccomp.CallCCompiler(changeFileExt(gProjectFull, "")) - if optCaasEnabled in gGlobalOptions: + if isServing: # caas will keep track only of the compilation commands lastCaasCmd = curCaasCmd resetCgenModules() @@ -377,10 +377,23 @@ proc CommandScan = rawMessage(errCannotOpenFile, f) proc CommandSuggest = - msgs.gErrorMax = high(int) # do not stop after first error - semanticPasses() - rodPass() - compileProject() + if isServing: + # XXX: hacky work-around ahead + # Currently, it's possible to issue a idetools command, before + # issuing the first compile command. This will leave the compiler + # cache in a state where "no recompilation is necessary", but the + # cgen pass was never executed at all. + CommandCompileToC() + if gDirtyBufferIdx != 0: + discard compileModule(gDirtyBufferIdx, {sfDirty}) + resetModule(gDirtyBufferIdx) + if optDef in gGlobalOptions: + defFromSourceMap(optTrackPos) + else: + msgs.gErrorMax = high(int) # do not stop after first error + semanticPasses() + rodPass() + compileProject() proc wantMainModule = if gProjectFull.len == 0: @@ -404,7 +417,7 @@ proc requireMainModuleOption = proc resetMemory = resetCompilationLists() ccgutils.resetCaches() - ResetAllModules() + resetAllModules() resetRopeCache() resetSysTypes() gOwners = @[] diff --git a/compiler/msgs.nim b/compiler/msgs.nim index e11e47bac..16ef06b61 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -526,13 +526,17 @@ proc SuggestWriteln*(s: string) = else: Writeln(stdout, s) stdoutSocket.send(s & "\c\L") - + proc SuggestQuit*() = - if not isServing: quit(0) - elif not isNil(stdoutSocket): - stdoutSocket.send("\c\L") + if not isServing: + quit(0) + elif isWorkingWithDirtyBuffer: + # No need to compile the rest if we are working with a + # throw-away buffer. Incomplete dot expressions frequently + # found in dirty buffers will result in errors few steps + # from now anyway. raise newException(ESuggestDone, "suggest done") - + # this format is understood by many text editors: it is the same that # Borland and Freepascal use const @@ -606,6 +610,7 @@ proc `??`* (info: TLineInfo, filename: string): bool = result = filename in info.toFilename var checkPoints*: seq[TLineInfo] = @[] +var optTrackPos*: TLineInfo proc addCheckpoint*(info: TLineInfo) = checkPoints.add(info) diff --git a/compiler/options.nim b/compiler/options.nim index 08a5ba010..f67ded163 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -107,10 +107,16 @@ var gLastCmdTime*: float # when caas is enabled, we measure each command gListFullPaths*: bool isServing*: bool = false + gDirtyBufferIdx* = 0'i32 # indicates the fileIdx of the dirty version of + # the tracked source X, saved by the CAAS client. + gDirtyOriginalIdx* = 0'i32 # the original source file of the dirtified buffer. proc importantComments*(): bool {.inline.} = gCmd in {cmdDoc, cmdIdeTools} proc usesNativeGC*(): bool {.inline.} = gSelectedGC >= gcRefc +template isWorkingWithDirtyBuffer*: expr = + gDirtyBufferIdx != 0 + template compilationCachePresent*: expr = {optCaasEnabled, optSymbolFiles} * gGlobalOptions != {} diff --git a/compiler/rodread.nim b/compiler/rodread.nim index d0a63cd99..562eaebab 100644 --- a/compiler/rodread.nim +++ b/compiler/rodread.nim @@ -328,9 +328,6 @@ proc decodeType(r: PRodReader, info: TLineInfo): PType = result.align = decodeVInt(r.s, r.pos) else: result.align = 2 - if r.s[r.pos] == '@': - inc(r.pos) - result.containerID = decodeVInt(r.s, r.pos) decodeLoc(r, result.loc, info) while r.s[r.pos] == '^': inc(r.pos) @@ -1012,9 +1009,6 @@ proc writeType(f: TFile; t: PType) = if t.align != 2: f.write('=') f.write($t.align) - if t.containerID != 0: - f.write('@') - f.write($t.containerID) for i in countup(0, sonsLen(t) - 1): if t.sons[i] == nil: f.write("^()") diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim index b64347ba9..0221977bf 100644 --- a/compiler/rodwrite.nim +++ b/compiler/rodwrite.nim @@ -233,9 +233,6 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) = if t.align != 2: add(result, '=') encodeVInt(t.align, result) - if t.containerID != 0: - add(result, '@') - encodeVInt(t.containerID, result) encodeLoc(w, t.loc, result) for i in countup(0, sonsLen(t) - 1): if t.sons[i] == nil: diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index f19b79c6a..2c3adfeda 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -693,9 +693,6 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) = openScope(c.tab) pushOwner(s) if s.magic == mNone: s.typ.kind = tyGenericBody - if s.typ.containerID != 0: - InternalError(a.info, "semTypeSection: containerID") - s.typ.containerID = s.typ.id # XXX for generic type aliases this is not correct! We need the # underlying Id really: # diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index b3a82c413..3abc994ef 100644 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -770,9 +770,6 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType = return newOrPrevType(tyError, prev, c) elif s.typ.kind != tyGenericBody: isConcrete = false - elif s.typ.containerID == 0: - InternalError(n.info, "semtypes.semGeneric") - return newOrPrevType(tyError, prev, c) elif sonsLen(n) != sonsLen(s.typ): LocalError(n.info, errWrongNumberOfArguments) return newOrPrevType(tyError, prev, c) diff --git a/compiler/service.nim b/compiler/service.nim index b3c7fbc83..8e8fe20bf 100644 --- a/compiler/service.nim +++ b/compiler/service.nim @@ -65,6 +65,9 @@ proc serve*(action: proc (){.nimcall.}) = curCaasCmd = cmd processCmdLine(passCmd2, cmd) action() + gDirtyBufferIdx = 0 + gDirtyOriginalIdx = 0 + gErrorCounter = 0 let typ = getConfigVar("server.type") case typ diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index ddda493ee..e1882e1fb 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -559,11 +559,10 @@ proc typeRel(c: var TCandidate, f, a: PType): TTypeRelation = # simply no match for now: nil elif x.kind == tyGenericInst and - (f.sons[0].containerID == x.sons[0].containerID) and - (sonsLen(x) - 1 == sonsLen(f)): - assert(x.sons[0].kind == tyGenericBody) - for i in countup(1, sonsLen(f) - 1): - if x.sons[i].kind == tyGenericParam: + (f.sons[0] == x.sons[0]) and + (sonsLen(x) - 1 == sonsLen(f)): + for i in countup(1, sonsLen(f) - 1): + if x.sons[i].kind == tyGenericParam: InternalError("wrong instantiated type!") elif typeRel(c, f.sons[i], x.sons[i]) <= isSubtype: return result = isGeneric diff --git a/compiler/suggest.nim b/compiler/suggest.nim index 130666f4d..18e6dbddf 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -9,7 +9,9 @@ ## This file implements features required for IDE support. -# imported from sigmatch.nim +# included from sigmatch.nim + +import algorithm const sep = '\t' @@ -238,12 +240,69 @@ proc findDefinition(node: PNode, s: PSym) = SuggestWriteln(SymToStr(s, isLocal=false, sectionDef)) SuggestQuit() +type + TSourceMap = object + lines: seq[TLineMap] + + TEntry = object + pos: int + sym: PSym + + TLineMap = object + entries: seq[TEntry] + +var + gSourceMaps: seq[TSourceMap] = @[] + +proc ensureIdx[T](x: var T, y: int) = + if x.len <= y: x.setLen(y+1) + +proc ensureSeq[T](x: var seq[T]) = + if x == nil: newSeq(x, 0) + +proc resetSourceMap*(fileIdx: int32) = + ensureIdx(gSourceMaps, fileIdx) + gSourceMaps[fileIdx].lines = @[] + +proc addToSourceMap(sym: Psym, info: TLineInfo) = + ensureIdx(gSourceMaps, info.fileIndex) + ensureSeq(gSourceMaps[info.fileIndex].lines) + ensureIdx(gSourceMaps[info.fileIndex].lines, info.line) + ensureSeq(gSourceMaps[info.fileIndex].lines[info.line].entries) + gSourceMaps[info.fileIndex].lines[info.line].entries.add(TEntry(pos: info.col, sym: sym)) + +proc defFromLine(entries: var seq[TEntry], col: int32) = + if entries == nil: return + # The sorting is done lazily here on purpose. + # No need to pay the price for it unless the user requests + # "goto definition" on a particular line + sort(entries) do (a,b: TEntry) -> int: + return cmp(a.pos, b.pos) + + for e in entries: + # currently, the line-infos for most expressions point to + # one position past the end of the expression. This means + # that the first expr that ends after the cursor column is + # the one we are looking for. + if e.pos >= col: + SuggestWriteln(SymToStr(e.sym, isLocal=false, sectionDef)) + return + +proc defFromSourceMap*(i: TLineInfo) = + if not ((i.fileIndex < gSourceMaps.len) and + (gSourceMaps[i.fileIndex].lines != nil) and + (i.line < gSourceMaps[i.fileIndex].lines.len)): return + + defFromLine(gSourceMaps[i.fileIndex].lines[i.line].entries, i.col) + proc suggestSym*(n: PNode, s: PSym) {.inline.} = ## misnamed: should be 'symDeclared' if optUsages in gGlobalOptions: findUsages(n, s) if optDef in gGlobalOptions: findDefinition(n, s) + if isServing: + addToSourceMap(s, n.info) proc markUsed(n: PNode, s: PSym) = incl(s.flags, sfUsed) diff --git a/tests/caas/compile-suggest.txt b/tests/caas/compile-suggest.txt new file mode 100644 index 000000000..4e2ab9729 --- /dev/null +++ b/tests/caas/compile-suggest.txt @@ -0,0 +1,7 @@ +main.nim +> c +SuccessX +> idetools --trackDirty:main_dirty.nim,main.nim,12,7 --suggest main.nim +skField\tx +skField\ty + diff --git a/tests/caas/def-def-compile.txt b/tests/caas/def-def-compile.txt new file mode 100644 index 000000000..64002aff1 --- /dev/null +++ b/tests/caas/def-def-compile.txt @@ -0,0 +1,10 @@ +main.nim +> idetools --track:main.nim,5,18 --def main.nim +strutils.toUpper +SuccessX +> idetools --track:main.nim,5,18 --def main.nim +strutils.toUpper +SuccessX +> c +SuccessX + diff --git a/tests/caas/main_dirty.nim b/tests/caas/main_dirty.nim new file mode 100644 index 000000000..95fb6c624 --- /dev/null +++ b/tests/caas/main_dirty.nim @@ -0,0 +1,14 @@ +import imported, strutils + +type + TFoo = object + x: int + y: string + +proc main = + var t1 = "text" + var t2 = t1.toUpper + var foo = TFoo(x: 10, y: "test") + foo. + echo(t1 +++ t2) + diff --git a/tests/caas/suggest-compile.txt b/tests/caas/suggest-compile.txt new file mode 100644 index 000000000..49d0dc431 --- /dev/null +++ b/tests/caas/suggest-compile.txt @@ -0,0 +1,7 @@ +main.nim +> idetools --trackDirty:main_dirty.nim,main.nim,12,7 --suggest main.nim +skField\tx +skField\ty +> c +SuccessX + |