summary refs log tree commit diff stats
path: root/nim
diff options
context:
space:
mode:
Diffstat (limited to 'nim')
-rw-r--r--nim/ast.pas154
-rw-r--r--nim/ccgexprs.pas161
-rw-r--r--nim/ccgstmts.pas6
-rw-r--r--nim/ccgtypes.pas20
-rw-r--r--nim/ccgutils.pas9
-rw-r--r--nim/cgen.pas70
-rw-r--r--nim/commands.pas3
-rw-r--r--nim/condsyms.pas3
-rw-r--r--nim/docgen.pas10
-rw-r--r--nim/ecmasgen.pas43
-rw-r--r--nim/evals.pas53
-rw-r--r--nim/extccomp.pas6
-rw-r--r--nim/magicsys.pas1
-rw-r--r--nim/msgs.pas1102
-rw-r--r--nim/nimconf.pas13
-rw-r--r--nim/nversion.pas4
-rw-r--r--nim/parsecfg.pas9
-rw-r--r--nim/paslex.pas10
-rw-r--r--nim/pnimsyn.pas11
-rw-r--r--nim/pragmas.pas9
-rw-r--r--nim/procfind.pas48
-rw-r--r--nim/rnimsyn.pas7
-rw-r--r--nim/rst.pas2
-rw-r--r--nim/scanner.pas60
-rw-r--r--nim/sem.pas4
-rw-r--r--nim/semexprs.pas126
-rw-r--r--nim/semfold.pas25
-rw-r--r--nim/semstmts.pas36
-rw-r--r--nim/semtypes.pas35
-rw-r--r--nim/sigmatch.pas42
-rw-r--r--nim/transf.pas58
-rw-r--r--nim/transtmp.pas2
-rw-r--r--nim/trees.pas4
-rw-r--r--nim/types.pas125
-rw-r--r--nim/wordrecg.pas60
35 files changed, 1328 insertions, 1003 deletions
diff --git a/nim/ast.pas b/nim/ast.pas
index aa83af4ed..681bf72d5 100644
--- a/nim/ast.pas
+++ b/nim/ast.pas
@@ -97,8 +97,8 @@ type
     nkStmtListExpr, nkBlockExpr, nkStmtListType, nkBlockType, 
     nkVm, nkTypeOfExpr, nkObjectTy, nkTupleTy, 
     nkRecList, nkRecCase, nkRecWhen, nkRefTy, 
-    nkPtrTy, nkVarTy, nkProcTy, nkEnumTy, 
-    nkEnumFieldDef, nkReturnToken);
+    nkPtrTy, nkVarTy, nkAbstractTy, nkProcTy, 
+    nkEnumTy, nkEnumFieldDef, nkReturnToken);
   TNodeKinds = set of TNodeKind;
 const
   NodeKindToStr: array [TNodeKind] of string = (
@@ -132,8 +132,8 @@ const
     'nkStmtListExpr', 'nkBlockExpr', 'nkStmtListType', 'nkBlockType', 
     'nkVm', 'nkTypeOfExpr', 'nkObjectTy', 'nkTupleTy', 
     'nkRecList', 'nkRecCase', 'nkRecWhen', 'nkRefTy', 
-    'nkPtrTy', 'nkVarTy', 'nkProcTy', 'nkEnumTy', 
-    'nkEnumFieldDef', 'nkReturnToken');
+    'nkPtrTy', 'nkVarTy', 'nkAbstractTy', 'nkProcTy', 
+    'nkEnumTy', 'nkEnumFieldDef', 'nkReturnToken');
 type
   TSymFlag = (
     sfUsed, sfStar, sfMinus, sfInInterface, 
@@ -142,7 +142,8 @@ type
     sfResult, sfNoSideEffect, sfMainModule, sfSystemModule, 
     sfNoReturn, sfAddrTaken, sfCompilerProc, sfCppMethod, 
     sfDiscriminant, sfDeprecated, sfInClosure, sfTypeCheck, 
-    sfCompileTime, sfThreadVar, sfMerge, sfDeadCodeElim);
+    sfCompileTime, sfThreadVar, sfMerge, sfDeadCodeElim, 
+    sfBorrow);
   TSymFlags = set of TSymFlag;
 const
   SymFlagToStr: array [TSymFlag] of string = (
@@ -152,30 +153,31 @@ const
     'sfResult', 'sfNoSideEffect', 'sfMainModule', 'sfSystemModule', 
     'sfNoReturn', 'sfAddrTaken', 'sfCompilerProc', 'sfCppMethod', 
     'sfDiscriminant', 'sfDeprecated', 'sfInClosure', 'sfTypeCheck', 
-    'sfCompileTime', 'sfThreadVar', 'sfMerge', 'sfDeadCodeElim');
+    'sfCompileTime', 'sfThreadVar', 'sfMerge', 'sfDeadCodeElim', 
+    'sfBorrow');
 type
   TTypeKind = (
     tyNone, tyBool, tyChar, tyEmpty, 
     tyArrayConstr, tyNil, tyGeneric, tyGenericInst, 
-    tyGenericParam, tyEnum, tyAnyEnum, tyArray, 
-    tyObject, tyTuple, tySet, tyRange, 
-    tyPtr, tyRef, tyVar, tySequence, 
-    tyProc, tyPointer, tyOpenArray, tyString, 
-    tyCString, tyForward, tyInt, tyInt8, 
-    tyInt16, tyInt32, tyInt64, tyFloat, 
-    tyFloat32, tyFloat64, tyFloat128);
+    tyGenericParam, tyAbstract, tyEnum, tyOrdinal, 
+    tyArray, tyObject, tyTuple, tySet, 
+    tyRange, tyPtr, tyRef, tyVar, 
+    tySequence, tyProc, tyPointer, tyOpenArray, 
+    tyString, tyCString, tyForward, tyInt, 
+    tyInt8, tyInt16, tyInt32, tyInt64, 
+    tyFloat, tyFloat32, tyFloat64, tyFloat128);
   TTypeKinds = set of TTypeKind;
 const
   TypeKindToStr: array [TTypeKind] of string = (
     'tyNone', 'tyBool', 'tyChar', 'tyEmpty', 
     'tyArrayConstr', 'tyNil', 'tyGeneric', 'tyGenericInst', 
-    'tyGenericParam', 'tyEnum', 'tyAnyEnum', 'tyArray', 
-    'tyObject', 'tyTuple', 'tySet', 'tyRange', 
-    'tyPtr', 'tyRef', 'tyVar', 'tySequence', 
-    'tyProc', 'tyPointer', 'tyOpenArray', 'tyString', 
-    'tyCString', 'tyForward', 'tyInt', 'tyInt8', 
-    'tyInt16', 'tyInt32', 'tyInt64', 'tyFloat', 
-    'tyFloat32', 'tyFloat64', 'tyFloat128');
+    'tyGenericParam', 'tyAbstract', 'tyEnum', 'tyOrdinal', 
+    'tyArray', 'tyObject', 'tyTuple', 'tySet', 
+    'tyRange', 'tyPtr', 'tyRef', 'tyVar', 
+    'tySequence', 'tyProc', 'tyPointer', 'tyOpenArray', 
+    'tyString', 'tyCString', 'tyForward', 'tyInt', 
+    'tyInt8', 'tyInt16', 'tyInt32', 'tyInt64', 
+    'tyFloat', 'tyFloat32', 'tyFloat64', 'tyFloat128');
 type
   TNodeFlag = (
     nfNone, nfBase2, nfBase8, nfBase16, 
@@ -220,36 +222,36 @@ type
     //cog.outl("m" + magics[-1])
     //]]]
     mNone, mDefined, mLow, mHigh, mSizeOf, mIs, 
-    mSucc, mPred, mInc, mDec, mOrd, mNew, 
-    mNewFinalize, mNewSeq, mRegisterFinalizer, mLengthOpenArray, mLengthStr, mLengthArray, 
-    mLengthSeq, mIncl, mExcl, mCard, mChr, mGCref, 
-    mGCunref, mAddI, mSubI, mMulI, mDivI, mModI, 
-    mAddI64, mSubI64, mMulI64, mDivI64, mModI64, mShrI, 
-    mShlI, mBitandI, mBitorI, mBitxorI, mMinI, mMaxI, 
-    mShrI64, mShlI64, mBitandI64, mBitorI64, mBitxorI64, mMinI64, 
-    mMaxI64, mAddF64, mSubF64, mMulF64, mDivF64, mMinF64, 
-    mMaxF64, mAddU, mSubU, mMulU, mDivU, mModU, 
-    mAddU64, mSubU64, mMulU64, mDivU64, mModU64, mEqI, 
-    mLeI, mLtI, mEqI64, mLeI64, mLtI64, mEqF64, 
-    mLeF64, mLtF64, mLeU, mLtU, mLeU64, mLtU64, 
-    mEqEnum, mLeEnum, mLtEnum, mEqCh, mLeCh, mLtCh, 
-    mEqB, mLeB, mLtB, mEqRef, mEqProc, mEqUntracedRef, 
-    mLePtr, mLtPtr, mEqCString, mXor, mUnaryMinusI, mUnaryMinusI64, 
-    mAbsI, mAbsI64, mNot, mUnaryPlusI, mBitnotI, mUnaryPlusI64, 
-    mBitnotI64, mUnaryPlusF64, mUnaryMinusF64, mAbsF64, mZe8ToI, mZe8ToI64, 
-    mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64, mToU8, mToU16, 
-    mToU32, mToFloat, mToBiggestFloat, mToInt, mToBiggestInt, mCharToStr, 
-    mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, mStrToStr, 
-    mEnumToStr, mAnd, mOr, mEqStr, mLeStr, mLtStr, 
-    mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, mMinusSet, 
-    mSymDiffSet, mConStrStr, mConArrArr, mConArrT, mConTArr, mConTT, 
-    mSlice, mAppendStrCh, mAppendStrStr, mAppendSeqElem, mAppendSeqSeq, mInRange, 
-    mInSet, mAsgn, mRepr, mExit, mSetLengthStr, mSetLengthSeq, 
+    mEcho, mSucc, mPred, mInc, mDec, mOrd, 
+    mNew, mNewFinalize, mNewSeq, mRegisterFinalizer, mLengthOpenArray, mLengthStr, 
+    mLengthArray, mLengthSeq, mIncl, mExcl, mCard, mChr, 
+    mGCref, mGCunref, mAddI, mSubI, mMulI, mDivI, 
+    mModI, mAddI64, mSubI64, mMulI64, mDivI64, mModI64, 
+    mShrI, mShlI, mBitandI, mBitorI, mBitxorI, mMinI, 
+    mMaxI, mShrI64, mShlI64, mBitandI64, mBitorI64, mBitxorI64, 
+    mMinI64, mMaxI64, mAddF64, mSubF64, mMulF64, mDivF64, 
+    mMinF64, mMaxF64, mAddU, mSubU, mMulU, mDivU, 
+    mModU, mAddU64, mSubU64, mMulU64, mDivU64, mModU64, 
+    mEqI, mLeI, mLtI, mEqI64, mLeI64, mLtI64, 
+    mEqF64, mLeF64, mLtF64, mLeU, mLtU, mLeU64, 
+    mLtU64, mEqEnum, mLeEnum, mLtEnum, mEqCh, mLeCh, 
+    mLtCh, mEqB, mLeB, mLtB, mEqRef, mEqProc, 
+    mEqUntracedRef, mLePtr, mLtPtr, mEqCString, mXor, mUnaryMinusI, 
+    mUnaryMinusI64, mAbsI, mAbsI64, mNot, mUnaryPlusI, mBitnotI, 
+    mUnaryPlusI64, mBitnotI64, mUnaryPlusF64, mUnaryMinusF64, mAbsF64, mZe8ToI, 
+    mZe8ToI64, mZe16ToI, mZe16ToI64, mZe32ToI64, mZeIToI64, mToU8, 
+    mToU16, mToU32, mToFloat, mToBiggestFloat, mToInt, mToBiggestInt, 
+    mCharToStr, mBoolToStr, mIntToStr, mInt64ToStr, mFloatToStr, mCStrToStr, 
+    mStrToStr, mEnumToStr, mAnd, mOr, mEqStr, mLeStr, 
+    mLtStr, mEqSet, mLeSet, mLtSet, mMulSet, mPlusSet, 
+    mMinusSet, mSymDiffSet, mConStrStr, mConArrArr, mConArrT, mConTArr, 
+    mConTT, mSlice, mAppendStrCh, mAppendStrStr, mAppendSeqElem, mAppendSeqSeq, 
+    mInRange, mInSet, mRepr, mExit, mSetLengthStr, mSetLengthSeq, 
     mAssert, mSwap, mIsNil, mArrToSeq, mCopyStr, mCopyStrLast, 
     mNewString, mArray, mOpenArray, mRange, mSet, mSeq, 
-    mInt, mInt8, mInt16, mInt32, mInt64, mFloat, 
-    mFloat32, mFloat64, mBool, mChar, mString, mCstring, 
-    mPointer, mAnyEnum, mEmptySet, mIntSetBaseType, mNil, mIsMainModule, 
+    mOrdinal, mInt, mInt8, mInt16, mInt32, mInt64, 
+    mFloat, mFloat32, mFloat64, mBool, mChar, mString, 
+    mCstring, mPointer, mEmptySet, mIntSetBaseType, mNil, mIsMainModule, 
     mCompileDate, mCompileTime, mNimrodVersion, mNimrodMajor, mNimrodMinor, mNimrodPatch, 
     mCpuEndian, mHostOS, mHostCPU, mNaN, mInf, mNegInf, 
     mNLen, mNChild, mNSetChild, mNAdd, mNAddMultiple, mNDel, 
@@ -479,36 +481,36 @@ const // "MagicToStr" array:
     //cog.outl("'%s'" % magics[-1])
     //]]]
     'None', 'Defined', 'Low', 'High', 'SizeOf', 'Is', 
-    'Succ', 'Pred', 'Inc', 'Dec', 'Ord', 'New', 
-    'NewFinalize', 'NewSeq', 'RegisterFinalizer', 'LengthOpenArray', 'LengthStr', 'LengthArray', 
-    'LengthSeq', 'Incl', 'Excl', 'Card', 'Chr', 'GCref', 
-    'GCunref', 'AddI', 'SubI', 'MulI', 'DivI', 'ModI', 
-    'AddI64', 'SubI64', 'MulI64', 'DivI64', 'ModI64', 'ShrI', 
-    'ShlI', 'BitandI', 'BitorI', 'BitxorI', 'MinI', 'MaxI', 
-    'ShrI64', 'ShlI64', 'BitandI64', 'BitorI64', 'BitxorI64', 'MinI64', 
-    'MaxI64', 'AddF64', 'SubF64', 'MulF64', 'DivF64', 'MinF64', 
-    'MaxF64', 'AddU', 'SubU', 'MulU', 'DivU', 'ModU', 
-    'AddU64', 'SubU64', 'MulU64', 'DivU64', 'ModU64', 'EqI', 
-    'LeI', 'LtI', 'EqI64', 'LeI64', 'LtI64', 'EqF64', 
-    'LeF64', 'LtF64', 'LeU', 'LtU', 'LeU64', 'LtU64', 
-    'EqEnum', 'LeEnum', 'LtEnum', 'EqCh', 'LeCh', 'LtCh', 
-    'EqB', 'LeB', 'LtB', 'EqRef', 'EqProc', 'EqUntracedRef', 
-    'LePtr', 'LtPtr', 'EqCString', 'Xor', 'UnaryMinusI', 'UnaryMinusI64', 
-    'AbsI', 'AbsI64', 'Not', 'UnaryPlusI', 'BitnotI', 'UnaryPlusI64', 
-    'BitnotI64', 'UnaryPlusF64', 'UnaryMinusF64', 'AbsF64', 'Ze8ToI', 'Ze8ToI64', 
-    'Ze16ToI', 'Ze16ToI64', 'Ze32ToI64', 'ZeIToI64', 'ToU8', 'ToU16', 
-    'ToU32', 'ToFloat', 'ToBiggestFloat', 'ToInt', 'ToBiggestInt', 'CharToStr', 
-    'BoolToStr', 'IntToStr', 'Int64ToStr', 'FloatToStr', 'CStrToStr', 'StrToStr', 
-    'EnumToStr', 'And', 'Or', 'EqStr', 'LeStr', 'LtStr', 
-    'EqSet', 'LeSet', 'LtSet', 'MulSet', 'PlusSet', 'MinusSet', 
-    'SymDiffSet', 'ConStrStr', 'ConArrArr', 'ConArrT', 'ConTArr', 'ConTT', 
-    'Slice', 'AppendStrCh', 'AppendStrStr', 'AppendSeqElem', 'AppendSeqSeq', 'InRange', 
-    'InSet', 'Asgn', 'Repr', 'Exit', 'SetLengthStr', 'SetLengthSeq', 
+    'Echo', 'Succ', 'Pred', 'Inc', 'Dec', 'Ord', 
+    'New', 'NewFinalize', 'NewSeq', 'RegisterFinalizer', 'LengthOpenArray', 'LengthStr', 
+    'LengthArray', 'LengthSeq', 'Incl', 'Excl', 'Card', 'Chr', 
+    'GCref', 'GCunref', 'AddI', 'SubI', 'MulI', 'DivI', 
+    'ModI', 'AddI64', 'SubI64', 'MulI64', 'DivI64', 'ModI64', 
+    'ShrI', 'ShlI', 'BitandI', 'BitorI', 'BitxorI', 'MinI', 
+    'MaxI', 'ShrI64', 'ShlI64', 'BitandI64', 'BitorI64', 'BitxorI64', 
+    'MinI64', 'MaxI64', 'AddF64', 'SubF64', 'MulF64', 'DivF64', 
+    'MinF64', 'MaxF64', 'AddU', 'SubU', 'MulU', 'DivU', 
+    'ModU', 'AddU64', 'SubU64', 'MulU64', 'DivU64', 'ModU64', 
+    'EqI', 'LeI', 'LtI', 'EqI64', 'LeI64', 'LtI64', 
+    'EqF64', 'LeF64', 'LtF64', 'LeU', 'LtU', 'LeU64', 
+    'LtU64', 'EqEnum', 'LeEnum', 'LtEnum', 'EqCh', 'LeCh', 
+    'LtCh', 'EqB', 'LeB', 'LtB', 'EqRef', 'EqProc', 
+    'EqUntracedRef', 'LePtr', 'LtPtr', 'EqCString', 'Xor', 'UnaryMinusI', 
+    'UnaryMinusI64', 'AbsI', 'AbsI64', 'Not', 'UnaryPlusI', 'BitnotI', 
+    'UnaryPlusI64', 'BitnotI64', 'UnaryPlusF64', 'UnaryMinusF64', 'AbsF64', 'Ze8ToI', 
+    'Ze8ToI64', 'Ze16ToI', 'Ze16ToI64', 'Ze32ToI64', 'ZeIToI64', 'ToU8', 
+    'ToU16', 'ToU32', 'ToFloat', 'ToBiggestFloat', 'ToInt', 'ToBiggestInt', 
+    'CharToStr', 'BoolToStr', 'IntToStr', 'Int64ToStr', 'FloatToStr', 'CStrToStr', 
+    'StrToStr', 'EnumToStr', 'And', 'Or', 'EqStr', 'LeStr', 
+    'LtStr', 'EqSet', 'LeSet', 'LtSet', 'MulSet', 'PlusSet', 
+    'MinusSet', 'SymDiffSet', 'ConStrStr', 'ConArrArr', 'ConArrT', 'ConTArr', 
+    'ConTT', 'Slice', 'AppendStrCh', 'AppendStrStr', 'AppendSeqElem', 'AppendSeqSeq', 
+    'InRange', 'InSet', 'Repr', 'Exit', 'SetLengthStr', 'SetLengthSeq', 
     'Assert', 'Swap', 'IsNil', 'ArrToSeq', 'CopyStr', 'CopyStrLast', 
     'NewString', 'Array', 'OpenArray', 'Range', 'Set', 'Seq', 
-    'Int', 'Int8', 'Int16', 'Int32', 'Int64', 'Float', 
-    'Float32', 'Float64', 'Bool', 'Char', 'String', 'Cstring', 
-    'Pointer', 'AnyEnum', 'EmptySet', 'IntSetBaseType', 'Nil', 'IsMainModule', 
+    'Ordinal', 'Int', 'Int8', 'Int16', 'Int32', 'Int64', 
+    'Float', 'Float32', 'Float64', 'Bool', 'Char', 'String', 
+    'Cstring', 'Pointer', 'EmptySet', 'IntSetBaseType', 'Nil', 'IsMainModule', 
     'CompileDate', 'CompileTime', 'NimrodVersion', 'NimrodMajor', 'NimrodMinor', 'NimrodPatch', 
     'CpuEndian', 'HostOS', 'HostCPU', 'NaN', 'Inf', 'NegInf', 
     'NLen', 'NChild', 'NSetChild', 'NAdd', 'NAddMultiple', 'NDel', 
diff --git a/nim/ccgexprs.pas b/nim/ccgexprs.pas
index a7a364a52..bf03365cd 100644
--- a/nim/ccgexprs.pas
+++ b/nim/ccgexprs.pas
@@ -56,7 +56,7 @@ begin
   if ty = nil then internalError(v.info, 'genLiteral: ty is nil');
   case v.kind of
     nkCharLit..nkInt64Lit: begin
-      case skipVarGenericRange(ty).kind of
+      case skipTypes(ty, abstractVarRange).kind of
         tyChar, tyInt64, tyNil: result := intLiteral(v.intVal);
         tyInt8:  
           result := ropef('((NI8) $1)', [intLiteral(biggestInt(int8(v.intVal)))]);
@@ -76,13 +76,13 @@ begin
         end;
         else
           result := ropef('(($1) $2)', [getTypeDesc(p.module,
-            skipVarGenericRange(ty)), intLiteral(v.intVal)])
+            skipTypes(ty, abstractVarRange)), intLiteral(v.intVal)])
       end
     end;
     nkNilLit:
       result := toRope('0'+'');
     nkStrLit..nkTripleStrLit: begin
-      if skipVarGenericRange(ty).kind = tyString then begin
+      if skipTypes(ty, abstractVarRange).kind = tyString then begin
         id := NodeTableTestOrSet(p.module.dataCache, v, gid);
         if id = gid then begin
           // string literal not found in the cache:
@@ -228,7 +228,7 @@ function rdCharLoc(const a: TLoc): PRope;
 // read a location that may need a char-cast:
 begin
   result := rdLoc(a);
-  if skipRange(a.t).kind = tyChar then
+  if skipTypes(a.t, abstractRange).kind = tyChar then
     result := ropef('((NU8)($1))', [result])
 end;
 
@@ -289,7 +289,7 @@ procedure genAssignment(p: BProc; const dest, src: TLoc;
 var
   ty: PType;
 begin;
-  ty := skipVarGenericRange(dest.t);
+  ty := skipTypes(dest.t, abstractVarRange);
   case ty.kind of
     tyRef:
       genRefAssign(p, dest, src, flags);
@@ -531,7 +531,7 @@ begin
   assert(e.sons[2].typ <> nil);
   InitLocExpr(p, e.sons[1], a);
   InitLocExpr(p, e.sons[2], b);
-  t := skipGenericRange(e.typ);
+  t := skipTypes(e.typ, abstractRange);
   if getSize(t) >= platform.IntSize then begin
     if optOverflowCheck in p.options then begin
       useMagic(p.module, prc[m]);
@@ -578,7 +578,7 @@ var
 begin
   assert(e.sons[1].typ <> nil);
   InitLocExpr(p, e.sons[1], a);
-  t := skipGenericRange(e.typ);
+  t := skipTypes(e.typ, abstractRange);
   if optOverflowCheck in p.options then begin
     useMagic(p.module, 'raiseOverflow');
     appf(p.s[cpsStmts], 'if ($1 == $2) raiseOverflow();$n', 
@@ -705,7 +705,7 @@ var
 begin
   assert(e.sons[1].typ <> nil);
   InitLocExpr(p, e.sons[1], a);
-  t := skipGenericRange(e.typ);
+  t := skipTypes(e.typ, abstractRange);
   putIntoDest(p, d, e.typ, ropef(unArithTab[op], 
               [rdLoc(a), toRope(getSize(t)*8)]));
 end;
@@ -718,7 +718,7 @@ begin
     expr(p, e.sons[0], d)
   else begin
     initLocExpr(p, e.sons[0], a);
-    case skipGeneric(a.t).kind of
+    case skipTypes(a.t, abstractInst).kind of
       tyRef: d.s := OnHeap;
       tyVar: d.s := OnUnknown;
       tyPtr: d.s := OnUnknown; // BUGFIX!
@@ -872,7 +872,7 @@ var
 begin
   initLocExpr(p, e.sons[0], a);
   initLocExpr(p, e.sons[1], b);
-  ty := skipPtrsGeneric(skipVarGenericRange(a.t));
+  ty := skipTypes(skipTypes(a.t, abstractVarRange), abstractPtrs);
   first := intLiteral(firstOrd(ty));
   // emit range check:
   if (optBoundsCheck in p.options) then begin
@@ -892,7 +892,7 @@ begin
     end;
   end;
   if d.k = locNone then d.s := a.s;
-  putIntoDest(p, d, elemType(skipVarGeneric(ty)), ropef('$1[($2)-$3]',
+  putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)), ropef('$1[($2)-$3]',
     [rdLoc(a), rdCharLoc(b), first]));
 end;
 
@@ -903,9 +903,9 @@ var
 begin
   initLocExpr(p, e.sons[0], a);
   initLocExpr(p, e.sons[1], b);
-  ty := skipVarGenericRange(a.t);
+  ty := skipTypes(a.t, abstractVarRange);
   if d.k = locNone then d.s := a.s;
-  putIntoDest(p, d, elemType(skipVarGeneric(ty)), ropef('$1[$2]',
+  putIntoDest(p, d, elemType(skipTypes(ty, abstractVar)), ropef('$1[$2]',
     [rdLoc(a), rdCharLoc(b)]));
 end;
 
@@ -923,7 +923,7 @@ begin
     // BUGFIX: ``>=`` and not ``>``!
   end;
   if d.k = locNone then d.s := a.s;
-  putIntoDest(p, d, elemType(skipVarGeneric(a.t)), ropef('$1[$2]',
+  putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)), ropef('$1[$2]',
     [rdLoc(a), rdCharLoc(b)]));
 end;
 
@@ -934,8 +934,9 @@ var
 begin
   initLocExpr(p, e.sons[0], a);
   initLocExpr(p, e.sons[1], b);
-  ty := skipVarGenericRange(a.t);
-  if ty.kind in [tyRef, tyPtr] then ty := skipVarGenericRange(ty.sons[0]);
+  ty := skipTypes(a.t, abstractVarRange);
+  if ty.kind in [tyRef, tyPtr] then 
+    ty := skipTypes(ty.sons[0], abstractVarRange);
   // emit range check:
   if (optBoundsCheck in p.options) then begin
     useMagic(p.module, 'raiseIndexError');
@@ -949,10 +950,10 @@ begin
         [rdLoc(b), rdLoc(a)])
   end;
   if d.k = locNone then d.s := OnHeap;
-  if skipVarGenericRange(a.t).kind in [tyRef, tyPtr] then
+  if skipTypes(a.t, abstractVar).kind in [tyRef, tyPtr] then
     a.r := ropef('(*$1)', [a.r]);
-  putIntoDest(p, d, elemType(skipVarGeneric(a.t)), ropef('$1->data[$2]',
-    [rdLoc(a), rdCharLoc(b)]));
+  putIntoDest(p, d, elemType(skipTypes(a.t, abstractVar)), 
+    ropef('$1->data[$2]', [rdLoc(a), rdCharLoc(b)]));
 end;
 
 procedure genAndOr(p: BProc; e: PNode; var d: TLoc; m: TMagic);
@@ -1040,6 +1041,20 @@ begin
     genAssignment(p, d, tmp, {@set}[]); // no need for deep copying
 end;
 
+procedure genEcho(p: BProc; n: PNode);
+var 
+  i: int;
+  a: TLoc;
+begin
+  useMagic(p.module, 'rawEcho');
+  useMagic(p.module, 'rawEchoNL');
+  for i := 1 to sonsLen(n)-1 do begin
+    initLocExpr(p, n.sons[i], a);
+    appf(p.s[cpsStmts], 'rawEcho($1);$n', [rdLoc(a)]);
+  end;
+  app(p.s[cpsStmts], 'rawEchoNL();' + tnl);
+end;
+
 procedure genCall(p: BProc; t: PNode; var d: TLoc);
 var
   param: PSym;
@@ -1120,7 +1135,7 @@ begin
   for i := 0 to sonsLen(e)-2 do begin
     // compute the length expression:
     initLocExpr(p, e.sons[i+1], a);
-    if skipVarGenericRange(e.sons[i+1].Typ).kind = tyChar then begin
+    if skipTypes(e.sons[i+1].Typ, abstractVarRange).kind = tyChar then begin
       Inc(L);
       useMagic(p.module, 'appendChar');
       appf(appends, 'appendChar($1, $2);$n', [tmp.r, rdLoc(a)])
@@ -1169,7 +1184,7 @@ begin
   for i := 0 to sonsLen(e)-3 do begin
     // compute the length expression:
     initLocExpr(p, e.sons[i+2], a);
-    if skipVarGenericRange(e.sons[i+2].Typ).kind = tyChar then begin
+    if skipTypes(e.sons[i+2].Typ, abstractVarRange).kind = tyChar then begin
       Inc(L);
       useMagic(p.module, 'appendChar');
       appf(appends, 'appendChar($1, $2);$n',
@@ -1202,8 +1217,8 @@ begin
   InitLocExpr(p, e.sons[2], b);
   appf(p.s[cpsStmts],
     '$1 = ($2) incrSeq(&($1)->Sup, sizeof($3));$n',
-    [rdLoc(a), getTypeDesc(p.module, skipVarGeneric(e.sons[1].typ)),
-    getTypeDesc(p.module, skipVarGeneric(e.sons[2].Typ))]);
+    [rdLoc(a), getTypeDesc(p.module, skipTypes(e.sons[1].typ, abstractVar)),
+    getTypeDesc(p.module, skipTypes(e.sons[2].Typ, abstractVar))]);
   initLoc(dest, locExpr, b.t, OnHeap);
   dest.r := ropef('$1->data[$1->Sup.len-1]', [rdLoc(a)]);
   genAssignment(p, dest, b, {@set}[needToCopy, afDestIsNil]);
@@ -1222,7 +1237,7 @@ begin
       s := t;
       while (s.kind = tyObject) and (s.sons[0] <> nil) do begin
         app(r, '.Sup');
-        s := skipGeneric(s.sons[0]);
+        s := skipTypes(s.sons[0], abstractInst);
       end;    
       appf(p.s[cpsStmts], '$1.m_type = $2;$n', [r, genTypeInfo(p.module, t)])
     end;
@@ -1242,15 +1257,15 @@ var
   reftype, bt: PType;
 begin
   useMagic(p.module, 'newObj');
-  refType := skipVarGenericRange(e.sons[1].typ);
+  refType := skipTypes(e.sons[1].typ, abstractVarRange);
   InitLocExpr(p, e.sons[1], a);
   initLoc(b, locExpr, a.t, OnHeap);
   b.r := ropef('($1) newObj($2, sizeof($3))',
     [getTypeDesc(p.module, reftype), genTypeInfo(p.module, refType),
-    getTypeDesc(p.module, skipGenericRange(reftype.sons[0]))]);
+    getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))]);
   genAssignment(p, a, b, {@set}[]);
   // set the object type:
-  bt := skipGenericRange(refType.sons[0]);
+  bt := skipTypes(refType.sons[0], abstractRange);
   genObjectInit(p, bt, a, false);
 end;
 
@@ -1260,7 +1275,7 @@ var
   seqtype: PType;
 begin
   useMagic(p.module, 'newSeq');
-  seqType := skipVarGenericRange(e.sons[1].typ);
+  seqType := skipTypes(e.sons[1].typ, abstractVarRange);
   InitLocExpr(p, e.sons[1], a);
   InitLocExpr(p, e.sons[2], b);
   initLoc(c, locExpr, a.t, OnHeap);
@@ -1278,20 +1293,20 @@ var
   r, nilcheck: PRope;
 begin
   initLocExpr(p, n.sons[1], a);
-  dest := skipPtrsGeneric(n.sons[2].typ);
+  dest := skipTypes(n.sons[2].typ, abstractPtrs);
   useMagic(p.module, 'isObj');
   r := rdLoc(a);
   nilCheck := nil;
-  t := skipGeneric(a.t);
+  t := skipTypes(a.t, abstractInst);
   while t.kind in [tyVar, tyPtr, tyRef] do begin
     if t.kind <> tyVar then nilCheck := r;
     r := ropef('(*$1)', [r]);
-    t := skipGeneric(t.sons[0])
+    t := skipTypes(t.sons[0], abstractInst)
   end;
   if gCmd <> cmdCompileToCpp then
     while (t.kind = tyObject) and (t.sons[0] <> nil) do begin
       app(r, '.Sup');
-      t := skipGeneric(t.sons[0]);
+      t := skipTypes(t.sons[0], abstractInst)
     end;
   if nilCheck <> nil then
     r := ropef('(($1) && isObj($2.m_type, $3))',
@@ -1310,7 +1325,7 @@ var
   oldModule: BModule;
 begin
   useMagic(p.module, 'newObj');
-  refType := skipVarGenericRange(e.sons[1].typ);
+  refType := skipTypes(e.sons[1].typ, abstractVarRange);
   InitLocExpr(p, e.sons[1], a);
   
   // This is a little hack: 
@@ -1326,11 +1341,11 @@ begin
   appf(gmti.s[cfsTypeInit3], '$1->finalizer = (void*)$2;$n', [
     ti, rdLoc(f)]);
   b.r := ropef('($1) newObj($2, sizeof($3))',
-                   [getTypeDesc(p.module, refType), ti,
-                    getTypeDesc(p.module, skipGenericRange(reftype.sons[0]))]);
+           [getTypeDesc(p.module, refType), ti,
+            getTypeDesc(p.module, skipTypes(reftype.sons[0], abstractRange))]);
   genAssignment(p, a, b, {@set}[]);
   // set the object type:
-  bt := skipGenericRange(refType.sons[0]);
+  bt := skipTypes(refType.sons[0], abstractRange);
   genObjectInit(p, bt, a, false);
 end;
 
@@ -1340,7 +1355,7 @@ var
   t: PType;
 begin
   InitLocExpr(p, e.sons[1], a);
-  t := skipVarGenericRange(e.sons[1].typ);
+  t := skipTypes(e.sons[1].typ, abstractVarRange);
   case t.kind of
     tyInt..tyInt64: begin
       UseMagic(p.module, 'reprInt');
@@ -1358,7 +1373,7 @@ begin
       UseMagic(p.module, 'reprChar');
       putIntoDest(p, d, e.typ, ropef('reprChar($1)', [rdLoc(a)]))
     end;
-    tyEnum, tyAnyEnum: begin
+    tyEnum, tyOrdinal: begin
       UseMagic(p.module, 'reprEnum');
       putIntoDest(p, d, e.typ,
         ropef('reprEnum($1, $2)', [rdLoc(a), genTypeInfo(p.module, t)]))
@@ -1416,7 +1431,7 @@ procedure genArrayLen(p: BProc; e: PNode; var d: TLoc; op: TMagic);
 var
   typ: PType;
 begin
-  typ := skipPtrsGeneric(e.sons[1].Typ);
+  typ := skipTypes(e.sons[1].Typ, abstractPtrs);
   case typ.kind of
     tyOpenArray: begin
       while e.sons[1].kind = nkPassAsOpenArray do
@@ -1457,7 +1472,7 @@ begin
   useMagic(p.module, 'setLengthSeq');
   InitLocExpr(p, e.sons[1], a);
   InitLocExpr(p, e.sons[2], b);
-  t := skipVarGeneric(e.sons[1].typ);
+  t := skipTypes(e.sons[1].typ, abstractVar);
   appf(p.s[cpsStmts],
     '$1 = ($3) setLengthSeq(&($1)->Sup, sizeof($4), $2);$n',
     [rdLoc(a), rdLoc(b), getTypeDesc(p.module, t),
@@ -1477,7 +1492,7 @@ procedure genSwap(p: BProc; e: PNode; var d: TLoc);
 var
   a, b, tmp: TLoc;
 begin
-  getTemp(p, skipVarGeneric(e.sons[1].typ), tmp);
+  getTemp(p, skipTypes(e.sons[1].typ, abstractVar), tmp);
   InitLocExpr(p, e.sons[1], a); // eval a
   InitLocExpr(p, e.sons[2], b); // eval b
   genAssignment(p, tmp, a, {@set}[]);
@@ -1518,7 +1533,7 @@ end;
 
 procedure genInExprAux(p: BProc; e: PNode; var a, b, d: TLoc);
 begin
-  case int(getSize(skipVarGeneric(e.sons[1].typ))) of
+  case int(getSize(skipTypes(e.sons[1].typ, abstractVar))) of
     1: binaryExprIn(p, e, a, b, d, '(($1 &(1<<(($2)&7)))!=0)');
     2: binaryExprIn(p, e, a, b, d, '(($1 &(1<<(($2)&15)))!=0)');
     4: binaryExprIn(p, e, a, b, d, '(($1 &(1<<(($2)&31)))!=0)');
@@ -1591,7 +1606,7 @@ var
   a, b, i: TLoc;
   ts: string;
 begin
-  setType := skipVarGeneric(e.sons[1].Typ);
+  setType := skipTypes(e.sons[1].Typ, abstractVar);
   size := int(getSize(setType));
   case size of
     1, 2, 4, 8: begin
@@ -1676,7 +1691,7 @@ var
   a: TLoc;
 begin
   InitLocExpr(p, e.sons[1], a);
-  if (skipGenericRange(e.typ).kind in ValueTypes)
+  if (skipTypes(e.typ, abstractRange).kind in ValueTypes)
   and not (lfIndirect in a.flags) then
     putIntoDest(p, d, e.typ, ropef('(*($1*) ($2))',
       [getTypeDesc(p.module, e.typ), addrLoc(a)]))
@@ -1690,7 +1705,7 @@ var
   a: TLoc;
   dest: PType;
 begin
-  dest := skipVarGeneric(n.typ);
+  dest := skipTypes(n.typ, abstractVar);
   if not (optRangeCheck in p.options) then begin
     InitLocExpr(p, n.sons[0], a);
     putIntoDest(p, d, n.typ, ropef('(($1) ($2))',
@@ -1720,8 +1735,8 @@ var
 begin
   while n.sons[0].kind = nkPassAsOpenArray do
     n.sons[0] := n.sons[0].sons[0]; // BUGFIX
-  dest := skipVarGeneric(n.typ);
-  case skipVarGeneric(n.sons[0].typ).kind of
+  dest := skipTypes(n.typ, abstractVar);
+  case skipTypes(n.sons[0].typ, abstractVar).kind of
     tyOpenArray: begin
       initLocExpr(p, n.sons[0], a);
       putIntoDest(p, d, dest, ropef('$1, $1Len0', [rdLoc(a)]));
@@ -1744,7 +1759,8 @@ var
   a: TLoc;
 begin
   initLocExpr(p, n.sons[0], a);
-  putIntoDest(p, d, skipVarGeneric(n.typ), ropef('$1->data', [rdLoc(a)]));
+  putIntoDest(p, d, skipTypes(n.typ, abstractVar), 
+              ropef('$1->data', [rdLoc(a)]));
 end;
 
 procedure convCStrToStr(p: BProc; n: PNode; var d: TLoc);
@@ -1753,7 +1769,7 @@ var
 begin
   useMagic(p.module, 'cstrToNimstr');
   initLocExpr(p, n.sons[0], a);
-  putIntoDest(p, d, skipVarGeneric(n.typ),
+  putIntoDest(p, d, skipTypes(n.typ, abstractVar),
               ropef('cstrToNimstr($1)', [rdLoc(a)]));
 end;
 
@@ -1793,7 +1809,7 @@ begin
     genTypeInfo(p.module, t.typ), intLiteral(sonsLen(t))]);
   genAssignment(p, d, newSeq, {@set}[afSrcIsNotNil]);
   for i := 0 to sonsLen(t)-1 do begin
-    initLoc(arr, locExpr, elemType(skipGeneric(t.typ)), OnHeap);
+    initLoc(arr, locExpr, elemType(skipTypes(t.typ, abstractInst)), OnHeap);
     arr.r := ropef('$1->data[$2]', [rdLoc(d), intLiteral(i)]);
     arr.s := OnHeap; // we know that sequences are on the heap
     expr(p, t.sons[i], arr)
@@ -1821,10 +1837,10 @@ begin
   genAssignment(p, d, newSeq, {@set}[afSrcIsNotNil]);
   initLocExpr(p, t.sons[1], a);
   for i := 0 to L-1 do begin
-    initLoc(elem, locExpr, elemType(skipGeneric(t.typ)), OnHeap);
+    initLoc(elem, locExpr, elemType(skipTypes(t.typ, abstractInst)), OnHeap);
     elem.r := ropef('$1->data[$2]', [rdLoc(d), intLiteral(i)]);
     elem.s := OnHeap; // we know that sequences are on the heap
-    initLoc(arr, locExpr, elemType(skipGeneric(t.sons[1].typ)), a.s);
+    initLoc(arr, locExpr, elemType(skipTypes(t.sons[1].typ, abstractInst)), a.s);
     arr.r := ropef('$1[$2]', [rdLoc(a), intLiteral(i)]);
     genAssignment(p, elem, arr, {@set}[afDestIsNil, needToCopy]);
   end
@@ -1841,12 +1857,7 @@ begin
     mUnaryMinusI..mAbsI64: unaryArithOverflow(p, e, d, op);
     mShrI..mXor: binaryArith(p, e, d, op);
     mAddi..mModi64: binaryArithOverflow(p, e, d, op);
-    mRepr: genRepr(p, e, d);
-    mAsgn: begin
-      InitLocExpr(p, e.sons[1], a);
-      assert(a.t <> nil);
-      expr(p, e.sons[2], a);
-    end;
+    mRepr: genRepr(p, e, d); 
     mSwap: genSwap(p, e, d);
     mPred: begin // XXX: range checking?
       if not (optOverflowCheck in p.Options) then
@@ -1900,7 +1911,7 @@ begin
     mInc: begin
       if not (optOverflowCheck in p.Options) then
         binaryStmt(p, e, d, '', '$1 += $2;$n')
-      else if skipVarGeneric(e.sons[1].typ).kind = tyInt64 then
+      else if skipTypes(e.sons[1].typ, abstractVar).kind = tyInt64 then
         binaryStmt(p, e, d, 'addInt64', '$1 = addInt64($1, $2);$n')
       else
         binaryStmt(p, e, d, 'addInt', '$1 = addInt($1, $2);$n')
@@ -1908,7 +1919,7 @@ begin
     ast.mDec: begin
       if not (optOverflowCheck in p.Options) then
         binaryStmt(p, e, d, '', '$1 -= $2;$n')
-      else if skipVarGeneric(e.sons[1].typ).kind = tyInt64 then
+      else if skipTypes(e.sons[1].typ, abstractVar).kind = tyInt64 then
         binaryStmt(p, e, d, 'subInt64', '$1 = subInt64($1, $2);$n')
       else
         binaryStmt(p, e, d, 'subInt', '$1 = subInt($1, $2);$n')
@@ -1919,8 +1930,8 @@ begin
     mSetLengthSeq: genSetLengthSeq(p, e, d);
     mIncl, mExcl, mCard, mLtSet, mLeSet, mEqSet, mMulSet, mPlusSet,
     mMinusSet, mInSet: genSetOp(p, e, d, op);
-    mNewString, mCopyStr, mCopyStrLast: genCall(p, e, d);
-    mExit: genCall(p, e, d);
+    mNewString, mCopyStr, mCopyStrLast, mExit: genCall(p, e, d);
+    mEcho: genEcho(p, e);
     mArrToSeq: genArrToSeq(p, e, d);
     mNLen..mNError:
       liMessage(e.info, errCannotGenerateCodeForX, e.sons[0].sym.name.s);
@@ -2057,7 +2068,7 @@ begin
   if not handleConstExpr(p, n, d) then begin
     if d.k = locNone then getTemp(p, n.typ, d);
     for i := 0 to sonsLen(n)-1 do begin
-      initLoc(arr, locExpr, elemType(skipGeneric(n.typ)), d.s);
+      initLoc(arr, locExpr, elemType(skipTypes(n.typ, abstractInst)), d.s);
       arr.r := ropef('$1[$2]', [rdLoc(d), intLiteral(i)]);
       expr(p, n.sons[i], arr)
     end
@@ -2087,21 +2098,21 @@ var
   r, nilCheck: PRope;
 begin
   initLocExpr(p, n.sons[0], a);
-  dest := skipPtrsGeneric(n.typ);
+  dest := skipTypes(n.typ, abstractPtrs);
   if (optObjCheck in p.options) and not (isPureObject(dest)) then begin
     useMagic(p.module, 'chckObj');
     r := rdLoc(a);
     nilCheck := nil;
-    t := skipGeneric(a.t);
+    t := skipTypes(a.t, abstractInst);
     while t.kind in [tyVar, tyPtr, tyRef] do begin
       if t.kind <> tyVar then nilCheck := r;
       r := ropef('(*$1)', [r]);
-      t := skipGeneric(t.sons[0])
+      t := skipTypes(t.sons[0], abstractInst)
     end;
     if gCmd <> cmdCompileToCpp then
       while (t.kind = tyObject) and (t.sons[0] <> nil) do begin
         app(r, '.Sup');
-        t := skipGeneric(t.sons[0]);
+        t := skipTypes(t.sons[0], abstractInst);
       end;
     if nilCheck <> nil then
       appf(p.s[cpsStmts], 'if ($1) chckObj($2.m_type, $3);$n',
@@ -2128,11 +2139,12 @@ begin
   if gCmd = cmdCompileToCpp then
     expr(p, n.sons[0], d) // downcast does C++ for us
   else begin
-    dest := skipPtrsGeneric(n.typ);
-    src := skipPtrsGeneric(n.sons[0].typ);
+    dest := skipTypes(n.typ, abstractPtrs);
+    src := skipTypes(n.sons[0].typ, abstractPtrs);
     initLocExpr(p, n.sons[0], a);
     r := rdLoc(a);
-    if skipGeneric(n.sons[0].typ).kind in [tyRef, tyPtr, tyVar] then begin
+    if skipTypes(n.sons[0].typ, abstractInst).kind in [tyRef, tyPtr, tyVar] 
+    then begin
       app(r, '->Sup');
       for i := 2 to abs(inheritanceDiff(dest, src)) do app(r, '.Sup');
       r := con('&'+'', r);
@@ -2201,7 +2213,7 @@ begin
     end;
     nkCurly: genSetConstr(p, e, d);
     nkBracket:
-      if (skipVarGenericRange(e.typ).kind = tySequence) then  // BUGFIX
+      if (skipTypes(e.typ, abstractVarRange).kind = tySequence) then
         genSeqConstr(p, e, d)
       else
         genArrayConstr(p, e, d);
@@ -2211,8 +2223,9 @@ begin
     nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, e, d);
     nkHiddenAddr, nkAddr: genAddr(p, e, d);
     nkBracketExpr: begin
-      ty := skipVarGenericRange(e.sons[0].typ);
-      if ty.kind in [tyRef, tyPtr] then ty := skipVarGenericRange(ty.sons[0]);
+      ty := skipTypes(e.sons[0].typ, abstractVarRange);
+      if ty.kind in [tyRef, tyPtr] then 
+        ty := skipTypes(ty.sons[0], abstractVarRange);
       case ty.kind of
         tyArray, tyArrayConstr: genArrayElem(p, e, d);
         tyOpenArray: genOpenArrayElem(p, e, d);
@@ -2253,7 +2266,7 @@ var
 begin
   result := copyNode(n);
   newSons(result, sonsLen(n));
-  t := getUniqueType(skipVarGenericRange(n.Typ));
+  t := getUniqueType(skipTypes(n.Typ, abstractVarRange));
   if t.n = nil then
     InternalError(n.info, 'transformRecordExpr: invalid type');
   for i := 0 to sonsLen(n)-1 do begin
diff --git a/nim/ccgstmts.pas b/nim/ccgstmts.pas
index 6cff9dc8d..90e5c1c77 100644
--- a/nim/ccgstmts.pas
+++ b/nim/ccgstmts.pas
@@ -68,8 +68,8 @@ procedure initVariable(p: BProc; v: PSym);
 begin
   if containsGarbageCollectedRef(v.typ) or (v.ast = nil) then
     // Language change: always initialize variables if v.ast == nil!
-    if not (skipVarGenericRange(v.typ).Kind in [tyArray, tyArrayConstr, tySet,
-                                                tyTuple, tyObject]) then begin
+    if not (skipTypes(v.typ, abstractVarRange).Kind in [tyArray, 
+            tyArrayConstr, tySet, tyTuple, tyObject]) then begin
       if gCmd = cmdCompileToLLVM then
         appf(p.s[cpsStmts], 'store $2 0, $2* $1$n', 
              [addrLoc(v.loc), getTypeDesc(p.module, v.loc.t)])
@@ -618,7 +618,7 @@ end;
 procedure genCaseStmt(p: BProc; t: PNode);
 begin
   genLineDir(p, t);
-  case skipVarGenericRange(t.sons[0].typ).kind of
+  case skipTypes(t.sons[0].typ, abstractVarRange).kind of
     tyString: genStringCase(p, t);
     tyFloat..tyFloat128:
       genCaseGeneric(p, t, 'if ($1 >= $2 && $1 <= $3) goto $4;$n',
diff --git a/nim/ccgtypes.pas b/nim/ccgtypes.pas
index 28db6e009..f9b3a36c1 100644
--- a/nim/ccgtypes.pas
+++ b/nim/ccgtypes.pas
@@ -62,7 +62,7 @@ begin
     app(result, toRope(s.id));
     if optGenMapping in gGlobalOptions then
       if s.owner <> nil then
-        appf(gMapping, '"$1.$2": $3$n',
+        appf(gMapping, 'r"$1.$2": $3$n',
           [toRope(s.owner.Name.s), toRope(s.name.s), result]);
     s.loc.r := result;
   end
@@ -116,8 +116,9 @@ begin
     end;
     tyOpenArray, tyArrayConstr, tyArray: result := ctArray;
     tyObject, tyTuple: result := ctStruct;
-    tyGeneric, tyGenericInst, tyGenericParam: result := mapType(lastSon(typ));
-    tyEnum, tyAnyEnum: begin
+    tyGeneric, tyGenericInst, tyGenericParam, tyAbstract, tyOrdinal: 
+      result := mapType(lastSon(typ));
+    tyEnum: begin
       if firstOrd(typ) < 0 then
         result := ctInt32
       else begin
@@ -150,7 +151,7 @@ end;
 
 function mapReturnType(typ: PType): TCTypeKind;
 begin
-  if skipGeneric(typ).kind = tyArray then result := ctPtr
+  if skipTypes(typ, abstractInst).kind = tyArray then result := ctPtr
   else result := mapType(typ)
 end;
 
@@ -173,8 +174,9 @@ begin
   else begin
     case mapType(rettype) of
       ctArray:
-        result := not (skipGeneric(rettype).kind in [tyVar, tyRef, tyPtr]);
-      ctStruct: result := needsComplexAssignment(skipGeneric(rettype));
+        result := not (skipTypes(rettype, abstractInst).kind in [tyVar, tyRef, tyPtr]);
+      ctStruct: 
+        result := needsComplexAssignment(skipTypes(rettype, abstractInst));
       else result := false;
     end
   end
@@ -285,7 +287,6 @@ begin
   if (t.sons[0] <> nil) and isInvalidReturnType(t.sons[0]) then begin
     if params <> nil then app(params, ', ');
     arr := t.sons[0];
-    //if skipGeneric(arr).kind = tyArray then arr := arr.sons[1];
     app(params, getTypeDescAux(m, arr, check));
     if (mapReturnType(t.sons[0]) <> ctArray) or (gCmd = cmdCompileToLLVM) then 
       app(params, '*'+'');
@@ -612,7 +613,7 @@ begin
       IdTablePut(m.typeCache, t, con(result, '*'+''));
       if not isImportedType(t) then begin
         useMagic(m, 'TGenericSeq');
-        if skipGeneric(t.sons[0]).kind <> tyEmpty then 
+        if skipTypes(t.sons[0], abstractInst).kind <> tyEmpty then 
           appf(m.s[cfsSeqTypes],
             'struct $2 {$n' +
             '  TGenericSeq Sup;$n' +
@@ -663,7 +664,8 @@ begin
         end
       end
     end;
-    tyGenericInst: result := getTypeDescAux(m, lastSon(t), check);
+    tyGenericInst, tyAbstract, tyOrdinal: 
+      result := getTypeDescAux(m, lastSon(t), check);
     else begin
       InternalError('getTypeDescAux(' + typeKindToStr[t.kind] + ')');
       result := nil
diff --git a/nim/ccgutils.pas b/nim/ccgutils.pas
index 49c1a8cee..de5cac13c 100644
--- a/nim/ccgutils.pas
+++ b/nim/ccgutils.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -56,7 +56,8 @@ begin
         result := key;
       end
     end;
-    tyGenericInst: result := GetUniqueType(lastSon(key));
+    tyGenericInst, tyAbstract, tyOrdinal: 
+      result := GetUniqueType(lastSon(key));
     tyProc: begin end;
     else begin
       // we have to do a slow linear search because types may need
@@ -75,7 +76,7 @@ begin
     tyInt..tyFloat128, tyProc, tyAnyEnum: begin end;
     tyNone, tyForward: 
       InternalError('GetUniqueType: ' + typeToString(key));
-    tyGenericParam, tyGeneric, tySequence,
+    tyGenericParam, tyGeneric, tyAbstract, tySequence,
     tyOpenArray, tySet, tyVar, tyRef, tyPtr, tyArrayConstr,
     tyArray, tyTuple, tyRange: begin
       // we have to do a slow linear search because types may need
@@ -94,7 +95,7 @@ begin
         result := key;
       end
     end;
-    tyGenericInst: result := GetUniqueType(lastSon(key));
+    tyGenericInst, tyAbstract: result := GetUniqueType(lastSon(key));
   end; *)
 end;
 
diff --git a/nim/cgen.pas b/nim/cgen.pas
index 6a0ab0390..fdae6feb6 100644
--- a/nim/cgen.pas
+++ b/nim/cgen.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -232,8 +232,8 @@ end;
 
 function isSimpleConst(typ: PType): bool;
 begin
-  result := not (skipVarGeneric(typ).kind in [tyTuple, tyObject, tyArray,
-                                            tyArrayConstr, tySet, tySequence])
+  result := not (skipTypes(typ, abstractVar).kind in [tyTuple, tyObject, 
+    tyArray, tyArrayConstr, tySet, tySequence])
 end;
 
 procedure useHeader(m: BModule; sym: PSym);
@@ -249,12 +249,6 @@ procedure UseMagic(m: BModule; const name: string); forward;
 {$include 'ccgtypes.pas'}
 
 // ------------------------------ Manager of temporaries ------------------
-(*
-function beEqualTypes(a, b: PType): bool;
-begin
-  // returns whether two type are equal for the backend
-  result := sameType(skipGenericRange(a), skipGenericRange(b))
-end; *)
 
 procedure getTemp(p: BProc; t: PType; var result: TLoc);
 begin
@@ -458,9 +452,35 @@ procedure genProcPrototype(m: BModule; sym: PSym); forward;
 
 // We don't finalize dynamic libs as this does the OS for us.
 
+procedure libCandidates(const s: string; var dest: TStringSeq);
+var
+  prefix, suffix: string;
+  le, ri, i, L: int;
+  temp: TStringSeq;
+begin
+  le := strutils.find(s, '(');
+  ri := strutils.find(s, ')');
+  if (le >= strStart) and (ri > le) then begin
+    prefix := ncopy(s, strStart, le-1);
+    suffix := ncopy(s, ri+1);
+    temp := splitSeq(ncopy(s, le+1, ri-1), {@set}['|']);
+    for i := 0 to high(temp) do 
+      libCandidates(prefix +{&} temp[i] +{&} suffix, dest);
+  end
+  else begin
+    {@ignore} 
+    L := length(dest);
+    setLength(dest, L+1);
+    dest[L] := s;
+    {@emit add(dest, s);}
+  end
+end;
+
 procedure loadDynamicLib(m: BModule; lib: PLib);
 var
-  tmp: PRope;
+  tmp, loadlib: PRope;
+  s: TStringSeq;
+  i: int;
 begin
   assert(lib <> nil);
   if not lib.generated then begin
@@ -471,18 +491,29 @@ begin
     // BUGFIX: useMagic has awful side-effects
     appff(m.s[cfsVars], 'static void* $1;$n', 
                         '$1 = linkonce global i8* zeroinitializer$n', [tmp]);
-    inc(m.labels);
-    appff(m.s[cfsDynLibInit],
-        '$1 = nimLoadLibrary((NimStringDesc*) &$2);$n',
-        '%MOC$4 = call i8* @nimLoadLibrary($3 $2)$n' +
-        'store i8* %MOC$4, i8** $1$n',
-        [tmp, getStrLit(m, lib.path), getTypeDesc(m, getSysType(tyString)),
-         toRope(m.labels)]);
+    {@ignore} s := nil; {@emit s := @[];}
+    libCandidates(lib.path, s);
+    loadlib := nil;
+    for i := 0 to high(s) do begin
+      inc(m.labels);
+      if i > 0 then app(loadlib, '||');
+      appff(loadlib,
+          '($1 = nimLoadLibrary((NimStringDesc*) &$2))$n',
+          '%MOC$4 = call i8* @nimLoadLibrary($3 $2)$n' +
+          'store i8* %MOC$4, i8** $1$n',
+          [tmp, getStrLit(m, s[i]), getTypeDesc(m, getSysType(tyString)),
+           toRope(m.labels)]);
+    end;
+    appff(m.s[cfsDynLibInit], 
+         'if (!($1)) nimLoadLibraryError((NimStringDesc*) &$2);$n', 
+         'XXX too implement',
+         [loadlib, getStrLit(m, lib.path)]);
     //appf(m.s[cfsDynLibDeinit],
     //  'if ($1 != NIM_NIL) nimUnloadLibrary($1);$n', [tmp]);
     useMagic(m, 'nimLoadLibrary');
     useMagic(m, 'nimUnloadLibrary');
     useMagic(m, 'NimStringDesc');
+    useMagic(m, 'nimLoadLibraryError');
   end;
   if lib.name = nil then InternalError('loadDynamicLib');
 end;
@@ -642,7 +673,7 @@ begin
     else begin
       fillResult(res);
       assignParam(p, res);
-      if skipGeneric(res.typ).kind = tyArray then begin
+      if skipTypes(res.typ, abstractInst).kind = tyArray then begin
         include(res.loc.flags, lfIndirect);
         res.loc.s := OnUnknown;
       end;
@@ -745,6 +776,7 @@ end;
 
 procedure genProc(m: BModule; prc: PSym);
 begin
+  if sfBorrow in prc.flags then exit;
   fillProcLoc(prc);
   if [sfForward, sfFromGeneric] * prc.flags <> [] then 
     addForwardedProc(m, prc)
@@ -1148,7 +1180,6 @@ begin
     addFileToCompile(cfilenoext);
   end;
   addFileToLink(cfilenoext);
-  if sfMainModule in m.module.flags then writeMapping(cfile, gMapping);
 end;
 
 function myClose(b: PPassContext; n: PNode): PNode;
@@ -1177,6 +1208,7 @@ begin
         finishModule(gPendingModules[i]);
     for i := 0 to high(gPendingModules) do writeModule(gPendingModules[i]);
     setLength(gPendingModules, 0);
+    writeMapping(gMapping);
   end;
   if not (optDeadCodeElim in gGlobalOptions) and 
       not (sfDeadCodeElim in m.module.flags) then
diff --git a/nim/commands.pas b/nim/commands.pas
index fde2d26c7..df6ab9da7 100644
--- a/nim/commands.pas
+++ b/nim/commands.pas
@@ -150,7 +150,8 @@ begin
   if (pass = passCmd1) and not helpWritten then begin

     // BUGFIX 19

     MessageOut(getCommandLineDesc());

-    helpWritten := true

+    helpWritten := true;
+    halt(0);

   end

 end;

 

diff --git a/nim/condsyms.pas b/nim/condsyms.pas
index 1df513bbc..465bc045e 100644
--- a/nim/condsyms.pas
+++ b/nim/condsyms.pas
@@ -111,8 +111,7 @@ begin
       DefineSymbol('mswindows');
       DefineSymbol('win32');
     end;
-    osLinux, osMorphOS, osSkyOS, osIrix, osPalmOS, osQNX,
-    osAtari, osAix: begin
+    osLinux, osMorphOS, osSkyOS, osIrix, osPalmOS, osQNX, osAtari, osAix: begin
       // these are all 'unix-like'
       DefineSymbol('unix');
       DefineSymbol('posix');
diff --git a/nim/docgen.pas b/nim/docgen.pas
index 784ab6c6c..5e8ecf7a3 100644
--- a/nim/docgen.pas
+++ b/nim/docgen.pas
@@ -235,6 +235,8 @@ begin
 end;
 
 function toXml(const s: string; splitAfter: int = -1): string;
+const
+  splitter = '<wbr />';
 var
   i, j, k, partLen: int;
 begin
@@ -244,9 +246,9 @@ begin
     j := strStart;
     while j < length(s)+strStart do begin
       k := nextSplitPoint(s, j);
-      if partLen + k - j + 1 > splitAfter then begin
+      if (splitter <> ' '+'') or (partLen + k - j + 1 > splitAfter) then begin
         partLen := 0;
-        addChar(result, ' ');
+        add(result, splitter);
       end;
       for i := j to k do addXmlChar(result, s[i]);
       inc(partLen, k - j + 1);
@@ -691,9 +693,10 @@ var
   langstr: string;
   lang: TSourceLanguage;
 begin
+  result := nil;
+  if n.sons[2] = nil then exit;
   m := n.sons[2].sons[0];
   if (m.kind <> rnLeaf) then InternalError('renderCodeBlock');
-  result := nil;
   langstr := strip(getArgument(n));
   if langstr = '' then lang := langNimrod // default language
   else lang := getSourceLanguage(langstr);
@@ -996,7 +999,6 @@ begin
   rst := rstParse(readFile(filen), false, filen, 0, 1, d.hasToc);
   d.modDesc := renderRstToHtml(d, rst);
   code := genHtmlFile(d);
-  assert(ropeInvariant(code));
   writeRope(code, getOutFile(filename, HtmlExt));
   generateIndex(d);
 end;
diff --git a/nim/ecmasgen.pas b/nim/ecmasgen.pas
index 2eecfba71..9ffa550ae 100644
--- a/nim/ecmasgen.pas
+++ b/nim/ecmasgen.pas
@@ -109,7 +109,7 @@ const
 
 function mapType(typ: PType): TEcmasTypeKind;
 begin
-  case skipGeneric(typ).kind of
+  case skipTypes(typ, abstractInst).kind of
     tyVar, tyRef, tyPtr: begin
       if typ.sons[0].kind in mappedToObject then
         result := etyObject
@@ -120,8 +120,8 @@ begin
       // treat a tyPointer like a typed pointer to an array of bytes
       result := etyInt;
     end;
-    tyRange: result := mapType(typ.sons[0]);
-    tyInt..tyInt64, tyEnum, tyAnyEnum, tyChar:
+    tyRange, tyAbstract, tyOrdinal: result := mapType(typ.sons[0]);
+    tyInt..tyInt64, tyEnum, tyChar:
       result := etyInt;
     tyBool: result := etyBool;
     tyFloat..tyFloat128: result := etyFloat;
@@ -298,7 +298,8 @@ begin
   if t.kind = tyGenericInst then t := lastSon(t);
   result := ropef('NTI$1', [toRope(t.id)]);
   if IntSetContainsOrIncl(p.globals.TypeInfoGenerated, t.id) then exit;
-  case t.kind of
+  case t.kind of 
+    tyAbstract: result := genTypeInfo(p, typ.sons[0]);
     tyPointer, tyProc, tyBool, tyChar, tyCString, tyString,
     tyInt..tyFloat128: begin
       s := ropef(
@@ -676,7 +677,7 @@ begin
   if n.sons[0] <> nil then begin
     gen(p, n.sons[0], a);
     if a.com <> nil then appf(r.com, '$1;$n', [a.com]);
-    typ := skipPtrsGeneric(n.sons[0].typ);
+    typ := skipTypes(n.sons[0].typ, abstractPtrs);
     useMagic(p, 'raiseException');
     appf(r.com, 'raiseException($1, $2);$n',
       [a.res, makeCString(typ.sym.name.s)]);
@@ -698,7 +699,7 @@ begin
   gen(p, n.sons[0], cond);
   if cond.com <> nil then
     appf(r.com, '$1;$n', [cond.com]);
-  stringSwitch := skipVarGeneric(n.sons[0].typ).kind = tyString;
+  stringSwitch := skipTypes(n.sons[0].typ, abstractVar).kind = tyString;
   if stringSwitch then begin
     useMagic(p, 'toEcmaStr');
     appf(r.com, 'switch (toEcmaStr($1)) {$n', [cond.res])
@@ -888,12 +889,12 @@ const
                                nkFloatLit..nkFloat64Lit,
                                nkCurly, nkPar, 
                                nkStringToCString, nkCStringToString,
-                               nkCall, nkHiddenCallConv];
+                               nkCall, nkCommand, nkHiddenCallConv];
 
 function needsNoCopy(y: PNode): bool;
 begin
   result := (y.kind in nodeKindsNeedNoCopy)
-      or (skipGeneric(y.typ).kind in [tyRef, tyPtr, tyVar])
+      or (skipTypes(y.typ, abstractInst).kind in [tyRef, tyPtr, tyVar])
 end;
 
 procedure genAsgnAux(var p: TProc; x, y: PNode; var r: TCompRes;
@@ -1014,7 +1015,7 @@ begin
   gen(p, n.sons[0], a);
   gen(p, n.sons[1], b);
   r.com := mergeExpr(a);
-  typ := skipPtrsGeneric(n.sons[0].typ);
+  typ := skipTypes(n.sons[0].typ, abstractPtrs);
   if typ.kind in [tyArray, tyArrayConstr] then first := FirstOrd(typ.sons[0])
   else first := 0;
   if (optBoundsCheck in p.options) and not isConstExpr(n.sons[1]) then begin
@@ -1201,9 +1202,9 @@ var
   i, len, c: int;
   t, e: PType;
 begin
-  t := skipGeneric(typ);
+  t := skipTypes(typ, abstractInst);
   case t.kind of
-    tyInt..tyInt64, tyEnum, tyAnyEnum, tyChar: begin
+    tyInt..tyInt64, tyEnum, tyChar: begin
       result := putToSeq('0'+'', indirect)
     end;
     tyFloat..tyFloat128: result := putToSeq('0.0', indirect);
@@ -1354,15 +1355,15 @@ var
   t: Ptype;
 begin
   gen(p, n.sons[1], a);
-  t := skipVarGeneric(n.sons[1].typ).sons[0];
+  t := skipTypes(n.sons[1].typ, abstractVar).sons[0];
   if a.com <> nil then appf(r.com, '$1;$n', [a.com]);
   appf(r.com, '$1 = $2;$n', [a.res, createVar(p, t, true)]);
 end;
 
 procedure genOrd(var p: TProc; n: PNode; var r: TCompRes);
 begin
-  case skipVarGeneric(n.sons[1].typ).kind of
-    tyEnum, tyAnyEnum, tyInt..tyInt64, tyChar: gen(p, n.sons[1], r);
+  case skipTypes(n.sons[1].typ, abstractVar).kind of
+    tyEnum, tyInt..tyInt64, tyChar: gen(p, n.sons[1], r);
     tyBool: unaryExpr(p, n, r, '', '($1 ? 1:0)');
     else InternalError(n.info, 'genOrd');
   end
@@ -1375,9 +1376,9 @@ begin
   gen(p, n.sons[1], a);
   gen(p, n.sons[2], b);
   r.com := mergeExpr(a.com, b.com);
-  if skipVarGenericRange(n.sons[1].typ).kind = tyChar then
+  if skipTypes(n.sons[1].typ, abstractVarRange).kind = tyChar then
     a.res := ropef('[$1, 0]', [a.res]);
-  if skipVarGenericRange(n.sons[2].typ).kind = tyChar then
+  if skipTypes(n.sons[2].typ, abstractVarRange).kind = tyChar then
     b.res := ropef('[$1, 0]', [b.res]);
   r.res := ropef('($1.slice(0,-1)).concat($2)', [a.res, b.res]);
 end;
@@ -1435,7 +1436,7 @@ begin
     mLengthSeq, mLengthOpenArray, mLengthArray:
       unaryExpr(p, n, r, '', '$1.length');
     mHigh: begin
-      if skipVarGeneric(n.sons[0].typ).kind = tyString then
+      if skipTypes(n.sons[0].typ, abstractVar).kind = tyString then
         unaryExpr(p, n, r, '', '($1.length-2)')
       else
         unaryExpr(p, n, r, '', '($1.length-1)');
@@ -1535,8 +1536,8 @@ procedure genConv(var p: TProc; n: PNode; var r: TCompRes);
 var
   src, dest: PType;
 begin
-  dest := skipVarGenericRange(n.typ);
-  src := skipVarGenericRange(n.sons[1].typ);
+  dest := skipTypes(n.typ, abstractVarRange);
+  src := skipTypes(n.sons[1].typ, abstractVarRange);
   gen(p, n.sons[1], r);
   if (dest.kind <> src.kind) and (src.kind = tyBool) then
     r.res := ropef('(($1)? 1:0)', [r.res])
@@ -1750,7 +1751,7 @@ begin
         r.res := toRope('null');
     end;
     nkStrLit..nkTripleStrLit: begin
-      if skipVarGenericRange(n.typ).kind = tyString then begin
+      if skipTypes(n.typ, abstractVarRange).kind = tyString then begin
         useMagic(p, 'cstrToNimstr');
         r.res := ropef('cstrToNimstr($1)', [makeCString(n.strVal)])
       end
@@ -1771,7 +1772,7 @@ begin
     end;
     nkBlockExpr: genBlock(p, n, r);
     nkIfExpr: genIfExpr(p, n, r);
-    nkCall, nkHiddenCallConv: begin
+    nkCall, nkHiddenCallConv, nkCommand: begin
       if (n.sons[0].kind = nkSym) and (n.sons[0].sym.magic <> mNone) then
         genMagic(p, n, r)
       else
diff --git a/nim/evals.pas b/nim/evals.pas
index 218046c7e..7c443bad6 100644
--- a/nim/evals.pas
+++ b/nim/evals.pas
@@ -27,10 +27,10 @@ type
   PStackFrame = ^TStackFrame;
   TStackFrame = record
     mapping: TIdNodeTable; // mapping from symbols to nodes
-    prc: PSym;        // current prc; proc that is evaluated
+    prc: PSym;             // current prc; proc that is evaluated
     call: PNode;
-    next: PStackFrame;   // for stacking
-    params: TNodeSeq;  // parameters passed to the proc
+    next: PStackFrame;     // for stacking
+    params: TNodeSeq;      // parameters passed to the proc
   end;
   
   TEvalContext = object(passes.TPassContext)
@@ -264,7 +264,7 @@ var
   i: int;
   t: PType;
 begin
-  t := skipGenericRange(typ);
+  t := skipTypes(typ, abstractRange);
   result := emptyNode;
   case t.kind of
     tyBool, tyChar, tyInt..tyInt64: result := newNodeIT(nkIntLit, info, t);
@@ -527,6 +527,27 @@ begin
   result := emptyNode
 end;
 
+function getStrValue(n: PNode): string;
+begin
+  case n.kind of
+    nkStrLit..nkTripleStrLit: result := n.strVal;
+    else begin InternalError(n.info, 'getStrValue'); result := '' end;
+  end
+end;
+
+function evalEcho(c: PEvalContext; n: PNode): PNode;
+var
+  i: int;
+begin
+  for i := 1 to sonsLen(n)-1 do begin
+    result := evalAux(c, n.sons[i]);
+    if result.kind = nkExceptBranch then exit;
+    Write(output, getStrValue(result));
+  end;
+  writeln(output, '');
+  result := emptyNode
+end;
+
 function evalExit(c: PEvalContext; n: PNode): PNode;
 begin
   result := evalAux(c, n.sons[1]);
@@ -555,7 +576,7 @@ function evalNew(c: PEvalContext; n: PNode): PNode;
 var
   t: PType;
 begin
-  t := skipVarGeneric(n.sons[1].typ);
+  t := skipTypes(n.sons[1].typ, abstractVar);
   result := newNodeIT(nkRefTy, n.info, t);
   addSon(result, getNullValue(t.sons[0], n.info));
 end;
@@ -604,8 +625,8 @@ var
 begin
   result := evalAux(c, n.sons[0]);
   if result.kind = nkExceptBranch then exit;
-  dest := skipPtrsGeneric(n.typ);
-  src := skipPtrsGeneric(result.typ);
+  dest := skipTypes(n.typ, abstractPtrs);
+  src := skipTypes(result.typ, abstractPtrs);
   if inheritanceDiff(src, dest) > 0 then
     stackTrace(c, n, errInvalidConversionFromTypeX, typeToString(src));
 end;
@@ -700,7 +721,7 @@ function evalHigh(c: PEvalContext; n: PNode): PNode;
 begin
   result := evalAux(c, n.sons[1]);
   if result.kind = nkExceptBranch then exit;
-  case skipVarGeneric(n.sons[1].typ).kind of
+  case skipTypes(n.sons[1].typ, abstractVar).kind of
     tyOpenArray, tySequence:
       result := newIntNodeT(sonsLen(result), n);
     tyString:
@@ -749,7 +770,7 @@ begin
   oldLen := sonsLen(a);
   setLength(a.sons, newLen);
   for i := oldLen to newLen-1 do
-    a.sons[i] := getNullValue(skipVarGeneric(n.sons[1].typ), n.info);
+    a.sons[i] := getNullValue(skipTypes(n.sons[1].typ, abstractVar), n.info);
   result := emptyNode
 end;
 
@@ -766,7 +787,7 @@ begin
   if result.kind = nkExceptBranch then exit;
   b := result;
 
-  t := skipVarGeneric(n.sons[1].typ);
+  t := skipTypes(n.sons[1].typ, abstractVar);
   if a.kind = nkEmpty then InternalError(n.info, 'first parameter is empty');
   a.kind := nkBracket;
   a.info := n.info;
@@ -835,14 +856,6 @@ begin
   result := emptyNode;
 end;
 
-function getStrValue(n: PNode): string;
-begin
-  case n.kind of
-    nkStrLit..nkTripleStrLit: result := n.strVal;
-    else begin InternalError(n.info, 'getStrValue'); result := '' end;
-  end
-end;
-
 function evalConStrStr(c: PEvalContext; n: PNode): PNode;
 // we cannot use ``evalOp`` for this as we can here have more than 2 arguments
 var
@@ -936,6 +949,7 @@ begin
     mSwap: result := evalSwap(c, n);
     mInc: result := evalIncDec(c, n, 1);
     ast.mDec: result := evalIncDec(c, n, -1);
+    mEcho: result := evalEcho(c, n);
     mSetLengthStr: result := evalSetLengthStr(c, n);
     mSetLengthSeq: result := evalSetLengthSeq(c, n);
     mIncl: result := evalIncl(c, n);
@@ -1237,7 +1251,8 @@ begin
     nkType..pred(nkNilLit): result := copyNode(n);
     nkNilLit: result := n; // end of atoms
 
-    nkCall, nkHiddenCallConv, nkMacroStmt: result := evalMagicOrCall(c, n);
+    nkCall, nkHiddenCallConv, nkMacroStmt, nkCommand: 
+      result := evalMagicOrCall(c, n);
     nkCurly, nkBracket, nkRange: begin
       result := copyNode(n);
       for i := 0 to sonsLen(n)-1 do addSon(result, evalAux(c, n.sons[i]));
diff --git a/nim/extccomp.pas b/nim/extccomp.pas
index a53ad1c10..a3e4ff367 100644
--- a/nim/extccomp.pas
+++ b/nim/extccomp.pas
@@ -288,7 +288,7 @@ function NameToCC(const name: string): TSystemCC;
 procedure initVars;
 
 procedure setCC(const ccname: string);
-procedure writeMapping(const cfile: string; gSymbolMapping: PRope);
+procedure writeMapping(gSymbolMapping: PRope);
 
 implementation
 
@@ -638,12 +638,12 @@ begin
   result := nil;
   it := PStrEntry(list.head);
   while it <> nil do begin
-    appf(result, '--file:"$1"$n', [toRope(AppendFileExt(it.data, cExt))]);
+    appf(result, '--file:r"$1"$n', [toRope(AppendFileExt(it.data, cExt))]);
     it := PStrEntry(it.next);
   end;
 end;
 
-procedure writeMapping(const cfile: string; gSymbolMapping: PRope);
+procedure writeMapping(gSymbolMapping: PRope);
 var
   code: PRope;
 begin
diff --git a/nim/magicsys.pas b/nim/magicsys.pas
index 462912995..db801d5f2 100644
--- a/nim/magicsys.pas
+++ b/nim/magicsys.pas
@@ -76,7 +76,6 @@ begin
       tyString:  result := sysTypeFromName('string');
       tyCstring: result := sysTypeFromName('cstring');
       tyPointer: result := sysTypeFromName('pointer');
-      tyAnyEnum: result := newSysType(tyAnyEnum, 1);
       tyNil: result := newSysType(tyNil, ptrSize);
       else InternalError('request for typekind: ' + typeKindToStr[kind]);
     end;  
diff --git a/nim/msgs.pas b/nim/msgs.pas
index d7f0d9f82..48ffc9ee5 100644
--- a/nim/msgs.pas
+++ b/nim/msgs.pas
@@ -49,557 +49,557 @@ uses
 //cog.out(warns)

 //cog.out(hints)

 //]]]

-type

-  TMsgKind = (

-    errUnknown,

-    errIllFormedAstX,

-    errCannotOpenFile,

-    errInternal,

-    errGenerated,

-    errXCompilerDoesNotSupportCpp,

-    errStringLiteralExpected,

-    errIntLiteralExpected,

-    errInvalidCharacterConstant,

-    errClosingTripleQuoteExpected,

-    errClosingQuoteExpected,

-    errTabulatorsAreNotAllowed,

-    errInvalidToken,

-    errLineTooLong,

-    errInvalidNumber,

-    errNumberOutOfRange,

-    errNnotAllowedInCharacter,

-    errClosingBracketExpected,

-    errMissingFinalQuote,

-    errIdentifierExpected,

-    errOperatorExpected,

-    errTokenExpected,

-    errStringAfterIncludeExpected,

-    errRecursiveInclude,

-    errOnOrOffExpected,

-    errNoneSpeedOrSizeExpected,

-    errInvalidPragma,

-    errUnknownPragma,

-    errPragmaXHereNotAllowed,

-    errUnknownDirective,

-    errInvalidDirective,

-    errAtPopWithoutPush,

-    errEmptyAsm,

-    errAsgnInvalidInExpr,

-    errInvalidIndentation,

-    errExceptionExpected,

-    errExceptionAlreadyHandled,

-    errReturnNotAllowedHere,

-    errYieldNotAllowedHere,

-    errInvalidNumberOfYieldExpr,

-    errReturnInvalidInIterator,

-    errCannotReturnExpr,

-    errAttemptToRedefine,

-    errStmtInvalidAfterReturn,

-    errStmtExpected,

-    errInvalidLabel,

-    errInvalidCmdLineOption,

-    errCmdLineArgExpected,

-    errCmdLineNoArgExpected,

-    errInvalidVarSubstitution,

-    errUnknownVar,

-    errUnknownCcompiler,

-    errOnOrOffExpectedButXFound,

-    errNoneBoehmRefcExpectedButXFound,

-    errNoneSpeedOrSizeExpectedButXFound,

-    errGuiConsoleOrLibExpectedButXFound,

-    errUnknownOS,

-    errUnknownCPU,

-    errGenOutExpectedButXFound,

-    errArgsNeedRunOption,

-    errInvalidMultipleAsgn,

-    errColonOrEqualsExpected,

-    errExprExpected,

-    errUndeclaredIdentifier,

-    errUseQualifier,

-    errTwiceForwarded,

-    errTypeExpected,

-    errSystemNeeds,

-    errExecutionOfProgramFailed,

-    errNotOverloadable,

-    errInvalidArgForX,

-    errStmtHasNoEffect,

-    errXExpectsTypeOrValue,

-    errXExpectsArrayType,

-    errIteratorCannotBeInstantiated,

-    errExprWithNoTypeCannotBeConverted,

-    errExprWithNoTypeCannotBeCasted,

-    errConstantDivisionByZero,

-    errOrdinalTypeExpected,

-    errOrdinalOrFloatTypeExpected,

-    errOverOrUnderflow,

-    errCannotEvalXBecauseIncompletelyDefined,

-    errChrExpectsRange0_255,

-    errStaticAssertFailed,

-    errStaticAssertCannotBeEval,

-    errDotRequiresRecordOrObjectType,

-    errUndeclaredFieldX,

-    errNilAccess,

-    errIndexOutOfBounds,

-    errIndexTypesDoNotMatch,

-    errBracketsInvalidForType,

-    errValueOutOfSetBounds,

-    errFieldInitTwice,

-    errFieldNotInit,

-    errExprCannotBeCalled,

-    errExprHasNoType,

-    errExprXHasNoType,

-    errCastNotInSafeMode,

-    errExprCannotBeCastedToX,

-    errUndefinedPrefixOpr,

-    errCommaOrParRiExpected,

-    errCurlyLeOrParLeExpected,

-    errSectionExpected,

-    errImplemenationExpected,

-    errRangeExpected,

-    errInvalidTypeDescription,

-    errAttemptToRedefineX,

-    errMagicOnlyInSystem,

-    errUnknownOperatorX,

-    errPowerOfTwoExpected,

-    errStringMayNotBeEmpty,

-    errCallConvExpected,

-    errProcOnlyOneCallConv,

-    errSymbolMustBeImported,

-    errExprMustBeBool,

-    errConstExprExpected,

-    errDuplicateCaseLabel,

-    errRangeIsEmpty,

-    errSelectorMustBeOfCertainTypes,

-    errSelectorMustBeOrdinal,

-    errOrdXMustNotBeNegative,

-    errLenXinvalid,

-    errWrongNumberOfVariables,

-    errExprCannotBeRaised,

-    errBreakOnlyInLoop,

-    errTypeXhasUnknownSize,

-    errConstNeedsConstExpr,

-    errConstNeedsValue,

-    errResultCannotBeOpenArray,

-    errSizeTooBig,

-    errSetTooBig,

-    errBaseTypeMustBeOrdinal,

-    errInheritanceOnlyWithNonFinalObjects,

-    errInheritanceOnlyWithEnums,

-    errIllegalRecursionInTypeX,

-    errCannotInstantiateX,

-    errExprHasNoAddress,

-    errVarForOutParamNeeded,

-    errPureTypeMismatch,

-    errTypeMismatch,

-    errButExpected,

-    errButExpectedX,

-    errAmbigiousCallXYZ,

-    errWrongNumberOfTypeParams,

-    errOutParamNoDefaultValue,

-    errInlineProcHasNoAddress,

-    errXCannotBeInParamDecl,

-    errPragmaOnlyInHeaderOfProc,

-    errImportedProcCannotHaveImpl,

-    errImplOfXNotAllowed,

-    errImplOfXexpected,

-    errDiscardValue,

-    errInvalidDiscard,

-    errUnknownPrecedence,

-    errIllegalConvFromXtoY,

-    errTypeMismatchExpectedXGotY,

-    errCannotBindXTwice,

-    errInvalidOrderInEnumX,

-    errEnumXHasWholes,

-    errExceptExpected,

-    errInvalidTry,

-    errEofExpectedButXFound,

-    errOptionExpected,

-    errCannotEvaluateForwardConst,

-    errXisNoLabel,

-    errXNeedsConcreteType,

-    errNotAllCasesCovered,

-    errStringRange,

-    errUnkownSubstitionVar,

-    errComplexStmtRequiresInd,

-    errXisNotCallable,

-    errNoPragmasAllowedForX,

-    errNoGenericParamsAllowedForX,

-    errInvalidParamKindX,

-    errDefaultArgumentInvalid,

-    errNamedParamHasToBeIdent,

-    errNoReturnTypeForX,

-    errConvNeedsOneArg,

-    errInvalidPragmaX,

-    errXNotAllowedHere,

-    errInvalidControlFlowX,

-    errATypeHasNoValue,

-    errXisNoType,

-    errCircumNeedsPointer,

-    errInvalidContextForBuiltinX,

-    errInvalidExpression,

-    errInvalidExpressionX,

-    errEnumHasNoValueX,

-    errNamedExprExpected,

-    errNamedExprNotAllowed,

-    errXExpectsOneTypeParam,

-    errArrayExpectsTwoTypeParams,

-    errInvalidVisibilityX,

-    errInitHereNotAllowed,

-    errXCannotBeAssignedTo,

-    errIteratorNotAllowed,

-    errIteratorNeedsImplementation,

-    errIteratorNeedsReturnType,

-    errInvalidCommandX,

-    errXOnlyAtModuleScope,

-    errTypeXNeedsImplementation,

-    errTemplateInstantiationTooNested,

-    errInstantiationFrom,

-    errInvalidIndexValueForTuple,

-    errCommandExpectsFilename,

-    errXExpected,

-    errInvalidSectionStart,

-    errGridTableNotImplemented,

-    errGeneralParseError,

-    errNewSectionExpected,

-    errWhitespaceExpected,

-    errXisNoValidIndexFile,

-    errCannotRenderX,

-    errVarVarTypeNotAllowed,

-    errIsExpectsTwoArguments,

-    errIsExpectsObjectTypes,

-    errXcanNeverBeOfThisSubtype,

-    errTooManyIterations,

-    errCannotInterpretNodeX,

-    errFieldXNotFound,

-    errInvalidConversionFromTypeX,

-    errAssertionFailed,

-    errCannotGenerateCodeForX,

-    errXNeedsReturnType,

-    errXRequiresOneArgument,

-    errUnhandledExceptionX,

-    errCyclicTree,

-    errXisNoMacroOrTemplate,

-    errUser,

-    warnCannotOpenFile,

-    warnOctalEscape,

-    warnXIsNeverRead,

-    warnXmightNotBeenInit,

-    warnCannotWriteMO2,

-    warnCannotReadMO2,

-    warnDeprecated,

-    warnSmallLshouldNotBeUsed,

-    warnUnknownMagic,

-    warnRedefinitionOfLabel,

-    warnUnknownSubstitutionX,

-    warnLanguageXNotSupported,

-    warnCommentXIgnored,

-    warnUser,

-    hintSuccess,

-    hintSuccessX,

-    hintLineTooLong,

-    hintXDeclaredButNotUsed,

-    hintConvToBaseNotNeeded,

-    hintConvFromXtoItselfNotNeeded,

-    hintExprAlwaysX,

-    hintQuitCalled,

-    hintProcessing,

-    hintCodeBegin,

-    hintCodeEnd,

-    hintConf,

-    hintUser);

-

-const

-  MsgKindToStr: array [TMsgKind] of string = (

-    'unknown error',

-    'illformed AST: $1',

-    'cannot open ''$1''',

-    'internal error: $1',

-    '$1',

-    '''$1'' compiler does not support C++',

-    'string literal expected',

-    'integer literal expected',

-    'invalid character constant',

-    'closing """ expected, but end of file reached',

-    'closing " expected',

-    'tabulators are not allowed',

-    'invalid token: $1',

-    'line too long',

-    '$1 is not a valid number',

-    'number $1 out of valid range',

-    '\n not allowed in character literal',

-    'closing '']'' expected, but end of file reached',

-    'missing final ''',

-    'identifier expected, but found ''$1''',

-    'operator expected, but found ''$1''',

-    '''$1'' expected',

-    'string after ''include'' expected',

-    'recursive include file: ''$1''',

-    '''on'' or ''off'' expected',

-    '''none'', ''speed'' or ''size'' expected',

-    'invalid pragma',

-    'unknown pragma: ''$1''',

-    'pragma ''$1'' here not allowed',

-    'unknown directive: ''$1''',

-    'invalid directive',

-    '''pop'' without a ''push'' pragma',

-    'empty asm statement makes no sense',

-    '''='' invalid in an expression; probably ''=='' meant',

-    'invalid indentation',

-    'exception expected',

-    'exception already handled',

-    '''return'' only allowed in routine',

-    '''yield'' only allowed in a loop of an iterator',

-    'invalid number of ''yield'' expresions',

-    '''return'' not allowed in iterator',

-    'current routine cannot return an expression',

-    'attempt to redefine ''$1''',

-    'statement not allowed after ''return'', ''break'' or ''raise''',

-    'statement expected',

-    '''$1'' is no label',

-    'invalid command line option: ''$1''',

-    'argument for command line option expected: ''$1''',

-    'invalid argument for command line option: ''$1''',

-    'invalid variable substitution in ''$1''',

-    'unknown variable: ''$1''',

-    'unknown C compiler: ''$1''',

-    '''on'' or ''off'' expected, but ''$1'' found',

-    '''none'', ''boehm'' or ''refc'' expected, but ''$1'' found',

-    '''none'', ''speed'' or ''size'' expected, but ''$1'' found',

-    '''gui'', ''console'' or ''lib'' expected, but ''$1'' found',

-    'unknown OS: ''$1''',

-    'unknown CPU: ''$1''',

-    '''c'', ''c++'' or ''yaml'' expected, but ''$1'' found',

-    'arguments can only be given if the ''--run'' option is selected',

-    'multiple assignment is not allowed',

-    ''':'' or ''='' expected, but found ''$1''',

-    'expression expected, but found ''$1''',

-    'undeclared identifier: ''$1''',

-    'ambigious identifier: ''$1'' -- use a qualifier',

-    '''$1'' is forwarded twice',

-    'type expected',

-    'system module needs ''$1''',

-    'execution of an external program failed',

-    'overloaded ''$1'' leads to ambigious calls',

-    'invalid argument for ''$1''',

-    'statement has no effect',

-    '''$1'' expects a type or value',

-    '''$1'' expects an array type',

-    '''$1'' cannot be instantiated because its body has not been compiled yet',

-    'expression with no type cannot be converted',

-    'expression with no type cannot be casted',

-    'constant division by zero',

-    'ordinal type expected',

-    'ordinal or float type expected',

-    'over- or underflow',

-    'cannot evalutate ''$1'' because type is not defined completely',

-    '''chr'' expects an int in the range 0..255',

-    '''staticAssert'' failed: condition is false',

-    'argument to ''staticAssert'' cannot be evaluated at compile time',

-    '''.'' requires a record or object type',

-    'undeclared field: ''$1''',

-    'attempt to access a nil address',

-    'index out of bounds',

-    'index types do not match',

-    '''[]'' operator invalid for this type',

-    'value out of set bounds',

-    'field initialized twice: ''$1''',

-    'field ''$1'' not initialized',

-    'expression cannot be called',

-    'expression has no type',

-    'expression ''$1'' has no type',

-    '''cast'' not allowed in safe mode',

-    'expression cannot be casted to $1',

-    'undefined prefix operator: $1',

-    ''','' or '')'' expected',

-    '''{'' or ''('' expected',

-    'section (''type'', ''proc'', etc.) expected',

-    '''implementation'' or end of file expected',

-    'range expected',

-    'invalid type description',

-    'attempt to redefine ''$1''',

-    '''magic'' only allowed in system module',

-    'unkown operator: ''$1''',

-    'power of two expected',

-    'string literal may not be empty',

-    'calling convention expected',

-    'a proc can only have one calling convention',

-    'symbol must be imported if ''lib'' pragma is used',

-    'expression must be of type ''bool''',

-    'constant expression expected',

-    'duplicate case label',

-    'range is empty',

-    'selector must be of an ordinal type, real or string',

-    'selector must be of an ordinal type',

-    'ord($1) must not be negative',

-    'len($1) must be less than 32768',

-    'wrong number of variables',

-    'only objects can be raised',

-    '''break'' only allowed in loop construct',

-    'type ''$1'' has unknown size',

-    'a constant can only be initialized with a constant expression',

-    'a constant needs a value',

-    'the result type cannot be on open array',

-    'computing the type''s size produced an overflow',

-    'set is too large',

-    'base type of a set must be an ordinal',

-    'inheritance only works with non-final objects',

-    'inheritance only works with an enum',

-    'illegal recursion in type ''$1''',

-    'cannot instantiate: ''$1''',

-    'expression has no address',

-    'for a ''var'' type a variable needs to be passed',

-    'type mismatch',

-    'type mismatch: got (',

-    'but expected one of: ',

-    'but expected ''$1''',

-    'ambigious call; both $1 and $2 match for: $3',

-    'wrong number of type parameters',

-    'out parameters cannot have default values',

-    'an inline proc has no address',

-    '$1 cannot be declared in parameter declaration',

-    'pragmas are only in the header of a proc allowed',

-    'an imported proc cannot have an implementation',

-    'implementation of ''$1'' is not allowed here',

-    'implementation of ''$1'' expected',

-    'value returned by statement has to be discarded',

-    'statement returns no value that can be discarded',

-    'unknown precedence for operator; use ''infix: prec'' pragma',

-    'conversion from $1 to $2 is invalid',

-    'type mismatch: expected ''$1'', but got ''$2''',

-    'cannot bind parameter ''$1'' twice',

-    'invalid order in enum ''$1''',

-    'enum ''$1'' has wholes',

-    '''except'' or ''finally'' expected',

-    'after catch all ''except'' or ''finally'' no section may follow',

-    'end of file expected, but found token ''$1''',

-    'option expected, but found ''$1''',

-    'cannot evaluate forwarded constant',

-    '''$1'' is not a label',

-    '''$1'' needs to be of a non-generic type',

-    'not all cases are covered',

-    'string range in case statement not allowed',

-    'unknown substitution variable: ''$1''',

-    'complex statement requires indentation',

-    '''$1'' is not callable',

-    'no pragmas allowed for $1',

-    'no generic parameters allowed for $1',

-    'invalid param kind: ''$1''',

-    'default argument invalid',

-    'named parameter has to be an identifier',

-    'no return type for $1 allowed',

-    'a type conversion needs exactly one argument',

-    'invalid pragma: $1',

-    '$1 here not allowed',

-    'invalid control flow: $1',

-    'a type has no value',

-    'invalid type: ''$1''',

-    '''^'' needs a pointer or reference type',

-    'invalid context for builtin ''$1''',

-    'invalid expression',

-    'invalid expression: ''$1''',

-    'enum has no value ''$1''',

-    'named expression expected',

-    'named expression here not allowed',

-    '''$1'' expects one type parameter',

-    'array expects two type parameters',

-    'invalid invisibility: ''$1''',

-    'initialization here not allowed',

-    '''$1'' cannot be assigned to',

-    'iterators can only be defined at the module''s top level',

-    'iterator needs an implementation',

-    'iterator needs a return type',

-    'invalid command: ''$1''',

-    '''$1'' is only allowed at top level',

-    'type ''$1'' needs an implementation',

-    'template instantiation too nested',

-    'instantiation from here',

-    'invalid index value for tuple subscript',

-    'command expects a filename argument',

-    '''$1'' expected',

-    'invalid section start',

-    'grid table is not implemented',

-    'general parse error',

-    'new section expected',

-    'whitespace expected, got ''$1''',

-    '''$1'' is no valid index file',

-    'cannot render reStructuredText element ''$1''',

-    'type ''var var'' is not allowed',

-    '''is'' expects two arguments',

-    '''is'' expects object types',

-    '''$1'' can never be of this subtype',

-    'interpretation requires too many iterations',

-    'cannot interpret node kind ''$1''',

-    'field ''$1'' cannot be found',

-    'invalid conversion from type ''$1''',

-    'assertion failed',

-    'cannot generate code for ''$1''',

-    'converter needs return type',

-    'converter requires one parameter',

-    'unhandled exception: $1',

-    'macro returned a cyclic abstract syntax tree',

-    '''$1'' is no macro or template',

-    '$1',

-    'cannot open ''$1'' [CannotOpenFile]',

-    'octal escape sequences do not exist; leading zero is ignored [OctalEscape]',

-    '''$1'' is never read [XIsNeverRead]',

-    '''$1'' might not have been initialized [XmightNotBeenInit]',

-    'cannot write file ''$1'' [CannotWriteMO2]',

-    'cannot read file ''$1'' [CannotReadMO2]',

-    '''$1'' is deprecated [Deprecated]',

-    '''l'' should not be used as an identifier; may look like ''1'' (one) [SmallLshouldNotBeUsed]',

-    'unknown magic ''$1'' might crash the compiler [UnknownMagic]',

-    'redefinition of label ''$1'' [RedefinitionOfLabel]',

-    'unknown substitution ''$1'' [UnknownSubstitutionX]',

-    'language ''$1'' not supported [LanguageXNotSupported]',

-    'comment ''$1'' ignored [CommentXIgnored]',

-    '$1 [User]',

-    'operation successful [Success]',

-    'operation successful ($1 lines compiled; $2 sec total) [SuccessX]',

-    'line too long [LineTooLong]',

-    '''$1'' is declared but not used [XDeclaredButNotUsed]',

-    'conversion to base object is not needed [ConvToBaseNotNeeded]',

-    'conversion from $1 to itself is pointless [ConvFromXtoItselfNotNeeded]',

-    'expression evaluates always to ''$1'' [ExprAlwaysX]',

-    'quit() called [QuitCalled]',

-    '$1 [Processing]',

-    'generated code listing: [CodeBegin]',

-    'end of listing [CodeEnd]',

-    'used config file ''$1'' [Conf]',

-    '$1 [User]'

-  );

-const

-  WarningsToStr: array [0..13] of string = (

-    'CannotOpenFile',

-    'OctalEscape',

-    'XIsNeverRead',

-    'XmightNotBeenInit',

-    'CannotWriteMO2',

-    'CannotReadMO2',

-    'Deprecated',

-    'SmallLshouldNotBeUsed',

-    'UnknownMagic',

-    'RedefinitionOfLabel',

-    'UnknownSubstitutionX',

-    'LanguageXNotSupported',

-    'CommentXIgnored',

-    'User'

-  );

-const

-  HintsToStr: array [0..12] of string = (

-    'Success',

-    'SuccessX',

-    'LineTooLong',

-    'XDeclaredButNotUsed',

-    'ConvToBaseNotNeeded',

-    'ConvFromXtoItselfNotNeeded',

-    'ExprAlwaysX',

-    'QuitCalled',

-    'Processing',

-    'CodeBegin',

-    'CodeEnd',

-    'Conf',

-    'User'

-  );

+type
+  TMsgKind = (
+    errUnknown,
+    errIllFormedAstX,
+    errCannotOpenFile,
+    errInternal,
+    errGenerated,
+    errXCompilerDoesNotSupportCpp,
+    errStringLiteralExpected,
+    errIntLiteralExpected,
+    errInvalidCharacterConstant,
+    errClosingTripleQuoteExpected,
+    errClosingQuoteExpected,
+    errTabulatorsAreNotAllowed,
+    errInvalidToken,
+    errLineTooLong,
+    errInvalidNumber,
+    errNumberOutOfRange,
+    errNnotAllowedInCharacter,
+    errClosingBracketExpected,
+    errMissingFinalQuote,
+    errIdentifierExpected,
+    errOperatorExpected,
+    errTokenExpected,
+    errStringAfterIncludeExpected,
+    errRecursiveInclude,
+    errOnOrOffExpected,
+    errNoneSpeedOrSizeExpected,
+    errInvalidPragma,
+    errUnknownPragma,
+    errPragmaXHereNotAllowed,
+    errUnknownDirective,
+    errInvalidDirective,
+    errAtPopWithoutPush,
+    errEmptyAsm,
+    errAsgnInvalidInExpr,
+    errInvalidIndentation,
+    errExceptionExpected,
+    errExceptionAlreadyHandled,
+    errReturnNotAllowedHere,
+    errYieldNotAllowedHere,
+    errInvalidNumberOfYieldExpr,
+    errReturnInvalidInIterator,
+    errCannotReturnExpr,
+    errAttemptToRedefine,
+    errStmtInvalidAfterReturn,
+    errStmtExpected,
+    errInvalidLabel,
+    errInvalidCmdLineOption,
+    errCmdLineArgExpected,
+    errCmdLineNoArgExpected,
+    errInvalidVarSubstitution,
+    errUnknownVar,
+    errUnknownCcompiler,
+    errOnOrOffExpectedButXFound,
+    errNoneBoehmRefcExpectedButXFound,
+    errNoneSpeedOrSizeExpectedButXFound,
+    errGuiConsoleOrLibExpectedButXFound,
+    errUnknownOS,
+    errUnknownCPU,
+    errGenOutExpectedButXFound,
+    errArgsNeedRunOption,
+    errInvalidMultipleAsgn,
+    errColonOrEqualsExpected,
+    errExprExpected,
+    errUndeclaredIdentifier,
+    errUseQualifier,
+    errTwiceForwarded,
+    errTypeExpected,
+    errSystemNeeds,
+    errExecutionOfProgramFailed,
+    errNotOverloadable,
+    errInvalidArgForX,
+    errStmtHasNoEffect,
+    errXExpectsTypeOrValue,
+    errXExpectsArrayType,
+    errIteratorCannotBeInstantiated,
+    errExprWithNoTypeCannotBeConverted,
+    errExprWithNoTypeCannotBeCasted,
+    errConstantDivisionByZero,
+    errOrdinalTypeExpected,
+    errOrdinalOrFloatTypeExpected,
+    errOverOrUnderflow,
+    errCannotEvalXBecauseIncompletelyDefined,
+    errChrExpectsRange0_255,
+    errStaticAssertFailed,
+    errStaticAssertCannotBeEval,
+    errDotRequiresRecordOrObjectType,
+    errUndeclaredFieldX,
+    errNilAccess,
+    errIndexOutOfBounds,
+    errIndexTypesDoNotMatch,
+    errBracketsInvalidForType,
+    errValueOutOfSetBounds,
+    errFieldInitTwice,
+    errFieldNotInit,
+    errExprCannotBeCalled,
+    errExprHasNoType,
+    errExprXHasNoType,
+    errCastNotInSafeMode,
+    errExprCannotBeCastedToX,
+    errUndefinedPrefixOpr,
+    errCommaOrParRiExpected,
+    errCurlyLeOrParLeExpected,
+    errSectionExpected,
+    errImplemenationExpected,
+    errRangeExpected,
+    errInvalidTypeDescription,
+    errAttemptToRedefineX,
+    errMagicOnlyInSystem,
+    errUnknownOperatorX,
+    errPowerOfTwoExpected,
+    errStringMayNotBeEmpty,
+    errCallConvExpected,
+    errProcOnlyOneCallConv,
+    errSymbolMustBeImported,
+    errExprMustBeBool,
+    errConstExprExpected,
+    errDuplicateCaseLabel,
+    errRangeIsEmpty,
+    errSelectorMustBeOfCertainTypes,
+    errSelectorMustBeOrdinal,
+    errOrdXMustNotBeNegative,
+    errLenXinvalid,
+    errWrongNumberOfVariables,
+    errExprCannotBeRaised,
+    errBreakOnlyInLoop,
+    errTypeXhasUnknownSize,
+    errConstNeedsConstExpr,
+    errConstNeedsValue,
+    errResultCannotBeOpenArray,
+    errSizeTooBig,
+    errSetTooBig,
+    errBaseTypeMustBeOrdinal,
+    errInheritanceOnlyWithNonFinalObjects,
+    errInheritanceOnlyWithEnums,
+    errIllegalRecursionInTypeX,
+    errCannotInstantiateX,
+    errExprHasNoAddress,
+    errVarForOutParamNeeded,
+    errPureTypeMismatch,
+    errTypeMismatch,
+    errButExpected,
+    errButExpectedX,
+    errAmbigiousCallXYZ,
+    errWrongNumberOfTypeParams,
+    errOutParamNoDefaultValue,
+    errInlineProcHasNoAddress,
+    errXCannotBeInParamDecl,
+    errPragmaOnlyInHeaderOfProc,
+    errImplOfXNotAllowed,
+    errImplOfXexpected,
+    errNoSymbolToBorrowFromFound,
+    errDiscardValue,
+    errInvalidDiscard,
+    errUnknownPrecedence,
+    errIllegalConvFromXtoY,
+    errTypeMismatchExpectedXGotY,
+    errCannotBindXTwice,
+    errInvalidOrderInEnumX,
+    errEnumXHasWholes,
+    errExceptExpected,
+    errInvalidTry,
+    errEofExpectedButXFound,
+    errOptionExpected,
+    errCannotEvaluateForwardConst,
+    errXisNoLabel,
+    errXNeedsConcreteType,
+    errNotAllCasesCovered,
+    errStringRange,
+    errUnkownSubstitionVar,
+    errComplexStmtRequiresInd,
+    errXisNotCallable,
+    errNoPragmasAllowedForX,
+    errNoGenericParamsAllowedForX,
+    errInvalidParamKindX,
+    errDefaultArgumentInvalid,
+    errNamedParamHasToBeIdent,
+    errNoReturnTypeForX,
+    errConvNeedsOneArg,
+    errInvalidPragmaX,
+    errXNotAllowedHere,
+    errInvalidControlFlowX,
+    errATypeHasNoValue,
+    errXisNoType,
+    errCircumNeedsPointer,
+    errInvalidContextForBuiltinX,
+    errInvalidExpression,
+    errInvalidExpressionX,
+    errEnumHasNoValueX,
+    errNamedExprExpected,
+    errNamedExprNotAllowed,
+    errXExpectsOneTypeParam,
+    errArrayExpectsTwoTypeParams,
+    errInvalidVisibilityX,
+    errInitHereNotAllowed,
+    errXCannotBeAssignedTo,
+    errIteratorNotAllowed,
+    errIteratorNeedsImplementation,
+    errIteratorNeedsReturnType,
+    errInvalidCommandX,
+    errXOnlyAtModuleScope,
+    errTypeXNeedsImplementation,
+    errTemplateInstantiationTooNested,
+    errInstantiationFrom,
+    errInvalidIndexValueForTuple,
+    errCommandExpectsFilename,
+    errXExpected,
+    errInvalidSectionStart,
+    errGridTableNotImplemented,
+    errGeneralParseError,
+    errNewSectionExpected,
+    errWhitespaceExpected,
+    errXisNoValidIndexFile,
+    errCannotRenderX,
+    errVarVarTypeNotAllowed,
+    errIsExpectsTwoArguments,
+    errIsExpectsObjectTypes,
+    errXcanNeverBeOfThisSubtype,
+    errTooManyIterations,
+    errCannotInterpretNodeX,
+    errFieldXNotFound,
+    errInvalidConversionFromTypeX,
+    errAssertionFailed,
+    errCannotGenerateCodeForX,
+    errXNeedsReturnType,
+    errXRequiresOneArgument,
+    errUnhandledExceptionX,
+    errCyclicTree,
+    errXisNoMacroOrTemplate,
+    errUser,
+    warnCannotOpenFile,
+    warnOctalEscape,
+    warnXIsNeverRead,
+    warnXmightNotBeenInit,
+    warnCannotWriteMO2,
+    warnCannotReadMO2,
+    warnDeprecated,
+    warnSmallLshouldNotBeUsed,
+    warnUnknownMagic,
+    warnRedefinitionOfLabel,
+    warnUnknownSubstitutionX,
+    warnLanguageXNotSupported,
+    warnCommentXIgnored,
+    warnUser,
+    hintSuccess,
+    hintSuccessX,
+    hintLineTooLong,
+    hintXDeclaredButNotUsed,
+    hintConvToBaseNotNeeded,
+    hintConvFromXtoItselfNotNeeded,
+    hintExprAlwaysX,
+    hintQuitCalled,
+    hintProcessing,
+    hintCodeBegin,
+    hintCodeEnd,
+    hintConf,
+    hintUser);
+
+const
+  MsgKindToStr: array [TMsgKind] of string = (
+    'unknown error',
+    'illformed AST: $1',
+    'cannot open ''$1''',
+    'internal error: $1',
+    '$1',
+    '''$1'' compiler does not support C++',
+    'string literal expected',
+    'integer literal expected',
+    'invalid character constant',
+    'closing """ expected, but end of file reached',
+    'closing " expected',
+    'tabulators are not allowed',
+    'invalid token: $1',
+    'line too long',
+    '$1 is not a valid number',
+    'number $1 out of valid range',
+    '\n not allowed in character literal',
+    'closing '']'' expected, but end of file reached',
+    'missing final ''',
+    'identifier expected, but found ''$1''',
+    'operator expected, but found ''$1''',
+    '''$1'' expected',
+    'string after ''include'' expected',
+    'recursive include file: ''$1''',
+    '''on'' or ''off'' expected',
+    '''none'', ''speed'' or ''size'' expected',
+    'invalid pragma',
+    'unknown pragma: ''$1''',
+    'pragma ''$1'' here not allowed',
+    'unknown directive: ''$1''',
+    'invalid directive',
+    '''pop'' without a ''push'' pragma',
+    'empty asm statement makes no sense',
+    '''='' invalid in an expression; probably ''=='' meant',
+    'invalid indentation',
+    'exception expected',
+    'exception already handled',
+    '''return'' only allowed in routine',
+    '''yield'' only allowed in a loop of an iterator',
+    'invalid number of ''yield'' expresions',
+    '''return'' not allowed in iterator',
+    'current routine cannot return an expression',
+    'attempt to redefine ''$1''',
+    'statement not allowed after ''return'', ''break'' or ''raise''',
+    'statement expected',
+    '''$1'' is no label',
+    'invalid command line option: ''$1''',
+    'argument for command line option expected: ''$1''',
+    'invalid argument for command line option: ''$1''',
+    'invalid variable substitution in ''$1''',
+    'unknown variable: ''$1''',
+    'unknown C compiler: ''$1''',
+    '''on'' or ''off'' expected, but ''$1'' found',
+    '''none'', ''boehm'' or ''refc'' expected, but ''$1'' found',
+    '''none'', ''speed'' or ''size'' expected, but ''$1'' found',
+    '''gui'', ''console'' or ''lib'' expected, but ''$1'' found',
+    'unknown OS: ''$1''',
+    'unknown CPU: ''$1''',
+    '''c'', ''c++'' or ''yaml'' expected, but ''$1'' found',
+    'arguments can only be given if the ''--run'' option is selected',
+    'multiple assignment is not allowed',
+    ''':'' or ''='' expected, but found ''$1''',
+    'expression expected, but found ''$1''',
+    'undeclared identifier: ''$1''',
+    'ambigious identifier: ''$1'' -- use a qualifier',
+    '''$1'' is forwarded twice',
+    'type expected',
+    'system module needs ''$1''',
+    'execution of an external program failed',
+    'overloaded ''$1'' leads to ambigious calls',
+    'invalid argument for ''$1''',
+    'statement has no effect',
+    '''$1'' expects a type or value',
+    '''$1'' expects an array type',
+    '''$1'' cannot be instantiated because its body has not been compiled yet',
+    'expression with no type cannot be converted',
+    'expression with no type cannot be casted',
+    'constant division by zero',
+    'ordinal type expected',
+    'ordinal or float type expected',
+    'over- or underflow',
+    'cannot evalutate ''$1'' because type is not defined completely',
+    '''chr'' expects an int in the range 0..255',
+    '''staticAssert'' failed: condition is false',
+    'argument to ''staticAssert'' cannot be evaluated at compile time',
+    '''.'' requires a record or object type',
+    'undeclared field: ''$1''',
+    'attempt to access a nil address',
+    'index out of bounds',
+    'index types do not match',
+    '''[]'' operator invalid for this type',
+    'value out of set bounds',
+    'field initialized twice: ''$1''',
+    'field ''$1'' not initialized',
+    'expression cannot be called',
+    'expression has no type',
+    'expression ''$1'' has no type',
+    '''cast'' not allowed in safe mode',
+    'expression cannot be casted to $1',
+    'undefined prefix operator: $1',
+    ''','' or '')'' expected',
+    '''{'' or ''('' expected',
+    'section (''type'', ''proc'', etc.) expected',
+    '''implementation'' or end of file expected',
+    'range expected',
+    'invalid type description',
+    'attempt to redefine ''$1''',
+    '''magic'' only allowed in system module',
+    'unkown operator: ''$1''',
+    'power of two expected',
+    'string literal may not be empty',
+    'calling convention expected',
+    'a proc can only have one calling convention',
+    'symbol must be imported if ''lib'' pragma is used',
+    'expression must be of type ''bool''',
+    'constant expression expected',
+    'duplicate case label',
+    'range is empty',
+    'selector must be of an ordinal type, real or string',
+    'selector must be of an ordinal type',
+    'ord($1) must not be negative',
+    'len($1) must be less than 32768',
+    'wrong number of variables',
+    'only objects can be raised',
+    '''break'' only allowed in loop construct',
+    'type ''$1'' has unknown size',
+    'a constant can only be initialized with a constant expression',
+    'a constant needs a value',
+    'the result type cannot be on open array',
+    'computing the type''s size produced an overflow',
+    'set is too large',
+    'base type of a set must be an ordinal',
+    'inheritance only works with non-final objects',
+    'inheritance only works with an enum',
+    'illegal recursion in type ''$1''',
+    'cannot instantiate: ''$1''',
+    'expression has no address',
+    'for a ''var'' type a variable needs to be passed',
+    'type mismatch',
+    'type mismatch: got (',
+    'but expected one of: ',
+    'but expected ''$1''',
+    'ambigious call; both $1 and $2 match for: $3',
+    'wrong number of type parameters',
+    'out parameters cannot have default values',
+    'an inline proc has no address',
+    '$1 cannot be declared in parameter declaration',
+    'pragmas are only in the header of a proc allowed',
+    'implementation of ''$1'' is not allowed',
+    'implementation of ''$1'' expected',
+    'no symbol to borrow from found',
+    'value returned by statement has to be discarded',
+    'statement returns no value that can be discarded',
+    'unknown precedence for operator; use ''infix: prec'' pragma',
+    'conversion from $1 to $2 is invalid',
+    'type mismatch: expected ''$1'', but got ''$2''',
+    'cannot bind parameter ''$1'' twice',
+    'invalid order in enum ''$1''',
+    'enum ''$1'' has wholes',
+    '''except'' or ''finally'' expected',
+    'after catch all ''except'' or ''finally'' no section may follow',
+    'end of file expected, but found token ''$1''',
+    'option expected, but found ''$1''',
+    'cannot evaluate forwarded constant',
+    '''$1'' is not a label',
+    '''$1'' needs to be of a non-generic type',
+    'not all cases are covered',
+    'string range in case statement not allowed',
+    'unknown substitution variable: ''$1''',
+    'complex statement requires indentation',
+    '''$1'' is not callable',
+    'no pragmas allowed for $1',
+    'no generic parameters allowed for $1',
+    'invalid param kind: ''$1''',
+    'default argument invalid',
+    'named parameter has to be an identifier',
+    'no return type for $1 allowed',
+    'a type conversion needs exactly one argument',
+    'invalid pragma: $1',
+    '$1 here not allowed',
+    'invalid control flow: $1',
+    'a type has no value',
+    'invalid type: ''$1''',
+    '''^'' needs a pointer or reference type',
+    'invalid context for builtin ''$1''',
+    'invalid expression',
+    'invalid expression: ''$1''',
+    'enum has no value ''$1''',
+    'named expression expected',
+    'named expression here not allowed',
+    '''$1'' expects one type parameter',
+    'array expects two type parameters',
+    'invalid invisibility: ''$1''',
+    'initialization here not allowed',
+    '''$1'' cannot be assigned to',
+    'iterators can only be defined at the module''s top level',
+    'iterator needs an implementation',
+    'iterator needs a return type',
+    'invalid command: ''$1''',
+    '''$1'' is only allowed at top level',
+    'type ''$1'' needs an implementation',
+    'template instantiation too nested',
+    'instantiation from here',
+    'invalid index value for tuple subscript',
+    'command expects a filename argument',
+    '''$1'' expected',
+    'invalid section start',
+    'grid table is not implemented',
+    'general parse error',
+    'new section expected',
+    'whitespace expected, got ''$1''',
+    '''$1'' is no valid index file',
+    'cannot render reStructuredText element ''$1''',
+    'type ''var var'' is not allowed',
+    '''is'' expects two arguments',
+    '''is'' expects object types',
+    '''$1'' can never be of this subtype',
+    'interpretation requires too many iterations',
+    'cannot interpret node kind ''$1''',
+    'field ''$1'' cannot be found',
+    'invalid conversion from type ''$1''',
+    'assertion failed',
+    'cannot generate code for ''$1''',
+    'converter needs return type',
+    'converter requires one parameter',
+    'unhandled exception: $1',
+    'macro returned a cyclic abstract syntax tree',
+    '''$1'' is no macro or template',
+    '$1',
+    'cannot open ''$1'' [CannotOpenFile]',
+    'octal escape sequences do not exist; leading zero is ignored [OctalEscape]',
+    '''$1'' is never read [XIsNeverRead]',
+    '''$1'' might not have been initialized [XmightNotBeenInit]',
+    'cannot write file ''$1'' [CannotWriteMO2]',
+    'cannot read file ''$1'' [CannotReadMO2]',
+    '''$1'' is deprecated [Deprecated]',
+    '''l'' should not be used as an identifier; may look like ''1'' (one) [SmallLshouldNotBeUsed]',
+    'unknown magic ''$1'' might crash the compiler [UnknownMagic]',
+    'redefinition of label ''$1'' [RedefinitionOfLabel]',
+    'unknown substitution ''$1'' [UnknownSubstitutionX]',
+    'language ''$1'' not supported [LanguageXNotSupported]',
+    'comment ''$1'' ignored [CommentXIgnored]',
+    '$1 [User]',
+    'operation successful [Success]',
+    'operation successful ($1 lines compiled; $2 sec total) [SuccessX]',
+    'line too long [LineTooLong]',
+    '''$1'' is declared but not used [XDeclaredButNotUsed]',
+    'conversion to base object is not needed [ConvToBaseNotNeeded]',
+    'conversion from $1 to itself is pointless [ConvFromXtoItselfNotNeeded]',
+    'expression evaluates always to ''$1'' [ExprAlwaysX]',
+    'quit() called [QuitCalled]',
+    '$1 [Processing]',
+    'generated code listing: [CodeBegin]',
+    'end of listing [CodeEnd]',
+    'used config file ''$1'' [Conf]',
+    '$1 [User]'
+  );
+const
+  WarningsToStr: array [0..13] of string = (
+    'CannotOpenFile',
+    'OctalEscape',
+    'XIsNeverRead',
+    'XmightNotBeenInit',
+    'CannotWriteMO2',
+    'CannotReadMO2',
+    'Deprecated',
+    'SmallLshouldNotBeUsed',
+    'UnknownMagic',
+    'RedefinitionOfLabel',
+    'UnknownSubstitutionX',
+    'LanguageXNotSupported',
+    'CommentXIgnored',
+    'User'
+  );
+const
+  HintsToStr: array [0..12] of string = (
+    'Success',
+    'SuccessX',
+    'LineTooLong',
+    'XDeclaredButNotUsed',
+    'ConvToBaseNotNeeded',
+    'ConvFromXtoItselfNotNeeded',
+    'ExprAlwaysX',
+    'QuitCalled',
+    'Processing',
+    'CodeBegin',
+    'CodeEnd',
+    'Conf',
+    'User'
+  );
 //[[[end]]]

 

 const

diff --git a/nim/nimconf.pas b/nim/nimconf.pas
index 8f908bf62..842446ae9 100644
--- a/nim/nimconf.pas
+++ b/nim/nimconf.pas
@@ -335,12 +335,19 @@ end;
 
 procedure LoadConfig(const project: string);
 var
-  conffile: string;
+  conffile, prefix: string;
 begin
   // set default value (can be overwritten):
-  if libpath = '' then
+  if libpath = '' then begin
     // choose default libpath:
-    libpath := joinPath(getPrefixDir(), 'lib');
+    prefix := getPrefixDir();
+    if (prefix = '/usr') then
+      libpath := '/usr/lib/nimrod'
+    else if (prefix = '/usr/local') then
+      libpath := '/usr/local/lib/nimrod'
+    else
+      libpath := joinPath(prefix, 'lib')
+  end;
   // read default config file:
   LoadSpecialConfig('nimrod.cfg');
   // read project config file:
diff --git a/nim/nversion.pas b/nim/nversion.pas
index ae6392db9..e15f88068 100644
--- a/nim/nversion.pas
+++ b/nim/nversion.pas
@@ -31,10 +31,10 @@ const
   //cog.outl('VersionMinor = %s;' % ver[1])

   //cog.outl('VersionPatch = %s;' % ver[2])

   //]]]

-  VersionAsString = '0.7.8';
+  VersionAsString = '0.7.10';
   VersionMajor = 0;
   VersionMinor = 7;
-  VersionPatch = 8;
+  VersionPatch = 10;
   //[[[[end]]]]

 

 implementation

diff --git a/nim/parsecfg.pas b/nim/parsecfg.pas
index 620335aa6..ba6a98679 100644
--- a/nim/parsecfg.pas
+++ b/nim/parsecfg.pas
@@ -1,7 +1,7 @@
 //
 //
 //            Nimrod's Runtime Library
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -201,6 +201,7 @@ begin
     inc(pos, 2); // skip ""
     // skip leading newline:
     pos := HandleCRLF(c, pos);
+    buf := c.buf;
     repeat
       case buf[pos] of
         '"': begin
@@ -211,6 +212,7 @@ begin
         end;
         CR, LF: begin
           pos := HandleCRLF(c, pos);
+          buf := c.buf;
           tok.literal := tok.literal +{&} nl;
         end;
         lexbase.EndOfFile: begin
@@ -278,7 +280,10 @@ begin
       ' ': Inc(pos);
       Tabulator: inc(pos);
       '#', ';': while not (buf[pos] in [CR, LF, lexbase.EndOfFile]) do inc(pos);
-      CR, LF: pos := HandleCRLF(c, pos);
+      CR, LF: begin
+        pos := HandleCRLF(c, pos);
+        buf := c.buf;
+      end
       else break // EndOfFile also leaves the loop
     end
   until false;
diff --git a/nim/paslex.pas b/nim/paslex.pas
index da9283163..f3d8daaeb 100644
--- a/nim/paslex.pas
+++ b/nim/paslex.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -529,6 +529,7 @@ begin
       addChar(tok.literal, buf[pos]); inc(pos);
     end;
     pos := handleCRLF(L, pos);
+    buf := L.buf;
     indent := 0;
     while buf[pos] = ' ' do begin inc(pos); inc(indent) end;
     if (col = indent) and (buf[pos] = '/') and (buf[pos+1] = '/') then
@@ -552,6 +553,7 @@ begin
     case buf[pos] of
       CR, LF: begin
         pos := HandleCRLF(L, pos);
+        buf := L.buf;
         tok.literal := tok.literal +{&} nl + '#';
       end;
       '}': begin inc(pos); break end;
@@ -578,6 +580,7 @@ begin
     case buf[pos] of
       CR, LF: begin
         pos := HandleCRLF(L, pos);
+        buf := L.buf;
         tok.literal := tok.literal +{&} nl + '#';
       end;
       '*': begin
@@ -606,7 +609,10 @@ begin
     case buf[pos] of
       ' ', Tabulator: Inc(pos);
       // newline is special:
-      CR, LF: pos := HandleCRLF(L, pos);
+      CR, LF: begin
+        pos := HandleCRLF(L, pos);
+        buf := L.buf;
+      end
       else break // EndOfFile also leaves the loop
     end
   until false;
diff --git a/nim/pnimsyn.pas b/nim/pnimsyn.pas
index 95d6e64f9..51c0cd4f5 100644
--- a/nim/pnimsyn.pas
+++ b/nim/pnimsyn.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -1663,6 +1663,14 @@ begin
   addSon(result, parseRecordPart(p));
 end;
 
+function parseAbstract(var p: TParser): PNode;
+begin
+  result := newNodeP(nkAbstractTy, p);
+  getTok(p);
+  optInd(p, result);
+  addSon(result, parseTypeDesc(p));
+end;
+
 function parseTypeDef(var p: TParser): PNode;
 var
   a: PNode;
@@ -1676,6 +1684,7 @@ begin
     case p.tok.tokType of
       tkObject: a := parseRecordOrObject(p, nkObjectTy);
       tkEnum: a := parseEnum(p);
+      tkAbstract: a := parseAbstract(p);
       else a := parseTypeDesc(p);
     end;
     addSon(result, a);
diff --git a/nim/pragmas.pas b/nim/pragmas.pas
index df48f27c9..9f4a543c5 100644
--- a/nim/pragmas.pas
+++ b/nim/pragmas.pas
@@ -522,6 +522,10 @@ begin
             if sym.typ = nil then invalidPragma(it);
             include(sym.typ.flags, tfVarargs);
           end;
+          wBorrow: begin
+            noVal(it);
+            include(sym.flags, sfBorrow);
+          end;
           wFinal: begin
             noVal(it);
             if sym.typ = nil then invalidPragma(it);
@@ -595,7 +599,8 @@ begin
   pragma(c, s, n, {@set}[FirstCallConv..LastCallConv,
     wImportc, wExportc, wNodecl, wMagic, wNosideEffect,
     wNoreturn, wDynLib, wHeader, wCompilerProc, wPure,
-    wCppMethod, wDeprecated, wVarargs, wCompileTime, wMerge]);
+    wCppMethod, wDeprecated, wVarargs, wCompileTime, wMerge,
+    wBorrow]);
 end;
 
 procedure pragmaMacro(c: PContext; s: PSym; n: PNode);
@@ -608,7 +613,7 @@ end;
 procedure pragmaIterator(c: PContext; s: PSym; n: PNode);
 begin
   pragma(c, s, n, {@set}[FirstCallConv..LastCallConv,
-         wImportc, wExportc, wNodecl, wMagic, wDeprecated]);
+         wImportc, wExportc, wNodecl, wMagic, wDeprecated, wBorrow]);
 end;
 
 procedure pragmaStmt(c: PContext; s: PSym; n: PNode);
diff --git a/nim/procfind.pas b/nim/procfind.pas
index 9c4786e53..c8792586a 100644
--- a/nim/procfind.pas
+++ b/nim/procfind.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -22,6 +22,10 @@ function SearchForProc(c: PContext; fn: PSym; tos: int): PSym;
 // Searchs for the fn in the symbol table. If the parameter lists are exactly
 // the same the sym in the symbol table is returned, else nil.
 
+function SearchForBorrowProc(c: PContext; fn: PSym; tos: int): PSym;
+// Searchs for the fn in the symbol table. If the parameter lists are suitable
+// for borrowing the sym in the symbol table is returned, else nil.
+
 implementation
 
 function equalGenericParams(procA, procB: PNode): Boolean;
@@ -69,4 +73,46 @@ begin
   end
 end;
 
+function paramsFitBorrow(a, b: PNode): bool;
+var
+  i, len: int;
+  m, n: PSym;
+begin
+  len := sonsLen(a);
+  result := false;
+  if len = sonsLen(b) then begin
+    for i := 1 to len-1 do begin
+      m := a.sons[i].sym;
+      n := b.sons[i].sym;
+      assert((m.kind = skParam) and (n.kind = skParam));
+      if not equalOrAbstractOf(m.typ, n.typ) then exit;
+    end;
+    // return type:
+    if not equalOrAbstractOf(a.sons[0].typ, b.sons[0].typ) then exit;
+    result := true
+  end
+end;
+
+function SearchForBorrowProc(c: PContext; fn: PSym; tos: int): PSym;
+// Searchs for the fn in the symbol table. If the parameter lists are suitable
+// for borrowing the sym in the symbol table is returned, else nil.
+var
+  it: TIdentIter;
+  scope: int;
+begin
+  for scope := tos downto 0 do begin
+    result := initIdentIter(it, c.tab.stack[scope], fn.Name);
+    while result <> nil do begin
+      // watchout! result must not be the same as fn!
+      if (result.Kind = fn.kind) and (result.id <> fn.id) then begin
+        if equalGenericParams(result.ast.sons[genericParamsPos], 
+                              fn.ast.sons[genericParamsPos]) then begin
+          if paramsFitBorrow(fn.typ.n, result.typ.n) then exit;
+        end
+      end;
+      result := NextIdentIter(it, c.tab.stack[scope])
+    end
+  end
+end;
+
 end.
diff --git a/nim/rnimsyn.pas b/nim/rnimsyn.pas
index 6cb78efcf..5be10a0f3 100644
--- a/nim/rnimsyn.pas
+++ b/nim/rnimsyn.pas
@@ -16,7 +16,7 @@ unit rnimsyn;
 interface
 
 uses
-  nsystem, charsets, lexbase, scanner, options, idents, strutils, ast, msgs,
+  nsystem, charsets, scanner, options, idents, strutils, ast, msgs,
   lists;
 
 type
@@ -543,6 +543,7 @@ begin
     nkRefTy:          result := lsub(n.sons[0])+length('ref_');
     nkPtrTy:          result := lsub(n.sons[0])+length('ptr_');
     nkVarTy:          result := lsub(n.sons[0])+length('var_');
+    nkAbstractTy:     result := lsub(n.sons[0])+length('abstract_');
     nkTypeDef:        result := lsons(n)+3;
     nkOfInherit:      result := lsub(n.sons[0])+length('of_');
     nkProcTy:         result := lsons(n)+length('proc_');
@@ -1159,6 +1160,10 @@ begin
       putWithSpace(g, tkVar, 'var');
       gsub(g, n.sons[0]);
     end;
+    nkAbstractTy: begin
+      putWithSpace(g, tkAbstract, 'abstract');
+      gsub(g, n.sons[0]);
+    end;
     nkTypeDef: begin
       gsub(g, n.sons[0]);
       gsub(g, n.sons[1]);
diff --git a/nim/rst.pas b/nim/rst.pas
index 6d0d476c9..d2afc7e33 100644
--- a/nim/rst.pas
+++ b/nim/rst.pas
@@ -1991,7 +1991,7 @@ begin
     addSon(n, newRstNode(rnLeaf, readFile(path)));
     result.sons[2] := n;
   end;
-  result.kind := rnCodeBlock
+  result.kind := rnCodeBlock;
 end;
 
 function dirContainer(var p: TRstParser): PRstNode;
diff --git a/nim/scanner.pas b/nim/scanner.pas
index 51532c801..d1f32135c 100644
--- a/nim/scanner.pas
+++ b/nim/scanner.pas
@@ -52,20 +52,20 @@ type
     //  i = i + 1
     //cog.out(idents)
     //]]]
-    tkAddr, tkAnd, tkAs, tkAsm, 
-    tkBlock, tkBreak, tkCase, tkCast, 
-    tkConst, tkContinue, tkConverter, tkDiscard, 
-    tkDiv, tkElif, tkElse, tkEnd, 
-    tkEnum, tkExcept, tkException, tkFinally, 
-    tkFor, tkFrom, tkGeneric, tkIf, 
-    tkImplies, tkImport, tkIn, tkInclude, 
-    tkIs, tkIsnot, tkIterator, tkLambda, 
-    tkMacro, tkMethod, tkMod, tkNil, 
-    tkNot, tkNotin, tkObject, tkOf, 
-    tkOr, tkOut, tkProc, tkPtr, 
-    tkRaise, tkRef, tkReturn, tkShl, 
-    tkShr, tkTemplate, tkTry, tkTuple, 
-    tkType, tkVar, tkWhen, tkWhere, 
+    tkAbstract, tkAddr, tkAnd, tkAs, 
+    tkAsm, tkBlock, tkBreak, tkCase, 
+    tkCast, tkConst, tkContinue, tkConverter, 
+    tkDiscard, tkDiv, tkElif, tkElse, 
+    tkEnd, tkEnum, tkExcept, tkException, 
+    tkFinally, tkFor, tkFrom, tkGeneric, 
+    tkIf, tkImplies, tkImport, tkIn, 
+    tkInclude, tkIs, tkIsnot, tkIterator, 
+    tkLambda, tkMacro, tkMethod, tkMod, 
+    tkNil, tkNot, tkNotin, tkObject, 
+    tkOf, tkOr, tkOut, tkProc, 
+    tkPtr, tkRaise, tkRef, tkReturn, 
+    tkShl, tkShr, tkTemplate, tkTry, 
+    tkTuple, tkType, tkVar, tkWhen, 
     tkWhile, tkWith, tkWithout, tkXor, 
     tkYield, 
     //[[[end]]]
@@ -96,20 +96,20 @@ const
     //[[[cog
     //cog.out(strings)
     //]]]
-    'addr', 'and', 'as', 'asm', 
-    'block', 'break', 'case', 'cast', 
-    'const', 'continue', 'converter', 'discard', 
-    'div', 'elif', 'else', 'end', 
-    'enum', 'except', 'exception', 'finally', 
-    'for', 'from', 'generic', 'if', 
-    'implies', 'import', 'in', 'include', 
-    'is', 'isnot', 'iterator', 'lambda', 
-    'macro', 'method', 'mod', 'nil', 
-    'not', 'notin', 'object', 'of', 
-    'or', 'out', 'proc', 'ptr', 
-    'raise', 'ref', 'return', 'shl', 
-    'shr', 'template', 'try', 'tuple', 
-    'type', 'var', 'when', 'where', 
+    'abstract', 'addr', 'and', 'as', 
+    'asm', 'block', 'break', 'case', 
+    'cast', 'const', 'continue', 'converter', 
+    'discard', 'div', 'elif', 'else', 
+    'end', 'enum', 'except', 'exception', 
+    'finally', 'for', 'from', 'generic', 
+    'if', 'implies', 'import', 'in', 
+    'include', 'is', 'isnot', 'iterator', 
+    'lambda', 'macro', 'method', 'mod', 
+    'nil', 'not', 'notin', 'object', 
+    'of', 'or', 'out', 'proc', 
+    'ptr', 'raise', 'ref', 'return', 
+    'shl', 'shr', 'template', 'try', 
+    'tuple', 'type', 'var', 'when', 
     'while', 'with', 'without', 'xor', 
     'yield', 
     //[[[end]]]
@@ -648,6 +648,7 @@ begin
     inc(pos, 2); // skip ""
     // skip leading newline:
     pos := HandleCRLF(L, pos);
+    buf := L.buf;
     repeat
       case buf[pos] of
         '"': begin
@@ -658,6 +659,7 @@ begin
         end;
         CR, LF: begin
           pos := HandleCRLF(L, pos);
+          buf := L.buf;
           tok.literal := tok.literal +{&} tnl;
         end;
         lexbase.EndOfFile: begin
@@ -842,6 +844,7 @@ begin
       addChar(tok.literal, buf[pos]); inc(pos);
     end;
     pos := handleCRLF(L, pos);
+    buf := L.buf;
     indent := 0;
     while buf[pos] = ' ' do begin inc(pos); inc(indent) end;
     if (buf[pos] = '#') and (col = indent) then begin
@@ -875,6 +878,7 @@ begin
       // newline is special:
       CR, LF: begin
         pos := HandleCRLF(L, pos);
+        buf := L.buf;
         indent := 0;
         while buf[pos] = ' ' do begin
           Inc(pos); Inc(indent)
diff --git a/nim/sem.pas b/nim/sem.pas
index 09f9bf49b..c0826bdbe 100644
--- a/nim/sem.pas
+++ b/nim/sem.pas
@@ -134,6 +134,7 @@ var
   p: PEvalContext;
   s: PStackFrame;
 begin
+  include(sym.flags, sfUsed);
   p := newEvalContext(c.module, '');
   s := newStackFrame();
   s.call := n;
@@ -156,7 +157,8 @@ end;
 
 procedure CheckBool(t: PNode);
 begin
-  if (t.Typ = nil) or (skipVarGeneric(t.Typ).kind <> tyBool) then
+  if (t.Typ = nil) or (skipTypes(t.Typ, {@set}[tyGenericInst, 
+      tyVar, tyOrdinal]).kind <> tyBool) then
     liMessage(t.Info, errExprMustBeBool);
 end;
 
diff --git a/nim/semexprs.pas b/nim/semexprs.pas
index 59d7f969a..74cd44b3d 100644
--- a/nim/semexprs.pas
+++ b/nim/semexprs.pas
@@ -58,8 +58,8 @@ begin
   end;
 
   // common case first (converting of objects)
-  d := skipVarGeneric(castDest);
-  s := skipVarGeneric(src);
+  d := skipTypes(castDest, abstractVar);
+  s := skipTypes(src, abstractVar);
   while (d <> nil) and (d.Kind in [tyPtr, tyRef])
   and (d.Kind = s.Kind) do begin
     d := base(d);
@@ -71,17 +71,20 @@ begin
         [typeToString(src), typeToString(castDest)]));
   if (d.Kind = tyObject) and (s.Kind = tyObject) then
     checkConversionBetweenObjects(info, d, s)
-  else if (skipVarGenericRange(castDest).Kind in IntegralTypes)
-  and (skipVarGenericRange(src).Kind in IntegralTypes) then begin
+  else if (skipTypes(castDest, abstractVarRange).Kind in IntegralTypes)
+  and (skipTypes(src, abstractVarRange).Kind in IntegralTypes) then begin
     // accept conversion between intregral types
   end
-  else begin
+  else begin          
+    // we use d, s here to speed up that operation a bit:
     case cmpTypes(d, s) of
-      isNone, isGeneric:
-        // we use d, s here to speed up that operation a bit
-        liMessage(info, errGenerated,
-          format(MsgKindToString(errIllegalConvFromXtoY),
-            [typeToString(src), typeToString(castDest)]));
+      isNone, isGeneric: begin
+        if not equalOrAbstractOf(castDest, src) and
+           not equalOrAbstractOf(src, castDest) then
+          liMessage(info, errGenerated,
+            format(MsgKindToString(errIllegalConvFromXtoY),
+              [typeToString(src), typeToString(castDest)]));
+      end
       else begin end
     end
   end
@@ -102,8 +105,8 @@ begin
   else if ss < 0 then result := false
   else 
     result := (ds >= ss) or
-      (skipGeneric(dst).kind in [tyInt..tyFloat128]) or
-      (skipGeneric(src).kind in [tyInt..tyFloat128])
+      (skipTypes(dst, abstractInst).kind in [tyInt..tyFloat128]) or
+      (skipTypes(src, abstractInst).kind in [tyInt..tyFloat128])
 end;
 
 function semConv(c: PContext; n: PNode; s: PSym): PNode;
@@ -138,7 +141,7 @@ begin
     liMessage(n.info, errXExpectsTypeOrValue, opToStr[m])
   else begin
     n.sons[1] := semExprWithType(c, n.sons[1], {@set}[efAllowType]);
-    typ := skipVarGenericRange(n.sons[1].typ);
+    typ := skipTypes(n.sons[1].typ, abstractVarRange);
     case typ.Kind of
       tySequence, tyString, tyOpenArray: begin
         n.typ := getSysType(tyInt);
@@ -279,7 +282,8 @@ begin
     addSon(result.typ, newTypeS(tyEmpty, c)) // needs an empty basetype!
   else begin
     addSon(result, semExprWithType(c, n.sons[0]));
-    typ := skipVar(result.sons[0].typ);
+    typ := skipTypes(result.sons[0].typ, 
+                    {@set}[tyGenericInst, tyVar, tyOrdinal]);
     for i := 1 to sonsLen(n)-1 do begin
       n.sons[i] := semExprWithType(c, n.sons[i]);
       addSon(result, fitNode(c, typ, n.sons[i]));
@@ -306,17 +310,18 @@ begin
       nkHiddenStdConv, nkHiddenSubConv: begin
         if it.sons[1].kind = nkBracket then
           it.sons[1] := semArrayConstr(c, it.sons[1]);
-        if skipVarGeneric(it.typ).kind = tyOpenArray then begin
-          s := skipVarGeneric(it.sons[1].typ);
+        if skipTypes(it.typ, abstractVar).kind = tyOpenArray then begin
+          s := skipTypes(it.sons[1].typ, abstractVar);
           if (s.kind = tyArrayConstr) and (s.sons[1].kind = tyEmpty) then begin
             s := copyType(s, getCurrOwner(), false);
-            skipVarGeneric(s).sons[1] := elemType(skipVarGeneric(it.typ));
+            skipTypes(s, abstractVar).sons[1] := elemType(
+              skipTypes(it.typ, abstractVar));
             it.sons[1].typ := s;
           end
         end
-        else if skipVarGeneric(it.sons[1].typ).kind in [tyNil, tyArrayConstr,
-                      tyTuple, tySet] then begin
-          s := skipVarGeneric(it.typ);
+        else if skipTypes(it.sons[1].typ, abstractVar).kind in 
+                  [tyNil, tyArrayConstr, tyTuple, tySet] then begin
+          s := skipTypes(it.typ, abstractVar);
           changeType(it.sons[1], s);
           n.sons[i] := it.sons[1];
         end
@@ -335,7 +340,7 @@ function skipObjConv(n: PNode): PNode;
 begin
   case n.kind of
     nkHiddenStdConv, nkHiddenSubConv, nkConv: begin
-      if skipPtrsGeneric(n.sons[1].typ).kind in [tyTuple, tyObject] then
+      if skipTypes(n.sons[1].typ, abstractPtrs).kind in [tyTuple, tyObject] then
         result := n.sons[1]
       else
         result := n
@@ -352,7 +357,7 @@ begin
     nkSym: result := n.sym.kind in [skVar, skTemp];
     nkDotExpr, nkQualified, nkBracketExpr: begin
       checkMinSonsLen(n, 1);
-      if skipGeneric(n.sons[0].typ).kind in [tyVar, tyPtr, tyRef] then
+      if skipTypes(n.sons[0].typ, abstractInst).kind in [tyVar, tyPtr, tyRef] then
         result := true
       else
         result := isAssignable(n.sons[0]);
@@ -361,7 +366,7 @@ begin
       // Object and tuple conversions are still addressable, so we skip them
       //if skipPtrsGeneric(n.sons[1].typ).kind in [tyOpenArray,
       //                                           tyTuple, tyObject] then
-      if skipPtrsGeneric(n.typ).kind in [tyOpenArray, tyTuple, tyObject] then
+      if skipTypes(n.typ, abstractPtrs).kind in [tyOpenArray, tyTuple, tyObject] then
         result := isAssignable(n.sons[1])
     end;
     nkHiddenDeref, nkDerefExpr: result := true;
@@ -391,7 +396,7 @@ begin
   result := n;
   case n.kind of
     nkSym: begin
-      if skipGeneric(n.sym.typ).kind <> tyVar then begin
+      if skipTypes(n.sym.typ, abstractInst).kind <> tyVar then begin
         include(n.sym.flags, sfAddrTaken);
         result := newHiddenAddrTaken(c, n);
       end
@@ -400,14 +405,14 @@ begin
       checkSonsLen(n, 2);
       if n.sons[1].kind <> nkSym then
         internalError(n.info, 'analyseIfAddressTaken');
-      if skipGeneric(n.sons[1].sym.typ).kind <> tyVar then begin
+      if skipTypes(n.sons[1].sym.typ, abstractInst).kind <> tyVar then begin
         include(n.sons[1].sym.flags, sfAddrTaken);
         result := newHiddenAddrTaken(c, n);
       end
     end;
     nkBracketExpr: begin
       checkMinSonsLen(n, 1);
-      if skipGeneric(n.sons[0].typ).kind <> tyVar then begin
+      if skipTypes(n.sons[0].typ, abstractInst).kind <> tyVar then begin
         if n.sons[0].kind = nkSym then
           include(n.sons[0].sym.flags, sfAddrTaken);
         result := newHiddenAddrTaken(c, n);
@@ -433,7 +438,7 @@ begin
   if (n.sons[0].kind = nkSym)
       and (n.sons[0].sym.magic in FakeVarParams) then exit;
   for i := 1 to sonsLen(n)-1 do
-    if (i < sonsLen(t)) and (skipGeneric(t.sons[i]).kind = tyVar) then
+    if (i < sonsLen(t)) and (skipTypes(t.sons[i], abstractInst).kind = tyVar) then
       n.sons[i] := analyseIfAddressTaken(c, n.sons[i]);
 end;
 
@@ -503,16 +508,16 @@ begin
   fixAbstractType(c, result);
   analyseIfAddressTakenInCall(c, result);
 end;
-
+(*
 function semIncSucc(c: PContext; n: PNode; const opr: string): PNode;
 // handles Inc, Dec, Succ and Pred
 var
   a: PNode;
   typ: PType;
 begin
-  checkMinSonsLen(n, 1);
+  checkMinSonsLen(n, 2);
   n.sons[1] := semExprWithType(c, n.sons[1]);
-  typ := skipVar(n.sons[1].Typ);
+  typ := skipTypes(n.sons[1].Typ, {@set}[tyGenericInst, tyVar]);
   if not isOrdinalType(typ) or enumHasWholes(typ) then
     liMessage(n.sons[1].Info, errOrdinalTypeExpected);
   if sonsLen(n) = 3 then begin
@@ -537,10 +542,27 @@ function semOrd(c: PContext; n: PNode): PNode;
 begin
   checkSonsLen(n, 2);
   n.sons[1] := semExprWithType(c, n.sons[1]);
-  if not isOrdinalType(skipVar(n.sons[1].Typ)) then
+  if not isOrdinalType(skipTypes(n.sons[1].Typ, {@set}[tyGenericInst, tyVar])) then
     liMessage(n.Info, errOrdinalTypeExpected);
   n.typ := getSysType(tyInt);
   result := n
+end; *)
+
+function semEcho(c: PContext; n: PNode): PNode;
+var
+  i: int;
+  call, arg: PNode;
+begin
+  // this really is a macro
+  checkMinSonsLen(n, 1);
+  for i := 1 to sonsLen(n)-1 do begin
+    arg := semExprWithType(c, n.sons[i]);
+    call := newNodeI(nkCall, arg.info);
+    addSon(call, newIdentNode(getIdent('$'+''), n.info));
+    addSon(call, arg);
+    n.sons[i] := semExpr(c, call);
+  end;
+  result := n;
 end;
 
 function LookUpForDefined(c: PContext; n: PNode): PSym;
@@ -609,6 +631,8 @@ begin
     mHigh:    result := semLowHigh(c, setMs(n, s), mHigh);
     mSizeOf:  result := semSizeof(c, setMs(n, s));
     mIs:      result := semIs(c, setMs(n, s));
+    mEcho:    result := semEcho(c, setMs(n, s)); 
+    (*
     mSucc:    begin
       result := semIncSucc(c, setMs(n, s), 'succ');
       result.typ := n.sons[1].typ;
@@ -619,7 +643,7 @@ begin
     end;
     mInc:     result := semIncSucc(c, setMs(n, s), 'inc');
     ast.mDec: result := semIncSucc(c, setMs(n, s), 'dec');
-    mOrd:     result := semOrd(c, setMs(n, s));
+    mOrd:     result := semOrd(c, setMs(n, s)); *)
     else      result := semDirectOp(c, n);
   end;
 end;
@@ -659,7 +683,14 @@ begin
         result.info := n.info;
         result.typ := s.typ;
       end
-    end
+    end;
+    skMacro: result := semMacroExpr(c, n, s);
+    skTemplate: begin
+      // Templates and macros can be invoked without ``()``
+      pushInfoContext(n.info);
+      result := evalTemplate(c, n, s);
+      popInfoContext();
+    end;
     else begin end
   end;
   checkDeprecated(n, s);
@@ -808,7 +839,7 @@ begin
     exit
   end;
 
-  ty := skipPtrsGeneric(ty);
+  ty := skipTypes(ty, {@set}[tyGenericInst, tyVar, tyPtr, tyRef]);
   if ty.kind = tyObject then begin
     while true do begin
       check := nil;
@@ -816,7 +847,7 @@ begin
       //f := lookupInRecord(ty.n, i);
       if f <> nil then break;
       if ty.sons[0] = nil then break;
-      ty := skipGeneric(ty.sons[0]);
+      ty := skipTypes(ty.sons[0], {@set}[tyGenericInst]);
     end;
     if f <> nil then begin
       if ([sfStar, sfMinus] * f.flags <> [])
@@ -883,7 +914,7 @@ begin
   // check if array type:
   checkMinSonsLen(n, 2);
   n.sons[0] := semExprWithType(c, n.sons[0], flags-[efAllowType]);
-  arr := skipPtrsGeneric(n.sons[0].typ);
+  arr := skipTypes(n.sons[0].typ, {@set}[tyGenericInst, tyVar, tyPtr, tyRef]);
   case arr.kind of
     tyArray, tyOpenArray, tyArrayConstr, tySequence, tyString,
     tyCString: begin
@@ -904,7 +935,8 @@ begin
       n.sons[0] := makeDeref(n.sons[0]);
       // [] operator for tuples requires constant expression
       n.sons[1] := semConstExpr(c, n.sons[1]);
-      if skipRange(n.sons[1].typ).kind in [tyInt..tyInt64] then begin
+      if skipTypes(n.sons[1].typ, {@set}[tyGenericInst, tyRange, tyOrdinal]).kind in
+          [tyInt..tyInt64] then begin
         idx := getOrdValue(n.sons[1]);
         if (idx >= 0) and (idx < sonsLen(arr)) then
           n.typ := arr.sons[int(idx)]
@@ -984,12 +1016,15 @@ begin
         checkSonsLen(n.sons[i], 2);
         n.sons[i].sons[0] := semExprWithType(c, n.sons[i].sons[0]);
         n.sons[i].sons[1] := semExprWithType(c, n.sons[i].sons[1]);
-        if typ = nil then typ := skipVar(n.sons[i].sons[0].typ);
+        if typ = nil then 
+          typ := skipTypes(n.sons[i].sons[0].typ, 
+            {@set}[tyGenericInst, tyVar, tyOrdinal]);
         n.sons[i].typ := n.sons[i].sons[1].typ; // range node needs type too
       end
       else begin
         n.sons[i] := semExprWithType(c, n.sons[i]);
-        if typ = nil then typ := skipVar(n.sons[i].typ)
+        if typ = nil then
+          typ := skipTypes(n.sons[i].typ, {@set}[tyGenericInst, tyVar, tyOrdinal])
       end
     end;
     if not isOrdinalType(typ) then begin
@@ -1156,10 +1191,7 @@ begin
   if (s <> nil) then begin
     checkDeprecated(n, s);
     case s.kind of
-      skMacro: begin
-        include(s.flags, sfUsed);
-        result := semMacroExpr(c, n, s);
-      end;
+      skMacro: result := semMacroExpr(c, n, s);
       skTemplate: begin
         include(s.flags, sfUsed);
         // transform
@@ -1234,7 +1266,6 @@ begin
         result := semExpr(c, result, flags)
       end;
     end;
-    // complex expressions
     nkCall, nkInfix, nkPrefix, nkPostfix, nkCommand: begin
       // check if it is an expression macro:
       checkMinSonsLen(n, 1);
@@ -1242,10 +1273,7 @@ begin
       if (s <> nil) then begin
         checkDeprecated(n, s);
         case s.kind of
-          skMacro: begin
-            include(s.flags, sfUsed);
-            result := semMacroExpr(c, n, s);
-          end;
+          skMacro: result := semMacroExpr(c, n, s);
           skTemplate: begin
             include(s.flags, sfUsed);
             pushInfoContext(n.info);
@@ -1307,7 +1335,7 @@ begin
       checkSonsLen(n, 1);
       n.sons[0] := semExprWithType(c, n.sons[0]);
       result := n;
-      case skipVarGeneric(n.sons[0].typ).kind of
+      case skipTypes(n.sons[0].typ, {@set}[tyGenericInst, tyVar]).kind of
         tyRef, tyPtr: n.typ := n.sons[0].typ.sons[0];
         else liMessage(n.sons[0].info, errCircumNeedsPointer);
       end;
diff --git a/nim/semfold.pas b/nim/semfold.pas
index 261e27fd5..556dabe9b 100644
--- a/nim/semfold.pas
+++ b/nim/semfold.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -39,7 +39,7 @@ implementation
 
 function newIntNodeT(const intVal: BiggestInt; n: PNode): PNode;
 begin
-  if skipVarGenericRange(n.typ).kind = tyChar then
+  if skipTypes(n.typ, abstractVarRange).kind = tyChar then
     result := newIntNode(nkCharLit, intVal)
   else
     result := newIntNode(nkIntLit, intVal);
@@ -102,7 +102,7 @@ var
   i: int;
 begin
   x := getInt(a);
-  n := a.typ.n;
+  n := skipTypes(a.typ, abstractInst).n;
   for i := 0 to sonsLen(n)-1 do begin
     if n.sons[i].kind <> nkSym then InternalError(a.info, 'enumValToString');
     field := n.sons[i].sym;
@@ -163,7 +163,7 @@ begin
       else result := newIntNodeT(getInt(b), n);
     end;
     mShlI, mShlI64: begin
-      case skipGenericRange(n.typ).kind of
+      case skipTypes(n.typ, abstractRange).kind of
         tyInt8:  result := newIntNodeT(int8(getInt(a)) shl int8(getInt(b)), n);
         tyInt16: result := newIntNodeT(int16(getInt(a)) shl int16(getInt(b)), n);
         tyInt32: result := newIntNodeT(int32(getInt(a)) shl int32(getInt(b)), n);
@@ -173,7 +173,7 @@ begin
       end
     end;
     mShrI, mShrI64: begin
-      case skipGenericRange(n.typ).kind of
+      case skipTypes(n.typ, abstractRange).kind of
         tyInt8:  result := newIntNodeT(int8(getInt(a)) shr int8(getInt(b)), n);
         tyInt16: result := newIntNodeT(int16(getInt(a)) shr int16(getInt(b)), n);
         tyInt32: result := newIntNodeT(int32(getInt(a)) shr int32(getInt(b)), n);
@@ -287,7 +287,7 @@ begin
       result := copyTree(a);
       result.typ := n.typ;
     end;
-    mNewString, mExit, mInc, ast.mDec, mAssert, mSwap,
+    mNewString, mExit, mInc, ast.mDec, mEcho, mAssert, mSwap,
     mAppendStrCh, mAppendStrStr, mAppendSeqElem, mAppendSeqSeq,
     mSetLengthStr, mSetLengthSeq, mNLen..mNError: begin end;
     else InternalError(a.info, 'evalOp(' +{&} magicToStr[m] +{&} ')');
@@ -417,7 +417,7 @@ begin
     end;
     nkCharLit..nkNilLit: result := copyNode(n);
     nkIfExpr: result := getConstIfExpr(module, n);
-    nkCall: begin
+    nkCall, nkCommand: begin
       if (n.sons[0].kind <> nkSym) then exit;
       s := n.sons[0].sym;
       if (s.kind <> skProc) then exit;
@@ -440,9 +440,10 @@ begin
           end;
           mLow:  result := newIntNodeT(firstOrd(n.sons[1].typ), n);
           mHigh: begin
-            if not (skipVarGeneric(n.sons[1].typ).kind in [tyOpenArray,
+            if not (skipTypes(n.sons[1].typ, abstractVar).kind in [tyOpenArray,
                                      tySequence, tyString]) then
-              result := newIntNodeT(lastOrd(skipVarGeneric(n.sons[1].typ)), n);
+              result := newIntNodeT(lastOrd(
+                skipTypes(n.sons[1].typ, abstractVar)), n);
           end;
           else begin
             a := getConstExpr(module, n.sons[1]);
@@ -537,9 +538,9 @@ begin
     nkHiddenStdConv, nkHiddenSubConv, nkConv, nkCast: begin
       a := getConstExpr(module, n.sons[1]);
       if a = nil then exit;
-      case skipRange(n.typ).kind of
+      case skipTypes(n.typ, abstractRange).kind of
         tyInt..tyInt64: begin
-          case skipRange(a.typ).kind of
+          case skipTypes(a.typ, abstractRange).kind of
             tyFloat..tyFloat64: 
               result := newIntNodeT(nsystem.toInt(getFloat(a)), n);
             tyChar: 
@@ -551,7 +552,7 @@ begin
           end
         end;
         tyFloat..tyFloat64: begin
-          case skipRange(a.typ).kind of
+          case skipTypes(a.typ, abstractRange).kind of
             tyInt..tyInt64, tyEnum, tyBool, tyChar: 
               result := newFloatNodeT(toFloat(int(getOrdValue(a))), n);
             else begin
diff --git a/nim/semstmts.pas b/nim/semstmts.pas
index a5242b526..c8b942df8 100644
--- a/nim/semstmts.pas
+++ b/nim/semstmts.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -205,7 +205,7 @@ begin
   n.sons[0] := semExprWithType(c, n.sons[0]);
   chckCovered := false;
   covered := 0;
-  case skipVarGenericRange(n.sons[0].Typ).Kind of
+  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);
@@ -302,7 +302,8 @@ begin
   n.sons[0] := semExprWithType(c, n.sons[0], {@set}[efLValue]);
   n.sons[1] := semExprWithType(c, n.sons[1]);
   le := n.sons[0].typ;
-  if (skipGeneric(le).kind <> tyVar) and not IsAssignable(n.sons[0]) then begin
+  if (skipTypes(le, {@set}[tyGenericInst]).kind <> tyVar) 
+  and not IsAssignable(n.sons[0]) then begin
     liMessage(n.sons[0].info, errXCannotBeAssignedTo,
               renderTree(n.sons[0], {@set}[renderNoComments]));
   end
@@ -410,7 +411,7 @@ begin
       def := nil;
     if not typeAllowed(typ, skVar) then
       liMessage(a.info, errXisNoType, typeToString(typ));
-    tup := skipGeneric(typ);
+    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
@@ -511,7 +512,7 @@ begin
     n.sons[len-2] := countupNode;
   end;
   n.sons[len-2] := semExprWithType(c, n.sons[len-2]);
-  iter := skipGeneric(n.sons[len-2].typ);
+  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);
@@ -742,6 +743,17 @@ begin
   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;
+
 function semIterator(c: PContext; n: PNode): PNode;
 var
   s: PSym;
@@ -774,6 +786,8 @@ begin
     pragmaIterator(c, s, n.sons[pragmasPos]);
   s.options := gOptions;
   if n.sons[codePos] <> nil then begin
+    if sfBorrow in s.flags then
+      liMessage(n.info, errImplOfXNotAllowed, s.name.s);
     if n.sons[genericParamsPos] = nil then begin
       c.p := newProcCon(s);
       openScope(c.tab);
@@ -784,6 +798,8 @@ begin
       n.sons[codePos] := resolveGenericParams(c, n.sons[codePos]);
     end
   end
+  else if (sfBorrow in s.flags) then
+    semBorrow(c, n, s)
   else
     liMessage(n.info, errIteratorNeedsImplementation);
   closeScope(c.tab);
@@ -849,7 +865,7 @@ begin
   s.options := gOptions;
   if n.sons[codePos] <> nil then begin
     if sfImportc in s.flags then
-      liMessage(n.sons[codePos].info, errImportedProcCannotHaveImpl);
+      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]);
@@ -937,8 +953,8 @@ begin
 
   s.options := gOptions;
   if n.sons[codePos] <> nil then begin
-    if sfImportc in s.flags then
-      liMessage(n.sons[codePos].info, errImportedProcCannotHaveImpl);
+    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);
       addResult(c, s.typ.sons[0], n.info);
@@ -952,7 +968,9 @@ begin
   else begin
     if proto <> nil then
       liMessage(n.info, errImplOfXexpected, proto.name.s);
-    if not (sfImportc in s.flags) then Include(s.flags, sfForward);
+    if [sfImportc, sfBorrow] * s.flags = [] then Include(s.flags, sfForward)
+    else if sfBorrow in s.flags then 
+      semBorrow(c, n, s);
   end;
   closeScope(c.tab); // close scope for parameters
   popOwner();
diff --git a/nim/semtypes.pas b/nim/semtypes.pas
index 014ff0216..c968d4b72 100644
--- a/nim/semtypes.pas
+++ b/nim/semtypes.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -140,6 +140,15 @@ begin
     liMessage(n.info, errXExpectsOneTypeParam, 'var');
 end;
 
+function semAbstract(c: PContext; n: PNode; prev: PType): PType;
+begin
+  result := newOrPrevType(tyAbstract, prev, c);
+  if sonsLen(n) = 1 then 
+    addSon(result, semTypeNode(c, n.sons[0], nil))
+  else
+    liMessage(n.info, errXExpectsOneTypeParam, 'abstract');
+end;
+
 function semRangeAux(c: PContext; n: PNode; prev: PType): PType;
 var
   a, b: PNode;
@@ -202,6 +211,23 @@ begin
     liMessage(n.info, errArrayExpectsTwoTypeParams);
 end;
 
+function semOrdinal(c: PContext; n: PNode; prev: PType): PType;
+var
+  base: PType;
+begin
+  result := newOrPrevType(tyOrdinal, prev, c);
+  if sonsLen(n) = 2 then begin
+    base := semTypeNode(c, n.sons[1], nil);
+    if base.kind <> tyGenericParam then begin
+      if not isOrdinalType(base) then
+        liMessage(n.sons[1].info, errOrdinalTypeExpected);
+    end;
+    addSon(result, base);
+  end
+  else
+    liMessage(n.info, errXExpectsOneTypeParam, 'ordinal');
+end;
+
 function semTypeIdent(c: PContext; n: PNode): PSym;
 begin
   result := qualifiedLookup(c, n, true);
@@ -441,7 +467,7 @@ begin
     internalError('semRecordCase: dicriminant is no symbol');
   include(a.sons[0].sym.flags, sfDiscriminant);
   covered := 0;
-  typ := skipVarGeneric(a.sons[0].Typ);
+  typ := skipTypes(a.sons[0].Typ, abstractVar);
   if not isOrdinalType(typ) then
     liMessage(n.info, errSelectorMustBeOrdinal);
   if firstOrd(typ) < 0 then
@@ -740,6 +766,7 @@ begin
         mOpenArray: result := semContainer(c, n, tyOpenArray, 'openarray', prev);
         mRange: result := semRange(c, n, prev);
         mSet: result := semSet(c, n, prev);
+        mOrdinal: result := semOrdinal(c, n, prev);
         mSeq: result := semContainer(c, n, tySequence, 'seq', prev);
         else result := semGeneric(c, n, s, prev);
       end
@@ -774,6 +801,7 @@ begin
     nkRefTy: result := semAnyRef(c, n, tyRef, 'ref', prev);
     nkPtrTy: result := semAnyRef(c, n, tyPtr, 'ptr', prev);
     nkVarTy: result := semVarType(c, n, prev);
+    nkAbstractTy: result := semAbstract(c, n, prev);
     nkProcTy: begin
       checkSonsLen(n, 2);
       result := semProcTypeNode(c, n.sons[0], prev);
@@ -821,7 +849,6 @@ begin
       addSon(m.typ, getSysType(tyChar));
     end;
     mPointer: setMagicType(m, tyPointer, ptrSize);
-    mAnyEnum: setMagicType(m, tyAnyEnum, 1);
     mEmptySet: begin
       setMagicType(m, tySet, 1);
       addSon(m.typ, newTypeS(tyEmpty, c));
@@ -832,7 +859,7 @@ begin
       exit
     end;
     mNil: setMagicType(m, tyNil, ptrSize);
-    mArray, mOpenArray, mRange, mSet, mSeq: exit;
+    mArray, mOpenArray, mRange, mSet, mSeq, mOrdinal: exit;
     else liMessage(m.info, errTypeExpected);
   end;
   //registerSysType(m.typ);
diff --git a/nim/sigmatch.pas b/nim/sigmatch.pas
index 5195de26c..d95745e0c 100644
--- a/nim/sigmatch.pas
+++ b/nim/sigmatch.pas
@@ -122,7 +122,7 @@ begin
   if a.kind = f.kind then
     result := isEqual
   else begin
-    k := skipRange(a).kind;
+    k := skipTypes(a, {@set}[tyRange]).kind;
     if k = f.kind then
       result := isSubtype
     else if (f.kind = tyInt) and (k in [tyInt..tyInt32]) then 
@@ -141,7 +141,7 @@ begin
   if a.kind = f.kind then
     result := isEqual
   else begin
-    k := skipRange(a).kind;
+    k := skipTypes(a, {@set}[tyRange]).kind;
     if k = f.kind then
       result := isSubtype
     else if (k >= tyFloat) and (k <= tyFloat128) then
@@ -203,7 +203,8 @@ begin // is a subtype of f?
   result := isNone;
   assert(f <> nil);
   assert(a <> nil);
-  if (a.kind = tyGenericInst) and (skipVar(f).kind <> tyGeneric) then begin
+  if (a.kind = tyGenericInst) and 
+      (skipTypes(f, {@set}[tyVar]).kind <> tyGeneric) then begin
     result := typeRel(mapping, f, lastSon(a));
     exit
   end;
@@ -214,18 +215,19 @@ begin // is a subtype of f?
   case f.kind of
     tyEnum: begin
       if (a.kind = f.kind) and (a.id = f.id) then result := isEqual
-      else if (skipRange(a).id = f.id) then result := isSubtype
+      else if (skipTypes(a, {@set}[tyRange]).id = f.id) then result := isSubtype
     end;
     tyBool, tyChar: begin
       if (a.kind = f.kind) then result := isEqual
-      else if skipRange(a).kind = f.kind then result := isSubtype
+      else if skipTypes(a, {@set}[tyRange]).kind = f.kind then 
+        result := isSubtype
     end;
     tyRange: begin
       if (a.kind = f.kind) then begin
         result := typeRel(mapping, base(a), base(f));
         if result < isGeneric then result := isNone
       end
-      else if skipRange(f).kind = a.kind then
+      else if skipTypes(f, {@set}[tyRange]).kind = a.kind then
         result := isConvertible // a convertible to f
     end;
     tyInt:   result := handleRange(f, a, tyInt8, tyInt32);
@@ -311,6 +313,13 @@ begin // is a subtype of f?
         else begin end
       end
     end;
+    tyOrdinal: begin
+      if isOrdinalType(a) then begin
+        if a.kind = tyOrdinal then x := a.sons[0] else x := a;
+        result := typeRel(mapping, f.sons[0], x);
+        if result < isGeneric then result := isNone
+      end
+    end;
     tyForward: InternalError('forward type in typeRel()');
     tyNil: begin
       if a.kind = f.kind then result := isEqual
@@ -324,6 +333,9 @@ begin // is a subtype of f?
         else if isObjectSubtype(a, f) then result := isSubtype
       end
     end;
+    tyAbstract: begin
+      if (a.kind = tyAbstract) and (a.id = f.id) then result := isEqual;
+    end;
     tySet: begin
       if a.kind = tySet then begin
         if (f.sons[0].kind <> tyGenericParam) and
@@ -418,8 +430,8 @@ begin // is a subtype of f?
         tyPtr: if a.sons[0].kind = tyChar then result := isConvertible;
         tyArray: begin
           if (firstOrd(a.sons[0]) = 0)
-              and (skipRange(a.sons[0]).kind in [tyInt..tyInt64])
-              and (a.sons[1].kind = tyChar) then
+             and (skipTypes(a.sons[0], {@set}[tyRange]).kind in [tyInt..tyInt64])
+             and (a.sons[1].kind = tyChar) then
             result := isConvertible;
         end
         else begin end
@@ -429,14 +441,6 @@ begin // is a subtype of f?
     tyEmpty: begin
       if a.kind = tyEmpty then result := isEqual;
     end;
-    tyAnyEnum: begin
-      case a.kind of
-        tyRange:   result := typeRel(mapping, f, base(a));
-        tyEnum:    result := isSubtype;
-        tyAnyEnum: result := isEqual;
-        else begin end
-      end
-    end;
     tyGenericInst: begin
       result := typeRel(mapping, lastSon(f), a);
     end;
@@ -572,7 +576,7 @@ begin
       result := copyTree(arg);
       result.typ := getInstantiatedType(c, arg, m, f);
       // BUG: f may not be the right key!
-      if (skipVarGeneric(result.typ).kind in [tyTuple, tyOpenArray]) then
+      if (skipTypes(result.typ, abstractVar).kind in [tyTuple, tyOpenArray]) then
         // BUGFIX: must pass length implicitely
         result := implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c);
       // BUGFIX: use ``result.typ`` and not `f` here
@@ -580,7 +584,7 @@ begin
     isEqual: begin
       inc(m.exactMatches);
       result := copyTree(arg);
-      if (skipVarGeneric(f).kind in [tyTuple, tyOpenArray]) then
+      if (skipTypes(f, abstractVar).kind in [tyTuple, tyOpenArray]) then
         // BUGFIX: must pass length implicitely
         result := implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c);
     end;
@@ -679,7 +683,7 @@ begin
       if f >= formalLen then begin // too many arguments?
         if tfVarArgs in m.callee.flags then begin
           // is ok... but don't increment any counters...
-          if skipVarGeneric(n.sons[a].typ).kind = tyString then
+          if skipTypes(n.sons[a].typ, abstractVar).kind = tyString then
             // conversion to cstring
             addSon(m.call, implicitConv(nkHiddenStdConv,
               getSysType(tyCString), copyTree(n.sons[a]), m, c))
diff --git a/nim/transf.pas b/nim/transf.pas
index 476ee4c33..b1812d52c 100644
--- a/nim/transf.pas
+++ b/nim/transf.pas
@@ -1,7 +1,7 @@
 //
 //
 //           The Nimrod Compiler
-//        (c) Copyright 2008 Andreas Rumpf
+//        (c) Copyright 2009 Andreas Rumpf
 //
 //    See the file "copying.txt", included in this
 //    distribution, for details about the copyright.
@@ -80,7 +80,8 @@ function newTemp(c: PTransf; typ: PType; const info: TLineInfo): PSym;
 begin
   result := newSym(skTemp, getIdent(genPrefix), getCurrOwner(c));
   result.info := info;
-  result.typ := skipGeneric(typ);
+  result.typ := skipTypes(typ, {@set}[tyGenericInst]);
+  // XXX really correct? maybe we need tyGenericInst for generic instantion?
   include(result.flags, sfFromGeneric);
 end;
 
@@ -148,23 +149,34 @@ end;
 function transformSym(c: PTransf; n: PNode): PNode;
 var
   tc: PTransCon;
+  b: PNode;
 begin
   if (n.kind <> nkSym) then internalError(n.info, 'transformSym');
   tc := c.transCon;
+  if sfBorrow in n.sym.flags then begin
+    // simply exchange the symbol:
+    b := n.sym.ast.sons[codePos];
+    if b.kind <> nkSym then 
+      internalError(n.info, 'wrong AST for borrowed symbol');
+    b := newSymNode(b.sym);
+    b.info := n.info;
+  end
+  else 
+    b := n;
   //writeln('transformSym', n.sym.id : 5);
   while tc <> nil do begin
-    result := IdNodeTableGet(tc.mapping, n.sym);
+    result := IdNodeTableGet(tc.mapping, b.sym);
     if result <> nil then exit;
     //write('not found in: ');
     //writeIdNodeTable(tc.mapping);
     tc := tc.next
   end;
-  result := n;
-  case n.sym.kind of
+  result := b;
+  case b.sym.kind of
     skConst, skEnumField: begin // BUGFIX: skEnumField was missing
-      if not (skipGeneric(n.sym.typ).kind in ConstantDataTypes) then begin
-        result := getConstExpr(c.module, n);
-        if result = nil then InternalError(n.info, 'transformSym: const');
+      if not (skipTypes(b.sym.typ, abstractInst).kind in ConstantDataTypes) then begin
+        result := getConstExpr(c.module, b);
+        if result = nil then InternalError(b.info, 'transformSym: const');
       end
     end
     else begin end
@@ -254,7 +266,7 @@ var
 begin
   result := newNodeI(nkStmtList, n.info);
   e := n.sons[0];
-  if skipGeneric(e.typ).kind = tyTuple then begin
+  if skipTypes(e.typ, {@set}[tyGenericInst]).kind = tyTuple then begin
     e := skipConv(e);
     if e.kind = nkPar then begin
       for i := 0 to sonsLen(e)-1 do begin
@@ -366,8 +378,8 @@ begin
   n.sons[1] := transform(c, n.sons[1]);
   result := n;
   // numeric types need range checks:
-  dest := skipVarGenericRange(n.typ);
-  source := skipVarGenericRange(n.sons[1].typ);
+  dest := skipTypes(n.typ, abstractVarRange);
+  source := skipTypes(n.sons[1].typ, abstractVarRange);
   case dest.kind of
     tyInt..tyInt64, tyEnum, tyChar, tyBool: begin
       if (firstOrd(dest) <= firstOrd(source)) and
@@ -381,16 +393,16 @@ begin
           result := newNodeIT(nkChckRange64, n.info, n.typ)
         else
           result := newNodeIT(nkChckRange, n.info, n.typ);
-        dest := skipVarGeneric(n.typ);
+        dest := skipTypes(n.typ, abstractVar);
         addSon(result, n.sons[1]);
         addSon(result, newIntTypeNode(nkIntLit, firstOrd(dest), source));
         addSon(result, newIntTypeNode(nkIntLit,  lastOrd(dest), source));
       end
     end;
     tyFloat..tyFloat128: begin
-      if skipVarGeneric(n.typ).kind = tyRange then begin
+      if skipTypes(n.typ, abstractVar).kind = tyRange then begin
         result := newNodeIT(nkChckRangeF, n.info, n.typ);
-        dest := skipVarGeneric(n.typ);
+        dest := skipTypes(n.typ, abstractVar);
         addSon(result, n.sons[1]);
         addSon(result, copyTree(dest.n.sons[0]));
         addSon(result, copyTree(dest.n.sons[1]));
@@ -413,8 +425,8 @@ begin
       end;
     end;
     tyRef, tyPtr: begin
-      dest := skipPtrsGeneric(dest);
-      source := skipPtrsGeneric(source);
+      dest := skipTypes(dest, abstractPtrs);
+      source := skipTypes(source, abstractPtrs);
       if source.kind = tyObject then begin
         diff := inheritanceDiff(dest, source);
         if diff < 0 then begin
@@ -444,7 +456,7 @@ begin
     tyArray, tySeq: begin
       if skipGeneric(dest
     end; *)
-    tyGenericParam, tyAnyEnum: result := n.sons[1];
+    tyGenericParam, tyOrdinal: result := n.sons[1];
       // happens sometimes for generated assignments, etc.
     else begin end
   end;
@@ -465,7 +477,7 @@ function putArgInto(arg: PNode; formal: PType): TPutArgInto;
 var
   i: int;
 begin
-  if skipGeneric(formal).kind = tyOpenArray then begin
+  if skipTypes(formal, abstractInst).kind = tyOpenArray then begin
     result := paDirectMapping; // XXX really correct?
     // what if ``arg`` has side-effects?
     exit
@@ -480,7 +492,7 @@ begin
       result := paDirectMapping;
     end;
     else begin
-      if skipGeneric(formal).kind = tyVar then
+      if skipTypes(formal, abstractInst).kind = tyVar then
         result := paVarAsgn
       else
         result := paFastAsgn
@@ -516,7 +528,7 @@ begin
   pushTransCon(c, newC);
   for i := 1 to sonsLen(call)-1 do begin
     arg := skipPassAsOpenArray(transform(c, call.sons[i]));
-    formal := skipGeneric(newC.owner.typ).n.sons[i].sym;
+    formal := skipTypes(newC.owner.typ, abstractInst).n.sons[i].sym;
     //if IdentEq(newc.Owner.name, 'items') then 
     //  liMessage(arg.info, warnUser, 'items: ' + nodeKindToStr[arg.kind]);
     case putArgInto(arg, formal.typ) of
@@ -529,7 +541,7 @@ begin
         IdNodeTablePut(newC.mapping, formal, newSymNode(temp));
       end;
       paVarAsgn: begin
-        assert(skipGeneric(formal.typ).kind = tyVar);
+        assert(skipTypes(formal.typ, abstractInst).kind = tyVar);
         InternalError(arg.info, 'not implemented: pass to var parameter');
       end;
     end;
@@ -820,13 +832,15 @@ var
 begin
   result := n;
   if n = nil then exit;
+  //if ToLinenumber(n.info) = 32 then
+  //  MessageOut(RenderTree(n));
   case n.kind of
     nkSym: begin
       result := transformSym(c, n);
       exit
     end;
     nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: begin
-      // nothing to be done for leafs
+      // nothing to be done for leaves
     end;
     nkBracketExpr: result := transformArrayAccess(c, n);
     nkLambda: result := transformLambda(c, n);
diff --git a/nim/transtmp.pas b/nim/transtmp.pas
index cfec21c98..77ba157f3 100644
--- a/nim/transtmp.pas
+++ b/nim/transtmp.pas
@@ -140,7 +140,7 @@ begin
         addSon(father, newAsgnStmt(dest, src));
       end
     end;
-    nkCall: begin
+    nkCall, nkCommand: begin
     
     end;
     
diff --git a/nim/trees.pas b/nim/trees.pas
index d271bfae8..4df85f6bb 100644
--- a/nim/trees.pas
+++ b/nim/trees.pas
@@ -144,7 +144,7 @@ end;
 
 function getOpSym(op: PNode): PSym;
 begin
-  if not (op.kind in [nkCall, nkGenericCall, nkHiddenCallConv]) then
+  if not (op.kind in [nkCall, nkGenericCall, nkHiddenCallConv, nkCommand]) then
     result := nil
   else begin
     if (sonsLen(op) <= 0) then InternalError(op.info, 'getOpSym');
@@ -158,7 +158,7 @@ end;
 function getMagic(op: PNode): TMagic;
 begin
   case op.kind of
-    nkCall, nkHiddenCallConv: begin
+    nkCall, nkHiddenCallConv, nkCommand: begin
       case op.sons[0].Kind of
         nkSym: begin
           result := op.sons[0].sym.magic;
diff --git a/nim/types.pas b/nim/types.pas
index af19a1671..b4558fe82 100644
--- a/nim/types.pas
+++ b/nim/types.pas
@@ -48,6 +48,7 @@ function mutateType(t: PType; iter: TTypeMutator; closure: PObject): PType;
 
 function SameType(x, y: PType): Boolean;
 function SameTypeOrNil(a, b: PType): Boolean;
+function equalOrAbstractOf(x, y: PType): bool;
 
 type
   TParamsEquality = (paramsNotEqual,      // parameters are not equal
@@ -64,6 +65,7 @@ function equalParams(a, b: PNode): TParamsEquality;
 function isOrdinalType(t: PType): Boolean;
 function enumHasWholes(t: PType): Boolean;
 
+(*
 function skipRange(t: PType): PType;
 function skipGeneric(t: PType): PType;
 function skipGenericRange(t: PType): PType;
@@ -71,6 +73,16 @@ function skipVar(t: PType): PType;
 function skipVarGeneric(t: PType): PType;
 function skipVarGenericRange(t: PType): PType;
 function skipPtrsGeneric(t: PType): PType;
+*)
+
+const
+  abstractPtrs = {@set}[tyVar, tyPtr, tyRef, tyGenericInst, tyAbstract, tyOrdinal];
+  abstractVar = {@set}[tyVar, tyGenericInst, tyAbstract, tyOrdinal];
+  abstractRange = {@set}[tyGenericInst, tyRange, tyAbstract, tyOrdinal];
+  abstractVarRange = {@set}[tyGenericInst, tyRange, tyVar, tyAbstract, tyOrdinal];
+  abstractInst = {@set}[tyGenericInst, tyAbstract, tyOrdinal];
+
+function skipTypes(t: PType; kinds: TTypeKinds): PType;
 
 function elemType(t: PType): PType;
 
@@ -171,7 +183,7 @@ begin
   result := false;
   if a.kind = tyArray then
     if (firstOrd(a.sons[0]) = 0)
-    and (skipRange(a.sons[0]).kind in [tyInt..tyInt64])
+    and (skipTypes(a.sons[0], {@set}[tyRange]).kind in [tyInt..tyInt64])
     and (a.sons[1].kind = tyChar) then
       result := true
 end;
@@ -200,7 +212,7 @@ function elemType(t: PType): PType;
 begin
   assert(t <> nil);
   case t.kind of
-    tyGenericInst: result := elemType(lastSon(t));
+    tyGenericInst, tyAbstract: result := elemType(lastSon(t));
     tyArray, tyArrayConstr: result := t.sons[1];
     else result := t.sons[0];
   end;
@@ -259,11 +271,17 @@ begin
     result := lastSon(result);
 end;
 
+function skipTypes(t: PType; kinds: TTypeKinds): PType;
+begin
+  result := t;
+  while result.kind in kinds do result := lastSon(result);
+end;
+
 function isOrdinalType(t: PType): Boolean;
 begin
   assert(t <> nil);
   result := (t.Kind in [tyChar, tyInt..tyInt64, tyBool, tyEnum])
-    or (t.Kind = tyRange) and isOrdinalType(t.sons[0]);
+    or (t.Kind in [tyRange, tyOrdinal]) and isOrdinalType(t.sons[0]);
 end;
 
 function enumHasWholes(t: PType): Boolean;
@@ -380,7 +398,8 @@ begin
       if not result then
         result := searchTypeNodeForAux(t.n, predicate, marker);
     end;
-    tyGenericInst: result := searchTypeForAux(lastSon(t), predicate, marker);
+    tyGenericInst, tyAbstract:
+      result := searchTypeForAux(lastSon(t), predicate, marker);
     tyArray, tyArrayConstr, tySet, tyTuple: begin
       for i := 0 to sonsLen(t)-1 do begin
         result := searchTypeForAux(t.sons[i], predicate, marker);
@@ -438,7 +457,8 @@ begin
       if result = frNone then
         if isObjectWithTypeFieldPredicate(t) then result := frHeader
     end;
-    tyGenericInst: result := analyseObjectWithTypeFieldAux(lastSon(t), marker);
+    tyGenericInst, tyAbstract: 
+      result := analyseObjectWithTypeFieldAux(lastSon(t), marker);
     tyArray, tyArrayConstr, tyTuple: begin
       for i := 0 to sonsLen(t)-1 do begin
         res := analyseObjectWithTypeFieldAux(t.sons[i], marker);
@@ -511,7 +531,7 @@ begin
   result := false;
   if t = nil then exit;
   if tfAcyclic in t.flags then exit;
-  case skipGeneric(t).kind of 
+  case skipTypes(t, abstractInst).kind of 
     tyTuple, tyObject, tyRef, tySequence, tyArray, tyArrayConstr,
     tyOpenArray: begin
       if not IntSetContainsOrIncl(marker, t.id) then begin
@@ -597,8 +617,8 @@ function TypeToString(typ: PType; prefer: TPreferedDesc = preferName): string;
 const
   typeToStr: array [TTypeKind] of string = (
     'None', 'bool', 'Char', 'empty', 'Array Constructor [$1]', 'nil',
-    'Generic', 'GenericInst', 'GenericParam',
-    'enum', 'anyenum',
+    'Generic', 'GenericInst', 'GenericParam', 'abstract $1',
+    'enum', 'ordinal[$1]',
     'array[$1, $2]', 'object', 'tuple', 'set[$1]', 'range[$1]',
     'ptr ', 'ref ', 'var ', 'seq[$1]', 'proc', 'pointer',
     'OpenArray[$1]', 'string', 'CString', 'Forward',
@@ -631,8 +651,10 @@ begin
       result := 'Array constructor[' +{&} rangeToStr(t.sons[0].n) +{&} ', '
                 +{&} typeToString(t.sons[1]) +{&} ']';
     tySequence: result := 'seq[' +{&} typeToString(t.sons[0]) +{&} ']';
+    tyOrdinal: result := 'ordinal[' +{&} typeToString(t.sons[0]) +{&} ']';
     tySet: result := 'set[' +{&} typeToString(t.sons[0]) +{&} ']';
     tyOpenArray: result := 'openarray[' +{&} typeToString(t.sons[0]) +{&} ']';
+    tyAbstract: result := 'abstract ' +{&} typeToString(t.sons[0], preferName);
     tyTuple: begin
       // we iterate over t.sons here, because t.n may be nil
       result := 'tuple[';
@@ -718,7 +740,7 @@ begin
         result := t.n.sons[0].sym.position;
       end;
     end;
-    tyGenericInst: result := firstOrd(lastSon(t));
+    tyGenericInst, tyAbstract: result := firstOrd(lastSon(t));
     else begin
       InternalError('invalid kind for first(' +{&}
         typeKindToStr[t.kind] +{&} ')');
@@ -754,7 +776,7 @@ begin
       assert(t.n.sons[sonsLen(t.n)-1].kind = nkSym);
       result := t.n.sons[sonsLen(t.n)-1].sym.position;
     end;
-    tyGenericInst: result := firstOrd(lastSon(t));
+    tyGenericInst, tyAbstract: result := firstOrd(lastSon(t));
     else begin
       InternalError('invalid kind for last(' +{&}
         typeKindToStr[t.kind] +{&} ')');
@@ -767,6 +789,7 @@ function lengthOrd(t: PType): biggestInt;
 begin
   case t.kind of
     tyInt64, tyInt32, tyInt: result := lastOrd(t);
+    tyAbstract: result := lengthOrd(t.sons[0]);
     else result := lastOrd(t) - firstOrd(t) + 1;
   end
 end;
@@ -855,7 +878,7 @@ begin
     SameLiteral(a.sons[1], b.sons[1])
 end;
 
-function sameTuple(a, b: PType): boolean;
+function sameTuple(a, b: PType; AbstractOf: bool): boolean;
 // two tuples are equivalent iff the names, types and positions are the same;
 // however, both types may not have any field names (t.n may be nil) which
 // complicates the matter a bit.
@@ -866,7 +889,10 @@ begin
   if sonsLen(a) = sonsLen(b) then begin
     result := true;
     for i := 0 to sonsLen(a)-1 do begin
-      result := SameType(a.sons[i], b.sons[i]);
+      if AbstractOf then 
+        result := equalOrAbstractOf(a.sons[i], b.sons[i])
+      else
+        result := SameType(a.sons[i], b.sons[i]);
       if not result then exit
     end;
     if (a.n <> nil) and (b.n <> nil) then begin
@@ -891,8 +917,8 @@ var
   a, b: PType;
 begin
   if x = y then begin result := true; exit end;
-  a := skipGeneric(x);
-  b := skipGeneric(y);
+  a := skipTypes(x, {@set}[tyGenericInst]);
+  b := skipTypes(y, {@set}[tyGenericInst]);
   assert(a <> nil);
   assert(b <> nil);
   if a.kind <> b.kind then begin result := false; exit end;
@@ -900,13 +926,13 @@ begin
     tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString, 
     tyInt..tyFloat128: 
       result := true;
-    tyEnum, tyForward, tyObject:
+    tyEnum, tyForward, tyObject, tyAbstract:
       result := (a.id = b.id);
     tyTuple: 
-      result := sameTuple(a, b);
+      result := sameTuple(a, b, false);
     tyGenericInst:
       result := sameType(lastSon(a), lastSon(b));
-    tyGenericParam, tyGeneric, tySequence,
+    tyGenericParam, tyGeneric, tySequence, tyOrdinal,
     tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr,
     tyArray, tyProc: begin
       if sonsLen(a) = sonsLen(b) then begin
@@ -926,7 +952,56 @@ begin
         and SameValue(a.n.sons[0], b.n.sons[0])
         and SameValue(a.n.sons[1], b.n.sons[1])
     end;
-    tyNone, tyAnyEnum: result := false;
+    tyNone: result := false;
+  end
+end;
+
+function equalOrAbstractOf(x, y: PType): bool;
+var
+  i: int;
+  a, b: PType;
+begin
+  if x = y then begin result := true; exit end;
+  if (x = nil) or (y = nil) then begin result := false; exit end;
+  a := skipTypes(x, {@set}[tyGenericInst]);
+  b := skipTypes(y, {@set}[tyGenericInst]);
+  assert(a <> nil);
+  assert(b <> nil);
+  if a.kind <> b.kind then begin 
+    if a.kind = tyAbstract then a := a.sons[0];
+    if a.kind <> b.kind then begin result := false; exit end
+  end;
+  case a.Kind of
+    tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCString, 
+    tyInt..tyFloat128: 
+      result := true;
+    tyEnum, tyForward, tyObject, tyAbstract:
+      result := (a.id = b.id);
+    tyTuple: 
+      result := sameTuple(a, b, true);
+    tyGenericInst:
+      result := equalOrAbstractOf(lastSon(a), lastSon(b));
+    tyGenericParam, tyGeneric, tySequence, tyOrdinal,
+    tyOpenArray, tySet, tyRef, tyPtr, tyVar, tyArrayConstr,
+    tyArray, tyProc: begin
+      if sonsLen(a) = sonsLen(b) then begin
+        result := true;
+        for i := 0 to sonsLen(a)-1 do begin
+          result := equalOrAbstractOf(a.sons[i], b.sons[i]);
+          if not result then exit
+        end;
+        if result and (a.kind = tyProc) then 
+          result := a.callConv = b.callConv
+      end
+      else
+        result := false;
+    end;
+    tyRange: begin
+      result := equalOrAbstractOf(a.sons[0], b.sons[0])
+        and SameValue(a.n.sons[0], b.n.sons[0])
+        and SameValue(a.n.sons[1], b.n.sons[1])
+    end;
+    tyNone: result := false;
   end
 end;
 
@@ -963,9 +1038,9 @@ begin
   // if we have already checked the type, return true, because we stop the
   // evaluation if something is wrong:
   if IntSetContainsOrIncl(marker, t.id) then exit;
-  case skipGeneric(t).kind of 
+  case skipTypes(t, abstractInst).kind of 
     tyVar: begin
-      case skipGeneric(t.sons[0]).kind of
+      case skipTypes(t.sons[0], abstractInst).kind of
         tyVar: result := false; // ``var var`` is always an invalid type:
         tyOpenArray: result := (kind = skParam) and 
                                 typeAllowedAux(marker, t.sons[0], kind);
@@ -985,9 +1060,11 @@ begin
     tyEmpty, tyNil: result := kind = skConst;
     tyString, tyBool, tyChar, tyEnum, tyInt..tyFloat128, tyCString, tyPointer: 
       result := true;
-    tyAnyEnum: result := kind = skParam;
-    tyGenericInst: result := typeAllowedAux(marker, lastSon(t), kind);
-    tyRange: result := skipGeneric(t.sons[0]).kind in 
+    tyOrdinal: result := kind = skParam;
+    tyGenericInst, tyAbstract: 
+      result := typeAllowedAux(marker, lastSon(t), kind);
+    tyRange: 
+      result := skipTypes(t.sons[0], abstractInst).kind in
                          [tyChar, tyEnum, tyInt..tyFloat128];
     tyOpenArray: 
       result := (kind = skParam) and typeAllowedAux(marker, t.sons[0], skVar);
@@ -1166,7 +1243,7 @@ begin
       if a < maxAlign then a := maxAlign;
       result := align(result, a);
     end;
-    tyGenericInst: begin
+    tyGenericInst, tyAbstract: begin
       result := computeSizeAux(lastSon(typ), a);
     end;
     else begin
diff --git a/nim/wordrecg.pas b/nim/wordrecg.pas
index 7957d354b..cd31a64e4 100644
--- a/nim/wordrecg.pas
+++ b/nim/wordrecg.pas
@@ -39,20 +39,20 @@ type
     //  i = i + 1
     //cog.out(idents)
     //]]]
-    wAddr, wAnd, wAs, wAsm, 
-    wBlock, wBreak, wCase, wCast, 
-    wConst, wContinue, wConverter, wDiscard, 
-    wDiv, wElif, wElse, wEnd, 
-    wEnum, wExcept, wException, wFinally, 
-    wFor, wFrom, wGeneric, wIf, 
-    wImplies, wImport, wIn, wInclude, 
-    wIs, wIsnot, wIterator, wLambda, 
-    wMacro, wMethod, wMod, wNil, 
-    wNot, wNotin, wObject, wOf, 
-    wOr, wOut, wProc, wPtr, 
-    wRaise, wRef, wReturn, wShl, 
-    wShr, wTemplate, wTry, wTuple, 
-    wType, wVar, wWhen, wWhere, 
+    wAbstract, wAddr, wAnd, wAs, 
+    wAsm, wBlock, wBreak, wCase, 
+    wCast, wConst, wContinue, wConverter, 
+    wDiscard, wDiv, wElif, wElse, 
+    wEnd, wEnum, wExcept, wException, 
+    wFinally, wFor, wFrom, wGeneric, 
+    wIf, wImplies, wImport, wIn, 
+    wInclude, wIs, wIsnot, wIterator, 
+    wLambda, wMacro, wMethod, wMod, 
+    wNil, wNot, wNotin, wObject, 
+    wOf, wOr, wOut, wProc, 
+    wPtr, wRaise, wRef, wReturn, 
+    wShl, wShr, wTemplate, wTry, 
+    wTuple, wType, wVar, wWhen, 
     wWhile, wWith, wWithout, wXor, 
     wYield, 
     //[[[end]]]
@@ -78,7 +78,7 @@ type
     wApp, wConsole, wGui, wPassc, wT, wPassl,
     wL, wListcmd, wGendoc, wGenmapping,
     wOs, wCpu, wGenerate, wG, wC, wCpp,
-    wYaml, wRun, wR, wVerbosity, wV, wHelp,
+    wBorrow, wRun, wR, wVerbosity, wV, wHelp,
     wH, wSymbolFiles, wFieldChecks, wX, wVersion, wAdvanced,
     wSkipcfg, wSkipProjCfg, wCc, wGenscript, wCheckPoint, wCheckPoints,
     wMaxErr, wExpr, wStmt, wTypeDesc,
@@ -113,20 +113,20 @@ const
     //[[[cog
     //cog.out(strings)
     //]]]
-    'addr', 'and', 'as', 'asm', 
-    'block', 'break', 'case', 'cast', 
-    'const', 'continue', 'converter', 'discard', 
-    'div', 'elif', 'else', 'end', 
-    'enum', 'except', 'exception', 'finally', 
-    'for', 'from', 'generic', 'if', 
-    'implies', 'import', 'in', 'include', 
-    'is', 'isnot', 'iterator', 'lambda', 
-    'macro', 'method', 'mod', 'nil', 
-    'not', 'notin', 'object', 'of', 
-    'or', 'out', 'proc', 'ptr', 
-    'raise', 'ref', 'return', 'shl', 
-    'shr', 'template', 'try', 'tuple', 
-    'type', 'var', 'when', 'where', 
+    'abstract', 'addr', 'and', 'as', 
+    'asm', 'block', 'break', 'case', 
+    'cast', 'const', 'continue', 'converter', 
+    'discard', 'div', 'elif', 'else', 
+    'end', 'enum', 'except', 'exception', 
+    'finally', 'for', 'from', 'generic', 
+    'if', 'implies', 'import', 'in', 
+    'include', 'is', 'isnot', 'iterator', 
+    'lambda', 'macro', 'method', 'mod', 
+    'nil', 'not', 'notin', 'object', 
+    'of', 'or', 'out', 'proc', 
+    'ptr', 'raise', 'ref', 'return', 
+    'shl', 'shr', 'template', 'try', 
+    'tuple', 'type', 'var', 'when', 
     'while', 'with', 'without', 'xor', 
     'yield', 
     //[[[end]]]
@@ -152,7 +152,7 @@ const
     'app', 'console', 'gui', 'passc', 't'+'', 'passl',
     'l'+'', 'listcmd', 'gendoc', 'genmapping',
     'os', 'cpu', 'generate', 'g'+'', 'c'+'', 'cpp',
-    'yaml', 'run', 'r'+'', 'verbosity', 'v'+'', 'help',
+    'borrow', 'run', 'r'+'', 'verbosity', 'v'+'', 'help',
     'h'+'', 'symbolfiles', 'fieldchecks', 'x'+'', 'version', 'advanced',
     'skipcfg', 'skipprojcfg', 'cc', 'genscript', 'checkpoint', 'checkpoints',
     'maxerr', 'expr', 'stmt', 'typedesc',