summary refs log tree commit diff stats
path: root/nim/semstmts.pas
diff options
context:
space:
mode:
Diffstat (limited to 'nim/semstmts.pas')
-rwxr-xr-xnim/semstmts.pas1116
1 files changed, 0 insertions, 1116 deletions
diff --git a/nim/semstmts.pas b/nim/semstmts.pas
deleted file mode 100755
index 1ece72023..000000000
--- a/nim/semstmts.pas
+++ /dev/null
@@ -1,1116 +0,0 @@
-//
-//
-//           The Nimrod Compiler
-//        (c) Copyright 2009 Andreas Rumpf
-//
-//    See the file "copying.txt", included in this
-//    distribution, for details about the copyright.
-//
-
-// this module does the semantic checking of statements
-
-function semWhen(c: PContext; n: PNode): PNode;
-var
-  i: int;
-  it, e: PNode;
-begin
-  result := nil;
-  for i := 0 to sonsLen(n)-1 do begin
-    it := n.sons[i];
-    if it = nil then illFormedAst(n);
-    case it.kind of
-      nkElifBranch: begin
-        checkSonsLen(it, 2);
-        e := semConstExpr(c, it.sons[0]);
-        checkBool(e);
-        if (e.kind <> nkIntLit) then InternalError(n.info, 'semWhen');
-        if (e.intVal <> 0) and (result = nil) then
-          result := semStmt(c, it.sons[1]); // do not open a new scope!
-      end;
-      nkElse: begin
-        checkSonsLen(it, 1);
-        if result = nil then result := semStmt(c, it.sons[0])
-        // do not open a new scope!
-      end;
-      else illFormedAst(n)
-    end
-  end;
-  if result = nil then result := newNodeI(nkNilLit, n.info);
-  // The ``when`` statement implements the mechanism for platform dependant
-  // code. Thus we try to ensure here consistent ID allocation after the
-  // ``when`` statement.
-  IDsynchronizationPoint(200);
-end;
-
-function semIf(c: PContext; n: PNode): PNode;
-var
-  i: int;
-  it: PNode;
-begin
-  result := n;
-  for i := 0 to sonsLen(n)-1 do begin
-    it := n.sons[i];
-    if it = nil then illFormedAst(n);
-    case it.kind of
-      nkElifBranch: begin
-        checkSonsLen(it, 2);
-        openScope(c.tab);
-        it.sons[0] := semExprWithType(c, it.sons[0]);
-        checkBool(it.sons[0]);
-        it.sons[1] := semStmt(c, it.sons[1]);
-        closeScope(c.tab);
-      end;
-      nkElse: begin
-        if sonsLen(it) = 1 then it.sons[0] := semStmtScope(c, it.sons[0])
-        else illFormedAst(it)
-      end;
-      else illFormedAst(n)
-    end
-  end
-end;
-
-function semDiscard(c: PContext; n: PNode): PNode;
-begin
-  result := n;
-  checkSonsLen(n, 1);
-  n.sons[0] := semExprWithType(c, n.sons[0]);
-  if n.sons[0].typ = nil then liMessage(n.info, errInvalidDiscard);
-end;
-
-function semBreakOrContinue(c: PContext; n: PNode): PNode;
-var
-  s: PSym;
-  x: PNode;
-begin
-  result := n;
-  checkSonsLen(n, 1);
-  if n.sons[0] <> nil then begin
-    case n.sons[0].kind of
-      nkIdent: s := lookUp(c, n.sons[0]);
-      nkSym: s := n.sons[0].sym;
-      else illFormedAst(n)
-    end;
-    if (s.kind = skLabel) and (s.owner.id = c.p.owner.id) then begin
-      x := newSymNode(s);
-      x.info := n.info;
-      include(s.flags, sfUsed);
-      n.sons[0] := x
-    end
-    else
-      liMessage(n.info, errInvalidControlFlowX, s.name.s)
-  end
-  else if (c.p.nestedLoopCounter <= 0) and (c.p.nestedBlockCounter <= 0) then
-    liMessage(n.info, errInvalidControlFlowX,
-              renderTree(n, {@set}[renderNoComments]))
-end;
-
-function semBlock(c: PContext; n: PNode): PNode;
-var
-  labl: PSym;
-begin
-  result := n;
-  Inc(c.p.nestedBlockCounter);
-  checkSonsLen(n, 2);
-  openScope(c.tab); // BUGFIX: label is in the scope of block!
-  if n.sons[0] <> nil then begin
-    labl := newSymS(skLabel, n.sons[0], c);
-    addDecl(c, labl);
-    n.sons[0] := newSymNode(labl); // BUGFIX
-  end;
-  n.sons[1] := semStmt(c, n.sons[1]);
-  closeScope(c.tab);
-  Dec(c.p.nestedBlockCounter);
-end;
-
-function semAsm(con: PContext; n: PNode): PNode;
-var
-  str, sub: string;
-  a, b, c: int;
-  e: PSym;
-  marker: char;
-begin
-  result := n;
-  checkSonsLen(n, 2);
-  marker := pragmaAsm(con, n.sons[0]);
-  if marker = #0 then marker := '`'; // default marker
-  case n.sons[1].kind of
-    nkStrLit, nkRStrLit, nkTripleStrLit: begin
-      result := copyNode(n);
-      str := n.sons[1].strVal;
-      if str = '' then liMessage(n.info, errEmptyAsm);
-      // now parse the string literal and substitute symbols:
-      a := strStart;
-      repeat
-        b := strutils.find(str, marker, a);
-        if b < strStart then
-          sub := ncopy(str, a)
-        else
-          sub := ncopy(str, a, b-1);
-        if sub <> '' then
-          addSon(result, newStrNode(nkStrLit, sub));
-
-        if b < strStart then break;
-        c := strutils.find(str, marker, b+1);
-        if c < strStart then
-          sub := ncopy(str, b+1)
-        else
-          sub := ncopy(str, b+1, c-1);
-        if sub <> '' then begin
-          e := SymtabGet(con.tab, getIdent(sub));
-          if e <> nil then begin
-            if e.kind = skStub then loadStub(e);
-            addSon(result, newSymNode(e))
-          end
-          else
-            addSon(result, newStrNode(nkStrLit, sub));
-        end;
-        if c < strStart then break;
-        a := c+1;
-      until false;
-    end;
-    else illFormedAst(n)
-  end
-end;
-
-function semWhile(c: PContext; n: PNode): PNode;
-begin
-  result := n;
-  checkSonsLen(n, 2);
-  openScope(c.tab);
-  n.sons[0] := semExprWithType(c, n.sons[0]);
-  CheckBool(n.sons[0]);
-  inc(c.p.nestedLoopCounter);
-  n.sons[1] := semStmt(c, n.sons[1]);
-  dec(c.p.nestedLoopCounter);
-  closeScope(c.tab);
-end;
-
-function semCase(c: PContext; n: PNode): PNode;
-var
-  i, len: int;
-  covered: biggestint;
-  // for some types we count to check if all cases have been covered
-  chckCovered: boolean;
-  x: PNode;
-begin
-  // check selector:
-  result := n;
-  checkMinSonsLen(n, 2);
-  openScope(c.tab);
-  n.sons[0] := semExprWithType(c, n.sons[0]);
-  chckCovered := false;
-  covered := 0;
-  case skipTypes(n.sons[0].Typ, abstractVarRange).Kind of
-    tyInt..tyInt64, tyChar, tyEnum: chckCovered := true;
-    tyFloat..tyFloat128, tyString: begin end
-    else liMessage(n.info, errSelectorMustBeOfCertainTypes);
-  end;
-  for i := 1 to sonsLen(n)-1 do begin
-    x := n.sons[i];
-    case x.kind of
-      nkOfBranch: begin
-        checkMinSonsLen(x, 2);
-        semCaseBranch(c, n, x, i, covered);
-        len := sonsLen(x);
-        x.sons[len-1] := semStmtScope(c, x.sons[len-1]);
-      end;
-      nkElifBranch: begin
-        chckCovered := false;
-        checkSonsLen(x, 2);
-        x.sons[0] := semExprWithType(c, x.sons[0]);
-        checkBool(x.sons[0]);
-        x.sons[1] := semStmtScope(c, x.sons[1])
-      end;
-      nkElse: begin
-        chckCovered := false;
-        checkSonsLen(x, 1);
-        x.sons[0] := semStmtScope(c, x.sons[0])
-      end;
-      else illFormedAst(x);
-    end;
-  end;
-  if chckCovered and (covered <> lengthOrd(n.sons[0].typ)) then
-    liMessage(n.info, errNotAllCasesCovered);
-  closeScope(c.tab);
-end;
-
-function semAsgn(c: PContext; n: PNode): PNode;
-var
-  le: PType;
-  a: PNode;
-  id: PIdent;
-begin
-  checkSonsLen(n, 2);
-  a := n.sons[0];
-  case a.kind of
-    nkDotExpr: begin
-      // r.f = x
-      // --> `f=` (r, x)
-      checkSonsLen(a, 2);
-      id := considerAcc(a.sons[1]);
-      result := newNodeI(nkCall, n.info);
-      addSon(result, newIdentNode(getIdent(id.s+'='), n.info));
-      addSon(result, semExpr(c, a.sons[0]));
-      addSon(result, semExpr(c, n.sons[1]));
-      result := semDirectCallAnalyseEffects(c, result, {@set}[]);
-      if result <> nil then begin
-        fixAbstractType(c, result);
-        analyseIfAddressTakenInCall(c, result);
-        exit;
-      end
-    end;
-    nkBracketExpr: begin
-      // a[i..j] = x
-      // --> `[..]=`(a, i, j, x)
-      result := newNodeI(nkCall, n.info);
-      checkSonsLen(a, 2);
-      if a.sons[1].kind = nkRange then begin
-        checkSonsLen(a.sons[1], 2);
-        addSon(result, newIdentNode(getIdent(whichSliceOpr(a.sons[1])+'='),
-                                    n.info));
-        addSon(result, semExpr(c, a.sons[0]));
-        addSonIfNotNil(result, semExpr(c, a.sons[1].sons[0]));
-        addSonIfNotNil(result, semExpr(c, a.sons[1].sons[1]));
-        addSon(result, semExpr(c, n.sons[1]));
-        result := semDirectCallAnalyseEffects(c, result, {@set}[]);
-        if result <> nil then begin
-          fixAbstractType(c, result);
-          analyseIfAddressTakenInCall(c, result);
-          exit;
-        end
-      end
-      else begin
-        addSon(result, newIdentNode(getIdent('[]='), n.info));
-        addSon(result, semExpr(c, a.sons[0]));
-        addSon(result, semExpr(c, a.sons[1]));
-        addSon(result, semExpr(c, n.sons[1]));
-        result := semDirectCallAnalyseEffects(c, result, {@set}[]);
-        if result <> nil then begin
-          fixAbstractType(c, result);
-          analyseIfAddressTakenInCall(c, result);
-          exit;
-        end
-      end;
-    end;
-    else begin end;
-  end;
-  n.sons[0] := semExprWithType(c, n.sons[0], {@set}[efLValue]);
-  n.sons[1] := semExprWithType(c, n.sons[1]);
-  le := n.sons[0].typ;
-  if (skipTypes(le, {@set}[tyGenericInst]).kind <> tyVar) 
-  and (IsAssignable(n.sons[0]) = arNone) then begin
-    // Direct assignment to a discriminant is allowed!
-    liMessage(n.sons[0].info, errXCannotBeAssignedTo,
-              renderTree(n.sons[0], {@set}[renderNoComments]));
-  end
-  else begin
-    n.sons[1] := fitNode(c, le, n.sons[1]);
-    fixAbstractType(c, n);
-  end;
-  result := n;
-end;
-
-function SemReturn(c: PContext; n: PNode): PNode;
-var
-  restype: PType;
-  a: PNode; // temporary assignment for code generator
-begin
-  result := n;
-  checkSonsLen(n, 1);
-  if not (c.p.owner.kind in [skConverter, skMethod, skProc, skMacro]) then
-    liMessage(n.info, errXNotAllowedHere, '''return''');
-  if (n.sons[0] <> nil) then begin
-    n.sons[0] := SemExprWithType(c, n.sons[0]);
-    // check for type compatibility:
-    restype := c.p.owner.typ.sons[0];
-    if (restype <> nil) then begin
-      a := newNodeI(nkAsgn, n.sons[0].info);
-
-      n.sons[0] := fitNode(c, restype, n.sons[0]);
-      // optimize away ``return result``, because it would be transformed
-      // to ``result = result; return``:
-      if (n.sons[0].kind = nkSym) and (sfResult in n.sons[0].sym.flags) then
-      begin
-        n.sons[0] := nil;
-      end
-      else begin
-        if (c.p.resultSym = nil) then InternalError(n.info, 'semReturn');
-        addSon(a, semExprWithType(c, newSymNode(c.p.resultSym)));
-        addSon(a, n.sons[0]);
-        n.sons[0] := a;
-      end
-    end
-    else
-      liMessage(n.info, errCannotReturnExpr);
-  end;
-end;
-
-function SemYield(c: PContext; n: PNode): PNode;
-var
-  restype: PType;
-begin
-  result := n;
-  checkSonsLen(n, 1);
-  if (c.p.owner = nil) or (c.p.owner.kind <> skIterator) then
-    liMessage(n.info, errYieldNotAllowedHere);
-  if (n.sons[0] <> nil) then begin
-    n.sons[0] := SemExprWithType(c, n.sons[0]);
-    // check for type compatibility:
-    restype := c.p.owner.typ.sons[0];
-    if (restype <> nil) then begin
-      n.sons[0] := fitNode(c, restype, n.sons[0]);
-      if (n.sons[0].typ = nil) then InternalError(n.info, 'semYield');
-    end
-    else
-      liMessage(n.info, errCannotReturnExpr);
-  end
-end;
-
-function fitRemoveHiddenConv(c: PContext; typ: Ptype; n: PNode): PNode;
-begin
-  result := fitNode(c, typ, n);
-  if (result.kind in [nkHiddenStdConv, nkHiddenSubConv]) then begin
-    changeType(result.sons[1], typ);
-    result := result.sons[1];
-  end
-  else if not sameType(result.typ, typ) then
-    changeType(result, typ)
-end;
-
-function semVar(c: PContext; n: PNode): PNode;
-var
-  i, j, len: int;
-  a, b, def: PNode;
-  typ, tup: PType;
-  v: PSym;
-begin
-  result := copyNode(n);
-  for i := 0 to sonsLen(n)-1 do begin
-    a := n.sons[i];
-    if a.kind = nkCommentStmt then continue;
-    if (a.kind <> nkIdentDefs) and (a.kind <> nkVarTuple) then IllFormedAst(a);
-    checkMinSonsLen(a, 3);
-    len := sonsLen(a);
-    if a.sons[len-2] <> nil then 
-      typ := semTypeNode(c, a.sons[len-2], nil)
-    else
-      typ := nil;
-    if a.sons[len-1] <> nil then begin
-      def := semExprWithType(c, a.sons[len-1]);
-      // BUGFIX: ``fitNode`` is needed here!
-      // check type compability between def.typ and typ:
-      if (typ <> nil) then def := fitNode(c, typ, def)
-      else typ := def.typ;
-    end
-    else
-      def := nil;
-    if not typeAllowed(typ, skVar) then begin
-      //debug(typ);
-      liMessage(a.info, errXisNoType, typeToString(typ));
-    end;
-    tup := skipTypes(typ, {@set}[tyGenericInst]);
-    if a.kind = nkVarTuple then begin
-      if tup.kind <> tyTuple then liMessage(a.info, errXExpected, 'tuple');
-      if len-2 <> sonsLen(tup) then
-        liMessage(a.info, errWrongNumberOfVariables);
-      b := newNodeI(nkVarTuple, a.info);
-      newSons(b, len);
-      b.sons[len-2] := nil; // no type desc
-      b.sons[len-1] := def;
-      addSon(result, b);
-    end;
-    for j := 0 to len-3 do begin
-      if (c.p.owner.kind = skModule) then begin
-        v := semIdentWithPragma(c, skVar, a.sons[j], {@set}[sfStar, sfMinus]);
-        include(v.flags, sfGlobal);
-      end
-      else
-        v := semIdentWithPragma(c, skVar, a.sons[j], {@set}[]);
-      if v.flags * [sfStar, sfMinus] <> {@set}[] then
-        include(v.flags, sfInInterface);
-      addInterfaceDecl(c, v);
-      if a.kind <> nkVarTuple then begin
-        v.typ := typ;
-        b := newNodeI(nkIdentDefs, a.info);
-        addSon(b, newSymNode(v));
-        addSon(b, nil); // no type description
-        addSon(b, copyTree(def));
-        addSon(result, b);
-      end
-      else begin
-        v.typ := tup.sons[j];
-        b.sons[j] := newSymNode(v);
-      end
-    end
-  end
-end;
-
-function semConst(c: PContext; n: PNode): PNode;
-var
-  a, def, b: PNode;
-  i: int;
-  v: PSym;
-  typ: PType;
-begin
-  result := copyNode(n);
-  for i := 0 to sonsLen(n)-1 do begin
-    a := n.sons[i];
-    if a.kind = nkCommentStmt then continue;
-    if (a.kind <> nkConstDef) then IllFormedAst(a);
-    checkSonsLen(a, 3);
-    if (c.p.owner.kind = skModule) then begin
-      v := semIdentWithPragma(c, skConst, a.sons[0], {@set}[sfStar, sfMinus]);
-      include(v.flags, sfGlobal);
-    end
-    else
-      v := semIdentWithPragma(c, skConst, a.sons[0], {@set}[]);
-
-    if a.sons[1] <> nil then typ := semTypeNode(c, a.sons[1], nil)
-    else typ := nil;
-    def := semAndEvalConstExpr(c, a.sons[2]);
-    // check type compability between def.typ and typ:
-    if (typ <> nil) then begin
-      def := fitRemoveHiddenConv(c, typ, def);
-    end
-    else typ := def.typ;
-    if not typeAllowed(typ, skConst) then
-      liMessage(a.info, errXisNoType, typeToString(typ));
-
-    v.typ := typ;
-    v.ast := def; // no need to copy
-    if v.flags * [sfStar, sfMinus] <> {@set}[] then
-      include(v.flags, sfInInterface);
-    addInterfaceDecl(c, v);
-    b := newNodeI(nkConstDef, a.info);
-    addSon(b, newSymNode(v));
-    addSon(b, nil); // no type description
-    addSon(b, copyTree(def));
-    addSon(result, b);
-  end;
-end;
-
-function semFor(c: PContext; n: PNode): PNode;
-var
-  i, len: int;
-  v, countup: PSym;
-  iter: PType;
-  countupNode, call: PNode;
-begin
-  result := n;
-  checkMinSonsLen(n, 3);
-  len := sonsLen(n);
-  openScope(c.tab);
-  if n.sons[len-2].kind = nkRange then begin
-    checkSonsLen(n.sons[len-2], 2);
-    // convert ``in 3..5`` to ``in countup(3, 5)``
-    countupNode := newNodeI(nkCall, n.sons[len-2].info);    
-    countUp := StrTableGet(magicsys.systemModule.Tab, getIdent('countup'));
-    if (countUp = nil) then
-      liMessage(countupNode.info, errSystemNeeds, 'countup');
-    newSons(countupNode, 3);
-    countupnode.sons[0] := newSymNode(countup);
-    countupNode.sons[1] := n.sons[len-2].sons[0];
-    countupNode.sons[2] := n.sons[len-2].sons[1];
-    
-    n.sons[len-2] := countupNode;
-  end;
-  n.sons[len-2] := semExprWithType(c, n.sons[len-2], {@set}[efWantIterator]);
-  call := n.sons[len-2];
-  if (call.kind <> nkCall) or (call.sons[0].kind <> nkSym)
-  or (call.sons[0].sym.kind <> skIterator) then
-    liMessage(n.sons[len-2].info, errIteratorExpected);
-  iter := skipTypes(n.sons[len-2].typ, {@set}[tyGenericInst]);
-  if iter.kind <> tyTuple then begin
-    if len <> 3 then liMessage(n.info, errWrongNumberOfVariables);
-    v := newSymS(skForVar, n.sons[0], c);
-    v.typ := iter;
-    n.sons[0] := newSymNode(v);
-    addDecl(c, v);
-  end
-  else begin
-    if len-2 <> sonsLen(iter) then liMessage(n.info, errWrongNumberOfVariables);
-    for i := 0 to len-3 do begin
-      v := newSymS(skForVar, n.sons[i], c);
-      v.typ := iter.sons[i];
-      n.sons[i] := newSymNode(v);
-      addDecl(c, v);
-    end
-  end;
-  // semantic checking for the sub statements:
-  Inc(c.p.nestedLoopCounter);
-  n.sons[len-1] := SemStmt(c, n.sons[len-1]);
-  closeScope(c.tab);
-  Dec(c.p.nestedLoopCounter);
-end;
-
-function semRaise(c: PContext; n: PNode): PNode;
-var
-  typ: PType;
-begin
-  result := n;
-  checkSonsLen(n, 1);
-  if n.sons[0] <> nil then begin
-    n.sons[0] := semExprWithType(c, n.sons[0]);
-    typ := n.sons[0].typ;
-    if (typ.kind <> tyRef) or (typ.sons[0].kind <> tyObject) then
-      liMessage(n.info, errExprCannotBeRaised)
-  end;
-end;
-
-function semTry(c: PContext; n: PNode): PNode;
-var
-  i, j, len: int;
-  a: PNode;
-  typ: PType;
-  check: TIntSet;
-begin
-  result := n;
-  checkMinSonsLen(n, 2);
-  n.sons[0] := semStmtScope(c, n.sons[0]);
-  IntSetInit(check);
-  for i := 1 to sonsLen(n)-1 do begin
-    a := n.sons[i];
-    checkMinSonsLen(a, 1);
-    len := sonsLen(a);
-    if a.kind = nkExceptBranch then begin
-      for j := 0 to len-2 do begin
-        typ := semTypeNode(c, a.sons[j], nil);
-        if typ.kind = tyRef then typ := typ.sons[0];
-        if (typ.kind <> tyObject) then
-          liMessage(a.sons[j].info, errExprCannotBeRaised);
-        a.sons[j] := newNodeI(nkType, a.sons[j].info);
-        a.sons[j].typ := typ;
-        if IntSetContainsOrIncl(check, typ.id) then
-          liMessage(a.sons[j].info, errExceptionAlreadyHandled);
-      end
-    end
-    else if a.kind <> nkFinally then
-      illFormedAst(n);
-    // last child of an nkExcept/nkFinally branch is a statement:
-    a.sons[len-1] := semStmtScope(c, a.sons[len-1]);
-  end;
-end;
-
-function semGenericParamList(c: PContext; n: PNode; father: PType = nil): PNode;
-var
-  i, j, L: int;
-  s: PSym;
-  a, def: PNode;
-  typ: PType;
-begin
-  result := copyNode(n);
-  if n.kind <> nkGenericParams then
-    InternalError(n.info, 'semGenericParamList');
-  for i := 0 to sonsLen(n)-1 do begin
-    a := n.sons[i];
-    if a.kind <> nkIdentDefs then illFormedAst(n);
-    L := sonsLen(a);
-    def := a.sons[L-1];
-    if a.sons[L-2] <> nil then
-      typ := semTypeNode(c, a.sons[L-2], nil)
-    else if def <> nil then
-      typ := newTypeS(tyExpr, c)
-    else
-      typ := nil;
-    for j := 0 to L-3 do begin
-      if (typ = nil) or (typ.kind = tyTypeDesc) then begin
-        s := newSymS(skType, a.sons[j], c);      
-        s.typ := newTypeS(tyGenericParam, c)
-      end
-      else begin
-        s := newSymS(skGenericParam, a.sons[j], c);
-        s.typ := typ
-      end;
-      s.ast := def;
-      s.typ.sym := s;
-      if father <> nil then addSon(father, s.typ);
-      s.position := i;
-      addSon(result, newSymNode(s));
-      addDecl(c, s);
-    end
-  end
-end;
-
-procedure addGenericParamListToScope(c: PContext; n: PNode);
-var
-  i: int;
-  a: PNode;
-begin
-  if n.kind <> nkGenericParams then
-    InternalError(n.info, 'addGenericParamListToScope');
-  for i := 0 to sonsLen(n)-1 do begin
-    a := n.sons[i];
-    if a.kind <> nkSym then internalError(a.info, 'addGenericParamListToScope');
-    addDecl(c, a.sym)
-  end
-end;
-
-function SemTypeSection(c: PContext; n: PNode): PNode;
-var
-  i: int;
-  s: PSym;
-  t, body: PType;
-  a: PNode;
-begin
-  result := n;
-  // process the symbols on the left side for the whole type section, before
-  // we even look at the type definitions on the right
-  for i := 0 to sonsLen(n)-1 do begin
-    a := n.sons[i];
-    if a.kind = nkCommentStmt then continue;
-    if (a.kind <> nkTypeDef) then IllFormedAst(a);
-    checkSonsLen(a, 3);
-    if (c.p.owner.kind = skModule) then begin
-      s := semIdentWithPragma(c, skType, a.sons[0], {@set}[sfStar, sfMinus]);
-      include(s.flags, sfGlobal);
-    end
-    else
-      s := semIdentWithPragma(c, skType, a.sons[0], {@set}[]);
-    if s.flags * [sfStar, sfMinus] <> {@set}[] then
-      include(s.flags, sfInInterface);
-    s.typ := newTypeS(tyForward, c);
-    s.typ.sym := s;
-    // process pragmas:
-    if a.sons[0].kind = nkPragmaExpr then
-      pragma(c, s, a.sons[0].sons[1], typePragmas);
-    // add it here, so that recursive types are possible:
-    addInterfaceDecl(c, s);
-    a.sons[0] := newSymNode(s);
-  end;
-
-  // process the right side of the types:
-  for i := 0 to sonsLen(n)-1 do begin
-    a := n.sons[i];
-    if a.kind = nkCommentStmt then continue;
-    if (a.kind <> nkTypeDef) then IllFormedAst(a);
-    checkSonsLen(a, 3);
-    if (a.sons[0].kind <> nkSym) then IllFormedAst(a);
-    s := a.sons[0].sym;
-    if (s.magic = mNone) and (a.sons[2] = nil) then
-      liMessage(a.info, errImplOfXexpected, s.name.s);
-    if s.magic <> mNone then processMagicType(c, s);
-    if a.sons[1] <> nil then begin
-      // We have a generic type declaration here. In generic types,
-      // symbol lookup needs to be done here.
-      openScope(c.tab);
-      pushOwner(s);
-      s.typ.kind := tyGenericBody;
-      if s.typ.containerID <> 0 then
-        InternalError(a.info, 'semTypeSection: containerID');
-      s.typ.containerID := getID();
-      a.sons[1] := semGenericParamList(c, a.sons[1], s.typ);
-      addSon(s.typ, nil); // to be filled out later
-      s.ast := a;
-      body := semTypeNode(c, a.sons[2], nil);
-      if body <> nil then body.sym := s;
-      s.typ.sons[sonsLen(s.typ)-1] := body;
-      //debug(s.typ);
-      popOwner();
-      closeScope(c.tab);
-    end
-    else if a.sons[2] <> nil then begin
-      // process the type's body:
-      pushOwner(s);
-      t := semTypeNode(c, a.sons[2], s.typ);
-      if (t <> s.typ) and (s.typ <> nil) then
-        internalError(a.info, 'semTypeSection()');
-      s.typ := t;
-      s.ast := a;
-      popOwner();
-    end;
-  end;
-  // unfortunately we need another pass over the section for checking of
-  // illegal recursions and type aliases:
-  for i := 0 to sonsLen(n)-1 do begin
-    a := n.sons[i];
-    if a.kind = nkCommentStmt then continue;
-    if (a.sons[0].kind <> nkSym) then IllFormedAst(a);
-    s := a.sons[0].sym;
-    // compute the type's size and check for illegal recursions:
-    if a.sons[1] = nil then begin
-      if (a.sons[2] <> nil)
-      and (a.sons[2].kind in [nkSym, nkIdent, nkAccQuoted]) then begin
-        // type aliases are hard:
-        //MessageOut('for type ' + typeToString(s.typ));
-        t := semTypeNode(c, a.sons[2], nil);
-        if t.kind in [tyObject, tyEnum] then begin
-          assignType(s.typ, t);
-          s.typ.id := t.id; // same id
-        end
-      end;
-      checkConstructedType(s.info, s.typ);
-    end
-  end
-end;
-
-procedure semParamList(c: PContext; n, genericParams: PNode; s: PSym);
-begin
-  s.typ := semProcTypeNode(c, n, genericParams, nil);
-end;
-
-procedure addParams(c: PContext; n: PNode);
-var
-  i: int;
-begin
-  for i := 1 to sonsLen(n)-1 do begin
-    if (n.sons[i].kind <> nkSym) then InternalError(n.info, 'addParams');
-    addDecl(c, n.sons[i].sym);
-  end
-end;
-
-procedure semBorrow(c: PContext; n: PNode; s: PSym);
-var
-  b: PSym;
-begin
-  // search for the correct alias:
-  b := SearchForBorrowProc(c, s, c.tab.tos-2);
-  if b = nil then liMessage(n.info, errNoSymbolToBorrowFromFound);
-  // store the alias:
-  n.sons[codePos] := newSymNode(b);
-end;
-
-procedure sideEffectsCheck(c: PContext; s: PSym);
-begin
-  if [sfNoSideEffect, sfSideEffect] * s.flags = 
-     [sfNoSideEffect, sfSideEffect] then 
-    liMessage(s.info, errXhasSideEffects, s.name.s);
-end;
-
-procedure addResult(c: PContext; t: PType; const info: TLineInfo);
-var
-  s: PSym;
-begin
-  if t <> nil then begin
-    s := newSym(skVar, getIdent('result'), getCurrOwner());
-    s.info := info;
-    s.typ := t;
-    Include(s.flags, sfResult);
-    Include(s.flags, sfUsed);
-    addDecl(c, s);
-    c.p.resultSym := s;
-  end
-end;
-
-procedure addResultNode(c: PContext; n: PNode);
-begin
-  if c.p.resultSym <> nil then addSon(n, newSymNode(c.p.resultSym));
-end;
-
-function semLambda(c: PContext; n: PNode): PNode;
-var
-  s: PSym;
-  oldP: PProcCon;
-begin
-  result := n;
-  checkSonsLen(n, codePos+1);
-  s := newSym(skProc, getIdent(':anonymous'), getCurrOwner());
-  s.info := n.info;
-
-  oldP := c.p; // restore later
-  s.ast := n;
-  n.sons[namePos] := newSymNode(s);
-
-  pushOwner(s);
-  openScope(c.tab);
-  if (n.sons[genericParamsPos] <> nil) then illFormedAst(n);
-  // process parameters:
-  if n.sons[paramsPos] <> nil then begin
-    semParamList(c, n.sons[ParamsPos], nil, s);
-    addParams(c, s.typ.n);
-  end
-  else begin
-    s.typ := newTypeS(tyProc, c);
-    addSon(s.typ, nil);
-  end;
-
-  // we are in a nested proc:
-  s.typ.callConv := ccClosure;
-  if n.sons[pragmasPos] <> nil then
-    pragma(c, s, n.sons[pragmasPos], lambdaPragmas);
-
-  s.options := gOptions;
-  if n.sons[codePos] <> nil then begin
-    if sfImportc in s.flags then
-      liMessage(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s);
-    c.p := newProcCon(s);
-    addResult(c, s.typ.sons[0], n.info);
-    n.sons[codePos] := semStmtScope(c, n.sons[codePos]);
-    addResultNode(c, n);
-  end
-  else
-    liMessage(n.info, errImplOfXexpected, s.name.s);
-  closeScope(c.tab); // close scope for parameters
-  popOwner();
-  c.p := oldP; // restore
-  result.typ := s.typ;
-end;
-
-function semProcAux(c: PContext; n: PNode; kind: TSymKind;
-                    const validPragmas: TSpecialWords): PNode;
-var
-  s, proto: PSym;
-  oldP: PProcCon;
-  gp: PNode;
-begin
-  result := n;
-  checkSonsLen(n, codePos+1);
-  if c.p.owner.kind = skModule then begin
-    s := semIdentVis(c, kind, n.sons[0], {@set}[sfStar]);
-    include(s.flags, sfGlobal);
-  end
-  else
-    s := semIdentVis(c, kind, n.sons[0], {@set}[]);
-  n.sons[namePos] := newSymNode(s);
-  oldP := c.p; // restore later
-  if sfStar in s.flags then include(s.flags, sfInInterface);
-  s.ast := n;
-
-  pushOwner(s);
-  openScope(c.tab);
-  if n.sons[genericParamsPos] <> nil then begin
-    n.sons[genericParamsPos] := semGenericParamList(c, n.sons[genericParamsPos]);
-    gp := n.sons[genericParamsPos]
-  end
-  else
-    gp := newNodeI(nkGenericParams, n.info);
-  // process parameters:
-  if n.sons[paramsPos] <> nil then begin
-    semParamList(c, n.sons[ParamsPos], gp, s);
-    if sonsLen(gp) > 0 then n.sons[genericParamsPos] := gp;
-    addParams(c, s.typ.n);
-  end
-  else begin
-    s.typ := newTypeS(tyProc, c);
-    addSon(s.typ, nil);
-  end;
-
-  proto := SearchForProc(c, s, c.tab.tos-2); // -2 because we have a scope open
-                                             // for parameters
-  if proto = nil then begin
-    if oldP.owner.kind <> skModule then // we are in a nested proc
-      s.typ.callConv := ccClosure
-    else
-      s.typ.callConv := lastOptionEntry(c).defaultCC;
-    // add it here, so that recursive procs are possible:
-    // -2 because we have a scope open for parameters
-    if kind in OverloadableSyms then
-      addInterfaceOverloadableSymAt(c, s, c.tab.tos-2)
-    else
-      addDeclAt(c, s, c.tab.tos-2);
-    if n.sons[pragmasPos] <> nil then
-      pragma(c, s, n.sons[pragmasPos], validPragmas)
-  end
-  else begin
-    if n.sons[pragmasPos] <> nil then
-      liMessage(n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProc);
-    if not (sfForward in proto.flags) then
-      liMessage(n.info, errAttemptToRedefineX, proto.name.s);
-    exclude(proto.flags, sfForward);
-    closeScope(c.tab); // close scope with wrong parameter symbols
-    openScope(c.tab); // open scope for old (correct) parameter symbols
-    if proto.ast.sons[genericParamsPos] <> nil then
-      addGenericParamListToScope(c, proto.ast.sons[genericParamsPos]);
-    addParams(c, proto.typ.n);
-    proto.info := s.info; // more accurate line information
-    s.typ := proto.typ;
-    s := proto;
-    n.sons[genericParamsPos] := proto.ast.sons[genericParamsPos];
-    n.sons[paramsPos] := proto.ast.sons[paramsPos];
-    if (n.sons[namePos].kind <> nkSym) then InternalError(n.info, 'semProcAux');
-    n.sons[namePos].sym := proto;
-    proto.ast := n; // needed for code generation
-    popOwner();
-    pushOwner(s);
-  end;
-
-  s.options := gOptions;
-  if n.sons[codePos] <> nil then begin
-    if [sfImportc, sfBorrow] * s.flags <> [] then
-      liMessage(n.sons[codePos].info, errImplOfXNotAllowed, s.name.s);
-    if (n.sons[genericParamsPos] = nil) then begin
-      c.p := newProcCon(s);
-      if (s.typ.sons[0] <> nil) and (kind <> skIterator) then
-        addResult(c, s.typ.sons[0], n.info);
-      n.sons[codePos] := semStmtScope(c, n.sons[codePos]);
-      if (s.typ.sons[0] <> nil) and (kind <> skIterator) then
-        addResultNode(c, n);
-    end
-    else begin
-      if (s.typ.sons[0] <> nil) and (kind <> skIterator) then
-        addDecl(c, newSym(skUnknown, getIdent('result'), nil));
-      n.sons[codePos] := semGenericStmtScope(c, n.sons[codePos]);
-    end
-  end
-  else begin
-    if proto <> nil then
-      liMessage(n.info, errImplOfXexpected, proto.name.s);
-    if [sfImportc, sfBorrow] * s.flags = [] then Include(s.flags, sfForward)
-    else if sfBorrow in s.flags then 
-      semBorrow(c, n, s);
-  end;
-  sideEffectsCheck(c, s);
-  closeScope(c.tab); // close scope for parameters
-  popOwner();
-  c.p := oldP; // restore
-end;
-
-function semIterator(c: PContext; n: PNode): PNode;
-var
-  t: PType;
-  s: PSym;
-begin
-  result := semProcAux(c, n, skIterator, iteratorPragmas);
-  s := result.sons[namePos].sym;
-  t := s.typ;
-  if t.sons[0] = nil then liMessage(n.info, errXNeedsReturnType, 'iterator');
-  if n.sons[codePos] = nil then liMessage(n.info, errImplOfXexpected, s.name.s);
-end;
-
-function semProc(c: PContext; n: PNode): PNode;
-begin
-  result := semProcAux(c, n, skProc, procPragmas);
-end;
-
-function semMethod(c: PContext; n: PNode): PNode;
-begin
-  if not isTopLevel(c) then
-    liMessage(n.info, errXOnlyAtModuleScope, 'method');
-  result := semProcAux(c, n, skMethod, methodPragmas);
-end;
-
-function semConverterDef(c: PContext; n: PNode): PNode;
-var
-  t: PType;
-  s: PSym;
-begin
-  if not isTopLevel(c) then
-    liMessage(n.info, errXOnlyAtModuleScope, 'converter');
-  checkSonsLen(n, codePos+1);
-  if n.sons[genericParamsPos] <> nil then
-    liMessage(n.info, errNoGenericParamsAllowedForX, 'converter');
-  result := semProcAux(c, n, skConverter, converterPragmas);
-  s := result.sons[namePos].sym;
-  t := s.typ;
-  if t.sons[0] = nil then liMessage(n.info, errXNeedsReturnType, 'converter');
-  if sonsLen(t) <> 2 then liMessage(n.info, errXRequiresOneArgument, 'converter');
-  addConverter(c, s);
-end;
-
-function semMacroDef(c: PContext; n: PNode): PNode;
-var
-  t: PType;
-  s: PSym;
-begin
-  checkSonsLen(n, codePos+1);
-  if n.sons[genericParamsPos] <> nil then
-    liMessage(n.info, errNoGenericParamsAllowedForX, 'macro');
-  result := semProcAux(c, n, skMacro, macroPragmas);
-  s := result.sons[namePos].sym;
-  t := s.typ;
-  if t.sons[0] = nil then liMessage(n.info, errXNeedsReturnType, 'macro');
-  if sonsLen(t) <> 2 then liMessage(n.info, errXRequiresOneArgument, 'macro');
-  if n.sons[codePos] = nil then liMessage(n.info, errImplOfXexpected, s.name.s);
-end;
-
-function evalInclude(c: PContext; n: PNode): PNode;
-var
-  i, fileIndex: int;
-  f: string;
-begin
-  result := newNodeI(nkStmtList, n.info);
-  addSon(result, n); // the rodwriter needs include information!
-  for i := 0 to sonsLen(n)-1 do begin
-    f := getModuleFile(n.sons[i]);
-    fileIndex := includeFilename(f);
-    if IntSetContainsOrIncl(c.includedFiles, fileIndex) then
-      liMessage(n.info, errRecursiveDependencyX, f);
-    addSon(result, semStmt(c, gIncludeFile(f)));
-    IntSetExcl(c.includedFiles, fileIndex);
-  end;
-end;
-
-function semCommand(c: PContext; n: PNode): PNode;
-begin
-  result := semExpr(c, n);
-  if result.typ <> nil then liMessage(n.info, errDiscardValue);
-end;
-
-function SemStmt(c: PContext; n: PNode): PNode;
-const
-  // must be last statements in a block:
-  LastBlockStmts = {@set}[nkRaiseStmt, nkReturnStmt, nkBreakStmt,
-                          nkContinueStmt];
-var
-  len, i, j: int;
-begin
-  result := n;
-  if n = nil then exit;
-  if nfSem in n.flags then exit;
-  case n.kind of
-    nkAsgn: result := semAsgn(c, n);
-    nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand, nkMacroStmt, nkCallStrLit:
-      result := semCommand(c, n);
-    nkEmpty, nkCommentStmt, nkNilLit: begin end;
-    nkBlockStmt: result := semBlock(c, n);
-    nkStmtList: begin
-      len := sonsLen(n);
-      for i := 0 to len-1 do begin
-        n.sons[i] := semStmt(c, n.sons[i]);
-        if (n.sons[i].kind in LastBlockStmts) then begin
-          for j := i+1 to len-1 do
-            case n.sons[j].kind of
-              nkPragma, nkCommentStmt, nkNilLit, nkEmpty: begin end;
-              else liMessage(n.sons[j].info, errStmtInvalidAfterReturn);
-            end
-        end
-      end
-    end;
-    nkRaiseStmt: result := semRaise(c, n);
-    nkVarSection: result := semVar(c, n);
-    nkConstSection: result := semConst(c, n);
-    nkTypeSection: result := SemTypeSection(c, n);
-    nkIfStmt: result := SemIf(c, n);
-    nkWhenStmt: result := semWhen(c, n);
-    nkDiscardStmt: result := semDiscard(c, n);
-    nkWhileStmt: result := semWhile(c, n);
-    nkTryStmt: result := semTry(c, n);
-    nkBreakStmt, nkContinueStmt: result := semBreakOrContinue(c, n);
-    nkForStmt: result := semFor(c, n);
-    nkCaseStmt: result := semCase(c, n);
-    nkReturnStmt: result := semReturn(c, n);
-    nkAsmStmt: result := semAsm(c, n);
-    nkYieldStmt: result := semYield(c, n);
-    nkPragma: pragma(c, c.p.owner, n, stmtPragmas);
-    nkIteratorDef: result := semIterator(c, n);
-    nkProcDef: result := semProc(c, n);
-    nkMethodDef: result := semMethod(c, n);
-    nkConverterDef: result := semConverterDef(c, n);
-    nkMacroDef: result := semMacroDef(c, n);
-    nkTemplateDef: result := semTemplateDef(c, n);
-    nkImportStmt: begin
-      if not isTopLevel(c) then
-        liMessage(n.info, errXOnlyAtModuleScope, 'import');
-      result := evalImport(c, n);
-    end;
-    nkFromStmt: begin
-      if not isTopLevel(c) then
-        liMessage(n.info, errXOnlyAtModuleScope, 'from');
-      result := evalFrom(c, n);
-    end;
-    nkIncludeStmt: begin
-      if not isTopLevel(c) then
-        liMessage(n.info, errXOnlyAtModuleScope, 'include');
-      result := evalInclude(c, n);
-    end;
-    else liMessage(n.info, errStmtExpected);
-  end;
-  if result = nil then InternalError(n.info, 'SemStmt: result = nil');
-  include(result.flags, nfSem);
-end;
-
-function semStmtScope(c: PContext; n: PNode): PNode;
-begin
-  openScope(c.tab);
-  result := semStmt(c, n);
-  closeScope(c.tab);
-end;