summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xcompiler/evals.nim9
-rwxr-xr-xcompiler/importer.nim32
-rwxr-xr-xcompiler/lookups.nim31
-rwxr-xr-xcompiler/msgs.nim2
-rwxr-xr-xcompiler/pragmas.nim52
-rwxr-xr-xcompiler/sem.nim28
-rwxr-xr-xcompiler/semdata.nim4
-rwxr-xr-xcompiler/semexprs.nim164
-rw-r--r--compiler/semmagic.nim2
-rwxr-xr-xcompiler/semstmts.nim138
-rwxr-xr-xcompiler/semtypes.nim180
-rwxr-xr-xcompiler/semtypinst.nim3
-rwxr-xr-xtodo.txt1
13 files changed, 378 insertions, 268 deletions
diff --git a/compiler/evals.nim b/compiler/evals.nim
index 1f79466ef..570e64dd3 100755
--- a/compiler/evals.nim
+++ b/compiler/evals.nim
@@ -918,18 +918,17 @@ proc expectString(n: PNode) =
 
 proc evalSlurp*(e: PNode, module: PSym): PNode =
   expectString(e)
+  result = newNodeIT(nkStrLit, e.info, getSysType(tyString))
   try:
     var filename = e.strVal.FindFile
-    var content = readFile(filename)
-    result = newStrNode(nkStrLit, content)
-    result.typ = getSysType(tyString)
-    result.info = e.info
+    result.strVal = readFile(filename)
     # we produce a fake include statement for every slurped filename, so that
     # the module dependencies are accurate:    
     appendToModule(module, newNode(nkIncludeStmt, e.info, @[
       newStrNode(nkStrLit, filename)]))
   except EIO:
-    GlobalError(e.info, errCannotOpenFile, e.strVal)
+    result.strVal = ""
+    LocalError(e.info, errCannotOpenFile, e.strVal)
 
 proc readOutput(p: PProcess): string =
   result = ""
diff --git a/compiler/importer.nim b/compiler/importer.nim
index 86511f228..19f0574b8 100755
--- a/compiler/importer.nim
+++ b/compiler/importer.nim
@@ -76,21 +76,23 @@ proc rawImportSymbol(c: PContext, s: PSym) =
 proc importSymbol(c: PContext, n: PNode, fromMod: PSym) = 
   let ident = lookups.considerAcc(n)
   let s = StrTableGet(fromMod.tab, ident)
-  if s == nil: GlobalError(n.info, errUndeclaredIdentifier, ident.s)
-  if s.kind == skStub: loadStub(s)
-  if s.Kind notin ExportableSymKinds:
-    InternalError(n.info, "importSymbol: 2")
-  # for an enumeration we have to add all identifiers
-  case s.Kind
-  of skProc, skMethod, skIterator, skMacro, skTemplate, skConverter:
-    # for a overloadable syms add all overloaded routines
-    var it: TIdentIter
-    var e = InitIdentIter(it, fromMod.tab, s.name)
-    while e != nil:
-      if e.name.id != s.Name.id: InternalError(n.info, "importSymbol: 3")
-      rawImportSymbol(c, e)
-      e = NextIdentIter(it, fromMod.tab)
-  else: rawImportSymbol(c, s)
+  if s == nil:
+    LocalError(n.info, errUndeclaredIdentifier, ident.s)
+  else:
+    if s.kind == skStub: loadStub(s)
+    if s.Kind notin ExportableSymKinds:
+      InternalError(n.info, "importSymbol: 2")
+    # for an enumeration we have to add all identifiers
+    case s.Kind
+    of skProc, skMethod, skIterator, skMacro, skTemplate, skConverter:
+      # for a overloadable syms add all overloaded routines
+      var it: TIdentIter
+      var e = InitIdentIter(it, fromMod.tab, s.name)
+      while e != nil:
+        if e.name.id != s.Name.id: InternalError(n.info, "importSymbol: 3")
+        rawImportSymbol(c, e)
+        e = NextIdentIter(it, fromMod.tab)
+    else: rawImportSymbol(c, s)
   
 proc importAllSymbols(c: PContext, fromMod: PSym) = 
   var i: TTabIter
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index 0ad1c7f01..c67520997 100755
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -36,6 +36,11 @@ proc considerAcc*(n: PNode): PIdent =
         result = getIdent(id)
   else:
     GlobalError(n.info, errIdentifierExpected, renderTree(n))
+ 
+proc errorSym*(n: PNode): PSym =
+  ## creates an error symbol to avoid cascading errors (for IDE support)
+  result = newSym(skUnknown, considerAcc(n), getCurrOwner())
+  result.info = n.info
 
 type 
   TOverloadIterMode* = enum 
@@ -122,13 +127,17 @@ proc lookUp*(c: PContext, n: PNode): PSym =
   case n.kind
   of nkIdent:
     result = SymtabGet(c.Tab, n.ident)
-    if result == nil: GlobalError(n.info, errUndeclaredIdentifier, n.ident.s)
+    if result == nil: 
+      LocalError(n.info, errUndeclaredIdentifier, n.ident.s)
+      result = errorSym(n)
   of nkSym:
     result = n.sym
   of nkAccQuoted:
     var ident = considerAcc(n)
     result = SymtabGet(c.Tab, ident)
-    if result == nil: GlobalError(n.info, errUndeclaredIdentifier, ident.s)
+    if result == nil:
+      LocalError(n.info, errUndeclaredIdentifier, ident.s)
+      result = errorSym(n)
   else: InternalError(n.info, "lookUp")
   if Contains(c.AmbiguousSymbols, result.id): 
     LocalError(n.info, errUseQualifier, result.name.s)
@@ -144,7 +153,8 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
     var ident = considerAcc(n)
     result = SymtabGet(c.Tab, ident)
     if result == nil and checkUndeclared in flags: 
-      GlobalError(n.info, errUndeclaredIdentifier, ident.s)
+      LocalError(n.info, errUndeclaredIdentifier, ident.s)
+      result = errorSym(n)
     elif checkAmbiguity in flags and result != nil and 
         Contains(c.AmbiguousSymbols, result.id): 
       LocalError(n.info, errUseQualifier, ident.s)
@@ -167,10 +177,12 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym =
         else: 
           result = StrTableGet(m.tab, ident)
         if result == nil and checkUndeclared in flags: 
-          GlobalError(n.sons[1].info, errUndeclaredIdentifier, ident.s)
-      elif checkUndeclared in flags: 
-        GlobalError(n.sons[1].info, errIdentifierExpected, 
-                    renderTree(n.sons[1]))
+          LocalError(n.sons[1].info, errUndeclaredIdentifier, ident.s)
+          result = errorSym(n.sons[1])
+      elif checkUndeclared in flags:
+        LocalError(n.sons[1].info, errIdentifierExpected, 
+                   renderTree(n.sons[1]))
+        result = errorSym(n.sons[1])
   else:
     result = nil
   if result != nil and result.kind == skStub: loadStub(result)
@@ -205,8 +217,9 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
         else: 
           result = InitIdentIter(o.it, o.m.tab, ident)
       else: 
-        GlobalError(n.sons[1].info, errIdentifierExpected, 
-                    renderTree(n.sons[1]))
+        LocalError(n.sons[1].info, errIdentifierExpected, 
+                   renderTree(n.sons[1]))
+        result = errorSym(n.sons[1])
   of nkSymChoice: 
     o.mode = oimSymChoice
     result = n.sons[0].sym
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index edcb66274..527c96dca 100755
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -576,7 +576,7 @@ proc handleError(msg: TMsgKind, eh: TErrorHandling, s: string) =
     assert(false)             # we want a stack trace here
   if msg >= fatalMin and msg <= fatalMax: 
     if gVerbosity >= 3: assert(false)
-    quit(1)
+    if gCmd != cmdIdeTools: quit(1)
   if msg >= errMin and msg <= errMax: 
     if gVerbosity >= 3: assert(false)
     inc(gErrorCounter)
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 7df477327..28f77d1b9 100755
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -109,14 +109,23 @@ proc processImportObjC(s: PSym, extname: string) =
   incl(s.flags, sfNamedParamCall)
   excl(s.flags, sfForward)
 
+proc newEmptyStrNode(n: PNode): PNode {.noinline.} =
+  result = newNodeIT(nkStrLit, n.info, getSysType(tyString))
+  result.strVal = ""
+
 proc getStrLitNode(c: PContext, n: PNode): PNode =
   if n.kind != nkExprColonExpr: 
-    GlobalError(n.info, errStringLiteralExpected)
-  else: 
+    LocalError(n.info, errStringLiteralExpected)
+    # error correction:
+    result = newEmptyStrNode(n)
+  else:
     n.sons[1] = c.semConstExpr(c, n.sons[1])
     case n.sons[1].kind
     of nkStrLit, nkRStrLit, nkTripleStrLit: result = n.sons[1]
-    else: GlobalError(n.info, errStringLiteralExpected)
+    else: 
+      LocalError(n.info, errStringLiteralExpected)
+      # error correction:
+      result = newEmptyStrNode(n)
 
 proc expectStrLit(c: PContext, n: PNode): string = 
   result = getStrLitNode(c, n).strVal
@@ -190,13 +199,17 @@ proc getLib(c: PContext, kind: TLibKind, path: PNode): PLib =
   Append(c.libs, result)
 
 proc expectDynlibNode(c: PContext, n: PNode): PNode = 
-  if n.kind != nkExprColonExpr: GlobalError(n.info, errStringLiteralExpected)
-  else: 
+  if n.kind != nkExprColonExpr: 
+    LocalError(n.info, errStringLiteralExpected)
+    # error correction:
+    result = newEmptyStrNode(n)
+  else:
     result = c.semExpr(c, n.sons[1])
     if result.kind == nkSym and result.sym.kind == skConst:
       result = result.sym.ast # look it up
     if result.typ == nil or result.typ.kind != tyString: 
-      GlobalError(n.info, errStringLiteralExpected)
+      LocalError(n.info, errStringLiteralExpected)
+      result = newEmptyStrNode(n)
     
 proc processDynLib(c: PContext, n: PNode, sym: PSym) = 
   if (sym == nil) or (sym.kind == skModule): 
@@ -359,7 +372,9 @@ proc semAsmOrEmit*(con: PContext, n: PNode, marker: char): PNode =
   of nkStrLit, nkRStrLit, nkTripleStrLit: 
     result = copyNode(n)
     var str = n.sons[1].strVal
-    if str == "": GlobalError(n.info, errEmptyAsm) 
+    if str == "":
+      LocalError(n.info, errEmptyAsm)
+      return
     # now parse the string literal and substitute symbols:
     var a = 0
     while true: 
@@ -405,15 +420,20 @@ proc PragmaLine(c: PContext, n: PNode) =
   if n.kind == nkExprColonExpr:
     n.sons[1] = c.semConstExpr(c, n.sons[1])
     let a = n.sons[1]
-    if a.kind != nkPar: GlobalError(n.info, errXExpected, "tuple")
-    var x = a.sons[0]
-    var y = a.sons[1]
-    if x.kind == nkExprColonExpr: x = x.sons[1]
-    if y.kind == nkExprColonExpr: y = y.sons[1]
-    if x.kind != nkStrLit: GlobalError(n.info, errStringLiteralExpected)
-    if y.kind != nkIntLit: GlobalError(n.info, errIntLiteralExpected)
-    n.info.fileIndex = msgs.fileInfoIdx(x.strVal)
-    n.info.line = int16(y.intVal)
+    if a.kind == nkPar: 
+      var x = a.sons[0]
+      var y = a.sons[1]
+      if x.kind == nkExprColonExpr: x = x.sons[1]
+      if y.kind == nkExprColonExpr: y = y.sons[1]
+      if x.kind != nkStrLit: 
+        LocalError(n.info, errStringLiteralExpected)
+      elif y.kind != nkIntLit: 
+        LocalError(n.info, errIntLiteralExpected)
+      else:
+        n.info.fileIndex = msgs.fileInfoIdx(x.strVal)
+        n.info.line = int16(y.intVal)
+    else:
+      LocalError(n.info, errXExpected, "tuple")
   else:
     # sensible default:
     n.info = getInfoContext(-1)
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 904adf955..c1ea6d1af 100755
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -37,7 +37,7 @@ proc addResultNode(c: PContext, n: PNode)
 proc instGenericContainer(c: PContext, n: PNode, header: PType): PType
 
 proc typeMismatch(n: PNode, formal, actual: PType) = 
-  GlobalError(n.Info, errGenerated, msgKindToString(errTypeMismatch) &
+  LocalError(n.Info, errGenerated, msgKindToString(errTypeMismatch) &
       typeToString(actual) & ") " &
       `%`(msgKindToString(errButExpectedX), [typeToString(formal)]))
 
@@ -45,6 +45,9 @@ proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
   result = IndexTypesMatch(c, formal, arg.typ, arg)
   if result == nil:
     typeMismatch(arg, formal, arg.typ)
+    # error correction:
+    result = copyNode(arg)
+    result.typ = formal
 
 proc isTopLevel(c: PContext): bool {.inline.} = 
   result = c.tab.tos <= 2
@@ -62,7 +65,7 @@ proc semStmtScope(c: PContext, n: PNode): PNode
 
 proc ParamsTypeCheck(c: PContext, typ: PType) {.inline.} =
   if not typeAllowed(typ, skConst):
-    GlobalError(typ.n.info, errXisNoType, typeToString(typ))
+    LocalError(typ.n.info, errXisNoType, typeToString(typ))
 
 proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym
 
@@ -80,13 +83,15 @@ proc evalTypedExpr(c: PContext, e: PNode): PNode =
   if result == nil:
     result = evalConstExpr(c.module, e)
     if result == nil or result.kind == nkEmpty:
-      GlobalError(e.info, errConstExprExpected)
+      LocalError(e.info, errConstExprExpected)
+      # error correction:
+      result = e
 
 proc semConstExpr(c: PContext, n: PNode): PNode =
   var e = semExprWithType(c, n)
   if e == nil:
-    GlobalError(n.info, errConstExprExpected)
-    return nil
+    LocalError(n.info, errConstExprExpected)
+    return n
   result = evalTypedExpr(c, e)
 
 include seminst, semcall
@@ -129,12 +134,15 @@ proc forceBool(c: PContext, n: PNode): PNode =
   if result == nil: result = n
 
 proc semConstBoolExpr(c: PContext, n: PNode): PNode = 
-  result = fitNode(c, getSysType(tyBool), semExprWithType(c, n))
-  if result == nil: 
-    GlobalError(n.info, errConstExprExpected)
-    return 
+  let nn = semExprWithType(c, n)
+  result = fitNode(c, getSysType(tyBool), nn)
+  if result == nil:
+    LocalError(n.info, errConstExprExpected)
+    return nn
   result = getConstExpr(c.module, result)
-  if result == nil: GlobalError(n.info, errConstExprExpected)
+  if result == nil: 
+    LocalError(n.info, errConstExprExpected)
+    result = nn
 
 include semtypes, semexprs, semgnrc, semstmts
 
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index fb5b8075a..26552c294 100755
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -224,6 +224,10 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType =
 proc newTypeS(kind: TTypeKind, c: PContext): PType = 
   result = newType(kind, getCurrOwner())
 
+proc errorType*(c: PContext): PType =
+  ## creates a type representing an error state
+  result = newTypeS(tyEmpty, c)
+
 proc fillTypeS(dest: PType, kind: TTypeKind, c: PContext) = 
   dest.kind = kind
   dest.owner = getCurrOwner()
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index d1606eef6..6a9af12ab 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -42,8 +42,9 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   if result.typ != nil: 
     if result.typ.kind == tyVar: result = newDeref(result)
   else:
-    GlobalError(n.info, errExprXHasNoType, 
-                renderTree(result, {renderNoComments}))
+    LocalError(n.info, errExprXHasNoType, 
+               renderTree(result, {renderNoComments}))
+    result.typ = errorType(c)
 
 proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = 
   result = semExpr(c, n, flags)
@@ -51,8 +52,9 @@ proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     # do not produce another redundant error message:
     raiseRecoverableError("")
   if result.typ == nil:
-    GlobalError(n.info, errExprXHasNoType, 
-                renderTree(result, {renderNoComments}))
+    LocalError(n.info, errExprXHasNoType, 
+               renderTree(result, {renderNoComments}))
+    result.typ = errorType(c)
 
 proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
   result = symChoice(c, n, s)
@@ -113,7 +115,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
       c.p.owner.typ.callConv = ccClosure
       if illegalCapture(s) or c.p.next.owner != s.owner:
         # Currently captures are restricted to a single level of nesting:
-        GlobalError(n.info, errIllegalCaptureX, s.name.s)
+        LocalError(n.info, errIllegalCaptureX, s.name.s)
     result = newSymNode(s, n.info)
   of skGenericParam:
     if s.ast == nil: InternalError(n.info, "no default for")
@@ -129,7 +131,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
 proc checkConversionBetweenObjects(info: TLineInfo, castDest, src: PType) =
   var diff = inheritanceDiff(castDest, src)
   if diff == high(int):
-    GlobalError(info, errGenerated, MsgKindToString(errIllegalConvFromXtoY) % [
+    LocalError(info, errGenerated, MsgKindToString(errIllegalConvFromXtoY) % [
         src.typeToString, castDest.typeToString])
 
 const 
@@ -147,7 +149,7 @@ proc checkConvertible(info: TLineInfo, castDest, src: PType) =
     d = base(d)
     s = base(s)
   if d == nil:
-    GlobalError(info, errGenerated, msgKindToString(errIllegalConvFromXtoY) % [
+    LocalError(info, errGenerated, msgKindToString(errIllegalConvFromXtoY) % [
         src.typeToString, castDest.typeToString])
   elif d.Kind == tyObject and s.Kind == tyObject: 
     checkConversionBetweenObjects(info, d, s)
@@ -159,7 +161,7 @@ proc checkConvertible(info: TLineInfo, castDest, src: PType) =
     case cmpTypes(d, s)
     of isNone, isGeneric: 
       if not compareTypes(castDest, src, dcEqIgnoreDistinct):
-        GlobalError(info, errGenerated, `%`(
+        LocalError(info, errGenerated, `%`(
             MsgKindToString(errIllegalConvFromXtoY), 
             [typeToString(src), typeToString(castDest)]))
     else: 
@@ -184,7 +186,9 @@ proc isCastable(dst, src: PType): bool =
         (skipTypes(src, abstractInst).kind in IntegralTypes)
   
 proc semConv(c: PContext, n: PNode, s: PSym): PNode = 
-  if sonsLen(n) != 2: GlobalError(n.info, errConvNeedsOneArg)
+  if sonsLen(n) != 2: 
+    LocalError(n.info, errConvNeedsOneArg)
+    return n
   result = newNodeI(nkConv, n.info)
   result.typ = semTypeNode(c, n.sons[0], nil)
   addSon(result, copyTree(n.sons[0]))
@@ -210,14 +214,14 @@ proc semCast(c: PContext, n: PNode): PNode =
   addSon(result, copyTree(n.sons[0]))
   addSon(result, semExprWithType(c, n.sons[1]))
   if not isCastable(result.typ, result.sons[1].Typ): 
-    GlobalError(result.info, errExprCannotBeCastedToX, 
-                typeToString(result.Typ))
+    LocalError(result.info, errExprCannotBeCastedToX, 
+               typeToString(result.Typ))
   
 proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode = 
   const 
     opToStr: array[mLow..mHigh, string] = ["low", "high"]
   if sonsLen(n) != 2: 
-    GlobalError(n.info, errXExpectsTypeOrValue, opToStr[m])
+    LocalError(n.info, errXExpectsTypeOrValue, opToStr[m])
   else: 
     n.sons[1] = semExprWithType(c, n.sons[1])
     restoreOldStyleType(n.sons[1])
@@ -229,12 +233,12 @@ proc semLowHigh(c: PContext, n: PNode, m: TMagic): PNode =
       n.typ = n.sons[1].typ.sons[0] # indextype
     of tyInt..tyInt64, tyChar, tyBool, tyEnum, tyUInt8, tyUInt16, tyUInt32: 
       n.typ = n.sons[1].typ
-    else: GlobalError(n.info, errInvalidArgForX, opToStr[m])
+    else: LocalError(n.info, errInvalidArgForX, opToStr[m])
   result = n
 
 proc semSizeof(c: PContext, n: PNode): PNode = 
   if sonsLen(n) != 2:
-    GlobalError(n.info, errXExpectsTypeOrValue, "sizeof")
+    LocalError(n.info, errXExpectsTypeOrValue, "sizeof")
   else: 
     n.sons[1] = semExprWithType(c, n.sons[1])
     restoreOldStyleType(n.sons[1])
@@ -253,26 +257,27 @@ proc semOf(c: PContext, n: PNode): PNode =
     let y = skipTypes(n.sons[2].typ, abstractPtrs)
 
     if x.kind == tyTypeDesc or y.kind != tyTypeDesc:
-      GlobalError(n.info, errXExpectsObjectTypes, "of")
+      LocalError(n.info, errXExpectsObjectTypes, "of")
     elif b.kind != tyObject or a.kind != tyObject:
-      GlobalError(n.info, errXExpectsObjectTypes, "of")
-    let diff = inheritanceDiff(a, b)
-    # | returns: 0 iff `a` == `b`
-    # | returns: -x iff `a` is the x'th direct superclass of `b`
-    # | returns: +x iff `a` is the x'th direct subclass of `b`
-    # | returns: `maxint` iff `a` and `b` are not compatible at all
-    if diff <= 0:
-      # optimize to true:
-      Message(n.info, hintConditionAlwaysTrue, renderTree(n))
-      result = newIntNode(nkIntLit, 1)
-      result.info = n.info
-      result.typ = getSysType(tyBool)
-      return result
-    elif diff == high(int):
-      GlobalError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
-    n.typ = getSysType(tyBool)
-  else: 
-    GlobalError(n.info, errXExpectsTwoArguments, "of")
+      LocalError(n.info, errXExpectsObjectTypes, "of")
+    else:
+      let diff = inheritanceDiff(a, b)
+      # | returns: 0 iff `a` == `b`
+      # | returns: -x iff `a` is the x'th direct superclass of `b`
+      # | returns: +x iff `a` is the x'th direct subclass of `b`
+      # | returns: `maxint` iff `a` and `b` are not compatible at all
+      if diff <= 0:
+        # optimize to true:
+        Message(n.info, hintConditionAlwaysTrue, renderTree(n))
+        result = newIntNode(nkIntLit, 1)
+        result.info = n.info
+        result.typ = getSysType(tyBool)
+        return result
+      elif diff == high(int):
+        LocalError(n.info, errXcanNeverBeOfThisSubtype, typeToString(a))
+  else:
+    LocalError(n.info, errXExpectsTwoArguments, "of")
+  n.typ = getSysType(tyBool)
   result = n
 
 proc semIs(c: PContext, n: PNode): PNode = 
@@ -283,9 +288,9 @@ proc semIs(c: PContext, n: PNode): PNode =
     if n[2].kind notin {nkStrLit..nkTripleStrLit}:
       let b = semTypeNode(c, n[2], nil)
       n.sons[2] = newNodeIT(nkType, n[2].info, b)
-    result = n
   else:
-    GlobalError(n.info, errXExpectsTwoArguments, "is")
+    LocalError(n.info, errXExpectsTwoArguments, "is")
+  result = n
 
 proc semOpAux(c: PContext, n: PNode) =
   for i in countup(1, sonsLen(n) - 1):
@@ -590,7 +595,7 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
     of skMacro, skTemplate: nil
     else:
       if (callee.kind == skIterator) and (callee.id == c.p.owner.id): 
-        GlobalError(n.info, errRecursiveDependencyX, callee.name.s)
+        LocalError(n.info, errRecursiveDependencyX, callee.name.s)
       if sfNoSideEffect notin callee.flags: 
         if {sfImportc, sfSideEffect} * callee.flags != {}:
           incl(c.p.owner.flags, sfSideEffect)
@@ -625,7 +630,8 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
     if m.state != csMatch:
       if c.inCompilesContext > 0:
         # speed up error generation:
-        GlobalError(n.Info, errTypeMismatch, "")
+        LocalError(n.Info, errTypeMismatch, "")
+        return emptyNode
       else:
         var msg = msgKindToString(errTypeMismatch)
         for i in countup(1, sonsLen(n) - 1): 
@@ -633,7 +639,8 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
           add(msg, typeToString(n.sons[i].typ))
         add(msg, ")\n" & msgKindToString(errButExpected) & "\n" &
             typeToString(n.sons[0].typ))
-        GlobalError(n.Info, errGenerated, msg)
+        LocalError(n.Info, errGenerated, msg)
+        return emptyNode
       result = nil
     else: 
       result = m.call
@@ -649,8 +656,9 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
       nOrig.sons[0] = prc
       result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
     if result == nil: 
-      GlobalError(n.info, errExprXCannotBeCalled, 
-                  renderTree(n, {renderNoComments}))
+      LocalError(n.info, errExprXCannotBeCalled, 
+                 renderTree(n, {renderNoComments}))
+      return emptyNode
   fixAbstractType(c, result)
   analyseIfAddressTakenInCall(c, result)
   if result.sons[0].kind == nkSym and result.sons[0].sym.magic != mNone:
@@ -664,7 +672,9 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
   result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
   if result == nil:
     result = overloadedCallOpr(c, n)
-    if result == nil: GlobalError(n.Info, errGenerated, getNotFoundError(c, n))
+    if result == nil: 
+      LocalError(n.Info, errGenerated, getNotFoundError(c, n))
+      return emptyNode
   let callee = result.sons[0].sym
   case callee.kind
   of skMacro: result = semMacroExpr(c, nOrig, callee)
@@ -696,8 +706,11 @@ proc buildEchoStmt(c: PContext, n: PNode): PNode =
   # we MUST not check 'n' for semantics again here!
   result = newNodeI(nkCall, n.info)
   var e = StrTableGet(magicsys.systemModule.Tab, getIdent"echo")
-  if e == nil: GlobalError(n.info, errSystemNeeds, "echo")
-  addSon(result, newSymNode(e))
+  if e != nil:
+    addSon(result, newSymNode(e))
+  else:
+    LocalError(n.info, errSystemNeeds, "echo")
+    addSon(result, emptyNode)
   var arg = buildStringify(c, n)
   # problem is: implicit '$' is not checked for semantics yet. So we give up
   # and check 'arg' for semantics again:
@@ -890,7 +903,8 @@ proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
         addSon(result, newIdentNode(i, n.info))
         addSon(result, copyTree(n[0]))
       else: 
-        GlobalError(n.Info, errUndeclaredFieldX, i.s)
+        LocalError(n.Info, errUndeclaredFieldX, i.s)
+        result = emptyNode
 
 proc buildOverloadedSubscripts(n: PNode, ident: PIdent): PNode =
   result = newNodeI(nkCall, n.info)
@@ -946,9 +960,9 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
         {tyInt..tyInt64}: 
       var idx = getOrdValue(n.sons[1])
       if idx >= 0 and idx < sonsLen(arr): n.typ = arr.sons[int(idx)]
-      else: GlobalError(n.info, errInvalidIndexValueForTuple)
+      else: LocalError(n.info, errInvalidIndexValueForTuple)
     else: 
-      GlobalError(n.info, errIndexTypesDoNotMatch)
+      LocalError(n.info, errIndexTypesDoNotMatch)
     result = n
   else: nil
   
@@ -972,7 +986,7 @@ proc propertyWriteAccess(c: PContext, n, nOrig, a: PNode): PNode =
     fixAbstractType(c, result)
     analyseIfAddressTakenInCall(c, result)
   else:
-    globalError(n.Info, errUndeclaredFieldX, id.s)
+    LocalError(n.Info, errUndeclaredFieldX, id.s)
 
 proc takeImplicitAddr(c: PContext, n: PNode): PNode =
   case n.kind
@@ -984,9 +998,9 @@ proc takeImplicitAddr(c: PContext, n: PNode): PNode =
   var valid = isAssignable(c, n)
   if valid != arLValue:
     if valid == arLocalLValue:
-      GlobalError(n.info, errXStackEscape, renderTree(n, {renderNoComments}))
+      LocalError(n.info, errXStackEscape, renderTree(n, {renderNoComments}))
     else:
-      GlobalError(n.info, errExprHasNoAddress)
+      LocalError(n.info, errExprHasNoAddress)
   result = newNodeIT(nkHiddenAddr, n.info, makePtrType(c, n.typ))
   result.add(n)
   
@@ -1062,13 +1076,13 @@ proc LookUpForDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PSym =
         else: 
           result = StrTableGet(m.tab, ident)
       else: 
-        GlobalError(n.sons[1].info, errIdentifierExpected, "")
+        LocalError(n.sons[1].info, errIdentifierExpected, "")
   of nkAccQuoted:
     result = lookupForDefined(c, considerAcc(n), onlyCurrentScope)
   of nkSym:
     result = n.sym
   else: 
-    GlobalError(n.info, errIdentifierExpected, renderTree(n))
+    LocalError(n.info, errIdentifierExpected, renderTree(n))
     result = nil
 
 proc semDefined(c: PContext, n: PNode, onlyCurrentScope: bool): PNode = 
@@ -1091,17 +1105,20 @@ proc setMs(n: PNode, s: PSym): PNode =
 proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym =
   ## The argument to the proc should be nkCall(...) or similar
   ## Returns the macro/template symbol
-  if not isCallExpr(n):
-    GlobalError(n.info, errXisNoMacroOrTemplate, n.renderTree)
-
-  var expandedSym = qualifiedLookup(c, n[0], {checkUndeclared})
-  if expandedSym == nil:
-    GlobalError(n.info, errUndeclaredIdentifier, n[0].renderTree)
+  if isCallExpr(n):
+    var expandedSym = qualifiedLookup(c, n[0], {checkUndeclared})
+    if expandedSym == nil:
+      LocalError(n.info, errUndeclaredIdentifier, n[0].renderTree)
+      return errorSym(n[0])
 
-  if expandedSym.kind notin {skMacro, skTemplate}:
-    GlobalError(n.info, errXisNoMacroOrTemplate, expandedSym.name.s)
+    if expandedSym.kind notin {skMacro, skTemplate}:
+      LocalError(n.info, errXisNoMacroOrTemplate, expandedSym.name.s)
+      return errorSym(n[0])
 
-  result = expandedSym
+    result = expandedSym
+  else:
+    LocalError(n.info, errXisNoMacroOrTemplate, n.renderTree)
+    result = errorSym(n)
 
 proc semExpandToAst(c: PContext, n: PNode, magicSym: PSym,
                     flags: TExprFlags): PNode =
@@ -1240,7 +1257,7 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
         if typ == nil: 
           typ = skipTypes(n.sons[i].typ, {tyGenericInst, tyVar, tyOrdinal})
     if not isOrdinalType(typ): 
-      GlobalError(n.info, errOrdinalTypeExpected)
+      LocalError(n.info, errOrdinalTypeExpected)
       return 
     if lengthOrd(typ) > MaxSetElements: 
       typ = makeRangeType(c, 0, MaxSetElements - 1, n.info)
@@ -1288,11 +1305,11 @@ proc checkPar(n: PNode): TParKind =
       if result == paTupleFields: 
         if (n.sons[i].kind != nkExprColonExpr) or
             not (n.sons[i].sons[0].kind in {nkSym, nkIdent}): 
-          GlobalError(n.sons[i].info, errNamedExprExpected)
+          LocalError(n.sons[i].info, errNamedExprExpected)
           return paNone
       else: 
         if n.sons[i].kind == nkExprColonExpr: 
-          GlobalError(n.sons[i].info, errNamedExprNotAllowed)
+          LocalError(n.sons[i].info, errNamedExprNotAllowed)
           return paNone
 
 proc semTupleFieldsConstr(c: PContext, n: PNode): PNode = 
@@ -1369,10 +1386,13 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
           addSon(result, n.sons[0].sons[i])
       for i in countup(1, sonsLen(n) - 1): addSon(result, n.sons[i])
       result = semTemplateExpr(c, result, s, semCheck)
-    else: GlobalError(n.info, errXisNoMacroOrTemplate, s.name.s)
-  else: 
-    GlobalError(n.info, errInvalidExpressionX, 
-                renderTree(a, {renderNoComments}))
+    else: 
+      LocalError(n.info, errXisNoMacroOrTemplate, s.name.s)
+      result = emptyNode
+  else:
+    LocalError(n.info, errInvalidExpressionX, 
+               renderTree(a, {renderNoComments}))
+    result = emptyNode
 
 proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = 
   result = n
@@ -1505,7 +1525,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     checkSonsLen(n, 1)
     n.sons[0] = semExprWithType(c, n.sons[0])
     if isAssignable(c, n.sons[0]) notin {arLValue, arLocalLValue}: 
-      GlobalError(n.info, errExprHasNoAddress)
+      LocalError(n.info, errExprHasNoAddress)
     n.typ = makePtrType(c, n.sons[0].typ)
   of nkHiddenAddr, nkHiddenDeref:
     checkSonsLen(n, 1)
@@ -1525,10 +1545,12 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   of nkTableConstr:
     result = semTableConstr(c, n)
   of nkSymChoice:
-    GlobalError(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments}))
+    LocalError(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments}))
+    # error correction: Pick first element:
+    result = n.sons[0]
   of nkStaticExpr:
     result = semStaticExpr(c, n)
   else:
-    GlobalError(n.info, errInvalidExpressionX, 
-                renderTree(n, {renderNoComments}))
+    LocalError(n.info, errInvalidExpressionX,
+               renderTree(n, {renderNoComments}))
   incl(result.flags, nfSem)
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index 646034218..c6a5aaa73 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -18,7 +18,7 @@ proc expectIntLit(c: PContext, n: PNode): int =
   let x = c.semConstExpr(c, n)
   case x.kind
   of nkIntLit..nkInt64Lit: result = int(x.intVal)
-  else: GlobalError(n.info, errIntLiteralExpected)
+  else: LocalError(n.info, errIntLiteralExpected)
 
 proc semInstantiationInfo(c: PContext, n: PNode): PNode =
   result = newNodeIT(nkPar, n.info, n.typ)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 7b1c6d76a..a5d2098c3 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -163,18 +163,20 @@ proc SemReturn(c: PContext, n: PNode): PNode =
   result = n
   checkSonsLen(n, 1)
   if c.p.owner.kind notin {skConverter, skMethod, skProc, skMacro}:
-    globalError(n.info, errXNotAllowedHere, "\'return\'")
-  if n.sons[0].kind != nkEmpty:
+    LocalError(n.info, errXNotAllowedHere, "\'return\'")
+  elif n.sons[0].kind != nkEmpty:
     # transform ``return expr`` to ``result = expr; return``
-    if c.p.resultSym == nil: globalError(n.info, errNoReturnTypeDeclared)
-    var a = newNodeI(nkAsgn, n.sons[0].info)
-    addSon(a, newSymNode(c.p.resultSym))
-    addSon(a, n.sons[0])
-    n.sons[0] = semAsgn(c, a)
-    # optimize away ``result = result``:
-    if n[0][1].kind == nkSym and n[0][1].sym.kind == skResult: 
-      n.sons[0] = ast.emptyNode
-  
+    if c.p.resultSym != nil: 
+      var a = newNodeI(nkAsgn, n.sons[0].info)
+      addSon(a, newSymNode(c.p.resultSym))
+      addSon(a, n.sons[0])
+      n.sons[0] = semAsgn(c, a)
+      # optimize away ``result = result``:
+      if n[0][1].kind == nkSym and n[0][1].sym.kind == skResult: 
+        n.sons[0] = ast.emptyNode
+    else:
+      LocalError(n.info, errNoReturnTypeDeclared)
+
 proc SemYieldVarResult(c: PContext, n: PNode, restype: PType) =
   var t = skipTypes(restype, {tyGenericInst})
   case t.kind
@@ -198,8 +200,8 @@ proc SemYield(c: PContext, n: PNode): PNode =
   result = n
   checkSonsLen(n, 1)
   if c.p.owner == nil or c.p.owner.kind != skIterator: 
-    GlobalError(n.info, errYieldNotAllowedHere)
-  if n.sons[0].kind != nkEmpty:
+    LocalError(n.info, errYieldNotAllowedHere)
+  elif n.sons[0].kind != nkEmpty:
     n.sons[0] = SemExprWithType(c, n.sons[0]) # check for type compatibility:
     var restype = c.p.owner.typ.sons[0]
     if restype != nil: 
@@ -254,22 +256,24 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
       else: typ = skipIntLit(def.typ)
     else:
       def = ast.emptyNode
-      if symkind == skLet: GlobalError(a.info, errLetNeedsInit)
+      if symkind == skLet: LocalError(a.info, errLetNeedsInit)
       
     # this can only happen for errornous var statements:
     if typ == nil: continue
     if not typeAllowed(typ, symkind): 
-      GlobalError(a.info, errXisNoType, typeToString(typ))
+      LocalError(a.info, errXisNoType, typeToString(typ))
     var tup = skipTypes(typ, {tyGenericInst})
     if a.kind == nkVarTuple: 
-      if tup.kind != tyTuple: GlobalError(a.info, errXExpected, "tuple")
-      if length-2 != sonsLen(tup): 
-        GlobalError(a.info, errWrongNumberOfVariables)
-      b = newNodeI(nkVarTuple, a.info)
-      newSons(b, length)
-      b.sons[length-2] = a.sons[length-2] # keep type desc for doc generator
-      b.sons[length-1] = def
-      addSon(result, b)
+      if tup.kind != tyTuple: 
+        localError(a.info, errXExpected, "tuple")
+      elif length-2 != sonsLen(tup): 
+        localError(a.info, errWrongNumberOfVariables)
+      else:
+        b = newNodeI(nkVarTuple, a.info)
+        newSons(b, length)
+        b.sons[length-2] = a.sons[length-2] # keep type desc for doc generator
+        b.sons[length-1] = def
+        addSon(result, b)
     elif tup.kind == tyTuple and def.kind == nkPar and 
         a.kind == nkIdentDefs and a.len > 3:
       Message(a.info, warnEachIdentIsTuple)
@@ -308,33 +312,19 @@ proc semConst(c: PContext, n: PNode): PNode =
     var typ: PType = nil
     if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil)
 
-    when true:
-      var def = semConstExpr(c, a.sons[2])
-      if def == nil: GlobalError(a.sons[2].info, errConstExprExpected)
-      # check type compatibility between def.typ and typ:
-      if typ != nil:
-        def = fitRemoveHiddenConv(c, typ, def)
-      else:
-        typ = def.typ
-      if not typeAllowed(typ, skConst):
-        GlobalError(a.info, errXisNoType, typeToString(typ))
+    var def = semConstExpr(c, a.sons[2])
+    if def == nil:
+      LocalError(a.sons[2].info, errConstExprExpected)
+      continue
+    # check type compatibility between def.typ and typ:
+    if typ != nil:
+      def = fitRemoveHiddenConv(c, typ, def)
     else:
-      var e = semExprWithType(c, a.sons[2])
-      if e == nil: GlobalError(a.sons[2].info, errConstExprExpected)
-      var def = getConstExpr(c.module, e)
-      if def == nil: 
-        v.flags.incl(sfFakeConst)
-        def = evalConstExpr(c.module, e)
-        if def == nil or def.kind == nkEmpty: def = e
-      # check type compatibility between def.typ and typ:
-      if typ != nil:
-        def = fitRemoveHiddenConv(c, typ, def)
-      else:
-        typ = def.typ
-      if not typeAllowed(typ, skConst):
-        v.flags.incl(sfFakeConst)
-        if not typeAllowed(typ, skVar):
-          GlobalError(a.info, errXisNoType, typeToString(typ))
+      typ = def.typ
+    if typ == nil: continue
+    if not typeAllowed(typ, skConst):
+      LocalError(a.info, errXisNoType, typeToString(typ))
+      continue
     v.typ = typ
     v.ast = def               # no need to copy
     addInterfaceDecl(c, v)
@@ -382,7 +372,10 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
   # a 'while true: stmt; break' loop ...
   result = newNodeI(nkWhileStmt, n.info)
   var trueSymbol = StrTableGet(magicsys.systemModule.Tab, getIdent"true")
-  if trueSymbol == nil: GlobalError(n.info, errSystemNeeds, "true")
+  if trueSymbol == nil: 
+    LocalError(n.info, errSystemNeeds, "true")
+    trueSymbol = newSym(skUnknown, getIdent"true", getCurrOwner())
+    trueSymbol.typ = getSysType(tyBool)
 
   result.add(newSymNode(trueSymbol, n.info))
   var stmts = newNodeI(nkStmtList, n.info)
@@ -391,7 +384,8 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
   var length = sonsLen(n)
   var call = n.sons[length-2]
   if length-2 != sonsLen(call)-1 + ord(m==mFieldPairs):
-    GlobalError(n.info, errWrongNumberOfVariables)
+    LocalError(n.info, errWrongNumberOfVariables)
+    return result
   
   var tupleTypeA = skipTypes(call.sons[1].typ, abstractVar)
   if tupleTypeA.kind != tyTuple: InternalError(n.info, "no tuple type!")
@@ -422,18 +416,20 @@ proc semForVars(c: PContext, n: PNode): PNode =
   # length == 3 means that there is one for loop variable
   # and thus no tuple unpacking:
   if iter.kind != tyTuple or length == 3: 
-    if length != 3: GlobalError(n.info, errWrongNumberOfVariables)
-    var v = newSymS(skForVar, n.sons[0], c)
-    if getCurrOwner().kind == skModule: incl(v.flags, sfGlobal)
-    # BUGFIX: don't use `iter` here as that would strip away
-    # the ``tyGenericInst``! See ``tests/compile/tgeneric.nim``
-    # for an example:
-    v.typ = n.sons[length-2].typ
-    n.sons[0] = newSymNode(v)
-    addDecl(c, v)
-  else: 
-    if length-2 != sonsLen(iter):
-      GlobalError(n.info, errWrongNumberOfVariables)
+    if length == 3:
+      var v = newSymS(skForVar, n.sons[0], c)
+      if getCurrOwner().kind == skModule: incl(v.flags, sfGlobal)
+      # BUGFIX: don't use `iter` here as that would strip away
+      # the ``tyGenericInst``! See ``tests/compile/tgeneric.nim``
+      # for an example:
+      v.typ = n.sons[length-2].typ
+      n.sons[0] = newSymNode(v)
+      addDecl(c, v)
+    else:
+      LocalError(n.info, errWrongNumberOfVariables)
+  elif length-2 != sonsLen(iter):
+    LocalError(n.info, errWrongNumberOfVariables)
+  else:
     for i in countup(0, length - 3): 
       var v = newSymS(skForVar, n.sons[i], c)
       if getCurrOwner().kind == skModule: incl(v.flags, sfGlobal)
@@ -461,12 +457,11 @@ proc semFor(c: PContext, n: PNode): PNode =
       call.sons[0].sym.kind != skIterator: 
     if length == 3:
       n.sons[length-2] = implicitIterator(c, "items", n.sons[length-2])
-      result = semForVars(c, n)
     elif length == 4:
       n.sons[length-2] = implicitIterator(c, "pairs", n.sons[length-2])
-      result = semForVars(c, n)
     else:
-      GlobalError(n.sons[length - 2].info, errIteratorExpected)
+      LocalError(n.sons[length-2].info, errIteratorExpected)
+    result = semForVars(c, n)
   elif call.sons[0].sym.magic != mNone:
     if call.sons[0].sym.magic == mOmpParFor:
       result = semForVars(c, n)
@@ -504,7 +499,7 @@ proc semTry(c: PContext, n: PNode): PNode =
         var typ = semTypeNode(c, a.sons[j], nil)
         if typ.kind == tyRef: typ = typ.sons[0]
         if typ.kind != tyObject:
-          GlobalError(a.sons[j].info, errExprCannotBeRaised)
+          LocalError(a.sons[j].info, errExprCannotBeRaised)
         a.sons[j] = newNodeI(nkType, a.sons[j].info)
         a.sons[j].typ = typ
         if ContainsOrIncl(check, typ.id):
@@ -549,7 +544,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
     if (a.sons[0].kind != nkSym): IllFormedAst(a)
     var s = a.sons[0].sym
     if s.magic == mNone and a.sons[2].kind == nkEmpty: 
-      GlobalError(a.info, errImplOfXexpected, s.name.s)
+      LocalError(a.info, errImplOfXexpected, s.name.s)
     if s.magic != mNone: processMagicType(c, s)
     if a.sons[1].kind != nkEmpty: 
       # We have a generic type declaration here. In generic types,
@@ -901,9 +896,10 @@ proc evalInclude(c: PContext, n: PNode): PNode =
     var f = checkModuleName(n.sons[i])
     var fileIndex = f.fileInfoIdx
     if ContainsOrIncl(c.includedFiles, fileIndex): 
-      GlobalError(n.info, errRecursiveDependencyX, f.extractFilename)
-    addSon(result, semStmt(c, gIncludeFile(f)))
-    Excl(c.includedFiles, fileIndex)
+      LocalError(n.info, errRecursiveDependencyX, f.extractFilename)
+    else:
+      addSon(result, semStmt(c, gIncludeFile(f)))
+      Excl(c.includedFiles, fileIndex)
   
 proc setLine(n: PNode, info: TLineInfo) =
   for i in 0 .. <safeLen(n): setLine(n.sons[i], info)
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 39c5acad1..e77bb9f86 100755
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -46,11 +46,14 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
       var strVal: PNode = nil
       case skipTypes(v.typ, abstractInst).kind 
       of tyTuple: 
-        if sonsLen(v) != 2: GlobalError(v.info, errWrongNumberOfVariables)
-        strVal = v.sons[1] # second tuple part is the string value
-        if skipTypes(strVal.typ, abstractInst).kind notin {tyString, tyCstring}:
-          GlobalError(strVal.info, errStringLiteralExpected)
-        x = getOrdValue(v.sons[0]) # first tuple part is the ordinal
+        if sonsLen(v) == 2:
+          strVal = v.sons[1] # second tuple part is the string value
+          if skipTypes(strVal.typ, abstractInst).kind in {tyString, tyCstring}:
+            x = getOrdValue(v.sons[0]) # first tuple part is the ordinal
+          else:
+            LocalError(strVal.info, errStringLiteralExpected)
+        else:
+          LocalError(v.info, errWrongNumberOfVariables)
       of tyString, tyCstring:
         strVal = v
         x = counter
@@ -59,7 +62,8 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
       if i != 1:
         if x != counter: incl(result.flags, tfEnumHasHoles)
         if x < counter: 
-          GlobalError(n.sons[i].info, errInvalidOrderInEnumX, e.name.s)
+          LocalError(n.sons[i].info, errInvalidOrderInEnumX, e.name.s)
+          x = counter
       e.ast = strVal # might be nil
       counter = x
     of nkSym: 
@@ -84,10 +88,13 @@ proc semSet(c: PContext, n: PNode, prev: PType): PType =
     addSonSkipIntLit(result, base)
     if base.kind == tyGenericInst: base = lastSon(base)
     if base.kind != tyGenericParam: 
-      if not isOrdinalType(base): GlobalError(n.info, errOrdinalTypeExpected)
-      if lengthOrd(base) > MaxSetElements: GlobalError(n.info, errSetTooBig)
-  else: 
-    GlobalError(n.info, errXExpectsOneTypeParam, "set")
+      if not isOrdinalType(base): 
+        LocalError(n.info, errOrdinalTypeExpected)
+      elif lengthOrd(base) > MaxSetElements: 
+        LocalError(n.info, errSetTooBig)
+  else:
+    LocalError(n.info, errXExpectsOneTypeParam, "set")
+    addSonSkipIntLit(result, errorType(c))
   
 proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string, 
                   prev: PType): PType = 
@@ -96,7 +103,8 @@ proc semContainer(c: PContext, n: PNode, kind: TTypeKind, kindStr: string,
     var base = semTypeNode(c, n.sons[1], nil)
     addSonSkipIntLit(result, base)
   else: 
-    GlobalError(n.info, errXExpectsOneTypeParam, kindStr)
+    LocalError(n.info, errXExpectsOneTypeParam, kindStr)
+    addSonSkipIntLit(result, errorType(c))
 
 proc semAnyRef(c: PContext, n: PNode, kind: TTypeKind, prev: PType): PType = 
   if sonsLen(n) == 1:
@@ -110,7 +118,9 @@ proc semVarType(c: PContext, n: PNode, prev: PType): PType =
   if sonsLen(n) == 1: 
     result = newOrPrevType(tyVar, prev, c)
     var base = semTypeNode(c, n.sons[0], nil)
-    if base.kind == tyVar: GlobalError(n.info, errVarVarTypeNotAllowed)
+    if base.kind == tyVar: 
+      LocalError(n.info, errVarVarTypeNotAllowed)
+      base = base.sons[0]
     addSonSkipIntLit(result, base)
   else:
     result = newConstraint(c, tyVar)
@@ -128,28 +138,32 @@ proc semRangeAux(c: PContext, n: PNode, prev: PType): PType =
   result = newOrPrevType(tyRange, prev, c)
   result.n = newNodeI(nkRange, n.info)
   if (n[1].kind == nkEmpty) or (n[2].kind == nkEmpty): 
-    GlobalError(n.Info, errRangeIsEmpty)
+    LocalError(n.Info, errRangeIsEmpty)
   var a = semConstExpr(c, n[1])
   var b = semConstExpr(c, n[2])
-  if not sameType(a.typ, b.typ): GlobalError(n.info, errPureTypeMismatch)
-  if a.typ.kind notin {tyInt..tyInt64,tyEnum,tyBool,tyChar,tyFloat..tyFloat128,
-                       tyUInt8..tyUInt32}:
-    GlobalError(n.info, errOrdinalTypeExpected)
-  if enumHasHoles(a.typ): 
-    GlobalError(n.info, errEnumXHasHoles, a.typ.sym.name.s)
-  if not leValue(a, b): GlobalError(n.Info, errRangeIsEmpty)
+  if not sameType(a.typ, b.typ): 
+    LocalError(n.info, errPureTypeMismatch)
+  elif a.typ.kind notin {tyInt..tyInt64,tyEnum,tyBool,tyChar,
+                         tyFloat..tyFloat128,tyUInt8..tyUInt32}:
+    LocalError(n.info, errOrdinalTypeExpected)
+  elif enumHasHoles(a.typ): 
+    LocalError(n.info, errEnumXHasHoles, a.typ.sym.name.s)
+  elif not leValue(a, b): LocalError(n.Info, errRangeIsEmpty)
   addSon(result.n, a)
   addSon(result.n, b)
   addSonSkipIntLit(result, b.typ)
 
-proc semRange(c: PContext, n: PNode, prev: PType): PType = 
+proc semRange(c: PContext, n: PNode, prev: PType): PType =
   result = nil
-  if sonsLen(n) == 2: 
+  if sonsLen(n) == 2:
     if isRange(n[1]): result = semRangeAux(c, n[1], prev)
-    else: GlobalError(n.sons[0].info, errRangeExpected)
-  else: 
-    GlobalError(n.info, errXExpectsOneTypeParam, "range")
-  
+    else:
+      LocalError(n.sons[0].info, errRangeExpected)
+      result = errorType(c)
+  else:
+    LocalError(n.info, errXExpectsOneTypeParam, "range")
+    result = errorType(c)
+
 proc semArray(c: PContext, n: PNode, prev: PType): PType = 
   var indx, base: PType
   result = newOrPrevType(tyArray, prev, c)
@@ -161,13 +175,14 @@ proc semArray(c: PContext, n: PNode, prev: PType): PType =
     if indx.kind == tyGenericInst: indx = lastSon(indx)
     if indx.kind != tyGenericParam: 
       if not isOrdinalType(indx): 
-        GlobalError(n.sons[1].info, errOrdinalTypeExpected)
-      if enumHasHoles(indx): 
-        GlobalError(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s)
+        LocalError(n.sons[1].info, errOrdinalTypeExpected)
+      elif enumHasHoles(indx): 
+        LocalError(n.sons[1].info, errEnumXHasHoles, indx.sym.name.s)
     base = semTypeNode(c, n.sons[2], nil)
     addSonSkipIntLit(result, base)
   else: 
-    GlobalError(n.info, errArrayExpectsTwoTypeParams)
+    LocalError(n.info, errArrayExpectsTwoTypeParams)
+    result = errorType(c)
   
 proc semOrdinal(c: PContext, n: PNode, prev: PType): PType = 
   result = newOrPrevType(tyOrdinal, prev, c)
@@ -175,10 +190,11 @@ proc semOrdinal(c: PContext, n: PNode, prev: PType): PType =
     var base = semTypeNode(c, n.sons[1], nil)
     if base.kind != tyGenericParam: 
       if not isOrdinalType(base): 
-        GlobalError(n.sons[1].info, errOrdinalTypeExpected)
+        LocalError(n.sons[1].info, errOrdinalTypeExpected)
     addSonSkipIntLit(result, base)
-  else: 
-    GlobalError(n.info, errXExpectsOneTypeParam, "ordinal")
+  else:
+    LocalError(n.info, errXExpectsOneTypeParam, "ordinal")
+    result = errorType(c)
   
 proc semTypeIdent(c: PContext, n: PNode): PSym =
   if n.kind == nkSym: 
@@ -205,14 +221,17 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
         while amb != nil and amb.kind != skType:
           amb = nextOverloadIter(ov, c, n)
         if amb != nil: result = amb
-        else: GlobalError(n.info, errTypeExpected)
+        else:
+          LocalError(n.info, errTypeExpected)
+          return errorSym(n)
       if result.typ.kind != tyGenericParam:
         # XXX get rid of this hack!
         reset(n[])
         n.kind = nkSym
         n.sym = result
     else:
-      GlobalError(n.info, errIdentifierExpected)
+      LocalError(n.info, errIdentifierExpected)
+      result = errorSym(n)
   
 proc semTuple(c: PContext, n: PNode, prev: PType): PType = 
   if n.sonsLen == 0: return newConstraint(c, tyTuple)
@@ -228,18 +247,21 @@ proc semTuple(c: PContext, n: PNode, prev: PType): PType =
     var length = sonsLen(a)
     if a.sons[length - 2].kind != nkEmpty: 
       typ = semTypeNode(c, a.sons[length - 2], nil)
-    else: GlobalError(a.info, errTypeExpected)
+    else:
+      LocalError(a.info, errTypeExpected)
+      typ = errorType(c)
     if a.sons[length - 1].kind != nkEmpty: 
-      GlobalError(a.sons[length - 1].info, errInitHereNotAllowed)
+      LocalError(a.sons[length - 1].info, errInitHereNotAllowed)
     for j in countup(0, length - 3): 
       var field = newSymS(skField, a.sons[j], c)
       field.typ = typ
       field.position = counter
       inc(counter)
       if ContainsOrIncl(check, field.name.id): 
-        GlobalError(a.sons[j].info, errAttemptToRedefine, field.name.s)
-      addSon(result.n, newSymNode(field))
-      addSonSkipIntLit(result, typ)
+        LocalError(a.sons[j].info, errAttemptToRedefine, field.name.s)
+      else:
+        addSon(result.n, newSymNode(field))
+        addSonSkipIntLit(result, typ)
 
 proc semIdentVis(c: PContext, kind: TSymKind, n: PNode, 
                  allowed: TSymFlags): PSym = 
@@ -290,8 +312,8 @@ proc semBranchRange(c: PContext, t, a, b: PNode, covered: var biggestInt): PNode
   result = newNodeI(nkRange, a.info)
   result.add(at)
   result.add(bt)
-  if emptyRange(ac, bc): GlobalError(b.info, errRangeIsEmpty)
-  covered = covered + getOrdValue(bc) - getOrdValue(ac) + 1
+  if emptyRange(ac, bc): LocalError(b.info, errRangeIsEmpty)
+  else: covered = covered + getOrdValue(bc) - getOrdValue(ac) + 1
 
 proc SemCaseBranchRange(c: PContext, t, b: PNode, 
                         covered: var biggestInt): PNode = 
@@ -349,11 +371,12 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
   incl(a.sons[0].sym.flags, sfDiscriminant)
   var covered: biggestInt = 0
   var typ = skipTypes(a.sons[0].Typ, abstractVar)
-  if not isOrdinalType(typ): GlobalError(n.info, errSelectorMustBeOrdinal)
-  if firstOrd(typ) < 0: 
-    GlobalError(n.info, errOrdXMustNotBeNegative, a.sons[0].sym.name.s)
-  if lengthOrd(typ) > 0x00007FFF: 
-    GlobalError(n.info, errLenXinvalid, a.sons[0].sym.name.s)
+  if not isOrdinalType(typ): 
+    LocalError(n.info, errSelectorMustBeOrdinal)
+  elif firstOrd(typ) < 0: 
+    LocalError(n.info, errOrdXMustNotBeNegative, a.sons[0].sym.name.s)
+  elif lengthOrd(typ) > 0x00007FFF: 
+    LocalError(n.info, errLenXinvalid, a.sons[0].sym.name.s)
   var chckCovered = true
   for i in countup(1, sonsLen(n) - 1): 
     var b = copyTree(n.sons[i])
@@ -426,10 +449,13 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
     else: a = ast.emptyNode
     if n.sons[length-1].kind != nkEmpty: 
       localError(n.sons[length-1].info, errInitHereNotAllowed)
+    var typ: PType
     if n.sons[length-2].kind == nkEmpty: 
-      GlobalError(n.info, errTypeExpected)
-    var typ = semTypeNode(c, n.sons[length-2], nil)
-    for i in countup(0, sonsLen(n)-3): 
+      LocalError(n.info, errTypeExpected)
+      typ = errorType(c)
+    else:
+      typ = semTypeNode(c, n.sons[length-2], nil)
+    for i in countup(0, sonsLen(n)-3):
       var f = semIdentWithPragma(c, skField, n.sons[i], {sfExported})
       f.typ = typ
       f.position = pos
@@ -568,7 +594,9 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
       let s = SymtabGet(c.tab, paramTypId)
       # tests/run/tinterf triggers this:
       if s != nil: result = s.typ
-      else: GlobalError(info, errCannotInstantiateX, paramName)
+      else: 
+        LocalError(info, errCannotInstantiateX, paramName)
+        result = errorType(c)
     else:
       block addImplicitGeneric:
         # is this a bindOnce type class already present in the param list?
@@ -700,13 +728,15 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
   result = newOrPrevType(tyGenericInvokation, prev, c)
   var isConcrete = true
   if s.typ == nil:
-    GlobalError(n.info, errCannotInstantiateX, s.name.s)
+    LocalError(n.info, errCannotInstantiateX, s.name.s)
+    return errorType(c)
   elif s.typ.kind != tyGenericBody:
     isConcrete = false
   elif s.typ.containerID == 0: 
     InternalError(n.info, "semtypes.semGeneric")
   elif sonsLen(n) != sonsLen(s.typ): 
-    GlobalError(n.info, errWrongNumberOfArguments)
+    LocalError(n.info, errWrongNumberOfArguments)
+    return errorType(c)
   addSonSkipIntLit(result, s.typ)
   # iterate over arguments:
   for i in countup(1, sonsLen(n)-1):
@@ -716,12 +746,15 @@ proc semGeneric(c: PContext, n: PNode, s: PSym, prev: PType): PType =
     if elem.isNil: rawAddSon(result, elem)
     else: addSonSkipIntLit(result, elem)
   if isConcrete:
-    if s.ast == nil: GlobalError(n.info, errCannotInstantiateX, s.name.s)
-    result = instGenericContainer(c, n, result)
+    if s.ast == nil: 
+      LocalError(n.info, errCannotInstantiateX, s.name.s)
+      result = errorType(c)
+    else:
+      result = instGenericContainer(c, n, result)
 
 proc semTypeFromMacro(c: PContext, n: PNode): PType =
   # Expands a macro or template until a type is returned
-  # results in GlobalError if the macro expands to something different
+  # results in an error type if the macro expands to something different
   var sym = expectMacroOrTemplateCall(c, n)
   markUsed(n, sym)
   case sym.kind
@@ -730,7 +763,8 @@ proc semTypeFromMacro(c: PContext, n: PNode): PType =
   of skTemplate:
     result = semTypeNode(c, semTemplateExpr(c, n, sym), nil)
   else:
-    GlobalError(n.info, errXisNoMacroOrTemplate, n.renderTree)
+    LocalError(n.info, errXisNoMacroOrTemplate, n.renderTree)
+    result = errorType(c)
 
 proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
   result = nil
@@ -743,16 +777,21 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
     result = semExprWithType(c, n.sons[0], {efInTypeof}).typ
   of nkPar: 
     if sonsLen(n) == 1: result = semTypeNode(c, n.sons[0], prev)
-    else: GlobalError(n.info, errTypeExpected)
+    else:
+      LocalError(n.info, errTypeExpected)
+      result = errorType(c)
   of nkCallKinds:
     let op = n.sons[0].ident
     if op.id in {ord(wAnd), ord(wOr)} or op.s == "|":
       var
         t1 = semTypeNode(c, n.sons[1], nil)
         t2 = semTypeNode(c, n.sons[2], nil)
-
-      if   t1 == nil: GlobalError(n.sons[1].info, errTypeExpected)
-      elif t2 == nil: GlobalError(n.sons[2].info, errTypeExpected)
+      if   t1 == nil: 
+        LocalError(n.sons[1].info, errTypeExpected)
+        result = errorType(c)
+      elif t2 == nil: 
+        LocalError(n.sons[2].info, errTypeExpected)
+        result = errorType(c)
       else:
         result = newTypeS(tyTypeClass, c)
         result.addSonSkipIntLit(t1)
@@ -783,14 +822,16 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
     else: result = semGeneric(c, n, s, prev)
   of nkIdent, nkDotExpr, nkAccQuoted: 
     var s = semTypeIdent(c, n)
-    if s.typ == nil: GlobalError(n.info, errTypeExpected)
-    if prev == nil: 
+    if s.typ == nil: 
+      LocalError(n.info, errTypeExpected)
+      result = errorType(c)
+    elif prev == nil:
       result = s.typ
     else: 
       assignType(prev, s.typ)
       prev.id = s.typ.id
       result = prev
-  of nkSym: 
+  of nkSym:
     if n.sym.kind == skType and n.sym.typ != nil:
       var t = n.sym.typ
       if prev == nil: 
@@ -799,8 +840,9 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
         assignType(prev, t)
         result = prev
       markUsed(n, n.sym)
-    else: 
-      GlobalError(n.info, errTypeExpected)
+    else:
+      LocalError(n.info, errTypeExpected)
+      result = errorType(c)
   of nkObjectTy: result = semObjectNode(c, n, prev)
   of nkTupleTy: result = semTuple(c, n, prev)
   of nkRefTy: result = semAnyRef(c, n, tyRef, prev)
@@ -826,7 +868,9 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
   of nkType: result = n.typ
   of nkStmtListType: result = semStmtListType(c, n, prev)
   of nkBlockType: result = semBlockType(c, n, prev)
-  else: GlobalError(n.info, errTypeExpected) 
+  else: 
+    LocalError(n.info, errTypeExpected)
+    result = errorType(c)
   
 proc setMagicType(m: PSym, kind: TTypeKind, size: int) = 
   m.typ.kind = kind
@@ -874,7 +918,7 @@ proc processMagicType(c: PContext, m: PSym) =
   of mSeq: setMagicType(m, tySequence, 0)
   of mOrdinal: setMagicType(m, tyOrdinal, 0)
   of mPNimrodNode: nil
-  else: GlobalError(m.info, errTypeExpected)
+  else: LocalError(m.info, errTypeExpected)
   
 proc semGenericConstraints(c: PContext, n: PNode, result: PType) = 
   var x = semTypeNode(c, n, nil)
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 8cd7c3d1a..d75594dff 100755
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -119,7 +119,8 @@ proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
 proc lookupTypeVar(cl: TReplTypeVars, t: PType): PType = 
   result = PType(idTableGet(cl.typeMap, t))
   if result == nil:
-    GlobalError(t.sym.info, errCannotInstantiateX, typeToString(t))
+    LocalError(t.sym.info, errCannotInstantiateX, typeToString(t))
+    result = errorType(cl.c)
   elif result.kind == tyGenericParam: 
     InternalError(cl.info, "substitution with generic parameter")
   
diff --git a/todo.txt b/todo.txt
index 2668945fa..0a7bcee89 100755
--- a/todo.txt
+++ b/todo.txt
@@ -29,6 +29,7 @@ Bugs
   compiles
 - bug: blocks can "export" an identifier but the CCG generates {} for them ...
 
+
 version 0.9.XX
 ==============