diff --git a/install.txt b/install.txt index eeea387f99..86b8285e7c 100755 --- a/install.txt +++ b/install.txt @@ -37,7 +37,7 @@ Installation on the Macintosh Only MacOS X is supported. Since MacOS X is UNIX based too, it works like the installation on Linux. -However, for unknown reasons the symbolic link method does not work MacOS X. +However, for unknown reasons the symbolic link method does not work on MacOS X. You need to install Apple's developer's tools for the GNU Compiler Collection. diff --git a/lib/system.nim b/lib/system.nim index 7822e6cad2..cf92594d9e 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -747,7 +747,7 @@ proc compileOption*(option, arg: string): bool {. include "system/inclrtl" -when not defined(ecmascript): +when not defined(ecmascript) and not defined(nimrodVm): include "system/cgprocs" proc add *[T](x: var seq[T], y: T) {.magic: "AppendSeqElem", noSideEffect.} @@ -1334,10 +1334,6 @@ proc quit*(errorcode: int = QuitSuccess) {. ## It does *not* call the garbage collector to free all the memory, ## unless a quit procedure calls ``GC_collect``. -when not defined(EcmaScript) and not defined(NimrodVM): - proc quit*(errormsg: string) {.noReturn.} - ## a shorthand for ``echo(errormsg); quit(quitFailure)``. - when not defined(EcmaScript) and not defined(NimrodVM): proc atomicInc*(memLoc: var int, x: int): int {.inline.} @@ -1558,10 +1554,6 @@ when not defined(EcmaScript) and not defined(NimrodVM): ## returns the OS file handle of the file ``f``. This is only useful for ## platform specific programming. - proc quit(errormsg: string) = - echo(errormsg) - quit(quitFailure) - proc cstringArrayToSeq*(a: cstringArray, len: int): seq[string] = ## converts a ``cstringArray`` to a ``seq[string]``. `a` is supposed to be ## of length ``len``. @@ -1669,5 +1661,10 @@ elif defined(ecmaScript) or defined(NimrodVM): if x < y: return -1 return 1 +proc quit*(errormsg: string) {.noReturn.} = + ## a shorthand for ``echo(errormsg); quit(quitFailure)``. + echo(errormsg) + quit(quitFailure) + {.pop.} # checks {.pop.} # hints diff --git a/lib/system/mmdisp.nim b/lib/system/mmdisp.nim index a85d69b0d7..de604869bf 100755 --- a/lib/system/mmdisp.nim +++ b/lib/system/mmdisp.nim @@ -56,7 +56,9 @@ var gOutOfMem: ref EOutOfMemory proc raiseOutOfMem() {.noreturn.} = - if gOutOfMem == nil: quit("out of memory; cannot even throw an exception") + if gOutOfMem == nil: + echo("out of memory; cannot even throw an exception") + quit(1) gOutOfMem.msg = "out of memory" raise gOutOfMem diff --git a/rod/evals.nim b/rod/evals.nim index 531ef8fbb3..1e2da01c47 100755 --- a/rod/evals.nim +++ b/rod/evals.nim @@ -75,11 +75,12 @@ proc popStackFrame(c: PEvalContext) = proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode -proc stackTraceAux(x: PStackFrame) = - if x != nil: +proc stackTraceAux(x: PStackFrame) = + if x != nil: stackTraceAux(x.next) + var info = if x.call != nil: x.call.info else: UnknownLineInfo() messageOut(`%`("file: $1, line: $2", - [toFilename(x.call.info), $(toLineNumber(x.call.info))])) + [toFilename(info), $(toLineNumber(info))])) proc stackTrace(c: PEvalContext, n: PNode, msg: TMsgKind, arg: string = "") = messageOut("stack trace: (most recent call last)") diff --git a/rod/llstream.nim b/rod/llstream.nim index 6fcd278a02..2ec13826fa 100755 --- a/rod/llstream.nim +++ b/rod/llstream.nim @@ -23,6 +23,7 @@ type f*: tfile s*: string rd*, wr*: int # for string streams + lineOffset*: int # for fake stdin line numbers PLLStream* = ref TLLStream @@ -65,6 +66,7 @@ proc LLStreamOpenStdIn(): PLLStream = new(result) result.kind = llsStdIn result.s = "" + result.lineOffset = -1 proc LLStreamClose(s: PLLStream) = case s.kind @@ -85,7 +87,8 @@ proc LLreadFromStdin(s: PLLStream, buf: pointer, bufLen: int): int = L = len(line) add(s.s, line) add(s.s, "\n") - if (L > 0) and (line[L - 1 + 0] == '#'): break + if (L > 0) and (line[L - 1 + 0] == '#'): break + inc(s.lineOffset) result = min(bufLen, len(s.s) - s.rd) if result > 0: copyMem(buf, addr(s.s[0 + s.rd]), result) diff --git a/rod/main.nim b/rod/main.nim index 5239227ac5..f413a03ef6 100755 --- a/rod/main.nim +++ b/rod/main.nim @@ -139,6 +139,7 @@ proc CommandCompileToEcmaScript(filename: string) = compileProject(filename) proc CommandInteractive() = + msgs.gErrorMax = high(int) # do not stop after first error incl(gGlobalOptions, optSafeCode) setTarget(osNimrodVM, cpuNimrodVM) initDefines() diff --git a/rod/msgs.nim b/rod/msgs.nim index dd7fea4cc3..0c1ca2137f 100755 --- a/rod/msgs.nim +++ b/rod/msgs.nim @@ -373,6 +373,8 @@ type ERecoverableError* = object of EInvalidValue +proc raiseRecoverableError*() {.noinline, noreturn.} = + raise newException(ERecoverableError, "") var gNotes*: TNoteKinds = {low(TNoteKind)..high(TNoteKind)} @@ -485,7 +487,7 @@ proc handleError(msg: TMsgKind, eh: TErrorHandling) = if gVerbosity >= 3: assert(false) quit(1) # one error stops the compiler elif eh == doRaise: - raise newException(ERecoverableError, "") + raiseRecoverableError() proc sameLineInfo(a, b: TLineInfo): bool = result = (a.line == b.line) and (a.fileIndex == b.fileIndex) @@ -518,36 +520,39 @@ proc rawMessage*(msg: TMsgKind, args: openarray[string]) = if not (msg in gNotes): return frmt = rawHintFormat inc(gHintCounter) - else: - assert(false) # cannot happen MessageOut(`%`(frmt, `%`(msgKindToString(msg), args))) handleError(msg, doAbort) proc rawMessage*(msg: TMsgKind, arg: string) = rawMessage(msg, [arg]) +var + lastError = UnknownLineInfo() + proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string, eh: TErrorHandling) = var frmt: string + var ignoreMsg = false case msg of errMin..errMax: writeContext(info) frmt = posErrorFormat + # we try to filter error messages so that not two error message + # in the same file and line are produced: + ignoreMsg = sameLineInfo(lastError, info) + lastError = info of warnMin..warnMax: - if not (optWarns in gOptions): return - if not (msg in gNotes): return + ignoreMsg = optWarns notin gOptions or msg notin gNotes frmt = posWarningFormat inc(gWarnCounter) of hintMin..hintMax: - if not (optHints in gOptions): return - if not (msg in gNotes): return + ignoreMsg = optHints notin gOptions or msg notin gNotes frmt = posHintFormat inc(gHintCounter) - else: - assert(false) # cannot happen - MessageOut(`%`(frmt, [toFilename(info), coordToStr(info.line), - coordToStr(info.col), getMessageStr(msg, arg)])) - handleError(msg, doAbort) + if not ignoreMsg: + MessageOut(frmt % [toFilename(info), coordToStr(info.line), + coordToStr(info.col), getMessageStr(msg, arg)]) + handleError(msg, eh) proc Fatal*(info: TLineInfo, msg: TMsgKind, arg = "") = liMessage(info, msg, arg, doAbort) diff --git a/rod/nimrod.nim b/rod/nimrod.nim index 5eac2db43d..4548a01869 100755 --- a/rod/nimrod.nim +++ b/rod/nimrod.nim @@ -68,17 +68,18 @@ proc HandleCmdLine() = ProcessCmdLine(passCmd2, command, filename) MainCommand(command, filename) if gVerbosity >= 2: echo(GC_getStatistics()) - when hasTinyCBackend: - if gCmd == cmdRun: - tccgen.run() - if gCmd notin {cmdInterpret, cmdRun} and msgs.gErrorCounter == 0: - rawMessage(hintSuccessX, [$gLinesCompiled, $(getTime() - start)]) - if optRun in gGlobalOptions: - when defined(unix): - var prog = "./" & quoteIfContainsWhite(changeFileExt(filename, "")) - else: - var prog = quoteIfContainsWhite(changeFileExt(filename, "")) - execExternalProgram(prog & ' ' & arguments) + if msgs.gErrorCounter == 0: + when hasTinyCBackend: + if gCmd == cmdRun: + tccgen.run() + if gCmd notin {cmdInterpret, cmdRun}: + rawMessage(hintSuccessX, [$gLinesCompiled, $(getTime() - start)]) + if optRun in gGlobalOptions: + when defined(unix): + var prog = "./" & quoteIfContainsWhite(changeFileExt(filename, "")) + else: + var prog = quoteIfContainsWhite(changeFileExt(filename, "")) + execExternalProgram(prog & ' ' & arguments) cmdLineInfo = newLineInfo("command line", - 1, - 1) condsyms.InitDefines() diff --git a/rod/scanner.nim b/rod/scanner.nim index 2560eb6f90..1e1105dadf 100755 --- a/rod/scanner.nim +++ b/rod/scanner.nim @@ -211,6 +211,7 @@ proc openLexer(lex: var TLexer, filename: string, inputstream: PLLStream) = lex.indentStack = @[0] lex.filename = filename lex.indentAhead = - 1 + inc(lex.Linenumber, inputstream.lineOffset) proc closeLexer(lex: var TLexer) = inc(gLinesCompiled, lex.LineNumber) diff --git a/rod/semexprs.nim b/rod/semexprs.nim index 0478cff827..3d5e393a5b 100755 --- a/rod/semexprs.nim +++ b/rod/semexprs.nim @@ -21,9 +21,12 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym, popInfoContext() proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode + proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = result = semExpr(c, n, flags) - if result.kind == nkEmpty: InternalError("semExprWithType") + if result.kind == nkEmpty: + # do not produce another redundant error message: + raiseRecoverableError() if result.typ != nil: if result.typ.kind == tyVar: var d = newNodeIT(nkHiddenDeref, result.info, result.typ.sons[0]) diff --git a/rod/semstmts.nim b/rod/semstmts.nim index d2e7322c2c..ad095d4f81 100755 --- a/rod/semstmts.nim +++ b/rod/semstmts.nim @@ -276,6 +276,8 @@ proc semVar(c: PContext, n: PNode): PNode = else: typ = def.typ else: def = ast.emptyNode + # this can only happen for errornous var statements: + if typ == nil: continue if not typeAllowed(typ, skVar): GlobalError(a.info, errXisNoType, typeToString(typ)) var tup = skipTypes(typ, {tyGenericInst}) diff --git a/rod/transf.nim b/rod/transf.nim index fb9c640cd1..49369bb74f 100755 --- a/rod/transf.nim +++ b/rod/transf.nim @@ -723,7 +723,9 @@ proc transform(c: PTransf, n: PNode): PTransNode = result = PTransNode(cnst) # do not miss an optimization proc processTransf(context: PPassContext, n: PNode): PNode = - if passes.skipCodegen(n): return n + # Note: For interactive mode we cannot call 'passes.skipCodegen' and skip + # this step! We have to rely that the semantic pass transforms too errornous + # nodes into an empty node. var c = PTransf(context) pushTransCon(c, newTransCon(getCurrOwner(c))) result = PNode(transform(c, n))