basic continue after error works; interactive mode more useful

This commit is contained in:
Araq 2011-02-13 03:39:11 +01:00
commit 627e192f64
12 changed files with 58 additions and 40 deletions

View file

@ -37,7 +37,7 @@ Installation on the Macintosh
Only MacOS X is supported. Only MacOS X is supported.
Since MacOS X is UNIX based too, it works like the installation on Linux. 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. You need to install Apple's developer's tools for the GNU Compiler Collection.

View file

@ -747,7 +747,7 @@ proc compileOption*(option, arg: string): bool {.
include "system/inclrtl" include "system/inclrtl"
when not defined(ecmascript): when not defined(ecmascript) and not defined(nimrodVm):
include "system/cgprocs" include "system/cgprocs"
proc add *[T](x: var seq[T], y: T) {.magic: "AppendSeqElem", noSideEffect.} 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, ## It does *not* call the garbage collector to free all the memory,
## unless a quit procedure calls ``GC_collect``. ## 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): when not defined(EcmaScript) and not defined(NimrodVM):
proc atomicInc*(memLoc: var int, x: int): int {.inline.} 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 ## returns the OS file handle of the file ``f``. This is only useful for
## platform specific programming. ## platform specific programming.
proc quit(errormsg: string) =
echo(errormsg)
quit(quitFailure)
proc cstringArrayToSeq*(a: cstringArray, len: int): seq[string] = proc cstringArrayToSeq*(a: cstringArray, len: int): seq[string] =
## converts a ``cstringArray`` to a ``seq[string]``. `a` is supposed to be ## converts a ``cstringArray`` to a ``seq[string]``. `a` is supposed to be
## of length ``len``. ## of length ``len``.
@ -1669,5 +1661,10 @@ elif defined(ecmaScript) or defined(NimrodVM):
if x < y: return -1 if x < y: return -1
return 1 return 1
proc quit*(errormsg: string) {.noReturn.} =
## a shorthand for ``echo(errormsg); quit(quitFailure)``.
echo(errormsg)
quit(quitFailure)
{.pop.} # checks {.pop.} # checks
{.pop.} # hints {.pop.} # hints

View file

@ -56,7 +56,9 @@ var
gOutOfMem: ref EOutOfMemory gOutOfMem: ref EOutOfMemory
proc raiseOutOfMem() {.noreturn.} = 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" gOutOfMem.msg = "out of memory"
raise gOutOfMem raise gOutOfMem

View file

@ -78,8 +78,9 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode
proc stackTraceAux(x: PStackFrame) = proc stackTraceAux(x: PStackFrame) =
if x != nil: if x != nil:
stackTraceAux(x.next) stackTraceAux(x.next)
var info = if x.call != nil: x.call.info else: UnknownLineInfo()
messageOut(`%`("file: $1, line: $2", 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 = "") = proc stackTrace(c: PEvalContext, n: PNode, msg: TMsgKind, arg: string = "") =
messageOut("stack trace: (most recent call last)") messageOut("stack trace: (most recent call last)")

View file

@ -23,6 +23,7 @@ type
f*: tfile f*: tfile
s*: string s*: string
rd*, wr*: int # for string streams rd*, wr*: int # for string streams
lineOffset*: int # for fake stdin line numbers
PLLStream* = ref TLLStream PLLStream* = ref TLLStream
@ -65,6 +66,7 @@ proc LLStreamOpenStdIn(): PLLStream =
new(result) new(result)
result.kind = llsStdIn result.kind = llsStdIn
result.s = "" result.s = ""
result.lineOffset = -1
proc LLStreamClose(s: PLLStream) = proc LLStreamClose(s: PLLStream) =
case s.kind case s.kind
@ -86,6 +88,7 @@ proc LLreadFromStdin(s: PLLStream, buf: pointer, bufLen: int): int =
add(s.s, line) add(s.s, line)
add(s.s, "\n") 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) result = min(bufLen, len(s.s) - s.rd)
if result > 0: if result > 0:
copyMem(buf, addr(s.s[0 + s.rd]), result) copyMem(buf, addr(s.s[0 + s.rd]), result)

View file

@ -139,6 +139,7 @@ proc CommandCompileToEcmaScript(filename: string) =
compileProject(filename) compileProject(filename)
proc CommandInteractive() = proc CommandInteractive() =
msgs.gErrorMax = high(int) # do not stop after first error
incl(gGlobalOptions, optSafeCode) incl(gGlobalOptions, optSafeCode)
setTarget(osNimrodVM, cpuNimrodVM) setTarget(osNimrodVM, cpuNimrodVM)
initDefines() initDefines()

View file

@ -373,6 +373,8 @@ type
ERecoverableError* = object of EInvalidValue ERecoverableError* = object of EInvalidValue
proc raiseRecoverableError*() {.noinline, noreturn.} =
raise newException(ERecoverableError, "")
var var
gNotes*: TNoteKinds = {low(TNoteKind)..high(TNoteKind)} gNotes*: TNoteKinds = {low(TNoteKind)..high(TNoteKind)}
@ -485,7 +487,7 @@ proc handleError(msg: TMsgKind, eh: TErrorHandling) =
if gVerbosity >= 3: assert(false) if gVerbosity >= 3: assert(false)
quit(1) # one error stops the compiler quit(1) # one error stops the compiler
elif eh == doRaise: elif eh == doRaise:
raise newException(ERecoverableError, "") raiseRecoverableError()
proc sameLineInfo(a, b: TLineInfo): bool = proc sameLineInfo(a, b: TLineInfo): bool =
result = (a.line == b.line) and (a.fileIndex == b.fileIndex) 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 if not (msg in gNotes): return
frmt = rawHintFormat frmt = rawHintFormat
inc(gHintCounter) inc(gHintCounter)
else:
assert(false) # cannot happen
MessageOut(`%`(frmt, `%`(msgKindToString(msg), args))) MessageOut(`%`(frmt, `%`(msgKindToString(msg), args)))
handleError(msg, doAbort) handleError(msg, doAbort)
proc rawMessage*(msg: TMsgKind, arg: string) = proc rawMessage*(msg: TMsgKind, arg: string) =
rawMessage(msg, [arg]) rawMessage(msg, [arg])
var
lastError = UnknownLineInfo()
proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string, proc liMessage(info: TLineInfo, msg: TMsgKind, arg: string,
eh: TErrorHandling) = eh: TErrorHandling) =
var frmt: string var frmt: string
var ignoreMsg = false
case msg case msg
of errMin..errMax: of errMin..errMax:
writeContext(info) writeContext(info)
frmt = posErrorFormat 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: of warnMin..warnMax:
if not (optWarns in gOptions): return ignoreMsg = optWarns notin gOptions or msg notin gNotes
if not (msg in gNotes): return
frmt = posWarningFormat frmt = posWarningFormat
inc(gWarnCounter) inc(gWarnCounter)
of hintMin..hintMax: of hintMin..hintMax:
if not (optHints in gOptions): return ignoreMsg = optHints notin gOptions or msg notin gNotes
if not (msg in gNotes): return
frmt = posHintFormat frmt = posHintFormat
inc(gHintCounter) inc(gHintCounter)
else: if not ignoreMsg:
assert(false) # cannot happen MessageOut(frmt % [toFilename(info), coordToStr(info.line),
MessageOut(`%`(frmt, [toFilename(info), coordToStr(info.line), coordToStr(info.col), getMessageStr(msg, arg)])
coordToStr(info.col), getMessageStr(msg, arg)])) handleError(msg, eh)
handleError(msg, doAbort)
proc Fatal*(info: TLineInfo, msg: TMsgKind, arg = "") = proc Fatal*(info: TLineInfo, msg: TMsgKind, arg = "") =
liMessage(info, msg, arg, doAbort) liMessage(info, msg, arg, doAbort)

View file

@ -68,17 +68,18 @@ proc HandleCmdLine() =
ProcessCmdLine(passCmd2, command, filename) ProcessCmdLine(passCmd2, command, filename)
MainCommand(command, filename) MainCommand(command, filename)
if gVerbosity >= 2: echo(GC_getStatistics()) if gVerbosity >= 2: echo(GC_getStatistics())
when hasTinyCBackend: if msgs.gErrorCounter == 0:
if gCmd == cmdRun: when hasTinyCBackend:
tccgen.run() if gCmd == cmdRun:
if gCmd notin {cmdInterpret, cmdRun} and msgs.gErrorCounter == 0: tccgen.run()
rawMessage(hintSuccessX, [$gLinesCompiled, $(getTime() - start)]) if gCmd notin {cmdInterpret, cmdRun}:
if optRun in gGlobalOptions: rawMessage(hintSuccessX, [$gLinesCompiled, $(getTime() - start)])
when defined(unix): if optRun in gGlobalOptions:
var prog = "./" & quoteIfContainsWhite(changeFileExt(filename, "")) when defined(unix):
else: var prog = "./" & quoteIfContainsWhite(changeFileExt(filename, ""))
var prog = quoteIfContainsWhite(changeFileExt(filename, "")) else:
execExternalProgram(prog & ' ' & arguments) var prog = quoteIfContainsWhite(changeFileExt(filename, ""))
execExternalProgram(prog & ' ' & arguments)
cmdLineInfo = newLineInfo("command line", - 1, - 1) cmdLineInfo = newLineInfo("command line", - 1, - 1)
condsyms.InitDefines() condsyms.InitDefines()

View file

@ -211,6 +211,7 @@ proc openLexer(lex: var TLexer, filename: string, inputstream: PLLStream) =
lex.indentStack = @[0] lex.indentStack = @[0]
lex.filename = filename lex.filename = filename
lex.indentAhead = - 1 lex.indentAhead = - 1
inc(lex.Linenumber, inputstream.lineOffset)
proc closeLexer(lex: var TLexer) = proc closeLexer(lex: var TLexer) =
inc(gLinesCompiled, lex.LineNumber) inc(gLinesCompiled, lex.LineNumber)

View file

@ -21,9 +21,12 @@ proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
popInfoContext() popInfoContext()
proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = semExpr(c, n, flags) 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 != nil:
if result.typ.kind == tyVar: if result.typ.kind == tyVar:
var d = newNodeIT(nkHiddenDeref, result.info, result.typ.sons[0]) var d = newNodeIT(nkHiddenDeref, result.info, result.typ.sons[0])

View file

@ -276,6 +276,8 @@ proc semVar(c: PContext, n: PNode): PNode =
else: typ = def.typ else: typ = def.typ
else: else:
def = ast.emptyNode def = ast.emptyNode
# this can only happen for errornous var statements:
if typ == nil: continue
if not typeAllowed(typ, skVar): if not typeAllowed(typ, skVar):
GlobalError(a.info, errXisNoType, typeToString(typ)) GlobalError(a.info, errXisNoType, typeToString(typ))
var tup = skipTypes(typ, {tyGenericInst}) var tup = skipTypes(typ, {tyGenericInst})

View file

@ -723,7 +723,9 @@ proc transform(c: PTransf, n: PNode): PTransNode =
result = PTransNode(cnst) # do not miss an optimization result = PTransNode(cnst) # do not miss an optimization
proc processTransf(context: PPassContext, n: PNode): PNode = 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) var c = PTransf(context)
pushTransCon(c, newTransCon(getCurrOwner(c))) pushTransCon(c, newTransCon(getCurrOwner(c)))
result = PNode(transform(c, n)) result = PNode(transform(c, n))