mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-14 07:13:27 +00:00
basic continue after error works; interactive mode more useful
This commit is contained in:
@@ -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.
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)")
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
29
rod/msgs.nim
29
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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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])
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user