From 0774af169b44e5e2a67a880e694f2140b3c694da Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Fri, 1 Mar 2013 12:12:53 +0200 Subject: [PATCH 1/8] containerID is no longer needed for generics --- compiler/ast.nim | 2 -- compiler/rodread.nim | 3 --- compiler/rodwrite.nim | 3 --- compiler/semstmts.nim | 3 --- compiler/semtypes.nim | 3 --- compiler/sigmatch.nim | 9 ++++----- 6 files changed, 4 insertions(+), 19 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 0e4700065d..65806ea1f2 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -675,7 +675,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 @@ -1012,7 +1011,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/rodread.nim b/compiler/rodread.nim index 5dccee9a71..a4287f8e8c 100755 --- a/compiler/rodread.nim +++ b/compiler/rodread.nim @@ -327,9 +327,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) diff --git a/compiler/rodwrite.nim b/compiler/rodwrite.nim index c0a0cc4eb7..9eab844d19 100755 --- a/compiler/rodwrite.nim +++ b/compiler/rodwrite.nim @@ -230,9 +230,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 c38e2f3ad6..9867c20bec 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -532,9 +532,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 bda0047cab..db2ef1b3f0 100755 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -769,9 +769,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/sigmatch.nim b/compiler/sigmatch.nim index 953dcfa747..72a5762a95 100755 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -493,11 +493,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 From 34cd22ba72e6b93b4f095d6424206627137d0ec6 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Sat, 4 May 2013 18:10:43 +0300 Subject: [PATCH 2/8] remove some more references of containerID after merging --- compiler/rodread.nim | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler/rodread.nim b/compiler/rodread.nim index 3e04a755dc..562eaebab9 100644 --- a/compiler/rodread.nim +++ b/compiler/rodread.nim @@ -1009,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("^()") From 519d5b834ad9601c487b4cc183f80b713e2da53f Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Sat, 4 May 2013 23:02:03 +0300 Subject: [PATCH 3/8] experimental support for answering idetools --def requests from an in-memory index built during compilation in caas mode --- compiler/commands.nim | 3 ++- compiler/main.nim | 20 +++++++++------ compiler/msgs.nim | 1 + compiler/suggest.nim | 58 ++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 72 insertions(+), 10 deletions(-) diff --git a/compiler/commands.nim b/compiler/commands.nim index 27da03bbe7..de52a4062c 100644 --- a/compiler/commands.nim +++ b/compiler/commands.nim @@ -215,7 +215,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}: diff --git a/compiler/main.nim b/compiler/main.nim index 46ef65e81f..6e3b1a3528 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 @@ -90,18 +90,19 @@ proc addDep(x: Psym, dep: int32) = gMemCacheData[x.position].deps.safeAdd(dep) proc ResetModule(fileIdx: int32) = - echo "HARD RESETTING ", fileIdx.toFilename + writeStackTrace() + # echo "HARD RESETTING ", fileIdx.toFilename gMemCacheData[fileIdx].needsRecompile = Yes gCompiledModules[fileIdx] = nil cgendata.gModules[fileIdx] = nil + resetSourceMap(fileIdx) proc ResetAllModules = for i in 0..gCompiledModules.high: if gCompiledModules[i] != nil: 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 = @@ -112,15 +113,15 @@ proc checkDepMem(fileIdx: int32): TNeedRecompile = 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 @@ -381,6 +382,9 @@ proc CommandSuggest = semanticPasses() rodPass() compileProject() + if isServing: + if optDef in gGlobalOptions: + defFromSourceMap(optTrackPos) proc wantMainModule = if gProjectFull.len == 0: diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 6062ebd7fc..a1eaf23bbc 100644 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -606,6 +606,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/suggest.nim b/compiler/suggest.nim index 130666f4d9..273347ef3f 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,66 @@ 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) = + # 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) = + InternalAssert i.fileIndex < gSourceMaps.len and + i.line < gSourceMaps[i.fileIndex].lines.len + 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) From 5a2720e99075166d2192fd40927f695f58124028 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Sun, 5 May 2013 00:42:16 +0300 Subject: [PATCH 4/8] bugfix: compiling after idetools usage is now possible in caas mode --- compiler/main.nim | 10 ++++++++++ tests/caas/def-def-compile.txt | 10 ++++++++++ 2 files changed, 20 insertions(+) create mode 100644 tests/caas/def-def-compile.txt diff --git a/compiler/main.nim b/compiler/main.nim index 6e3b1a3528..dde18825e1 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -214,6 +214,9 @@ proc rodPass = if optSymbolFiles in gGlobalOptions: registerPass(rodwritePass) +proc codegenPass = + registerPass cgenPass + proc semanticPasses = registerPass verbosePass registerPass semPass @@ -381,6 +384,13 @@ proc CommandSuggest = msgs.gErrorMax = high(int) # do not stop after first error semanticPasses() rodPass() + 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. + codegenPass() compileProject() if isServing: if optDef in gGlobalOptions: diff --git a/tests/caas/def-def-compile.txt b/tests/caas/def-def-compile.txt new file mode 100644 index 0000000000..64002aff16 --- /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 + From f52ea04d229b5cdf70a352efd93e0e01fa8faadf Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Sun, 5 May 2013 15:12:50 +0300 Subject: [PATCH 5/8] support suggest after compile in caas mode --- compiler/ast.nim | 1 + compiler/commands.nim | 19 +++++++++++++++++++ compiler/main.nim | 7 ++++++- compiler/msgs.nim | 14 +++++++++----- compiler/options.nim | 6 ++++++ compiler/service.nim | 4 +++- tests/caas/compile-suggest.txt | 7 +++++++ tests/caas/main_dirty.nim | 14 ++++++++++++++ tests/caas/suggest-compile.txt | 7 +++++++ 9 files changed, 72 insertions(+), 7 deletions(-) create mode 100644 tests/caas/compile-suggest.txt create mode 100644 tests/caas/main_dirty.nim create mode 100644 tests/caas/suggest-compile.txt diff --git a/compiler/ast.nim b/compiler/ast.nim index aee99c833d..bcfb946cad 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 diff --git a/compiler/commands.nim b/compiler/commands.nim index de52a4062c..63704b3289 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") @@ -470,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/main.nim b/compiler/main.nim index dde18825e1..c9b3967e55 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -150,7 +150,12 @@ proc newModule(fileIdx: int32): PSym = initStrTable(result.tab) StrTableAdd(result.tab, result) # a module knows itself -proc compileModule(fileIdx: int32, flags: TSymFlags): PSym = +proc compileModule(fileIdxArg: int32, flagsArg: TSymFlags): PSym = + let (fileIdx, flags) = if fileIdxArg == gDirtyOriginalIdx: + (gDirtyBufferIdx, flagsArg + {sfDirty}) + else: + (fileIdxArg, flagsArg) + result = getModule(fileIdx) if result == nil: growCache gMemCacheData, fileIdx diff --git a/compiler/msgs.nim b/compiler/msgs.nim index a1eaf23bbc..b38d67b55b 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 diff --git a/compiler/options.nim b/compiler/options.nim index a7d513dc55..3b71dca478 100644 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -106,10 +106,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/service.nim b/compiler/service.nim index b3c7fbc830..6a0cfd292c 100644 --- a/compiler/service.nim +++ b/compiler/service.nim @@ -65,7 +65,9 @@ proc serve*(action: proc (){.nimcall.}) = curCaasCmd = cmd processCmdLine(passCmd2, cmd) action() - + gDirtyBufferIdx = 0 + gDirtyOriginalIdx = 0 + let typ = getConfigVar("server.type") case typ of "stdin": diff --git a/tests/caas/compile-suggest.txt b/tests/caas/compile-suggest.txt new file mode 100644 index 0000000000..4e2ab97294 --- /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/main_dirty.nim b/tests/caas/main_dirty.nim new file mode 100644 index 0000000000..95fb6c6240 --- /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 0000000000..49d0dc4313 --- /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 + From 961d3de8e5ae24778e0c2882656a3771b8332d38 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Sun, 5 May 2013 16:34:00 +0300 Subject: [PATCH 6/8] fix compiling after suggest --- compiler/cgen.nim | 34 +++++++++++++++++----------------- compiler/main.nim | 40 +++++++++++++++++----------------------- compiler/service.nim | 3 ++- 3 files changed, 36 insertions(+), 41 deletions(-) diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 753576aa08..7837ca1606 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -1266,10 +1266,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 @@ -1279,24 +1275,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/main.nim b/compiler/main.nim index c9b3967e55..2ff7691d8c 100644 --- a/compiler/main.nim +++ b/compiler/main.nim @@ -89,24 +89,23 @@ proc addDep(x: Psym, dep: int32) = growCache gMemCacheData, dep gMemCacheData[x.position].deps.safeAdd(dep) -proc ResetModule(fileIdx: int32) = - writeStackTrace() +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" proc checkDepMem(fileIdx: int32): TNeedRecompile = template markDirty = - ResetModule(fileIdx) + resetModule(fileIdx) return Yes if gMemCacheData[fileIdx].needsRecompile != Maybe: @@ -150,12 +149,7 @@ proc newModule(fileIdx: int32): PSym = initStrTable(result.tab) StrTableAdd(result.tab, result) # a module knows itself -proc compileModule(fileIdxArg: int32, flagsArg: TSymFlags): PSym = - let (fileIdx, flags) = if fileIdxArg == gDirtyOriginalIdx: - (gDirtyBufferIdx, flagsArg + {sfDirty}) - else: - (fileIdxArg, flagsArg) - +proc compileModule(fileIdx: int32, flags: TSymFlags): PSym = result = getModule(fileIdx) if result == nil: growCache gMemCacheData, fileIdx @@ -260,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() @@ -386,20 +377,23 @@ proc CommandScan = rawMessage(errCannotOpenFile, f) proc CommandSuggest = - msgs.gErrorMax = high(int) # do not stop after first error - semanticPasses() - rodPass() 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. - codegenPass() - compileProject() - if isServing: + 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: @@ -423,7 +417,7 @@ proc requireMainModuleOption = proc resetMemory = resetCompilationLists() ccgutils.resetCaches() - ResetAllModules() + resetAllModules() resetRopeCache() resetSysTypes() gOwners = @[] diff --git a/compiler/service.nim b/compiler/service.nim index 6a0cfd292c..8e8fe20bf2 100644 --- a/compiler/service.nim +++ b/compiler/service.nim @@ -67,7 +67,8 @@ proc serve*(action: proc (){.nimcall.}) = action() gDirtyBufferIdx = 0 gDirtyOriginalIdx = 0 - + gErrorCounter = 0 + let typ = getConfigVar("server.type") case typ of "stdin": From 11ee2261929117972256fc2117101ead3dfff11d Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Sun, 5 May 2013 16:50:01 +0300 Subject: [PATCH 7/8] don't perform unnecessary linking --- compiler/extccomp.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim index bb2f091516..a7e4eceb7f 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 = "" From f0be93bfa2cb49ab88595478efb4457391d49a31 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Sun, 5 May 2013 19:34:14 +0300 Subject: [PATCH 8/8] handle invalid data in --def --- compiler/suggest.nim | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/compiler/suggest.nim b/compiler/suggest.nim index 273347ef3f..18e6dbddfc 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -272,6 +272,7 @@ proc addToSourceMap(sym: Psym, info: TLineInfo) = 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 @@ -288,8 +289,10 @@ proc defFromLine(entries: var seq[TEntry], col: int32) = return proc defFromSourceMap*(i: TLineInfo) = - InternalAssert i.fileIndex < gSourceMaps.len and - i.line < gSourceMaps[i.fileIndex].lines.len + 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.} =