Index: branches/compiler/cSharp/ooasCompiler/doc/examples/AlarmSystem_manual_timeasparam_flags.ooas
===================================================================
--- branches/compiler/cSharp/ooasCompiler/doc/examples/AlarmSystem_manual_timeasparam_flags.ooas	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/doc/examples/AlarmSystem_manual_timeasparam_flags.ooas	(revision 3)
@@ -0,0 +1,211 @@
+types
+	TimeSteps = {Int0 = 0 , Int20 = 20, Int30 = 30, Int270 = 270} ;
+	Int = int[0..270] ;
+	SmallInt = int[0..3] ;
+	AlarmSystem = autocons system
+	|[
+		var
+			open : bool = true ;
+			locked : bool = false ;
+			armed : bool = false ;
+			soundAlarm : bool = false ;
+			flashAlarm : bool = false ;
+			blockingLevel : SmallInt = 0 ;
+			armedOnNow : bool = false ;
+			armedOnLater : bool = false ;
+			armedOff : bool = false ;
+			soundOn : bool = false ;
+			soundOffNow : bool = false ;
+			soundOffLater : bool = false ;
+			flashOn : bool = false ;
+			flashOffNow : bool = false ;
+			flashOffLater : bool = false  ;
+			silent : bool = false # true after alarms turned off
+		actions
+			ctr Close ( waittime : Int) =
+				requires not flashAlarm and not soundAlarm :
+					requires open and waittime = 0 and blockingLevel = 0 and locked and silent:
+						open := false ;
+						blockingLevel := 1 ;
+						armedOnNow := true ;
+						silent := false			
+
+					end []
+					requires open and waittime = 0 and blockingLevel = 0 and not locked and silent:
+						silent := false ;			
+						open := false 
+					end []
+					requires open and waittime = 0 and blockingLevel = 0 and locked and not silent:
+						open := false ;
+						blockingLevel := 1 ;
+						armedOnLater := true
+
+					end []
+					requires open and waittime = 0 and blockingLevel = 0 and not locked and not silent:
+						open := false 
+					end
+
+				end ;
+
+			ctr Open ( waittime : Int) =
+				requires true :
+					requires not open and waittime = 0 and blockingLevel = 0 and not armed :
+						open := true
+					end []
+					requires not open and waittime = 0 and blockingLevel = 0 and armed :
+						open := true ;
+						armed := false ;
+						blockingLevel := 3 ;
+						armedOff := true ;
+						soundOn := true ;
+						flashOn := true
+					end 
+				end ;
+
+#				requires not open and waittime = 0 and blockingLevel = 0 :
+#					open := true ;
+#					(requires not armed :
+#						skip
+#					end []
+#					requires armed :
+#						armed := false ;
+#						blockingLevel := 3 ;
+#						armedOff := true ;
+#						soundOn := true ;
+#						flashOn := true 
+#					end)
+#				end ;
+			ctr Unlock ( waittime : Int) =
+				requires true : 
+					requires locked and waittime = 0 and blockingLevel = 0 and not flashAlarm and soundAlarm:
+						locked := false ;
+						silent := false ;
+						soundOffLater := false ;
+						soundOffNow := true ;
+						blockingLevel := 1 
+					end []
+					requires locked and waittime = 0 and blockingLevel = 0 and flashAlarm and soundAlarm :
+						locked := false ;
+						flashOffNow := true ;
+						blockingLevel := 2 ;
+						silent := false ;
+						soundOffLater := false ;
+						soundOffNow := true
+
+					end []
+					requires locked and waittime = 0 and blockingLevel = 0 and not flashAlarm and not soundAlarm:
+						locked := false ;
+						silent := false ;
+						armedOff := true ;
+						blockingLevel := 1
+					end []
+					requires locked and waittime = 0 and blockingLevel = 0 and flashAlarm and not soundAlarm:
+						locked := false ;
+						flashOffNow := true ;
+						flashOffLater := false ;
+						blockingLevel := 1 ;
+						silent := false
+					end
+				end;
+				
+			ctr Lock ( waittime : Int) =
+				requires true :
+					requires not locked and waittime = 0 and blockingLevel = 0 and open :
+						locked := true
+					end []
+					requires not locked and waittime = 0 and blockingLevel = 0 and not open :
+						locked := true ;
+						blockingLevel := 1 ;
+						armedOnLater := true
+					end 
+				end ;
+			obs ArmedOn (waittime : Int) =
+				requires (armedOnNow or armedOnLater):
+					requires (waittime = 20 and armedOnLater) :
+						armedOnLater := false ;
+						blockingLevel := blockingLevel - 1 ;
+						armed := true
+					end
+					[] requires (waittime = 0 and armedOnNow) :
+						armedOnNow := false ;
+						blockingLevel := blockingLevel - 1 ;
+						armed := true
+					end
+				end ;
+			obs ArmedOff (waittime : Int) =
+				requires (waittime = 0 and armedOff) :
+					armedOff := false ;
+					blockingLevel := blockingLevel - 1 ;
+					armed := false
+				end ;
+			obs SoundOn (waittime : Int) =
+				requires true :
+					requires (waittime = 0 and soundOn and blockingLevel = 1) :
+						soundOn := false ;
+						blockingLevel := blockingLevel - 1 ;
+						soundAlarm := true ;
+						soundOffLater := true 
+					end []
+					requires (waittime = 0 and soundOn and blockingLevel <> 1) :
+						soundOn := false ;
+						blockingLevel := blockingLevel - 1 ;
+						soundAlarm := true
+					end 
+	
+				end ;
+			obs SoundOff (waittime : Int) =
+				requires (soundOffNow or soundOffLater) :
+					requires (waittime = 30 and soundOffLater) :
+						soundOffLater := false ;
+						flashOffLater := true ;
+						soundAlarm := false
+					end
+					[] requires (waittime = 0 and soundOffNow) :
+						soundOffNow := false ;
+						blockingLevel := blockingLevel - 1 ;
+						soundAlarm := false
+					end
+				end ;
+			obs FlashOn (waittime : Int) =
+				requires true :
+					requires (waittime = 0 and flashOn and blockingLevel = 1) :
+						flashOn := false ;
+						blockingLevel := blockingLevel - 1 ;
+						flashAlarm := true ;
+						soundOffLater := true 
+					end []
+					requires (waittime = 0 and flashOn and blockingLevel <> 1) :
+						flashOn := false ;
+						blockingLevel := blockingLevel - 1 ;
+						flashAlarm := true
+				end 
+				end ;
+			obs FlashOff (waittime : Int) =
+				requires (flashOffNow or flashOffLater) :
+					requires (waittime = 270 and flashOffLater) :
+						flashOffLater := false ;
+#						blockingLevel := blockingLevel - 1 ;
+						flashAlarm := false ;
+						silent := true
+					end
+					[] requires (waittime = 0 and flashOffNow) :
+						flashOffNow := false ;
+						blockingLevel := blockingLevel - 1 ;
+						flashAlarm := false
+					end
+				end
+	do
+		var A : TimeSteps : Close (A) [] 
+		var B : TimeSteps : Open (B) []
+		var C : TimeSteps : Lock (C) []
+		var D : TimeSteps : Unlock (D) []
+		var E : TimeSteps : ArmedOn (E) []        
+		var F : TimeSteps : ArmedOff (F) []        
+		var G : TimeSteps : SoundOn (G) []        
+		var H : TimeSteps : SoundOff (H) []   
+    		var I : TimeSteps : FlashOn (I) []        
+		var J : TimeSteps : FlashOff (J)    
+	od
+	]|
+system
+	AlarmSystem
Index: branches/compiler/cSharp/ooasCompiler/doc/examples/Cast.ooas
===================================================================
--- branches/compiler/cSharp/ooasCompiler/doc/examples/Cast.ooas	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/doc/examples/Cast.ooas	(revision 3)
@@ -0,0 +1,23 @@
+types
+  Class1 = autocons system
+  |[
+  var
+	O2 : Class2 = new (Class2);
+	O3 : Class3 = new (Class3);
+	OL : list[2] of Class2 = [nil]
+  actions
+	ctr fill = requires true :
+		OL := [O2]^[O3 as Class2]
+		end
+  do
+        fill
+  od
+  ]| ;
+  Class2 = system
+  |[
+  ]| ;
+  Class3 = system (Class2)
+  |[
+  ]| 
+system
+        Class1 
Index: branches/compiler/cSharp/ooasCompiler/doc/examples/HelloWorld.ooas
===================================================================
--- branches/compiler/cSharp/ooasCompiler/doc/examples/HelloWorld.ooas	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/doc/examples/HelloWorld.ooas	(revision 3)
@@ -0,0 +1,15 @@
+types
+  Greeter = autocons system
+  |[
+  var
+        done : bool = false
+  actions
+        obs HelloWorld = requires done = false :
+                done := true
+                end
+  do
+        HelloWorld
+  od
+  ]|
+system
+        Greeter
Index: branches/compiler/cSharp/ooasCompiler/doc/examples/Objects.ooas
===================================================================
--- branches/compiler/cSharp/ooasCompiler/doc/examples/Objects.ooas	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/doc/examples/Objects.ooas	(revision 3)
@@ -0,0 +1,24 @@
+types
+  RootClass = autocons system
+  |[
+  var
+        myOtherClassObject : OtherClass = new(OtherClass,"OtherClassObject") ;
+        initialized : bool = false
+  actions
+        obs init = requires initialized = false : initialized := true end
+  do
+        init ()
+  od
+  ]| ;
+  OtherClass = system
+  |[
+  var
+        initialized : bool = false
+  actions
+        obs init = requires initialized = false : initialized := true end
+  do
+        init ()
+  od
+  ]|
+system
+        RootClass [] OtherClass
Index: branches/compiler/cSharp/ooasCompiler/doc/examples/Primes.ooas
===================================================================
--- branches/compiler/cSharp/ooasCompiler/doc/examples/Primes.ooas	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/doc/examples/Primes.ooas	(revision 3)
@@ -0,0 +1,26 @@
+types
+  MyInt = int [2..100];
+  LengthInt = int [0..40];
+  Primes = autocons system
+  |[
+  var
+        initialized : bool = false ;
+        primes : list [ 40 ] of MyInt = [3]
+  actions
+    obs init = requires initialized = false :
+      primes := [ x | var x: MyInt & (forall tmp : MyInt : 
+            (tmp < x => (x mod tmp <> 0 )))  ] ;
+      initialized := true end;
+
+    obs Prime(a: MyInt) =
+      requires (exists i : LengthInt : (primes[i] = a)) :
+        skip
+      end
+
+  do
+        init() // var A : MyInt : Prime(A)
+  od
+  ]|
+system
+        Primes
+
Index: branches/compiler/cSharp/ooasCompiler/doc/examples/Self.ooas
===================================================================
--- branches/compiler/cSharp/ooasCompiler/doc/examples/Self.ooas	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/doc/examples/Self.ooas	(revision 3)
@@ -0,0 +1,30 @@
+types
+  Class1 = autocons system
+  |[
+  var
+	O2 : Class2 = new (Class2);
+	flag : bool = false
+  methods
+	doSomething =
+		flag := true
+	end
+  actions
+	ctr init = requires true :
+		O2.init(self)
+		end
+  do
+        init
+  od
+  ]| ;
+  Class2 = system
+  |[
+  var
+	O1 : Class1 = nil
+  methods 
+	init (object : Class1) = requires (object <> nil) :
+		O1 := object
+		end
+	end
+  ]| 
+system
+        Class1 [] Class2 
Index: branches/compiler/cSharp/ooasCompiler/doc/examples/Stack.ooas
===================================================================
--- branches/compiler/cSharp/ooasCompiler/doc/examples/Stack.ooas	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/doc/examples/Stack.ooas	(revision 3)
@@ -0,0 +1,24 @@
+types
+  SmallInt = int [0..3];
+  Stack = autocons system
+  |[
+  var
+        my_stack : list [10] of SmallInt = [0]
+  actions
+        obs top (a : SmallInt) = requires (a = hd my_stack) :
+                skip
+                end ;
+        obs pop = requires (len my_stack > 0) :
+                my_stack := tl my_stack
+                end;
+        obs push (a : SmallInt) = requires len my_stack < 10 :
+                my_stack := [a] ^ my_stack
+                end
+
+  do
+        var A : SmallInt : push(A) []  pop() [] var B : SmallInt : top(B)
+  od
+  ]|
+system
+  Stack
+
Index: branches/compiler/cSharp/ooasCompiler/doc/examples/Sum.ooas
===================================================================
--- branches/compiler/cSharp/ooasCompiler/doc/examples/Sum.ooas	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/doc/examples/Sum.ooas	(revision 3)
@@ -0,0 +1,31 @@
+types
+  MyInt = int [0..42];
+  SmallInt = int [0..3];
+  MyTuple = (MyInt, SmallInt);
+  Sum = autocons system
+  |[
+  var
+        my_list : list [4] of SmallInt = [5,5,5,5]
+  methods
+    add(a: MyInt, b: SmallInt) : MyInt =
+        requires true :
+          result := a + b
+        end
+    end ;
+    sum(Xs : list [4] of SmallInt) : MyInt =
+        requires true  :
+          result := add :: (0) :>: (Xs)
+        end
+    end
+  actions
+        obs Sum(a: MyInt) =
+                requires a = sum(my_list) :
+                        skip
+                end
+  do
+        var A : MyInt : Sum(A)
+  od
+  ]|
+system
+        Sum
+
Index: branches/compiler/cSharp/ooasCompiler/doc/examples/Tuple.ooas
===================================================================
--- branches/compiler/cSharp/ooasCompiler/doc/examples/Tuple.ooas	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/doc/examples/Tuple.ooas	(revision 3)
@@ -0,0 +1,21 @@
+types
+  MyInt = int [0..42] ;
+  MyTuple = (MyInt, MyInt) ;
+  TupleDemo = autocons system
+  |[
+  var
+	theTuple : MyTuple = MyTuple(1,1) 
+  actions
+	ctr change1 = requires theTuple = MyTuple(1,1) :
+		theTuple := MyTuple(1,2) 
+		end ; 
+        ctr change2 = requires theTuple[1] = 2 :
+		theTuple := MyTuple(1,3)
+                end 
+  do
+        change1 [] change2 
+  od
+  ]|
+system
+	TupleDemo
+     
Index: branches/compiler/cSharp/ooasCompiler/doc/figures/SM_AlarmSystem.pdf
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: branches/compiler/cSharp/ooasCompiler/doc/figures/SM_AlarmSystem.pdf
===================================================================
--- branches/compiler/cSharp/ooasCompiler/doc/figures/SM_AlarmSystem.pdf	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/doc/figures/SM_AlarmSystem.pdf	(revision 3)

Property changes on: branches/compiler/cSharp/ooasCompiler/doc/figures/SM_AlarmSystem.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: branches/compiler/cSharp/ooasCompiler/doc/figures/out.png
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: branches/compiler/cSharp/ooasCompiler/doc/figures/out.png
===================================================================
--- branches/compiler/cSharp/ooasCompiler/doc/figures/out.png	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/doc/figures/out.png	(revision 3)

Property changes on: branches/compiler/cSharp/ooasCompiler/doc/figures/out.png
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: branches/compiler/cSharp/ooasCompiler/doc/manual.pdf
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: branches/compiler/cSharp/ooasCompiler/doc/manual.pdf
===================================================================
--- branches/compiler/cSharp/ooasCompiler/doc/manual.pdf	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/doc/manual.pdf	(revision 3)

Property changes on: branches/compiler/cSharp/ooasCompiler/doc/manual.pdf
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: branches/compiler/cSharp/ooasCompiler/doc/manual.tex
===================================================================
--- branches/compiler/cSharp/ooasCompiler/doc/manual.tex	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/doc/manual.tex	(revision 3)
@@ -0,0 +1,1414 @@
+\documentclass[11pt]{scrartcl}
+
+\usepackage{cancel}
+\usepackage{listings}
+\usepackage{xspace}
+\usepackage{longtable}
+\usepackage{graphicx}
+\usepackage{url}
+
+
+\newcommand{\doodblock}{{\bf do} {\bf od}-block \xspace}
+\newcommand{\doodblocks}{{\bf do} {\bf od}-blocks \xspace}
+
+
+\lstdefinelanguage{ooa} {
+  morekeywords={autocons, types, methods, do, obs, action, end, ctr, requires, od, true, and,
+     signal, after, false, actions, var, |[, ]|, [], public, of, len,
+     //, hd, tl, system},
+   sensitive=true,
+   morecomment=[s]{/*}{*/},
+   showspaces=false,
+   showstringspaces=false,
+   numbers=left,
+   numbersep=5pt,
+   numberstyle=\tiny,
+   tabsize=2,
+   escapeinside={@}{@},
+   framexleftmargin=9pt,
+  }
+
+
+\begin{document}
+
+
+
+
+
+
+\begin{titlepage}
+\begin{center}
+
+\vspace*{15mm}
+
+{\Large TECHNICAL REPORT}
+
+\vspace{10mm}
+
+{\large IST-MBT-2012-01}
+
+\vspace{15mm}
+
+{\huge \bf The Argos Manual}
+
+\vspace{5mm}
+
+{\Large for Argos version: 0.39}
+
+\vspace{15mm}
+
+{\Large Stefan Tiran}
+
+\vspace{5mm}
+
+{\large stiran@ist.tugraz.at}
+
+\vspace{15mm}
+
+{\large March 2012} % 13.03.2012
+
+\vspace{10mm}
+
+{\large
+Institute for Software Technology (IST)\\
+Graz University of Technology\\
+A-8010 Graz, Austria\\}
+
+\end{center}
+\end{titlepage}
+
+
+
+
+
+%\title{The Argos Manual}
+
+%\author{Stefan Tiran}
+
+%\subtitle{for Argos version: 0.39}
+
+%\maketitle
+\newpage
+\tableofcontents
+\listoffigures
+
+
+\section{Introduction}
+
+Argos is a compiler for Object-Oriented Action Systems (OOAS). It has been developed
+by Willibald Krenn from Graz University of Technology within the MOGENTES project.
+
+Its main target is producing Action Systems in the proprietary format that \emph{Ulysses}
+can process. \emph{Ulysses} is an ioco-checker written by Harald Brandl also within the
+MOGENTES project.
+
+\section{How To Run Argos}
+
+Argos is a .NET based command line program. To run it you need either
+the .NET Framework or mono (\url{http://www.mono-project.com}).
+
+\subsection{Program Invocation}
+
+Since Argos is a command line tool you need to open a command line prompt
+(using Windows) resp. a shell (using a UNIX-like system).
+
+When using Windows change to the Argos directory and simply run argos.exe:
+
+\texttt{
+c:\textbackslash Argos \textbackslash > argos}
+
+When using a UNIX-like system run mono with argos.exe as parameter:
+
+\texttt{
+\$ mono argos.exe}
+
+In both cases one should now see this welcome screen:
+
+\begin{verbatim}
+          >> Mogentes OO-Action System Parser <<
+
+          Version: 0.39 (16471)
+  Grammar-Version: 0.06
+
+Usage:    argos [options] <oo-actionsystem-file>
+Options:
+     -o<name>   ... write output to file <name> (overwrites!)
+     -n<name>   ... use namespace <name> (default: as)
+     -d<depth>  ... set max. search depth (default: 35)
+     -q         ... "quiet" mode: doesn't print Warnings to console
+
+     -a         ... create pseudo-action system code
+     -p         ... create prolog code
+     -c         ... create CADP implicit LTS
+
+\end{verbatim}
+
+\subsection{Options and Arguments}
+
+As can be seen in the welcome screen for translating Action Systems the
+last parameter has to be the OOAS-File you want to convert, every other
+options has to come before.
+
+If no other option is given, Argos will translate the given OOAS-File to
+C\#-Pseudo-Code and print it out on the screen. Since this most probably
+won't be something you will find extremely useful, you should at least
+specify an output-file and the desired language.
+
+For specifying the output-file use option \texttt{-o} followed by the
+file name resp. the relative path of the file you want to create. There
+should be NO space between \texttt{-o} and the file name!
+
+For specifying the language include option \texttt{-c} for creating
+C-Code for the CADP-Toolbox resp. option \texttt{-p} for creating
+Prolog-Code for use with the Ulysses tool.
+
+When creating Prolog-Code the following options are important:
+\begin{itemize}
+\item[-n] With this option one can specify the namespace within the Prolog-File;
+	the only meaningful use of this option is \texttt{-nasm} for letting
+	the Ulysses tool know, that this file represents the mutant rather
+	then the original file.
+\item[-d] With this option one can specify the max. depth, to which the Ulysses
+	tool will search for differences. Please note that this option has
+	to be followed by a number WITHOUT a space before! The default value
+	is 35, so leaving out this option is equivalent to writing
+	\texttt{-d35}.
+
+\subsection{Examples}
+
+To illustrate the use of the options, we hereby provide the following examples:
+
+\begin{itemize}
+\item Translate an original OOAS specification \texttt{original.ooas} to a Prolog
+	file \texttt{original.pl} for the Ulysses tool with max. search depth
+	42:
+	\begin{verbatim} argos.exe -p -d42 -ooriginal.pl original.ooas \end{verbatim}
+\item Translate a mutated OOAS specification \texttt{mutant.ooas} to a Prolog
+	file \texttt{mutant.pl} for the Ulysses tool with max. search depth
+	42:
+	\begin{verbatim} argos.exe -p -d42 -nasm -omutant.pl mutant.ooas \end{verbatim}
+\item Translate OOAS specification \texttt{original.ooas} to a C file 
+	\texttt{original.c} for the use with the CADP toolbox:
+	\begin{verbatim} argos.exe -c -ooriginal.c original.ooas \end{verbatim}
+	
+
+\end{itemize}
+
+\end{itemize} 
+
+\section{OOAS Language}
+
+The Argos tool will only work if the given file is well formed according
+to the language that is described in this section. The language is based
+on the language proposed in \cite{Bonsangue1998} but only a subset of features
+is actually implemented.
+
+\subsection{Base structure}
+
+To illustrate the base structure of an OOAS file let us consider the simple
+Hello World program in Figure \ref{HelloWorld}.
+
+\begin{figure}[h]
+ \begin{lstlisting}[language=ooa,linewidth=\textwidth,breaklines,basicstyle=\scriptsize]
+types
+  Greeter = autocons system
+  |[
+  var
+        done : bool = false
+  actions
+        obs HelloWorld = requires done = false :
+                done := true
+                end
+  do
+        HelloWorld
+  od
+  ]|
+system
+        Greeter
+
+ \end{lstlisting}
+\caption{HelloWorld}
+\label{HelloWorld}
+\end{figure}
+
+Every OOAS consists of two different regions: The type definition block and
+the system assembling block. In the HelloWorld system the type definition block
+consists of Lines 1 - 13 and the system assembling consists of Lines 14 and 15.
+
+Let us now discuss the system Line by Line:
+Line 1 just consists of the keyword \texttt{types} stating that here begins
+the type definition block.
+In Line 2 a class called \texttt{Greeter} is defined. The keyword
+\texttt{autocons} states that one instance of the class will automatically
+be created at system start. This instance is called the ``root object''.
+The symbols in Line 3 and 13 state the begin and the end of the class
+definition.
+In Lines 4 and 5 there is  a variable definition
+block. Even though this block is not formally necessary for Argos to compile
+a file, Argos will not create a valid prolog file if this block is missing.
+In Lines 6 - 9 there is the action block consisting of the action
+\texttt{HelloWorld}. The keyword \texttt{obs} states that this action is
+\emph{observable} rather then \emph{controllable} (keyword: \texttt{ctr}) or
+internal (no keyword).
+The keyword \texttt{requires} states the beginning of the guard, which enables
+the action.
+The body of this action consists of Lines 8 and 9. Line 8 contains an
+assignment, the keyword \texttt{end} in Line 9 marks the end of the action.
+Lines 10 - 12 contains the so-called \doodblock. The \doodblock is
+described in Section \ref{dood}.
+
+As already mentioned, Lines 14 + 15 contain the system assembling block. In this
+block the system is composed of its classes. Since this example system only
+contains of one class, the block is quite simple and needs no further
+explanation.
+
+\subsection{The Type Definition Block}
+
+The type definition block has two purposes: As we have already seen it can be
+used for defining the classes of which the system consists of. However it
+can also be used for creating named types which is similar to the use of
+\texttt{type-def} in C.
+
+The latter use is quite important as OOAS has a very strict typing system.
+For example if you want to define a variable as integer, you also have to
+define the range of the values. This is due to the fact that too wide ranges
+can lead to enormous efficiency problems when simulating the model.
+
+\subsubsection{Defining Integer Types}
+
+Integer types can be defined by the lower and upper range.
+
+Consider you want to define a type \texttt{MyInt} that can contain values
+between 0 and 31, then you can write
+\begin{verbatim}
+  MyInt = int [0..31];
+\end{verbatim}
+
+Please note that the semicolon has to be placed if and only if this is not
+the last definition.
+
+\subsubsection{Defining Enum Types}
+
+Enums can be defined by enumerating the possible values and optionally assigning them
+integer values. If integer values are explicitly assigned, enum types can be casted to
+integer types.
+
+Consider you want to define an enum type \texttt{Color} that can contain the
+values \texttt{red}, \texttt{green}, \texttt{blue}, \texttt{yellow} and \texttt{black},
+then you can write:
+\begin{verbatim}
+  Color = {red, green, blue, yellow, black};
+\end{verbatim}
+
+The possibility to explicitly assign integer values is especially useful when
+dealing with equivalent classes of integers. Consider you need an integer type
+that can only contain small number of different values but these values define
+a range with "holes" rather then a complete one.
+
+So in case you need a type that can hold the values 1, 42 and 1337 you can write
+\begin{verbatim}
+    CoolValueSet = {CoolValue1 = 1, CoolValue2 = 42, CoolValue3 = 1337};
+\end{verbatim}
+
+\subsubsection{Defining Complex Types (Lists, Tuples)}
+
+Additional to the former so-called simple types the OOAS language also
+supports so-called complex types. These are: lists and tuples.
+
+A list is defined by the number and the type of its elements.
+
+An example for the former variant would be:
+\begin{verbatim}
+  MyList = list [42] of char;
+\end{verbatim}
+
+A tuple is defined by the types of its elements. Unlike a list the types can
+differ among the different elements.
+
+An example would be:
+\begin{verbatim}
+  MyTuple = (MyInt, SmallInt);
+\end{verbatim}
+
+Even though maps and qualitative reasoning types would be specified by the
+OOAS language, Argos does not support them yet.
+
+\subsubsection{Defining Classes}
+
+In the OOAS language the definition of a class (ooActionSystem) does not differ
+from the definition of any other type.
+
+\subsection{Structure of Classes}
+
+\subsubsection{Inheritance}
+
+As common in Object-Oriented languages, classes can be derived from other classes
+and inherit their behavior.
+A sample class \texttt{Desc} inheriting from a class \texttt{base} could look like this:
+
+\begin{verbatim}
+  Desc = system (base)
+  |[
+  ]|
+
+\end{verbatim}
+
+\subsubsection{Defining Variables (Attributes)}
+\label{Variables}
+
+Variables store the information of the state of an object. An alternative name
+of variables often used in error messages is ``attributes''. Variables can be
+static and have to be initialized with a valid value. For objects there is a
+predefined object \texttt{nil}. There is also a self-reference called
+\texttt{self}.
+
+The definition of a variable can look like this:
+\begin{verbatim}
+        done : bool = false;
+\end{verbatim}
+
+Please note that the semicolon has to be placed if and only if this is not
+the last definition.
+
+\subsubsection{Creating Objects}
+
+The only place where an object can be created is in the variable definition block.
+Line 5 in Figure \ref{object} demonstrates how a variable with the name
+\texttt{myOtherClassObject} can be initialized with an object with the name
+\texttt{OtherClassObject} of a class \texttt{OtherClass}.
+
+For details on the System Assembling Block (Lines 23 and 24) see Section
+\ref{SAB}.
+
+\begin{figure}[h]
+ \begin{lstlisting}[language=ooa,linewidth=\textwidth,breaklines,basicstyle=\scriptsize]
+types
+  RootClass = autocons system
+  |[
+  var
+        myOtherClassObject : OtherClass = new(OtherClass,"OtherClassObject") ;
+        initialized : bool = false
+  actions
+        obs init = requires initialized = false : initialized := true end
+  do
+        init ()
+  od
+  ]| ;
+  OtherClass = system
+  |[
+  var
+        initialized : bool = false
+  actions
+        obs init = requires initialized = false : initialized := true end
+  do
+        init ()
+  od
+  ]|
+system
+        RootClass [] OtherClass
+ \end{lstlisting}
+\caption{Creating an object}
+\label{object}
+\end{figure}
+
+\subsubsection{Defining Methods}
+
+Methods can be used for defining subroutines. Methods can have parameters,
+variables and a return value. Methods can be called from actions and
+from other methods, but not recursively - neither directly nor indirectly.
+
+The body of a method isn't any different from the body of an action
+and therefore described in Section \ref{Actions}.
+
+A sample method, that returns the bigger of two values could look like this:
+
+\begin{verbatim}
+  maxValue(a : MyInt, b : MyInt) : MyInt =
+    result := if (a > b) then a else b end
+  end;
+\end{verbatim}
+
+Returning a value is done by assigning it to the variable result.
+For a list of possible expressions we refer to Section \ref{Expressions}.
+
+One important aspect of methods is their pureness. A method is pure
+iff there is no assignment to a variable other than \texttt{result}.
+This property is checked on compile
+time. Only if a method is pure it can be used in a guard or in a list
+comprehension.
+
+\subsubsection{Defining Actions}
+\label{Actions}
+
+Named actions consist of an optional parameter list, a variable definition
+block and a body but they lack a return value. Named actions can only be
+called in the so-called \doodblock.
+
+A named action can be controllable (keyword \texttt{ctr}),
+observable (keyword \texttt{obs}) or internal (no keyword). 
+
+The definition of local variables does not differ from any
+other variable definition so we refer to Section \ref{Variables}.
+
+The body of a named action can consist of one or more basic actions.
+Every action has a guard which ``enables'' it. The general form of a guard
+is \texttt{requires p : $S_1$ end} where p is the condition
+and $S_1$ is the action. The condition can be any expression that doesn't
+involve the calling of a non-pure method or a non-pure assignment.
+
+For further details about expressions see Section \ref{Expressions}!
+
+Basic actions can be the built-in action \texttt{skip},
+single or multiple assignment or a sequential composition of two other actions.
+For details on the composition we refer to Section \ref{Composition}.
+
+The built-in action \texttt{skip} doesn't do anything at all.
+Sometimes this is called \emph{identity assignment}.
+
+Single assignment has the simple form \texttt{v := e} where
+v is a variable and e is an expression.
+
+However you can also assign multiple expressions to multiple
+variables by separating them with commas.
+
+So if \texttt{done} and \texttt{multi} are both variables of
+type \texttt{bool}, then you can write:
+
+\begin{verbatim}
+                done, multi := true, true
+\end{verbatim}
+
+\subsection{Composition}
+\label{Composition}
+\subsubsection{Sequential Composition}
+
+The easiest way of composing two actions is the sequential
+composition. It has the general form \texttt{A ; B} where
+A and B are both actions and has the meaning that iff
+A and B are \emph{enabled}, first action A is executed and then
+action B is executed. Note that it is not necessary for B
+to be enabled before A. It is also possible that B becomes
+enabled because of A.
+
+Please note that despite of the
+apparent resemblance with the semicolon as marker of the
+end of a line in many imperative programming languages
+there are two very important differences:
+
+The first difference is that since it is a composition operator,
+there must not be a semicolon after the last action. This
+difference seems to be more on a syntactical level, but should
+also warn about the other very important difference:
+
+The second difference is that since actions have guards, no
+action of a sequence block is executed, if a single action is
+not enabled. This also means that an action can hinder actions
+to be executed, which were called \emph{before}!
+
+\subsubsection{Non-deterministic Choice}
+
+The counterpart of the ``sequential composition'' is the so
+called ``non-deterministic choice''.
+
+The general form of a non-deterministic choice is \texttt{ A [] B }
+where A and B are both actions and the meaning is that either
+A or B is executed. However an action can only be chosen if it
+is enabled. According to the theory of action systems an action has to be
+chosen if it is aborting. However there is no abort feature implemented yet.
+
+\subsubsection{Prioritizing Composition}
+
+The ``prioritizing composition'' is rather an abbreviation
+than an actual new type of composition.
+
+The general form is \texttt{ A // B } and it means that if A
+is enabled, it is chosen and otherwise B is chosen.
+
+\subsection{Expressions}
+\label{Expressions}
+
+Expressions can be evaluated and their values can be assigned to variables.
+
+\subsubsection{Conditional Assignment}
+
+Conditional Assignments are expressions. They can not be used for branching
+the control sequence. Branching the control sequence has to be done by using
+guards and non-deterministic choice.
+
+A conditional assignment can look like this:
+\begin{verbatim}
+  c := if (a > b) then a else b end
+\end{verbatim}
+
+\subsubsection{Fold}
+
+For the purpose of iterating through a list in OOAS \emph{fold} is used.
+\emph{Fold} is a higher-order function well known from the functional
+programming paradigm.
+
+In the OOAS language both \emph{right fold} and \emph{left fold} are
+defined. The symbol for the former is \texttt{:>:} whereas the symbol
+for the latter is \texttt{:<:}. However in Argos only \emph{right fold} is
+implemented.
+
+The general form of a fold expression is \texttt{method :: (init\_expression) :>:  (list\_\\expression)}
+where \texttt{method} is the name of the method, \texttt{init\_expression} is the value for the last
+parameter of the method for the first call. For any other call the result of the former call is used instead.
+Finally \texttt{list\_expression} is the expression that evaluates to the list to be iterated.
+
+
+Figure \ref{Sum} shows how to define a method \texttt{Sum}
+using a method \texttt{Add} and the \emph{fold} operator.
+
+\begin{figure}[h]
+ \begin{lstlisting}[language=ooa,linewidth=\textwidth,breaklines,basicstyle=\scriptsize]
+types
+  MyInt = int [0..42];
+  SmallInt = int [0..3];
+  MyTuple = (MyInt, SmallInt);
+  Sum = autocons system
+  |[
+  var
+        my_list : list [4] of SmallInt = [5,5,5,5]
+  methods
+    add(a: MyInt, b: SmallInt) : MyInt =
+        requires true :
+          result := a + b
+        end
+    end ;
+    sum(Xs : list [4] of SmallInt) : MyInt =
+        requires true  :
+          result := add :: (0) :>: (Xs)
+        end
+    end
+  actions
+        obs Sum(a: MyInt) =
+                requires a = sum(my_list) :
+                        skip
+                end
+  do
+        var A : MyInt : Sum(A)
+  od
+  ]|
+system
+        Sum
+ \end{lstlisting}
+\caption{Defining sum of all list elements using the fold meta function}
+\label{Sum}
+\end{figure}
+
+\subsubsection{Quantifier Expressions}
+
+The OOAS language allows to use the quantifiers \texttt{forall} and
+\texttt{exists}. The resulting expressions will evaluate to Boolean
+values. The general form is \texttt{(quantifier : Type  : (logical sentence))}.
+
+For example an existential quantification can look like this:
+\texttt{(exists i : LengthInt : (primes[i] = a))}.
+
+
+\subsubsection{List Comprehension}
+
+The OOAS language allows to construct new list expressions based on existing lists
+by using the set-builder notation. These expressions can be assigned to list
+variables at any time after the initialization, but not in the declaration.
+
+The general form of a list comprehension is:
+
+\texttt{list := [x | var x : Type \& (condition)]}, where \texttt{Type} is the type
+of the list elements and \texttt{condition} is a logical sentence which determines
+whether a value should be inserted to the list.
+
+The example in Figure \ref{Prime} illustrates both \emph{Quantifier Expressions}
+and \emph{List Comprehension} by computing prime numbers.
+
+\begin{figure}[h]
+ \begin{lstlisting}[language=ooa,linewidth=\textwidth,breaklines,basicstyle=\scriptsize]
+types
+  MyInt = int [2..100];
+  LengthInt = int [0..40];
+  Primes = autocons system
+  |[
+  var
+        initialized : bool = false ;
+        primes : list [ 40 ] of MyInt = [3]
+  actions
+    obs init = requires initialized = false :
+      primes := [ x | var x: MyInt & (forall tmp : MyInt : 
+            (tmp < x => (x mod tmp <> 0 )))  ] ;
+      initialized := true end;
+
+    obs Prime(a: MyInt) =
+      requires (exists i : LengthInt : (primes[i] = a)) :
+        skip
+      end
+
+  do
+        init() // var A : MyInt : Prime(A)
+  od
+  ]|
+system
+        Primes
+ \end{lstlisting}
+\caption{Prime number calculation}
+\label{Prime}
+\end{figure}
+
+\subsubsection{Tuple Expressions}
+
+The general form of an expression that evaluates to a tuple is:
+\begin{verbatim}
+	TupleType(v_1,...,v_n)
+\end{verbatim}
+where TupleType is the type of the tuple and v\_1,...,v\_n are the values.
+
+An example for using Tuples can be found in Figure \ref{Tuple}
+\begin{figure}[h]
+ \begin{lstlisting}[language=ooa,linewidth=\textwidth,breaklines,basicstyle=\scriptsize]
+types
+  MyInt = int [0..42] ;
+  MyTuple = (MyInt, MyInt) ;
+  TupleDemo = autocons system
+  |[
+  var
+        theTuple : MyTuple = MyTuple(1,1)
+  actions
+        ctr change1 = requires theTuple = MyTuple(1,1) :
+                theTuple := MyTuple(1,2)
+                end ;
+        ctr change2 = requires theTuple[1] = 2 :
+                theTuple := MyTuple(1,3)
+                end
+  do
+        change1 [] change2
+  od
+  ]|
+system
+        TupleDemo
+
+\end{lstlisting}
+\caption{Tuple Example}
+\label{Tuple}
+\end{figure}
+
+
+\subsubsection{Access Expressions}
+
+\emph{Access Expression} is the general term for the access of elements
+in a list or tuple, call of method or access to an attribute of an object.
+
+Accessing elements of a list is done by using the index operator \texttt{[]}
+well known from accessing arrays in imperative languages like C.
+The index starts with 0.
+
+The index operator \texttt{[]} can also be used to access a specific element of
+a tuple. This feature is illustrated in the guard of action \texttt{change2} in
+Figure \ref{Tuple}. However this feature is not implemented in the left hand
+side of an assignment, e. g. it is not possible to write \texttt{theTuple[0] := 1}.
+
+\subsubsection{Cast Expressions}
+
+When dealing with a class hierarchy it is possibly to use an object of a
+sub class instead of an object of its super class. This is called \emph{upcast}
+and done implicitly in most contexts. However, when concatenating two
+lists it has to be done explicitly using the operator \texttt{as} as illustrated
+in Line 10 in Figure \ref{Cast}.
+
+\begin{figure}[h]
+ \begin{lstlisting}[language=ooa,linewidth=\textwidth,breaklines,basicstyle=\scriptsize]
+types
+  Class1 = autocons system
+  |[
+  var
+        O2 : Class2 = new (Class2);
+        O3 : Class3 = new (Class3);
+        OL : list[2] of Class2 = [nil]
+  actions
+        ctr fill = requires true :
+                OL := [O2]^[O3 as Class2]
+                end
+  do
+        fill
+  od
+  ]| ;
+  Class2 = system
+  |[
+  ]| ;
+  Class3 = system (Class2)
+  |[
+  ]|
+system
+        Class1
+\end{lstlisting}
+\caption{Cast Example}
+\label{Cast}
+\end{figure}
+
+
+\subsection{Operators}
+
+\subsubsection{Numeric Operators}
+
+The numeric operators are \texttt{+} for adding two numbers of an integer or
+float type, \texttt{-} for subtracting, \texttt{*} for multiplying. The operator
+for the division of two numbers of a float type is \texttt{/}. For the division
+of two numbers of an integer type there are operators \texttt{div} for the
+quotient and \texttt{mod} for the remainder.
+
+\subsubsection{Logical Operators} 
+
+The logical operators are inspired by VDM and written \texttt{and} for logical
+and, \texttt{or} for logical or, \texttt{not} for negation, \texttt{=>} for
+implication, and \texttt{<=>} for bi-implication.
+
+\subsubsection{Comparison Operators}
+
+For comparing two values of the same type there are \texttt{=} for equality
+
+and \texttt{<>} for inequality.
+
+Values of integer and float types can also be compared with \texttt{>} for
+greater, \texttt{>=} for greater or equal, \texttt{<} for less, and \texttt{<=}
+for less or equal.
+
+\subsubsection{List Operators (Head, Tail, Length, Concatenation)}
+
+The OOAS language provides several basic list operators that make it
+easy to use lists.
+
+The first operator is \texttt{hd} which is short for \emph{head}. This
+operator returns the first element of a list. Therefore if \texttt{my\_list}
+is a list, then \texttt{hd my\_list} is equivalent to \texttt{my\_list[0]}.
+
+The counterpart to \emph{head} is \emph{tail}, which returns the list without
+the first element. In OOAS the operator token is \texttt{tl}. So if you want
+to remove the first element from a list \texttt{my\_stack} you can write
+\texttt{my\_stack := tl my\_stack}.
+
+The next important operation is determining how many elements are currently
+in a list, which is the so-called \emph{length} of a list. In OOAS this
+operator is written \texttt{len}. For example if an action should only be
+enabled if there are less than 10 elements in the list \texttt{my\_stack} you
+can write \texttt{requires len my\_stack < 10}.
+
+The last operation is creating a list that contains all the elements of two
+given lists, which is called \emph{concatenation}. The operator is written
+\texttt{\^}. If for instance you want to append an element \texttt{a} to
+a list \texttt{my\_stack}, you can write
+
+\begin{verbatim}
+my_stack := [a] ^ my_stack
+\end{verbatim}
+
+The example in Figure \ref{Stack} illustrates how these operators can be used
+to build a stack.
+
+\begin{figure}[h]
+ \begin{lstlisting}[language=ooa,linewidth=\textwidth,breaklines,basicstyle=\scriptsize]
+types
+  SmallInt = int [0..3];
+  Stack = autocons system
+  |[
+  var
+        my_stack : list [10] of SmallInt = [0]
+  actions
+        obs top (a : SmallInt) = requires (a = hd my_stack) :
+                skip
+                end ;
+        obs pop = requires (len my_stack > 0) :
+                my_stack := tl my_stack
+                end;
+        obs push (a : SmallInt) = requires len my_stack < 10 :
+                my_stack := [a] ^ my_stack
+                end
+
+  do
+        var A : SmallInt : push(A) []  pop() [] var B : SmallInt : top(B)
+  od
+  ]|
+system
+  Stack
+\end{lstlisting}
+\caption{Stack}
+\label{Stack}
+\end{figure}
+
+\subsection{The Dood Block}
+\label{dood}
+
+The actual behavior of an action system is defined in the so-called \doodblock.
+The \doodblock was inspired by Dijkstra's guarded iteration statement. The
+canonical form of a \doodblock is to list all named actions of the class
+and connect them using the \texttt{[]} operator. In this case in each iteration
+an action is available iff its guard evaluates to \texttt{true} and the system
+terminates iff no action is enabled.
+
+However, in OOAS actions are neither limited to named actions nor is the
+non-deterministic choice the only possible operator.
+
+Instead, all operators described in Section \ref{Composition} are available
+as well as the built-in action \texttt{skip} and so-called anonymous actions.
+An anonymous action is a guard followed by assignments, methods or built-in
+action \texttt{skip}. In literature anonymous actions are often referred to
+as \emph{guarded commands}.
+
+If (named) actions are parametrized, enumeration can be used as generalization
+of the non-deterministic choice over the values of a data type.
+
+For instance given a data type \texttt{SmallInt = int[0..3]} and a named action
+\texttt{doSomething ( a : SmallInt )} it is possible to write
+\begin{verbatim}
+do
+	var : A : SmallInt : doSomething(A)
+od
+\end{verbatim}
+
+as abbreviation for
+\begin{verbatim}
+do
+	doSomething(0) [] doSomething(1) [] doSomething(2) [] doSomething(3)
+od
+\end{verbatim}
+
+
+
+\subsection{The System Assembling Block}
+\label{SAB}
+
+In the System Assembling Block the system is assembled by its classes. All
+the classes used by the system are connected either by the non-deterministic
+choice operator \texttt{[]} or by the prioritized composition operator
+\texttt{//}. This feature allows the user to manually set the priority among
+the classes.
+
+
+\clearpage
+
+\subsection{Comments}
+
+The OOAS language supports single line comments. Comments start
+with a \texttt{\#} symbol.
+
+\subsection{Formal Syntax}
+
+The following EBNF grammar defines the syntax of an Object-Oriented action
+system (OOAS). Features that are not implemented at all are left out. However
+there are some features that are not completely implemented and do produce
+code that doesn't work. These features are stroked out.
+\\
+
+\begin{longtable}[h]{lll}
+OOAS &:=& ['\texttt{consts}' ConstList] '\texttt{types}' TypeList '\texttt{system}' ASTypeComp \\
+ConstList &:=& NamedConst \{ '\texttt{;}' NamedConst \} \\
+NamedConst &:=& Identifier '=' Exp \\
+TypeList &:=& NamedType \{ '\texttt{;}' NamedType \} \\
+NamedType &:=& Identifier '=' ( ComplexType $\vert$ OOActionSystem ) \\
+ComplexType &:=& ( '\texttt{list}' '\texttt{[}'  ( Num $\vert$ Identifier )  '\texttt{]}'  '\texttt{of}' ComplexType ) \\
+ & &  $\vert$ ( '\texttt{[}' Identifier \{ '\texttt{,}' Identifier \} '\texttt{]}'  ) \\
+ & & $\vert$ ( '\texttt{(}' ComplexType \{ '\texttt{,}' ComplexType \}  '\texttt{)}'  ) \\
+ & & $\vert$ SimpleType \\
+SimpleType &:=& '\texttt{bool}'\\ 
+ & & $\vert$ ( '\texttt{int}' '\texttt{[}' ( Num $\vert$ Identifier ) '\texttt{..}' ( Num $\vert$ Identifier )  '\texttt{]}' )\\
+ & & $\vert$ ( '\texttt{float}' '\texttt{[}' ( FloatNum $\vert$ Identifier ) '\texttt{..}' ( FloatNum $\vert$ Identifier )  '\texttt{]}' )\\
+ & & $\vert$ '\texttt{char}' \\
+ & & $\vert$ '\texttt{\{}' Identifier [ '\texttt{=}' Num] \{ '\texttt{,} Identifier [ '\texttt{=}' Num ] \} '\texttt{\}}' \\
+ & & $\vert$ Identifier \\
+OOActionSystem &:=& [ '\texttt{autocons}' ] '\texttt{system}' [ Identifier ] \\
+ & & '\texttt{|[}'  [ '\texttt{var}' AttrList ] [ '\texttt{methods}' MethodList ] \\
+& & [ '\texttt{actions}' NamedActionList ] [ '\texttt{do}' [ActionBlock] '\texttt{od}'] '\texttt{]|}' \\
+AttrList &:=& Attr \{ '\texttt{;}' Attr \} \\
+Attr &:=& [ '\texttt{static}' ]  [ '\texttt{obs}' $\vert$ '\texttt{ctr}' ] Identifier '\texttt{:}' ComplexType [ '\texttt{=}' Exp ] \\ 
+MethodList &:=& Method \{ '\texttt{;}' Method \} \\
+Method &:=& Identifier [ '\texttt{(}' MethodParamList '\texttt{)}' ] [ '\texttt{:}' ComplexType ] '\texttt{=}' \\
+ & & [ '\texttt{var}' LocalActionVars '\texttt{begin}' ] ActionBody '\texttt{end}' \\
+MethodParamList &:=& Identifier '\texttt{:}' ComplexType \{ '\texttt{,}' Identifier '\texttt{:}' ComplexType  \} \\
+NamedActionList &:=& NamedAction \{ '\texttt{;}' NamedAction \} \\
+NamedAction &:=& [ '\texttt{obs}' $\vert$ '\texttt{ctr}' ]  Identifier [ '\texttt{(}' MethodParamList '\texttt{)}' ] \\
+ & &  [ '\texttt{:}' ComplexType ] '\texttt{=}'  [ '\texttt{var}' LocalActionVars ] DiscreteActionBody \\
+LocalActionVars &:=& Identifier '\texttt{:}' ComplexType \{ '\texttt{;}' Identifier '\texttt{:}' ComplexType\} \\
+DiscreteActionBody &:=& '\texttt{requires}' Exp '\texttt{:}' ActionBody '\texttt{end}'\\
+Exp &:=& AtomExpression BinOperator AtomExpression \\
+AtomExpression &:=& ( [ OpUn ] ( Reference $\vert$ Constant $\vert$ InitComplexType $\vert$ QuantExp\\
+&& $\vert$ '\texttt{(}' Exp '\texttt{)}' \{ '\texttt{.}' Identifier \} [ AccessExp] ) \\
+&& [ '\texttt{as}' Identifier ] ) \\
+& & $\vert$ ( '\texttt{if}' Exp '\texttt{then}' Exp '\texttt{else}' Exp '\texttt{end}' ) \\
+OpUn &:=& '\texttt{-}'  $\vert$ '\texttt{not}' $\vert$ '\texttt{hd}' $\vert$ '\texttt{tl'} $\vert$ '\texttt{len}'\\
+Constant &:=& ('\texttt{true}') $\vert$ ('\texttt{false'}) $\vert$ ('\texttt{nil}') $\vert$ ('\texttt{self}') $\vert$ (FloatNum) $\vert$ (Num) $\vert$ \\
+&& (\cancel{StringLiteral}) \\
+InitComplexType &:=& InitListType $\vert$ ('\texttt{new}' '\texttt{(}' Identifier [ '\texttt{,}' StringLiteral ] '\texttt{)}') \\
+InitListType &:=& '\texttt{[}' Exp [ ListComp $\vert$ \{ '\texttt{,} Exp'\} ] '\texttt{]}' \\
+ListComp &:=& '\texttt{|}' '\texttt{var}' Identifier '\texttt{:}' ComplexType \{ \texttt{;} Identifier ComplexType \} '\texttt{\&}' Exp \\
+QuantExp &:=& ('\texttt{forall}' $\vert$ '\texttt{exists}') Identifier '\texttt{:}' SimpleType \\
+&& \{ '\texttt{,}' Identifier '\texttt{:} SimpleType' \}  '\texttt{:}' '\texttt{(}' Exp '\texttt{)}' \\
+ActionBody &:=& ActionBodyParallel '\texttt{//}' ActionBodyParallel \\
+ActionBodyParallel &:=& ActionBodySeq '\texttt{[]}' ActionBodySeq \\
+ActionBodySeq &:=& ActionBodyParen '\texttt{;}' ActionBodyParen \\
+ActionBodyParen &:=& ( '\texttt{(}' ActionBody '\texttt{)}' ) $\vert$ ( Statement ) \\
+Statement &:=& ( '\texttt{skip'} ) $\vert$ ( Reference \{ '\texttt{,}' Reference  \} '\texttt{:=}' Exp \{ '\texttt{,}' Exp\} ) \\
+Reference &:=& QualId [ AccessExp ] [ [ '\texttt{::}' '\texttt{(}' Exp '\texttt{)}' ] '\texttt{:>:}' '\texttt{(}' Exp '\texttt{)}'  ] \\
+AccessExp &:=& ( ( '\texttt{[}' Exp '\texttt{]}' )  $\vert$ ( '\texttt{(}' MethodCallParam '\texttt{)}') ) \\
+&& \{( ( '\texttt{[}' Exp '\texttt{]}' )  | ( '\texttt{(}' MethodCallParam '\texttt{)}') ) \} \\
+&& [ '\texttt{.}' Identifier \{ '\texttt{.}' Identifier\} AccessExp] \\
+QualId &:=& [ '\texttt{self}' '\texttt{.}' ] Identifier \{ '\texttt{.} Identifier'\} \\
+MethodCallParam &:=&  [ Exp \{ '\texttt{,}' Exp\}]\\
+ActionBlock &:=& ActionBlockPar \{ '\texttt{//}' ActionBlockPar\} \\
+ActionBlockPar &:=& ActionBlockSeq \{ '\texttt{[]}' ActionBlockSeq\} \\
+ActionBlockSeq &:=& [ '\texttt{var}' BlockVarList [\cancel{'\texttt{\&}' Exp} ] '\texttt{:}' ] \\
+&&ActionBlockParen  \{ '\texttt{;}' ActionBlockParen\}\\
+ActionBlockParen &:=& ('\texttt{(}' ActionBlock '\texttt{)}' ) $\vert$ (AnonOrNamedAct)\\
+AnonOrNamedAct &:=&  DiscreteActionBody $\vert$ '\texttt{skip}' $\vert$ \\
+&& Identifier [ '\texttt{(}' MethodCallParam '\texttt{)}' ] [ '\texttt{:>:}' '\texttt{(}' Exp '\texttt{)}'  ]  \\
+BlockVarList &:=& BlockVar \{ '\texttt{;} BlockVar'\} \\
+BlockVar &:=& Identifier '\texttt{:}' ComplexType \\
+ASTypeComp &:=& ASTypeCompPar \{ '\texttt{//}' ASTypeCompPar\} \\
+ASTypeCompPar &:=& ASTypeCompSeq \{ '\texttt{[]}' ASTypeCompSeq\} \\
+ASTypeCompSeq &:=& ASTypeCompBP \\
+ASTypeCompBP &:=& ('\texttt{(}' ASTypeComp '\texttt{)}' ) \\
+BinOperator &:=& ('\texttt{<=>}') $\vert$ ('\texttt{>}')$\vert$ ('\texttt{>=}')$\vert$ ('\texttt{<}')$\vert$ ('\texttt{<=)}')$\vert$ ('\texttt{=}')$\vert$ ('\texttt{<>}')$\vert$ ('\texttt{=>}') $\vert$ ('\texttt{-}')$\vert$ ('\texttt{+}') \\
+&&$\vert$ ('\texttt{or}')$\vert$ ('\texttt{and}')$\vert$ ('\texttt{/}') $\vert$ ('\texttt{div}') $\vert$ ('\texttt{*}') $\vert$ ('\texttt{mod}') $\vert$ ('\texttt{\^}')\\
+
+Identifier &:=& Letter \{Letter $\vert$ Digit\}\\
+Num &:=& ['\texttt{+}' $\vert$ '\texttt{-}'] Digit \{ Digit \} \\
+FloatNum &:=& ['\texttt{+}' $\vert$ '\texttt{-}'] Digit \{ Digit \} '\texttt{.}' Digit \{Digit\} ['\texttt{e}' $\vert$ '\texttt{E}' ['\texttt{+}' $\vert$ '\texttt{-}' ] Digit \{ Digit \}]\\
+Letter &:=& '\texttt{\$}' $\vert$ '\texttt{\_}' $\vert$ '\texttt{A}'..'\texttt{Z}' $\vert$ '\texttt{a}'..'\texttt{z}'\\
+Digit &:=& '\texttt{0}'..'\texttt{9}'\\
+
+\end{longtable}
+\clearpage
+
+\section{Incomplete Features}
+
+The following features are supported by the grammar, but do not produce
+executable or useful code.
+
+\subsection{Sequential Block Expression}
+
+In the \doodblock when calling an action with a variable it is possible
+to add an additional guard. However if the guard is true, the produced
+Prolog-Code will not work.
+
+Example:
+\begin{verbatim}
+do
+	var A : SmallInt & A < 3 : push(A)
+od
+\end{verbatim}
+
+\subsection{String}
+
+It is possible to assign a string to a variable of any list type of char.
+
+Example:
+\begin{verbatim}
+  var
+	my_string : list[20] of char = [0] 
+  actions
+	obs fill = requires true :
+		my_string := "Hello World!"
+		end
+\end{verbatim}
+
+However, in the produced Prolog-Code the characters stored in the list are
+not of type char, but instead Prolog atoms. This may lead to strange behaviour.
+
+\section{CADP Target}
+\subsection{The Argos CADP-Target}
+
+The CADP-Target is an Add-On for Argos. It produces C files for the use
+with the CADP toolbox available at \url{http://www.inrialpes.fr/vasy/cadp/}.
+It is deployed as dynamic library
+with the file name \texttt{ArgosCadpTarget.dll}. If this file is present
+an additional Argos option \texttt{-c} is available.
+
+The invocation of Argos to produce C files for CADP is very similar
+to the invocation of Argos to produce prolog files for Ulysses. Instead
+of using the option \texttt{-p} one has to use the option \texttt{-c} and
+the options \texttt{-n} and \texttt{-d} should be omitted as they are
+meaningless in this context.
+
+\subsection{Generating BCG}
+
+The generated C file can be used to produce a graph in CADP's proprietary
+BCG format. This is done by compiling the file against CADP's tools using
+the \texttt{cadp\_cc} compiler.
+
+Given a shell with the environment variables \texttt{\$CADP} set to the
+CADP directory and \texttt{\$ARGOS} set to the Argos directory one
+can compile an Argos generated C file \texttt{model.c} into an object
+file \texttt{model.o} using the following command:
+\begin{verbatim}
+$CADP/src/com/cadp_cc -g3 -O0 -I. -I$CADP/incl -I$CADP/src/open_caesar \
+-I $ARGOS/trunk/src/cadp/cadpruntime/ -c model.c -o model.o
+\end{verbatim}
+
+Now the generator from the CADP toolbox can be compiled using the command:
+\begin{verbatim}
+$CADP/src/com/cadp_cc  -g3 -O0 -I. -I$CADP/incl -I$CADP/src/open_caesar \
+-c $CADP/src/open_caesar/generator.c -o generator.o
+\end{verbatim}
+
+Finally the two object files can be linked into an executable using the command:
+\begin{verbatim}
+$CADP/src/com/cadp_cc generator.o model.o -o generator \
+-L${BCG:-$CADP}/bin.`$CADP/com/arch` -lcaesar -lBCG_IO -lBCG -lm
+\end{verbatim}
+
+\subsection{Animator}
+
+For debugging purposes Argos provides a so-called Animator that enables
+one to walk step wise through a model. The models can be either encoded as
+graphs in \texttt{aut} files or as dynamic link library compiled from an Argos
+generated C file. The compilation can be done using any C compiler that is
+capable of generating dynamic link libraries for 32 bit Windows platforms.
+
+However, compiling the model to a dynamic link library can be a little bit
+tricky, so a solution file for Microsoft Visual Studio 2008 can be found
+in the argos source directory or to be exact in the sub-directory
+\texttt{cadp/model}. Unfortunately some paths in this file are absolute,
+so they have to be changed to match the paths that are actually used.
+
+This can be done by a right-click on \emph{model} within the
+\emph{Solution Explorer}. Now a \emph{model Property Pages} window
+pops up, providing an element \emph{Configuration Properties}. This
+element can be expanded, and \emph{C/C++} has to be chosen. The first
+entry of this page, called \emph{Additional Include Directories} has
+to be changed to fit.
+
+\section{Alarm System}
+
+\subsection{Overview}
+In this section a model of a Car Alarm System is presented. The purpose is
+to show how Object-Oriented Action Systems can be used to model real world
+system in contrast to the examples presented so far. The Car Alarm System
+has been a demonstrator in the MOGENTES project. The specifications were
+provided by Ford. This demonstrator was also used in \cite{Aichernig2010a}.
+
+
+\subsection{Requirements}
+
+In \cite{Aichernig2010a} the specification was condensed to the following three
+requirements:
+
+\textbf{R1: Arming.} The system is armed 20 seconds
+after the vehicle is locked and the bonnet, luggage compartment, and
+all doors are closed.
+
+\textbf{R2: Alarm.} The alarm sounds for 30 seconds if
+an unauthorized person opens the door, the luggage compartment, or the
+bonnet. The hazard flasher lights will flash for five minutes.
+
+\textbf{R3: Deactivation.} The CAS
+can be deactivated at any time, even when the alarm is sounding, by
+unlocking the vehicle from outside.
+
+\subsection{State Chart}
+
+In \cite{Aichernig2010a} a UML transformation tool was used to generate an
+Object-Oriented action system. The paper contains a state chart which is cited
+in Figure \ref{statechart}. In contrast the action system presented in this
+manual was written by hand but it is somehow based on this State Chart
+regarding the interpretation of the requirements.
+
+\begin{figure}[h]
+ \includegraphics[width=1\linewidth,keepaspectratio]{figures/SM_AlarmSystem}
+\caption{State Chart of Car Alarm System}
+\label{statechart}
+\end{figure}
+\clearpage
+\subsection{Object-Oriented Action System}
+
+\subsubsection{Interface}
+
+In the context of generating labeled transition systems for \emph{Ulysses}
+the interface of an Object-Oriented action system consists of named actions.
+According to the ioco theory, labels have to be marked as either input or
+output. In Object-Oriented action systems the corresponding keywords are
+\texttt{ctr} resp. \texttt{obs}.
+
+Therefore the interface of the Car Alarm System consists of 4 controllable
+actions \texttt{Close}, \texttt{Open}, \texttt{Lock} and \texttt{Unlock}.
+In the context of the implementation these actions correspond to the input
+coming from various sensors. In the context of a generated test case these
+actions correspond to outputs to the System Under Test.
+
+Also there are 6 observable actions \texttt{ArmedOn}, \texttt{ArmedOff},
+\texttt{SoundOn}, \texttt{SoundOff}, \texttt{FlashOn}, and \texttt{FlashOff}.
+In the context of the implementation these action correspond to output that
+triggers the resp. signals to the environment.
+In the context of the generated test cases these actions correspond to the
+expected inputs coming from the System Under Test.
+
+\subsubsection{Time Handling}
+
+One important aspect of modeling such a system is time handling. In former
+models within the MOGENTES project passing of time had been modeled by
+introducing an observable action \emph{after}. Later in the project this
+caused some problems as some test cases were not generated.
+
+To solve these problems the after action in this model is removed. Instead,
+elapsed time is now encoded as first parameter of every remaining action.
+
+\subsubsection{Protocol Layer}
+
+In the context of model-ling an embedded system the \doodblock can be thought
+as protocol layer. To keep the model simple, the most canonical form of the
+\doodblock has been used. That is, all named actions are connected using
+the non-deterministic choice. Since the named actions are parametrized,
+enumeration is used. Unfortunately the size of the state space grows
+exponentially by number of enumerated values, so it is very important
+to keep the resp. ranges as small as possible. In the context of this model,
+where the meaning of each action's parameter is the elapsed time, this
+means that only ``interesting'' time periods are considered. Actually,
+``interesting'' events only happen immediately, 20, 30 or 270 seconds
+after the previous event. Exactly these values are contained in the
+Enum Type \texttt{TimeSteps}.
+
+\subsubsection{Non-determinism}
+
+This model makes use of non-determinism. That means that there are situations
+in which the system can choose how it responses to a certain input.
+More technically that means, that there sequences of controllable and
+observable actions, after which there is more than one observable action.
+In the context of using the model to specify a system that means
+underspecification. A system can choose among some possible options how to
+react.
+
+In this particular model, non-determinism is used so that the implementation
+has some freedom with regards to the exact sequence of observable actions.
+For example when an intrusion is detected by the alarm system, then three
+events happen immediately: The arming is set off, the sound alarm is set
+on and the flash alarm is set on. A deterministic system would specify the
+exact order, in which these actions must be triggered. In the context of
+test case generation this could lead to some false positives, as the
+requirements do not specify a fixed order.
+ 
+\subsubsection{Code}
+%\begin{figure}[h]
+ \begin{lstlisting}[language=ooa,linewidth=\textwidth,breaklines,basicstyle=\scriptsize]
+types
+	TimeSteps = {Int0 = 0 , Int20 = 20, Int30 = 30, Int270 = 270} ;
+	Int = int[0..270] ;
+	SmallInt = int[0..3] ;
+	AlarmSystem = autocons system
+	|[
+		var
+			open : bool = true ;
+			locked : bool = false ;
+			armed : bool = false ;
+			soundAlarm : bool = false ;
+			flashAlarm : bool = false ;
+			blockingLevel : SmallInt = 0 ;
+			armedOnNow : bool = false ;
+			armedOnLater : bool = false ;
+			armedOff : bool = false ;
+			soundOn : bool = false ;
+			soundOffNow : bool = false ;
+			soundOffLater : bool = false ;
+			flashOn : bool = false ;
+			flashOffNow : bool = false ;
+			flashOffLater : bool = false  ;
+			silent : bool = false # true after alarms turned off
+		actions
+			ctr Close ( waittime : Int) =
+				requires not flashAlarm and not soundAlarm :
+					requires open and waittime = 0 and blockingLevel = 0 and locked and silent:
+						open := false ;
+						blockingLevel := 1 ;
+						armedOnNow := true ;
+						silent := false			
+					end []
+					requires open and waittime = 0 and blockingLevel = 0 and not locked and silent:
+						silent := false ;
+						open := false 
+					end []
+					requires open and waittime = 0 and blockingLevel = 0 and locked and not silent:
+						open := false ;
+						blockingLevel := 1 ;
+						armedOnLater := true
+					end []
+					requires open and waittime = 0 and blockingLevel = 0 and not locked and not silent:
+						open := false 
+					end
+				end ;
+			ctr Open ( waittime : Int) =
+				requires true :
+					requires not open and waittime = 0 and blockingLevel = 0 and not armed :
+						open := true
+					end []
+					requires not open and waittime = 0 and blockingLevel = 0 and armed :
+						open := true ;
+						armed := false ;
+						blockingLevel := 3 ;
+						armedOff := true ;
+						soundOn := true ;
+						flashOn := true
+					end 
+				end ;
+			ctr Unlock ( waittime : Int) =
+				requires true : 
+					requires locked and waittime = 0 and blockingLevel = 0 and not flashAlarm and soundAlarm:
+						locked := false ;
+						silent := false ;
+						soundOffLater := false ;
+						soundOffNow := true ;
+						blockingLevel := 1 
+					end []
+					requires locked and waittime = 0 and blockingLevel = 0 and flashAlarm and soundAlarm :
+						locked := false ;
+						flashOffNow := true ;
+						blockingLevel := 2 ;
+						silent := false ;
+						soundOffLater := false ;
+						soundOffNow := true
+					end []
+					requires locked and waittime = 0 and blockingLevel = 0 and not flashAlarm and not soundAlarm:
+						locked := false ;
+						silent := false ;
+						armedOff := true ;
+						blockingLevel := 1
+					end []
+					requires locked and waittime = 0 and blockingLevel = 0 and flashAlarm and not soundAlarm:
+						locked := false ;
+						flashOffNow := true ;
+						flashOffLater := false ;
+						blockingLevel := 1 ;
+						silent := false
+					end
+				end;
+			ctr Lock ( waittime : Int) =
+				requires true :
+					requires not locked and waittime = 0 and blockingLevel = 0 and open :
+						locked := true
+					end []
+					requires not locked and waittime = 0 and blockingLevel = 0 and not open :
+						locked := true ;
+						blockingLevel := 1 ;
+						armedOnLater := true
+					end 
+				end ;
+			obs ArmedOn (waittime : Int) =
+				requires (armedOnNow or armedOnLater):
+					requires (waittime = 20 and armedOnLater) :
+						armedOnLater := false ;
+						blockingLevel := blockingLevel - 1 ;
+						armed := true
+					end
+					[] requires (waittime = 0 and armedOnNow) :
+						armedOnNow := false ;
+						blockingLevel := blockingLevel - 1 ;
+						armed := true
+					end
+				end ;
+			obs ArmedOff (waittime : Int) =
+				requires (waittime = 0 and armedOff) :
+					armedOff := false ;
+					blockingLevel := blockingLevel - 1 ;
+					armed := false
+				end ;
+			obs SoundOn (waittime : Int) =
+				requires true :
+					requires (waittime = 0 and soundOn and blockingLevel = 1) :
+						soundOn := false ;
+						blockingLevel := blockingLevel - 1 ;
+						soundAlarm := true ;
+						soundOffLater := true 
+					end []
+					requires (waittime = 0 and soundOn and blockingLevel <> 1) :
+						soundOn := false ;
+						blockingLevel := blockingLevel - 1 ;
+						soundAlarm := true
+					end 
+				end ;
+			obs SoundOff (waittime : Int) =
+				requires (soundOffNow or soundOffLater) :
+					requires (waittime = 30 and soundOffLater) :
+						soundOffLater := false ;
+						flashOffLater := true ;
+						soundAlarm := false
+					end
+					[] requires (waittime = 0 and soundOffNow) :
+						soundOffNow := false ;
+						blockingLevel := blockingLevel - 1 ;
+						soundAlarm := false
+					end
+				end ;
+			obs FlashOn (waittime : Int) =
+				requires true :
+					requires (waittime = 0 and flashOn and blockingLevel = 1) :
+						flashOn := false ;
+						blockingLevel := blockingLevel - 1 ;
+						flashAlarm := true ;
+						soundOffLater := true 
+					end []
+					requires (waittime = 0 and flashOn and blockingLevel <> 1) :
+						flashOn := false ;
+						blockingLevel := blockingLevel - 1 ;
+						flashAlarm := true
+				end 
+				end ;
+			obs FlashOff (waittime : Int) =
+				requires (flashOffNow or flashOffLater) :
+					requires (waittime = 270 and flashOffLater) :
+						flashOffLater := false ;
+						flashAlarm := false ;
+						silent := true
+					end
+					[] requires (waittime = 0 and flashOffNow) :
+						flashOffNow := false ;
+						blockingLevel := blockingLevel - 1 ;
+						flashAlarm := false
+					end
+				end
+	do
+		var A : TimeSteps : Close (A) [] 
+		var B : TimeSteps : Open (B) []
+		var C : TimeSteps : Lock (C) []
+		var D : TimeSteps : Unlock (D) []
+		var E : TimeSteps : ArmedOn (E) []        
+		var F : TimeSteps : ArmedOff (F) []        
+		var G : TimeSteps : SoundOn (G) []        
+		var H : TimeSteps : SoundOff (H) []   
+		var I : TimeSteps : FlashOn (I) []        
+		var J : TimeSteps : FlashOff (J)    
+	od
+	]|
+system
+	AlarmSystem
+\end{lstlisting}
+%\caption{Car Alarm System in OOAS}
+%\label{Stack}
+%\end{figure}
+
+\subsection{Labeled Transition System}
+
+In Figure \ref{lts} you can find a graphical representation
+of labeled transition system that corresponds to the Object-Oriented
+action system. It is a ioco product graph produced by \emph{Ulysses}.
+So there is an additional observable action \emph{delta} that denotes
+quiescence. Iff in a given state the system has no specified output,
+there is a self loop labeled with \emph{delta}.
+
+\begin{figure}[h]
+ \includegraphics[angle=90,width=0.42\linewidth,keepaspectratio]{figures/out}
+\caption{Labeled Transition System}
+\label{lts}
+\end{figure}
+
+\section*{Acknowledgements}
+%Research herein was 
+Funded by the European Artemis Joint Undertaking project
+MBAT, Combined Model-based Analysis and Testing of Embedded Systems %.
+%ART Call 2010: 269335.
+and by the Austrian Research Promotion Agency
+(FFG), program line ``Trust in IT Systems'', project number 829583, TRUst via Failed FALsification of Complex
+Dependable Systems Using Automated Test Case Generation through Model
+Mutation (TRUFAL).
+
+\clearpage
+
+
+\bibliographystyle{plain}
+\bibliography{papers}
+
+ 
+\end{document}
Index: branches/compiler/cSharp/ooasCompiler/doc/papers.bib
===================================================================
--- branches/compiler/cSharp/ooasCompiler/doc/papers.bib	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/doc/papers.bib	(revision 3)
@@ -0,0 +1,6151 @@
+% This file was created with JabRef 2.5.
+% Encoding: UTF-8
+
+@INPROCEEDINGS{Aichernig2009b,
+  author = {Bernhard K. Aichernig and Harald Brandl and Elisabeth J{\"o}bstl
+	and Willibald Krenn},
+  title = {Model-Based Mutation Testing of Hybrid Systems},
+  booktitle = {FMCO},
+  year = {2009},
+  pages = {228-249},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://dx.doi.org/10.1007/978-3-642-17071-3_12}
+}
+
+@INPROCEEDINGS{Alfaro2003,
+  author = {Luca de Alfaro},
+  title = {Game Models for Open Systems},
+  booktitle = {Verification: Theory and Practice},
+  year = {2003},
+  pages = {269-289},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/birthday/2003manna},
+  ee = {http://springerlink.metapress.com/openurl.asp?genre=article{\&}issn=0302-9743{\&}volume=2772{\&}spage=269},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Alur1998,
+  author = {Rajeev Alur and Thomas A. Henzinger and Orna Kupferman and Moshe
+	Y. Vardi},
+  title = {Alternating Refinement Relations},
+  booktitle = {CONCUR},
+  year = {1998},
+  pages = {163-178},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/concur/1998},
+  ee = {http://link.springer.de/link/service/series/0558/bibs/1466/14660163.htm},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Bacherini2006,
+  author = {Stefano Bacherini and Alessandro Fantechi and Matteo Tempestini and
+	Niccol{\`o} Zingoni},
+  title = {A Story About Formal Methods Adoption by a Railway Signaling Manufacturer},
+  booktitle = {FM},
+  year = {2006},
+  pages = {179-189},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/fm/2006},
+  ee = {http://dx.doi.org/10.1007/11813040_13},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Baker2002,
+  author = {Paul Baker and Paul Bristow and Clive Jervis and David J. King and
+	Bill Mitchell},
+  title = {Automatic Generation of Conformance Tests from Message Sequence Charts},
+  booktitle = {SAM},
+  year = {2002},
+  pages = {170-198},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/sam/2002},
+  ee = {http://link.springer.de/link/service/series/0558/bibs/2599/25990170.htm},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Ball2006,
+  author = {Thomas Ball and Ella Bounimova and Byron Cook and Vladimir Levin
+	and Jakob Lichtenberg and Con McGarvey and Bohus Ondrusek and Sriram
+	K. Rajamani and Abdullah Ustuner},
+  title = {Thorough static analysis of device drivers},
+  booktitle = {EuroSys},
+  year = {2006},
+  pages = {73-85},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/eurosys/2006},
+  ee = {http://doi.acm.org/10.1145/1217935.1217943},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Bigot2003,
+  author = {C{\'e}line Bigot and Alain Faivre and Jean-Pierre Gallois and Arnault
+	Lapitre and David Lugato and Jean-Yves Pierron and Nicolas Rapin},
+  title = {Automatic Test Generation with AGATHA},
+  booktitle = {TACAS},
+  year = {2003},
+  pages = {591-596},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/tacas/2003},
+  ee = {http://link.springer.de/link/service/series/0558/bibs/2619/26190591.htm},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Blackburn2002,
+  author = {Mark R. Blackburn and Robert Busser and Aaron Nauman and Robert Knickerbocker
+	and Richard Kasuda},
+  title = {Mars Polar Lander Fault Identification Using Model-based Testing},
+  booktitle = {ICECCS},
+  year = {2002},
+  pages = {163-},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/iceccs/2002},
+  ee = {http://csdl.computer.org/comp/proceedings/iceccs/2002/1757/00/17570163abs.htm},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Blom2004,
+  author = {Johan Blom and Anders Hessel and Bengt Jonsson and Paul Pettersson},
+  title = {Specifying and Generating Test Cases Using Observer Automata},
+  booktitle = {FATES},
+  year = {2004},
+  pages = {125-139},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/fates/2004},
+  ee = {http://springerlink.metapress.com/openurl.asp?genre=article{\&}issn=0302-9743{\&}volume=3395{\&}spage=125},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Blom2003,
+  author = {Johan Blom and Bengt Jonsson},
+  title = {Automated test generation for industrial Erlang applications},
+  booktitle = {Erlang Workshop},
+  year = {2003},
+  pages = {8-14},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/erlang/2003},
+  ee = {http://doi.acm.org/10.1145/940880.940882},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Bohnenkamp2005,
+  author = {Henrik C. Bohnenkamp and Axel Belinfante},
+  title = {Timed Testing with TorX},
+  booktitle = {FM},
+  year = {2005},
+  pages = {173-188},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/fm/2005},
+  ee = {http://dx.doi.org/10.1007/11526841_13},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Boonstoppel2008,
+  author = {Peter Boonstoppel and Cristian Cadar and Dawson R. Engler},
+  title = {RWset: Attacking Path Explosion in Constraint-Based Test Generation},
+  booktitle = {TACAS},
+  year = {2008},
+  pages = {351-366},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/tacas/2008},
+  ee = {http://dx.doi.org/10.1007/978-3-540-78800-3_27},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Bozga2004,
+  author = {Marius Bozga and Susanne Graf and Ileana Ober and Iulian Ober and
+	Joseph Sifakis},
+  title = {The IF Toolset},
+  booktitle = {SFM},
+  year = {2004},
+  pages = {237-267},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/sfm/2004},
+  ee = {http://springerlink.metapress.com/openurl.asp?genre=article{\&}issn=0302-9743{\&}volume=3185{\&}spage=237},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Brandl2008c,
+  author = {Harald Brandl and Gordon Fraser and Franz Wotawa},
+  title = {Coverage-based Testing Using Qualitative Reasoning Models},
+  booktitle = {SEKE},
+  year = {2008},
+  pages = {393-398},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/seke/2008}
+}
+
+@INPROCEEDINGS{Braspenning,
+  author = {N.C.W.M. Braspenning and J.M. van de Mortel-Fronczak and H.A.J. Neerhof
+	and J.E. Rooda},
+  title = {Model-based integration and testing in practice},
+  booktitle = {Tangram: Model-based integration and testing of complex high-tech
+	systems},
+  note = {chapter 7},
+  crossref = {Tangram2007},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Brucker2009,
+  author = {Achim D. Brucker and Burkhart Wolff},
+  title = {hol-TestGen},
+  booktitle = {FASE},
+  year = {2009},
+  pages = {417-420},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/fase/2009},
+  ee = {http://dx.doi.org/10.1007/978-3-642-00593-0_28},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Brucker2004,
+  author = {Achim D. Brucker and Burkhart Wolff},
+  title = {Symbolic Test Case Generation for Primitive Recursive Functions},
+  booktitle = {FATES},
+  year = {2004},
+  pages = {16-32},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/fates/2004},
+  ee = {http://springerlink.metapress.com/openurl.asp?genre=article{\&}issn=0302-9743{\&}volume=3395{\&}spage=16},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Cadar2006,
+  author = {Cristian Cadar and Vijay Ganesh and Peter M. Pawlowski and David
+	L. Dill and Dawson R. Engler},
+  title = {EXE: automatically generating inputs of death},
+  booktitle = {ACM Conference on Computer and Communications Security},
+  year = {2006},
+  pages = {322-335},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/ccs/2006usa},
+  ee = {http://doi.acm.org/10.1145/1180405.1180445},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Calame2006,
+  author = {Jens R. Calame and Nicolae Goga and Natalia Ioustinova and Jaco van
+	de Pol},
+  title = {TTCN-3 Testing of Hoorn-Kersenboogerd Railway Interlocking},
+  booktitle = {CCECE},
+  year = {2006},
+  pages = {620-623},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/ccece/2006},
+  ee = {http://dx.doi.org/10.1109/CCECE.2006.277762},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Caspi2003,
+  author = {Paul Caspi and Adrian Curic and Aude Maignan and Christos Sofronis
+	and Stavros Tripakis},
+  title = {Translating Discrete-Time Simulink to Lustre},
+  booktitle = {EMSOFT},
+  year = {2003},
+  pages = {84-99},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/emsoft/2003},
+  ee = {http://springerlink.metapress.com/openurl.asp?genre=article{\&}issn=0302-9743{\&}volume=2855{\&}spage=84},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Cheon2007a,
+  author = {Yoonsik Cheon},
+  title = {Automated Random Testing to Detect Specification-Code Inconsistencies},
+  booktitle = {SETP},
+  year = {2007},
+  pages = {112-119},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/setp/2007},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Cheon2007,
+  author = {Yoonsik Cheon and Carlos E. Rubio-Medrano},
+  title = {Random Test Data Generation for Java Classes Annotated with JML Specifications},
+  booktitle = {Software Engineering Research and Practice},
+  year = {2007},
+  pages = {385-391},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/serp/2007-2},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Clarke2002,
+  author = {Duncan Clarke and Thierry J{\'e}ron and Vlad Rusu and Elena Zinovieva},
+  title = {STG: A Symbolic Test Generation Tool},
+  booktitle = {TACAS},
+  year = {2002},
+  pages = {470-475},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/tacas/2002},
+  ee = {http://link.springer.de/link/service/series/0558/bibs/2280/22800470.htm},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Constant2007,
+  author = {Camille Constant and Bertrand Jeannet and Thierry J{\'e}ron},
+  title = {Automatic Test Generation from Interprocedural Specifications},
+  booktitle = {TestCom/FATES},
+  year = {2007},
+  pages = {41-57},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/pts/2007},
+  ee = {http://dx.doi.org/10.1007/978-3-540-73066-8_4},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Csallner2008,
+  author = {Christoph Csallner and Nikolai Tillmann and Yannis Smaragdakis},
+  title = {DySy: dynamic symbolic execution for invariant inference},
+  booktitle = {ICSE},
+  year = {2008},
+  pages = {281-290},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/icse/2008},
+  ee = {http://doi.acm.org/10.1145/1368088.1368127},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Dauchy1991,
+  author = {Pierre Dauchy and Bruno Marre},
+  title = {Test Data Selection From Algebraic Specifications: Application to
+	an Automatic Subway Module},
+  booktitle = {ESEC},
+  year = {1991},
+  pages = {80-100},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/esec/1991},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Dulz2003,
+  author = {Winfried Dulz and Fenhua Zhen},
+  title = {MaTeLo - Statistical Usage Testing by Annotated Sequence Diagrams,
+	Markov Chains and TTCN-3},
+  booktitle = {QSIC},
+  year = {2003},
+  pages = {336-342},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/qsic/2003},
+  ee = {http://csdl.computer.org/comp/proceedings/qsic/2003/2015/00/20150336abs.htm},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Faivre2007,
+  author = {Alain Faivre and Christophe Gaston and Pascale Le Gall},
+  title = {Symbolic Model Based Testing for Component Oriented Systems},
+  booktitle = {TestCom/FATES},
+  year = {2007},
+  pages = {90-106},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/pts/2007},
+  ee = {http://dx.doi.org/10.1007/978-3-540-73066-8_7},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Fritzson1998,
+  author = {Peter Fritzson},
+  title = {Modelica - A Language for Equation-Based Physical Modeling and High
+	Performance Simulation},
+  booktitle = {PARA},
+  year = {1998},
+  pages = {149-160},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/para/1998},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Garavel2007,
+  author = {Hubert Garavel and Radu Mateescu and Fr{\'e}d{\'e}ric Lang and Wendelin
+	Serwe},
+  title = {CADP 2006: A Toolbox for the Construction and Analysis of Distributed
+	Processes},
+  booktitle = {CAV},
+  year = {2007},
+  pages = {158-163},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/cav/2007},
+  ee = {http://dx.doi.org/10.1007/978-3-540-73368-3_18},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Gaston2006,
+  author = {Christophe Gaston and Pascale Le Gall and Nicolas Rapin and Assia
+	Touil},
+  title = {Symbolic Execution Techniques for Test Purpose Definition},
+  booktitle = {TestCom},
+  year = {2006},
+  pages = {1-18},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/pts/2006},
+  ee = {http://dx.doi.org/10.1007/11754008_1},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Godefroid2005,
+  author = {Patrice Godefroid and Nils Klarlund and Koushik Sen},
+  title = {{DART}: directed automated random testing},
+  booktitle = {PLDI},
+  year = {2005},
+  pages = {213-223},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/pldi/2005},
+  ee = {http://doi.acm.org/10.1145/1065010.1065036},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Goga2001,
+  author = {Nicolae Goga},
+  title = {Comparing TorX, Autolink, TGV and UIO Test Algorithms},
+  booktitle = {SDL Forum},
+  year = {2001},
+  pages = {379-402},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/sdl/2001},
+  ee = {http://link.springer.de/link/service/series/0558/bibs/2078/20780379.htm},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Hackner2008,
+  author = {Daniel R. Hackner and Atif M. Memon},
+  title = {Test case generator for GUITAR},
+  booktitle = {ICSE Companion},
+  year = {2008},
+  pages = {959-960},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/icse/2008c},
+  ee = {http://doi.acm.org/10.1145/1370175.1370207},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Hartman2004a,
+  author = {A. Hartman and K. Nagin},
+  title = {The AGEDIS tools for model based testing},
+  booktitle = {ISSTA},
+  year = {2004},
+  pages = {129-132},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/issta/2004},
+  ee = {http://doi.acm.org/10.1145/1007512.1007529},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Hessel2008,
+  author = {Anders Hessel and Kim Guldstrand Larsen and Marius Mikucionis and
+	Brian Nielsen and Paul Pettersson and Arne Skou},
+  title = {Testing Real-Time Systems Using UPPAAL},
+  booktitle = {Formal Methods and Testing},
+  year = {2008},
+  pages = {77-117},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/fortest/2008},
+  ee = {http://dx.doi.org/10.1007/978-3-540-78917-8_3},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Hessel2006,
+  author = {Anders Hessel and Paul Pettersson},
+  title = {Model-Based Testing of a WAP Gateway: An Industrial Case-Study},
+  booktitle = {FMICS/PDMC},
+  year = {2006},
+  pages = {116-131},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/fmics/2006},
+  ee = {http://dx.doi.org/10.1007/978-3-540-70952-7_8},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Jeannet2005,
+  author = {Bertrand Jeannet and Thierry J{\'e}ron and Vlad Rusu and Elena Zinovieva},
+  title = {Symbolic Test Selection Based on Approximate Analysis},
+  booktitle = {TACAS},
+  year = {2005},
+  pages = {349-364},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/tacas/2005},
+  ee = {http://springerlink.metapress.com/openurl.asp?genre=article{\&}issn=0302-9743{\&}volume=3440{\&}spage=349},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Julius2007,
+  author = {A. Agung Julius and Georgios E. Fainekos and Madhukar Anand and Insup
+	Lee and George J. Pappas},
+  title = {Robust Test Generation and Coverage for Hybrid Systems},
+  booktitle = {HSCC},
+  year = {2007},
+  pages = {329-342},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/hybrid/2007},
+  ee = {http://dx.doi.org/10.1007/978-3-540-71493-4_27},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Koch1998,
+  author = {Beat Koch and Jens Grabowski and Dieter Hogrefe and Michael Schmitt
+	II},
+  title = {Autolink: A Tool for Automatic Test Generation from SDL Specifications},
+  booktitle = {WIFT},
+  year = {1998},
+  pages = {114-},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/wift/1998},
+  ee = {http://csdl.computer.org/comp/proceedings/wift/1998/0081/00/00810114abs.htm},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Longuet2009,
+  author = {Delphine Longuet and Marc Aiguier},
+  title = {Integration Testing from Structured First-Order Specifications via
+	Deduction Modulo},
+  booktitle = {ICTAC},
+  year = {2009},
+  pages = {261-276},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/ictac/2009},
+  ee = {http://dx.doi.org/10.1007/978-3-642-03466-4_17},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Lugato2004,
+  author = {David Lugato and Fr{\'e}d{\'e}ric Maraux and Yves Le Traon and V{\'e}ronique
+	Normand and Hubert Dubois and Jean-Yves Pierron and Jean-Pierre Gallois
+	and Cl{\'e}mentine Nebut},
+  title = {Automated Functional Test Case Synthesis from THALES industrial Requirements},
+  booktitle = {IEEE Real-Time and Embedded Technology and Applications Symposium},
+  year = {2004},
+  pages = {104-111},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/rtas/2004},
+  ee = {http://csdl.computer.org/comp/proceedings/rtas/2004/2148/00/21480104abs.htm},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Marre1995,
+  author = {Bruno Marre},
+  title = {LOFT: A Tool for Assisting Selection of Test Data Sets from Algebraic
+	Specifications},
+  booktitle = {TAPSOFT},
+  year = {1995},
+  pages = {799-800},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/tapsoft/1995},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Moser2007,
+  author = {Andreas Moser and Christopher Kr{\"u}gel and Engin Kirda},
+  title = {Exploring Multiple Execution Paths for Malware Analysis},
+  booktitle = {IEEE Symposium on Security and Privacy},
+  year = {2007},
+  pages = {231-245},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/sp/2007},
+  ee = {http://dx.doi.org/10.1109/SP.2007.17},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Moura2008,
+  author = {Leonardo Mendon\c{c}a de Moura and Nikolaj Bj{\o}rner},
+  title = {Z3: An Efficient SMT Solver},
+  booktitle = {TACAS},
+  year = {2008},
+  pages = {337-340},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/tacas/2008},
+  ee = {http://dx.doi.org/10.1007/978-3-540-78800-3_24},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Nicola2005,
+  author = {Giuseppe De Nicola and Pasquale di Tommaso and Rosaria Esposito and
+	Francesco Flammini and Pietro Marmo and Antonio Orazzo},
+  title = {A Grey-Box Approach to the Functional Testing of Complex Automatic
+	Train Protection Systems},
+  booktitle = {EDCC},
+  year = {2005},
+  pages = {305-317},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/edcc/2005},
+  ee = {http://springerlink.metapress.com/openurl.asp?genre=article{\&}issn=0302-9743{\&}volume=3463{\&}spage=305},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{N'unez2005,
+  author = {Manuel N{\'u}{\~n}ez and Ismael Rodr\'{\i}guez},
+  title = {Conformance Testing Relations for Timed Systems},
+  booktitle = {FATES},
+  year = {2005},
+  pages = {103-117},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/fates/2005},
+  ee = {http://dx.doi.org/10.1007/11759744_8},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Osch2006,
+  author = {Michiel van Osch},
+  title = {Hybrid Input-Output Conformance and Test Generation},
+  booktitle = {FATES/RV},
+  year = {2006},
+  pages = {70-84},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/fates/2006},
+  ee = {http://dx.doi.org/10.1007/11940197_5},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Petrenko2005,
+  author = {Alexandre Petrenko and Nina Yevtushenko},
+  title = {Conformance Tests as Checking Experiments for Partial Nondeterministic
+	FSM},
+  booktitle = {FATES},
+  year = {2005},
+  pages = {118-133},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/fates/2005},
+  ee = {http://dx.doi.org/10.1007/11759744_9},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Rusu2000,
+  author = {Vlad Rusu and Lydie du Bousquet and Thierry J{\'e}ron},
+  title = {An Approach to Symbolic Test Generation},
+  booktitle = {IFM},
+  year = {2000},
+  pages = {338-357},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/ifm/2000},
+  ee = {http://link.springer.de/link/service/series/0558/bibs/1945/19450338.htm},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Schieferdecker2008,
+  author = {Ina Schieferdecker and Jens Grabowski and Theofanis Vassiliou-Gioles
+	and George Din},
+  title = {The Test Technology TTCN-3},
+  booktitle = {Formal Methods and Testing},
+  year = {2008},
+  pages = {292-319},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/fortest/2008},
+  ee = {http://dx.doi.org/10.1007/978-3-540-78917-8_10},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Sen2006,
+  author = {Koushik Sen and Gul Agha},
+  title = {CUTE and jCUTE: Concolic Unit Testing and Explicit Path Model-Checking
+	Tools},
+  booktitle = {CAV},
+  year = {2006},
+  pages = {419-423},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/cav/2006},
+  ee = {http://dx.doi.org/10.1007/11817963_38},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Tillmann2008,
+  author = {Nikolai Tillmann and Jonathan de Halleux},
+  title = {Pex-White Box Test Generation for .NET},
+  booktitle = {TAP},
+  year = {2008},
+  pages = {134-153},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/tap/2008},
+  ee = {http://dx.doi.org/10.1007/978-3-540-79124-9_10},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Tretmans1993,
+  author = {Jan Tretmans},
+  title = {A Formal Approach to Conformance Testing},
+  booktitle = {Protocol Test Systems},
+  year = {1993},
+  pages = {257-276},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/pts/1993},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Veanes2009,
+  author = {Margus Veanes and Nikolaj Bj{\o}rner},
+  title = {Input-Output Model Programs},
+  booktitle = {ICTAC},
+  year = {2009},
+  pages = {322-335},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/ictac/2009},
+  ee = {http://dx.doi.org/10.1007/978-3-642-03466-4_21},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Veanes2008,
+  author = {Margus Veanes and Colin Campbell and Wolfgang Grieskamp and Wolfram
+	Schulte and Nikolai Tillmann and Lev Nachmanson},
+  title = {Model-Based Testing of Object-Oriented Reactive Systems with Spec
+	Explorer},
+  booktitle = {Formal Methods and Testing},
+  year = {2008},
+  pages = {39-76},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/fortest/2008},
+  ee = {http://dx.doi.org/10.1007/978-3-540-78917-8_2},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Weiglhofer2009,
+  author = {Martin Weiglhofer and Franz Wotawa},
+  title = {Asynchronous Input-Output Conformance Testing},
+  booktitle = {COMPSAC (1)},
+  year = {2009},
+  pages = {154-159},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  crossref = {DBLP:conf/compsac/2009},
+  ee = {http://dx.doi.org/10.1109/COMPSAC.2009.194}
+}
+
+@MISC{(OMG),
+  author = {The Object Management Group (OMG)},
+  title = {OMG Systems Modeling Language},
+  owner = {harald},
+  timestamp = {2009.09.18},
+  url = {http://www.omgsysml.org}
+}
+
+@ARTICLE{Abrial2007,
+  author = {Jean-Raymond Abrial},
+  title = {Formal Methods: Theory Becoming Practice},
+  journal = {J. UCS},
+  year = {2007},
+  volume = {13},
+  pages = {619-628},
+  number = {5},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://www.jucs.org/jucs_13_5/formal_methods_theory_becoming},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Abrial1996,
+  title = {The B-book: assigning programs to meaningsp},
+  publisher = {Cambridge University Press},
+  year = {1996},
+  author = {J.-R. Abrial},
+  address = {New York, NY, USA},
+  isbn = {0-521-49619-5},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@TECHREPORT{Acree1979,
+  author = {A. T. Acree and T. A. Budd and R. A. DeMillo and R. J. Lipton and
+	F. G. Sayward},
+  title = {Mutation Analysis},
+  institution = {School of Information and Computer Science, Georgia Inst. of Technology,
+	Atlanta, Ga.},
+  year = {1979},
+  month = {Sept.},
+  owner = {gordon},
+  timestamp = {2006.04.10}
+}
+
+@ARTICLE{Aichernig2006a,
+  author = {Aichernig, Bernhard and Delgado, Carlo },
+  title = {From Faults Via Test Purposes to Test Cases: On the Fault-Based Testing
+	of Concurrent Systems},
+  journal = {Fundamental Approaches to Software Engineering},
+  year = {2006},
+  pages = {324--338},
+  abstract = {Fault-based testing is a technique where testers anticipate errors
+	in a system under test in order to assess or generate test cases.
+	The idea is to have enough test cases capable of detecting these
+	anticipated errors. This paper presents a theory and technique for
+	generating fault-based test cases for concurrent systems. The novel
+	idea is to generate test purposes from faults that have been injected
+	into a model of the system under test. Such test purposes form a
+	specification of a more detailed test case that can detect the injected
+	fault. The theory is based on the notion of refinement. The technique
+	is automated using the TGV test case generator and an equivalence
+	checker of the CADP tools. A case study of testing web servers demonstrates
+	the practicability of the approach.},
+  citeulike-article-id = {2637989},
+  doi = {10.1007/11693017\_24},
+  keywords = {bibtex-import, tug},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/fase06.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:41},
+  priority = {2},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1007/11693017\_24}
+}
+
+@ARTICLE{Aichernig2003,
+  author = {Bernhard K. Aichernig},
+  title = {Mutation Testing in the Refinement Calculus},
+  journal = {Formal Aspects of Computing Journal},
+  year = {2003},
+  volume = {15},
+  pages = {280--295},
+  number = {2},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Aichernig2001,
+  author = {Bernhard K.~Aichernig},
+  title = {Test-Design through Abstraction: a Systematic Approach Based on the
+	Refinement Calculus},
+  journal = {Journal of Universal Computer Science},
+  year = {2001},
+  volume = {7},
+  pages = {710--735},
+  number = {8},
+  month = aug,
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Aichernig2011,
+  author = {Bernhard K. Aichernig and Harald Brandl and Elisabeth J\"obstl and
+	Willibald Krenn},
+  title = {Efficient Mutation Killers in Action},
+  booktitle = {Proceedings of the fourth IEEE International Conference on Software
+	Testing, Verification and Validation (ICST)},
+  year = {2011},
+  month = {March},
+  note = {in press}
+}
+
+@INPROCEEDINGS{Aichernig2010a,
+  author = {Bernhard K. Aichernig and Harald Brandl and Elisabeth J\"obstl and
+	Willibald Krenn},
+  title = {{UML} in Action: A Two-Layered Interpretation for Testing},
+  booktitle = {UML\&FM},
+  year = {2010},
+  series = {ACM Software Engineering Notes (SEN)},
+  note = {in press}
+}
+
+@CONFERENCE{Aichernig2009c,
+  author = {Bernhard K. Aichernig and Harald Brandl and Willibald Krenn},
+  title = {Qualitative Action Systems},
+  booktitle = {ICFEM},
+  year = {2009},
+  editor = {Karin Breitman and Ana Cavalcanti},
+  volume = {5885},
+  series = {LNCS},
+  publisher = {Springer},
+  longbooktitle = {Formal Methods and Software Engineering, 11th International Conference
+	on Formal Engineering Methods, ICFEM 2009, Rio de Janeiro, Brasil,
+	December 9-12, 2009. Proceedings}
+}
+
+@TECHREPORT{Aichernig2009a,
+  author = {Bernhard K. Aichernig and Harald Brandl and Willibald Krenn and Rudolf
+	Schlatte},
+  title = {Model-Based Test Case Generation Techniques: A Survey},
+  institution = {Institute for Software Technology, TU Graz},
+  year = {2009},
+  owner = {harald},
+  timestamp = {2010.10.31}
+}
+
+@ARTICLE{Aichernig2009,
+  author = {Aichernig, Bernhard K. and Brandl, Harald and Wotawa, Franz},
+  title = {Conformance Testing of Hybrid Systems with Qualitative Reasoning
+	Models},
+  journal = {Electron. Notes Theor. Comput. Sci.},
+  year = {2009},
+  volume = {253},
+  pages = {53--69},
+  number = {2},
+  address = {Amsterdam, The Netherlands, The Netherlands},
+  doi = {http://dx.doi.org/10.1016/j.entcs.2009.09.051},
+  issn = {1571-0661},
+  publisher = {Elsevier Science Publishers B. V.}
+}
+
+@INPROCEEDINGS{Aichernig2006,
+  author = {Bernhard K. Aichernig and Carlo Corrales Delgado},
+  title = {From Faults Via Test Purposes to Test Cases: On the Fault-Based Testing
+	of Concurrent Systems.},
+  booktitle = {Proceedings of the 9th International Conference on Fundamental Approaches
+	to Software Engineering},
+  year = {2006},
+  volume = {3922},
+  series = {LNCS},
+  pages = {324-338},
+  publisher = {Springer},
+  abstract = {This paper discusses how to use a fault based approach for test purpose
+	generation. The authors generate test purposes by generating a mutant
+	from the specification. Therfore they apply one of 27 mutation operators
+	to the specification. Afterwards, they generate the labeled transition
+	systems of the specification and the mutant. By doing an equivalence
+	check between the two LTSs the authors generate a discriminating
+	sequence. This sequence is used as new test purpose on the specification.},
+  comment = {p,r},
+  file = {aichernig2006faults.pdf:aichernig2006faults.pdf:PDF},
+  keywords = {mutation, test purpose generation, lts, refinement,},
+  owner = {martin},
+  timestamp = {2007.07.27}
+}
+
+@ARTICLE{Aichernig2007b,
+  author = {Aichernig, Bernhard K. and He, Jifeng },
+  title = {Mutation Testing in UTP},
+  journal = {Under consideration for publication in Formal Aspects of Computing},
+  year = {2007},
+  abstract = {This paper presents a theory of testing that integrates into Hoare
+	and He's Unifying Theory of Programming (UTP).We give test cases
+	a denotational semantics by viewing them as specification predicates.
+	This reformulation of test cases allows for relating test cases via
+	refinement to specifications and programs. Having such a refinement
+	order that integrates test cases, we develop a testing theory for
+	fault-based testing. Fault-based testing uses test data designed
+	to demonstrate the absence of a set of pre-specified faults. A well-known
+	fault-based technique is mutation testing. In mutation testing, first,
+	faults are injected into a program by altering (mutating) its source
+	code. Then, test cases that can detect these errors are designed.
+	The assumption is that other faults will be caught, too. In this
+	paper, we apply the mutation technique to both, specifications and
+	programs. Using our theory of testing, two new test case generation
+	laws for detecting injected (anticipated) faults are presented: one
+	is based on the semantic level of UTP design predicates, the other
+	on the algebraic properties of a small programming language. Keywords:
+	specification-based testing; fault-based testing; mutation testing;
+	Unifying Theories of Programming; refinement calculus; algebra of
+	programming.},
+  citeulike-article-id = {2637991},
+  keywords = {bibtex-import, mutation-testing, reading-group-testing, softnet, tug},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/facj08.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:41},
+  priority = {2},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Aichernig2005,
+  author = {Bernhard K. Aichernig and Percy Antonio {Pari Salas}},
+  title = {Test Case Generation by {OCL} Mutation and Constraint Solving},
+  booktitle = {{QSIC 2OO5}, Proceedings of the Fifth International Conference on
+	Quality Software, Melbourne, Australia, September 19-21, 2005},
+  year = {2005},
+  editor = {Kai-Yuan Cai and Atsushi Ohnishi and M.F. Lau},
+  pages = {64--71},
+  publisher = {IEEE Computer Society Press},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Aichernig2007a,
+  author = {Bernhard K. Aichernig and Bernhard Peischl and Martin Weiglhofer
+	and Franz Wotawa},
+  title = {Protocol Conformance Testing a {SIP} Registrar: An Industrial Application
+	of Formal Methods},
+  booktitle = {Proceedings of the 5th IEEE International Conference on Software
+	Engineering and Formal Methods},
+  year = {2007},
+  editor = {Mike Hinchey and Tiziana Margaria},
+  pages = {215--224},
+  address = {London, UK},
+  publisher = {IEEE},
+  comment = {a},
+  file = {aichernig2007protocol.pdf:aichernig2007protocol.pdf:PDF},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Aichernig19-20Sept.2005,
+  author = {Aichernig, B. K. and Salas, P. A. P. },
+  title = {Test case generation by OCL mutation and constraint solving},
+  journal = {Quality Software, 2005. (QSIC 2005). Fifth International Conference
+	on},
+  year = {19-20 Sept. 2005},
+  pages = {64--71},
+  citeulike-article-id = {2637988},
+  doi = {10.1109/QSIC.2005.63},
+  keywords = {bibtex-import, case, constraint, fault, fault-based, formal, generation,
+	language, languages, mutation, ocl, problem, program, programming,
+	satisfaction, semantics, software, solving, specification, state-based,
+	test, testing, theory, tolerance, tug},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/01579121.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:41},
+  priority = {2},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1109/QSIC.2005.63}
+}
+
+@INPROCEEDINGS{Aichernig2007,
+  author = {Aichernig, Bernhard K. and Weiglhofer, Martin and Peischl, Bernhard
+	and Wotawa, Franz },
+  title = {Test purpose generation in an industrial application},
+  booktitle = {A-MOST '07: Proceedings of the 3rd international workshop on Advances
+	in model-based testing},
+  year = {2007},
+  pages = {115--125},
+  address = {New York, NY, USA},
+  publisher = {ACM},
+  citeulike-article-id = {2637993},
+  doi = {http://doi.acm.org/10.1145/1291535.1291547},
+  keywords = {bibtex-import, tug},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/amost2007.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:41},
+  priority = {2},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1145/1291535.1291547}
+}
+
+@ARTICLE{Aichernig2008,
+  author = {Bernhard K. Aichernig and Martin Weiglhofer and Franz Wotawa},
+  title = {Improving Fault-based Conformance Testing},
+  journal = {Electronic Notes in Theoretical Computer Science},
+  year = {2008},
+  note = {to appear},
+  comment = {a},
+  file = {aichernig2008improving.pdf:aichernig2008improving.pdf:PDF},
+  owner = {martin},
+  timestamp = {2008.05.20}
+}
+
+@INPROCEEDINGS{Alur1990,
+  author = {Rajcev Alur and Costas Courcoubetis and David Dill},
+  title = {Model-{C}hecking for {R}eal-{T}ime {S}ystems},
+  booktitle = {Proceedings of the {F}ifth {A}nnual {IEEE} {S}ymposium on {L}ogic
+	in {C}omputer {S}cience ({LICS} 90)},
+  year = {1990},
+  pages = {414-425},
+  owner = {gordon},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Alur2000,
+  author = {Rajeev Alur and Radu Grosu and Yerang Hur and Vijay Kumar and Insup
+	Lee},
+  title = {Modular Specification of Hybrid Systems in CHARON},
+  booktitle = {HSCC '00: Proceedings of the Third International Workshop on Hybrid
+	Systems: Computation and Control},
+  year = {2000},
+  pages = {6--19},
+  address = {London, UK},
+  publisher = {Springer-Verlag},
+  isbn = {3-540-67259-1},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Ammann1999,
+  author = {Paul Ammann and Paul E. Black},
+  title = {A {S}pecification-{B}ased {C}overage {M}etric to {E}valuate {T}est
+	{S}ets.},
+  booktitle = {{HASE} '99: The 4th {IEEE} International Symposium on High-Assurance
+	Systems Engineering},
+  year = {1999},
+  pages = {239--248},
+  address = {Washington, DC, USA},
+  publisher = {IEEE Computer Society},
+  isbn = {0-7695-0418-3},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Back1988,
+  author = {R. J. R. Back and F. Kurki-Suonio},
+  title = {Distributed cooperation with action systems},
+  journal = {ACM Trans. Program. Lang. Syst.},
+  year = {1988},
+  volume = {10},
+  pages = {513--554},
+  number = {4},
+  address = {New York, NY, USA},
+  doi = {http://doi.acm.org/10.1145/48022.48023},
+  issn = {0164-0925},
+  owner = {harald},
+  publisher = {ACM},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Back1983,
+  author = {Back, Ralph-Johan and Kurki-Suonio, Reino},
+  title = {Decentralization of Process Nets with Centralized Control},
+  booktitle = {Proceedings of the 2nd ACM SIGACT-SIGOPS Symp. on Principles of Distributed
+	Computing},
+  year = {1983},
+  pages = {131-142},
+  address = {Montreal, Quebec, Canada},
+  organization = {ACM},
+  project = {actions distributed}
+}
+
+@ARTICLE{Back2001,
+  author = {Back, Ralph-Johan and Petre, Luigia and Porres, Ivan},
+  title = {Continuous Action Systems as a Model for Hybrid Systems},
+  journal = {Nordic Journal of Computing},
+  year = {2001},
+  volume = {8},
+  pages = {2--21},
+  number = {1},
+  timestamp = {2009.04.01}
+}
+
+@ARTICLE{Back1991,
+  author = {Back, Ralph-Johan and Sere, Kaisa},
+  title = {Stepwise Refinement of Action Systems},
+  journal = {Structured Programming},
+  year = {1991},
+  volume = {12},
+  pages = {17--30}
+}
+
+@INPROCEEDINGS{Back1994,
+  author = {Back, Ralph-Johan and von Wright, Joakim},
+  title = {Trace Refinement of Action Systems},
+  booktitle = {CONCUR-94:Concurrency Theory},
+  year = {1994},
+  editor = {Jonsson, B and Parrow, J.},
+  volume = {836},
+  series = {Lecture Notes in Computer Science},
+  pages = {367-384},
+  address = {Uppsala, Sweden},
+  month = {Aug},
+  publisher = {Springer-Verlag}
+}
+
+@BOOK{Back1998,
+  title = {Refinement Calculus, a Systematic Introduction},
+  publisher = {Springer},
+  year = {1998},
+  author = {Ralph-Johan Back and Joakim von Wright},
+  series = {Graduate Texts in Computer Science},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Backus1978,
+  author = {John W. Backus},
+  title = {Can Programming Be Liberated From the von Neumann Style? A Functional
+	Style and its Algebra of Programs},
+  journal = {Commun. ACM},
+  year = {1978},
+  volume = {21},
+  pages = {613-641},
+  number = {8},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Badban2006,
+  author = {Bahareh Badban and Martin Fr\"{a}nzle and Jan Peleska and Tino Teige},
+  title = {Test automation for hybrid systems},
+  booktitle = {SOQUA '06: Proceedings of the 3rd international workshop on Software
+	quality assurance},
+  year = {2006},
+  pages = {14--21},
+  address = {New York, NY, USA},
+  publisher = {ACM},
+  doi = {http://doi.acm.org/10.1145/1188895.1188902},
+  isbn = {1-59593-584-3},
+  location = {Portland, Oregon},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@MASTERSTHESIS{Bakker2006,
+  author = {Elinor Bakker},
+  title = {Qualitative models of population dynamics},
+  school = {University of Amsterdam},
+  year = {2006},
+  owner = {harald},
+  timestamp = {2010.08.31}
+}
+
+@ARTICLE{Balcer1989,
+  author = {M. Balcer and W. Hasling and T. Ostrand},
+  title = {Automatic generation of test scripts from formal test specifications},
+  journal = {SIGSOFT Softw. Eng. Notes},
+  year = {1989},
+  volume = {14},
+  pages = {210--218},
+  number = {8},
+  address = {New York, NY, USA},
+  doi = {http://doi.acm.org/10.1145/75309.75332},
+  issn = {0163-5948},
+  owner = {harald},
+  publisher = {ACM},
+  timestamp = {2009.09.18}
+}
+
+@TECHREPORT{Ball2004,
+  author = {Ball, Thomas },
+  title = {A Theory of Predicate-Complete Test Coverage and Generation},
+  institution = {Microsoft Research},
+  year = {2004},
+  abstract = {Consider a program with m statements and n predicates, where the predicates
+	are derived from the conditional state- ments and assertions in a
+	program, as well as from implicit run-time safety checks. An observable
+	state is an evaluation of the n predicates under some state at a
+	program statement. The goal of predicate-complete testing (PCT) is
+	to cover every reachable observable state (at most m x 2n of them)
+	in a program. PCT coverage is a new form of coverage motivated by
+	the observation that certain errors in a pro- gram only can be exposed
+	by considering the complex depen- dences between the predicates in
+	a program and the state- ments whose execution they control. PCT
+	coverage sub- sumes many existing control-flow coverage criteria
+	and is incomparable to path coverage. To support the generation of
+	tests to achieve high PCT coverage, we show how to define an upper
+	bound U and lower bound L to the (unknown) set of reachable observable
+	states R. These bounds are constructed automatically using Boolean
+	(predicate) abstraction over modal transition sys- tems and can be
+	used to guide test generation via symbolic execution. We define a
+	static coverage metric as |L|/|U |, which measures the ability of
+	the Boolean abstraction to achieve high PCT coverage. Finally we
+	show how to in- crease this ratio by the addition of new predicates.},
+  citeulike-article-id = {2638017},
+  keywords = {bibtex-import},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/TR-2004-28.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:45},
+  priority = {2},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{BANDELJ2002,
+  author = {Aleksander Bandelj and Ivan Bratko and Dorian Šuc},
+  title = {Qualitative simulation with {CLP}},
+  booktitle = {In Proc. of 16th International Workshop on Qualitative Reasoning
+	(QR’02},
+  year = {2002}
+}
+
+@INPROCEEDINGS{Barbey1994,
+  author = {S. Barbey and D. Buchs},
+  title = {Testing {Ada} abstract data types using formal specifications.},
+  booktitle = {1st Int. Eurospace-Ada-Europe Symposium},
+  year = {1994},
+  volume = {887},
+  series = {Lecture Notes in Computer Science},
+  pages = {76--89},
+  publisher = {Springer-Verlag},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Barnes2003,
+  title = {High Integrity Software: The SPARK Approach to Safety and Security},
+  publisher = {Addison-Wesley Longman Publishing Co., Inc.},
+  year = {2003},
+  author = {John Barnes},
+  address = {Boston, MA, USA},
+  isbn = {0321136160},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INCOLLECTION{Barnett2005,
+  author = {Mike Barnett and K. Rustan M. Leino and Wolfram Schulte},
+  title = {The {Spec\#} Programming System: An Overview},
+  booktitle = {Construction and Analysis of Safe, Secure, and Interoperable Smart
+	Devices},
+  publisher = {Springer-Verlag},
+  year = {2005},
+  volume = {3362},
+  series = {Lecture Notes in Computer Science},
+  pages = {49--69},
+  keywords = {survey, testing},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Bauer2007,
+  author = {Bauer, A. and Pister, M. and Tautschnig, M. },
+  title = {Tool-support for the analysis of hybrid systems and models},
+  booktitle = {Design, Automation \& Test in Europe Conference \& Exhibition, 2007.
+	DATE '07},
+  year = {2007},
+  pages = {1--6},
+  abstract = {This paper introduces a method and tool-support for the automatic
+	analysis and verification of hybrid and embedded control systems,
+	whose continuous dynamics are often modelled using MATLAB/Simulink.
+	The method is based upon converting system models into the uniform
+	input language of our efficient multi-domain constraint solving library,
+	ABSOLVER, which is then used for subsequent analysis. Basically,
+	ABSOLVER is an extensible SMT-solver which addresses mixed Boolean
+	and (nonlinear) arithmetic constraint problems as they appear in
+	the design of hybrid control systems. It allows the integration and
+	semantic connection of various domain specific solvers via a logical
+	circuit, such that almost arbitrary multi-domain constraint problems
+	can be formulated and solved. Its design has been tailored for extensibility,
+	and thus facilitates the reuse of expert knowledge, in that the most
+	appropriate solver for a given task can be integrated and used. As
+	such the only constraint over the problem domain is the capability
+	of the employed solvers. Our approach to systems verification has
+	been validated in an industrial case study using the model of a car's
+	steering control system. However, additional benchmarks show that
+	other hard instances of problems could also be solved by ABSOLVER
+	in respectable time, and that for some instances, ABsOLVER's approach
+	was the only means of solving a problem at all},
+  citeulike-article-id = {2721207},
+  doi = {10.1109/DATE.2007.364411},
+  journal = {Design, Automation \& Test in Europe Conference \& Exhibition, 2007.
+	DATE '07},
+  keywords = {mogentes, sat, smt, testing},
+  owner = {harald},
+  posted-at = {2008-05-05 12:40:32},
+  priority = {2},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1109/DATE.2007.364411}
+}
+
+@INPROCEEDINGS{Beckman2008,
+  author = {Nels E. Beckman and Aditya V. Nori and Sriram K. Rajamani and Robert
+	J. Simmons},
+  title = {Proofs from Tests},
+  booktitle = {Poceedings of the International Symposium on Software Testing and
+	Analysis},
+  year = {2008},
+  note = {to appear},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Belinfante2010,
+  author = {Axel Belinfante},
+  title = {{JT}or{X}: A Tool for On-Line Model-Driven Test Derivation and Execution},
+  booktitle = {TACAS},
+  year = {2010},
+  pages = {266-270},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://dx.doi.org/10.1007/978-3-642-12002-2_21}
+}
+
+@INPROCEEDINGS{Belinfante2004,
+  author = {Axel Belinfante and Lars Frantzen and Christian Schallhart},
+  title = {Tools for Test Case Generation},
+  booktitle = {Model-Based Testing of Reactive Systems},
+  year = {2004},
+  pages = {391-438},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://dx.doi.org/10.1007/11498490_18},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Bernard2004,
+  author = {Eddy Bernard and Bruno Legeard and Xavier Luck and Fabien Peureux},
+  title = {Generation of test sequences from formal specifications: GSM 11-11
+	standard case study},
+  journal = {Softw., Pract. Exper.},
+  year = {2004},
+  volume = {34},
+  pages = {915-948},
+  number = {10},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://dx.doi.org/10.1002/spe.597},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Bernot1991a,
+  author = {Bernot, Gilles},
+  title = {Testing Against Formal Specifications: A Theoretical View},
+  booktitle = {TAPSOFT '91: Proceedings of the International Joint Conference on
+	Theory and Practice of Software Development, Volume 2: Advances in
+	Distributed Computing (ADC) and Colloquium on Combining Paradigms
+	for Software Developmemnt (CCPSD)},
+  year = {1991},
+  pages = {99--119},
+  address = {London, UK},
+  publisher = {Springer-Verlag},
+  isbn = {3-540-53981-6}
+}
+
+@ARTICLE{Bernot1991,
+  author = {G. Bernot and M.-C. Gaudel and B. Marre},
+  title = {Software testing based on formal specifications: a theory and a tool.},
+  journal = {Software Engineering Journal},
+  year = {1991},
+  volume = {6},
+  pages = {387--405},
+  number = {6},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Berry1992,
+  author = {Gerard Berry and Georges Gonthier},
+  title = {The Esterel Synchronous Programming Language: Design, Semantics,
+	Implementation},
+  journal = {Science of Computer Programming},
+  year = {1992},
+  volume = {19},
+  pages = {87-152},
+  number = {2},
+  owner = {harald},
+  timestamp = {2009.09.18},
+  url = {citeseer.ist.psu.edu/berry92esterel.html}
+}
+
+@ARTICLE{Beyer2004,
+  author = {Beyer, Dirk and Chlipala, Adam J. and Henzinger, Thomas A. and Jhala,
+	Ranjit and Majumdar, Rupak },
+  title = {Generating Tests from Counterexamples},
+  journal = {icse},
+  year = {2004},
+  volume = {0},
+  pages = {326--335},
+  abstract = {We have extended the software model checker BLAST to automatically
+	generate test suites that guarantee full coverage with respect to
+	a given predicate. More precisely, given a C program and a target
+	predicate, BLAST determines the set  of program locations which
+	program execution can reach with true, and automatically generates
+	a set of test vectors that exhibit the truth of at all locations
+	in . We have used BLAST to generate test suites and to detect dead
+	code in C programs with up to 30 K lines of code. The analysis and
+	test-vector generation is fully automatic (no user intervention)
+	and exact (no false positives).},
+  address = {Los Alamitos, CA, USA},
+  citeulike-article-id = {2638016},
+  doi = {http://doi.ieeecomputersociety.org/10.1109/ICSE.2004.1317455},
+  keywords = {bibtex-import},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/2004-ICSE.Generating\_Tests\_from\_Counterexamples.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:45},
+  priority = {2},
+  publisher = {IEEE Computer Society},
+  timestamp = {2009.09.18},
+  url = {http://doi.ieeecomputersociety.org/10.1109/ICSE.2004.1317455}
+}
+
+@ARTICLE{Biere2003,
+  author = {Armin Biere and Alessandro Cimatti and Edmund M. Clarke and Ofer
+	Strichman and Yunshan Zhu},
+  title = {Bounded model checking},
+  journal = {Advances in Computers},
+  year = {2003},
+  volume = {58},
+  pages = {118-149},
+  bibsource = {DBLP, http://dblp.uni-trier.de}
+}
+
+@INPROCEEDINGS{Black2000,
+  author = {Paul E. Black and Vadim Okun and Yaacov Yesha},
+  title = {Mutation {O}perators for {S}pecifications},
+  booktitle = {Proceedings of the {F}ifteenth {IEEE} {I}nternational {C}onference
+	on {A}utomated {S}oftware {E}ngineering ({ASE}'00)},
+  year = {2000},
+  address = {Washington, DC, USA},
+  publisher = {IEEE Computer Society},
+  owner = {gordon},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Blackburn1996,
+  author = {Blackburn, MR and Busser, RD},
+  title = {{T-VEC: a tool for developing critical systems}},
+  journal = {Computer Assurance, 1996. COMPASS'96,'Systems Integrity. Software
+	Safety. Process Security'. Proceedings of the Eleventh Annual Conference
+	on},
+  year = {1996},
+  pages = {237--249},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Bohn2002,
+  author = {J. Bohn and W. Damm and J. Klose and A. Moik and H. Wittke},
+  title = {Modeling and validating train system applications using Statemate
+	and Live Sequence Charts},
+  booktitle = {Proceedings of the Conference on Integrated Design and Process Technology
+	(IDPT2002)},
+  year = {2002},
+  editor = {H. Ehrig and B. J. Kramer and A. Ertas},
+  owner = {harald},
+  timestamp = {2009.09.18},
+  url = {citeseer.ist.psu.edu/bohn02modeling.html}
+}
+
+@INPROCEEDINGS{Bonsangue1998,
+  author = {Marcello M. Bonsangue and Joost N. Kok and Kaisa Sere},
+  title = {An Approach to Object-Orientation in Action Systems},
+  booktitle = {Mathematics of Program Construction, LNCS 1422},
+  year = {1998},
+  pages = {68--95},
+  publisher = {Springer},
+  owner = {wkrenn},
+  timestamp = {2010.02.04}
+}
+
+@ARTICLE{Borras2006,
+  author = {Cari Borr\'as},
+  title = {{Overexposure of Radiation Therapy Patients in Panama: Problem Recognition
+	and Follow-Up Measures}},
+  journal = {{Rev Panam Salud Publica}},
+  year = {2006},
+  volume = {20},
+  pages = {173-187},
+  number = {2/3},
+  file = {:home/elisabeth/Diplomarbeit/Literatur/PDFs/panama.pdf:PDF},
+  keywords = {http://journal.paho.org/uploads/1162234952.pdf},
+  owner = {elisabeth},
+  timestamp = {2009.09.08},
+  url = {http://journal.paho.org/uploads/1162234952.pdf}
+}
+
+@ARTICLE{Boug'e1985,
+  author = {L. Boug\'{e}},
+  title = {A contribution to the theory of program testing},
+  journal = {Theoretical Computer Science},
+  year = {1985},
+  volume = {37},
+  pages = {151--181},
+  number = {2},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PHDTHESIS{Boug'e1982,
+  author = {L. Boug\'{e}},
+  title = {Mod\'{e}lisation de la notion de test de programmes, application
+	\`{a} la production de jeux de test},
+  school = {Universit\'{e} de Paris 6},
+  year = {1982},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Boug'e1986,
+  author = {L. Boug\'{e} and N. Choquet and L. Fribourg and M.-C. Gaudel},
+  title = {Test set generation from algebraic specifications using logic programming.},
+  journal = {Journal of Systems and Software},
+  year = {1986},
+  volume = {6},
+  pages = {343--360},
+  number = {4},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Bouissou2008,
+  author = {Bouissou, Olivier and Martel, Matthieu},
+  title = {Abstract interpretation of the physical inputs of embedded programs},
+  booktitle = {VMCAI'08: Proceedings of the 9th international conference on Verification,
+	model checking, and abstract interpretation},
+  year = {2008},
+  pages = {37--51},
+  address = {Berlin, Heidelberg},
+  publisher = {Springer-Verlag},
+  isbn = {3-540-78162-5, 978-3-540-78162-2},
+  location = {San Francisco, USA}
+}
+
+@INPROCEEDINGS{Bouissou2008a,
+  author = {Bouissou, Olivier and Martel, Matthieu},
+  title = {A hybrid denotational semantics for hybrid systems},
+  booktitle = {ESOP'08/ETAPS'08: Proceedings of the Theory and practice of software,
+	17th European conference on Programming languages and systems},
+  year = {2008},
+  pages = {63--77},
+  address = {Berlin, Heidelberg},
+  publisher = {Springer-Verlag},
+  isbn = {3-540-78738-0, 978-3-540-78738-9},
+  location = {Budapest, Hungary}
+}
+
+@ARTICLE{Bourque2004,
+  author = {Bourque, P. and Dupuis, R.},
+  title = {Guide to the Software Engineering Body of Knowledge 2004 Version},
+  journal = {Guide to the Software Engineering Body of Knowledge, 2004. SWEBOK},
+  year = {2004},
+  month = { }
+}
+
+@MANUAL{Bouwer2005,
+  title = {User Manual for Single-User Version of QR Workbench},
+  author = {Bouwer, A. and Liem, J. and Bredeweg, B.},
+  organization = {Naturnet-Redime, STREP project co-funded by the European Commission
+	within the Sixth Framework Programme (2002-2006)},
+  year = {2005},
+  note = {Project no. 004074. Project deliverable D4.2.1.},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Boyapati2002,
+  author = {Boyapati, Chandrasekhar and Khurshid, Sarfraz and Marinov, Darko
+	},
+  title = {Korat: automated testing based on Java predicates},
+  booktitle = {ISSTA '02: Proceedings of the 2002 ACM SIGSOFT international symposium
+	on Software testing and analysis},
+  year = {2002},
+  pages = {123--133},
+  address = {New York, NY, USA},
+  publisher = {ACM},
+  abstract = {This paper presents Korat, a novel framework for automated testing
+	of Java programs. Given a formal specification for a method, Korat
+	uses the method precondition to automatically generate all (nonisomorphic)
+	test cases up to a given small size. Korat then executes the method
+	on each test case, and uses the method postcondition as a test oracle
+	to check the correctness of each output. To generate test cases for
+	a method, Korat constructs a Java predicate (i.e., a method that
+	returns a boolean) from the method's precondition. The heart of Korat
+	is a technique for automatic test case generation: given a predicate
+	and a bound on the size of its inputs, Korat generates all (nonisomorphic)
+	inputs for which the predicate returns true. Korat exhaustively explores
+	the bounded input space of the predicate but does so efficiently
+	by monitoring the predicate's executions and pruning large portions
+	of the search space. This paper illustrates the use of Korat for
+	testing several data structures, including some from the Java Collections
+	Framework. The experimental results show that it is feasible to generate
+	test cases from Java predicates, even when the search space for inputs
+	is very large. This paper also compares Korat with a testing framework
+	based on declarative specifications. Contrary to our initial expectation,
+	the experiments show that Korat generates test cases much faster
+	than the declarative framework.},
+  citeulike-article-id = {2638005},
+  doi = {http://doi.acm.org/10.1145/566172.566191},
+  keywords = {bibtex-import, boundingsymbolic, execution, loop},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/p123-boyapati.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:44},
+  priority = {2},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1145/566172.566191}
+}
+
+@INCOLLECTION{Bozga1998,
+  author = {Bozga, Marius and Daws, Conrado and Maler, Oded and Olivero, Alfredo
+	and Tripakis, Stavros and Yovine, Sergio},
+  title = {Kronos: A model-checking tool for real-time systems},
+  booktitle = {Formal Techniques in Real-Time and Fault-Tolerant Systems},
+  publisher = {Springer Berlin / Heidelberg},
+  year = {1998},
+  editor = {Ravn, Anders and Rischel, Hans},
+  volume = {1486},
+  series = {Lecture Notes in Computer Science},
+  pages = {298-302},
+  note = {10.1007/BFb0055357},
+  affiliation = {Verimag, Centre équation 2 avenue de Vignate 38610 Gières France 2
+	avenue de Vignate 38610 Gières France},
+  url = {http://dx.doi.org/10.1007/BFb0055357}
+}
+
+@INPROCEEDINGS{Brandl2009,
+  author = {Harald Brandl},
+  title = {Testing of Hybrid Systems using Qualitative Models},
+  year = {2009},
+  editor = {MohammadReza Mousavi and Emil Sekerinski},
+  volume = {Proceedings of Formal Methods 2009 Doctoral Symposium},
+  pages = {46--52},
+  month = {11},
+  owner = {harald},
+  timestamp = {2010.10.09},
+  url = {http://www.win.tue.nl/~mousavi/fm09ds.pdf}
+}
+
+@INPROCEEDINGS{Brandl2008,
+  author = {Harald Brandl and Gordon Fraser and Franz Wotawa},
+  title = {A report on {QR}-based testing},
+  booktitle = {22nd International Workshop on Qualitative Reasoning},
+  year = {2008},
+  pages = {1--9},
+  location = {Boulder, CO},
+  url = {www.cs.colorado.edu/~lizb/qr08/papers/Brandl.pdf}
+}
+
+@INPROCEEDINGS{Brandl2008b,
+  author = {Harald Brandl and Gordon Fraser and Franz Wotawa},
+  title = {{QR}-model based testing},
+  booktitle = {AST '08: Proceedings of the 3rd international workshop on Automation
+	of software test},
+  year = {2008},
+  pages = {17--20},
+  address = {New York, NY, USA},
+  publisher = {ACM},
+  doi = {http://doi.acm.org/10.1145/1370042.1370046},
+  isbn = {978-1-60558-030-2},
+  location = {Leipzig, Germany},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Brandl2010,
+  author = {Harald Brandl and Martin Weiglhofer and Bernhard K. Aichernig},
+  title = {Automated Conformance Verification of Hybrid Systems},
+  journal = {Quality Software, International Conference on},
+  year = {2010},
+  volume = {0},
+  pages = {3-12},
+  address = {Los Alamitos, CA, USA},
+  doi = {http://doi.ieeecomputersociety.org/10.1109/QSIC.2010.53},
+  issn = {1550-6002},
+  publisher = {IEEE Computer Society}
+}
+
+@INPROCEEDINGS{Brandl2008a,
+  author = {Harald Brandl and Franz Wotawa},
+  title = {Test Case Generation from {QR} Models},
+  booktitle = {21st International Conference on Industrial, Engineering \& Other
+	Applications of Applied Intelligent Systems},
+  year = {2008},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Braspenning2006,
+  author = {N. C. W. M. Braspenning and J. M. van de Mortel-Fronczak and J. E.
+	Rooda},
+  title = {A Model-based Integration and Testing Method to Reduce System Development
+	Effort},
+  journal = {Electr. Notes Theor. Comput. Sci.},
+  year = {2006},
+  volume = {164},
+  pages = {13-28},
+  number = {4},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://dx.doi.org/10.1016/j.entcs.2006.09.003},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Bredeweg2006,
+  author = {Bert Bredeweg and Anders Bouwer and Jelmer Jellema and Dirk Bertels
+	and Floris Floris Linnebank and Jochem Liem},
+  title = {Garp3 - A new Workbench for Qualitative Reasoning and Modelling},
+  booktitle = {Proceedings of 20th International Workshop on Qualitative Reasoning
+	(QR-06)},
+  year = {2006},
+  pages = {21-28},
+  address = {Hannover, New Hampshire, USA},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@MANUAL{Bredeweg2005,
+  title = {Curriculum for learning about QR modelling},
+  author = {Bredeweg, B. and Liem, J. and Bouwer, A. and Salles, P},
+  organization = {Naturnet-Redime, STREP project co-funded by the European Commission
+	within the Sixth Framework Programme (2002-2006)},
+  year = {2005},
+  note = {Project no. 004074. Project deliverable D6.9.1.},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Brinksma1988,
+  author = {Ed Brinksma},
+  title = {A theory for the derivation of tests},
+  booktitle = {Protocol Specification, Testing, and Verification VIII},
+  year = {1988},
+  editor = {S. Aggarwal and K. Sabnani},
+  pages = {402--416},
+  publisher = {North-Holland}
+}
+
+@INPROCEEDINGS{Brinksma1995,
+  author = {Brinksma, Ed and Scollo, Giuseppe and Steenbergen, Chris},
+  title = {Lotos specifications, their implementations and their tests},
+  booktitle = {Conformance testing methodologies and architectures for OSI protocols},
+  year = {1995},
+  editor = {Richard Jerry Linn and M. {\"U}mit Uyar},
+  pages = {468--479},
+  address = {Los Alamitos, CA, USA},
+  publisher = {IEEE Computer Society Press},
+  isbn = {0-8186-5352-3}
+}
+
+@INPROCEEDINGS{Brinksma2000,
+  author = {Ed Brinksma and Jan Tretmans},
+  title = {Testing Transition Systems: An Annotated Bibliography},
+  booktitle = {MOVEP},
+  year = {2000},
+  pages = {187-195},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://link.springer.de/link/service/series/0558/bibs/2067/20670187.htm},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Broy1999,
+  author = {Manfred Broy and Franz Huber and Bernhard Sch{\"a}tz},
+  title = {AutoFocus - Ein Werkzeugprototyp zur Entwicklung eingebetteter Systeme},
+  journal = {Inform., Forsch. Entwickl.},
+  year = {1999},
+  volume = {14},
+  pages = {121-134},
+  number = {3},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://link.springer.de/link/service/journals/00450/bibs/9014003/90140121.htm},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Brucker2008,
+  author = {Achim D. Brucker and Lukas Br{\"u}gger and Burkhart Wolff},
+  title = {Verifying Test-Hypotheses -- An Experiment in Test and Proof},
+  booktitle = {Model-based Testing (MBT 2008)},
+  year = {2008},
+  editor = {Bernd Finkbeiner and Yuri Gurevich and Alexander K. Petrenko},
+  series = j-entcs,
+  address = {Budapest, Hungary},
+  publisher = {Elsevier Science Publishers},
+  note = {To appear.},
+  abstract = {\testgen is a specification and test case generation environment extending
+	the interactive theorem prover Isabelle/\acs{hol}. The \testgen method
+	is two-staged: first, the original formula, called \emph{test specification},
+	is partitioned into \emph{test cases} by transformation into a normal
+	form called \emph{test theorem}. Second, the test cases are analyzed
+	for ground instances (the \emph{test data}) satisfying the constraints
+	of the test cases. Particular emphasis is put on the control of explicit
+	test hypotheses which can be proven over concrete programs. As such,
+	explicit test hypotheses establish a logical link between validation
+	by test and by proof. Since \testgen generates explicit test hypotheses
+	and makes them amenable to formal proof, the system is in a unique
+	position to explore the relations between them at an example.},
+  categories = {holtestgen},
+  classification = {workshop},
+  file = {brucker.ea-verifying-2008.pdf:http\://www.brucker.ch/bibliography/download/2008/brucker.ea-verifying-2008.pdf:PDF;brucker.ea-verifying-2008.ps.gz:http\://www.brucker.ch/bibliography/download/2008/brucker.ea-verifying-2008.ps.gz:PostScript},
+  keywords = {symbolic test case generations, black box testing, theorem proving,
+	formal verification, Isabelle/HOL},
+  language = {USenglish},
+  owner = {harald},
+  public = {yes},
+  timestamp = {2009.09.18},
+  url = {http://www.brucker.ch/bibliography/abstract/brucker.ea-verifying-2008}
+}
+
+@ARTICLE{Bryant1986,
+  author = {Randal E. Bryant},
+  title = {Graph-based algorithms for Boolean function manipulation},
+  journal = {IEEE Trans. Comput.},
+  year = {1986},
+  volume = {35},
+  pages = {677--691},
+  number = {8},
+  address = {Washington, DC, USA},
+  issn = {0018-9340},
+  owner = {harald},
+  publisher = {IEEE Computer Society},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Budd1985,
+  author = {Timothy Alan Budd and Ajei Sarat Gopal},
+  title = {Program Testing by Specification Mutation},
+  journal = {Computer Languages},
+  year = {1985},
+  volume = {10},
+  pages = {63-73},
+  owner = {wkrenn},
+  timestamp = {2009.09.17}
+}
+
+@ARTICLE{Burdy2005,
+  author = {Lilian Burdy and Yoonsik Cheon and David R. Cok and Michael D. Ernst
+	and Joseph R. Kiniry and Gary T. Leavens and K. Rustan M. Leino and
+	Erik Poll},
+  title = {An overview of JML tools and applications},
+  journal = {STTT},
+  year = {2005},
+  volume = {7},
+  pages = {212-232},
+  number = {3},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://dx.doi.org/10.1007/s10009-004-0167-4},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Callahan1996,
+  author = {John Callahan and Francis Schneider and Steve Easterbrook},
+  title = {Automated {S}oftware {T}esting {U}sing {M}odel-{C}hecking},
+  booktitle = {Proceedings 1996 {SPIN} {W}orkshop},
+  year = {1996},
+  month = {August},
+  note = {Also WVU Technical Report NASA-IVV-96-022.},
+  owner = {gordon},
+  timestamp = {2009.09.18}
+}
+
+@TECHREPORT{Campbell,
+  author = {Campbell, Colin and Grieskamp, Wolfgang and Nachmanson, Lev and Schulte,
+	Wolfram and Tillmann, Nikolai and Veanes, Margus },
+  title = {Model-Based Testing of Object-Oriented Reactive Systems with Spec
+	Explorer},
+  abstract = {Testing is one of the costliest aspects of commercial software development.
+	Model-based testing is a promising approach addressing these deficits.
+	At Microsoft, model-based testing technology developed by the Foundations
+	of Software Engineering group in Microsoft Research has been used
+	since 2003. The second generation of this tool set, Spec Explorer,
+	deployed in 2004, is now used on a daily basis by Microsoft product
+	groups for testing operating system components, .NET framework components
+	and other areas. This paper provides a comprehensive survey of the
+	concepts of the tool and their foundations.},
+  citeulike-article-id = {2626080},
+  keywords = {microsoft, spec, testing},
+  owner = {harald},
+  posted-at = {2008-04-07 15:41:30},
+  priority = {0},
+  school = {Microsoft Research},
+  timestamp = {2009.09.18},
+  url = {ftp://ftp.research.microsoft.com/pub/tr/TR-2005-59.pdf}
+}
+
+@INPROCEEDINGS{Cavalcanti2007,
+  author = {Cavalcanti, Ana and Gaudel, Marie-Claude},
+  title = {Testing for refinement in CSP},
+  booktitle = {ICFEM'07: Proceedings of the formal engineering methods 9th international
+	conference on Formal methods and software engineering},
+  year = {2007},
+  pages = {151--170},
+  address = {Berlin, Heidelberg},
+  publisher = {Springer-Verlag},
+  isbn = {3-540-76648-0, 978-3-540-76648-3},
+  location = {Boca Raton, FL, USA}
+}
+
+@UNPUBLISHED{Cengarle,
+  author = {Maria Victoria Cengarle and Armando Martin Haeberer},
+  title = {Towards an epistemology-based methodology for verification and validation
+	testing},
+  note = {Technical report, Ludwig-Maximilians-Universit\"at M\"{u}nchen, unpublished
+	draft of March 2, 2000},
+  libnum = {195},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Cengarle2000,
+  author = {Maria Victoria Cengarle and Armando Martin Haeberer},
+  title = {{A formal approach to specification-based black-box testing}},
+  booktitle = {{Proceedings of the Workshop on Modelling Software System Structures
+	in a Fastly Moving Scenario, June 13-16, 2000, Santa Margherita Ligure,
+	Italia}},
+  year = {2000},
+  libnum = {196},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Chen2001,
+  author = {H.Y. Chen and T.H. Tse and T.Y. Chen},
+  title = {{TACCLE}: a methodology for object-oriented software testing at the
+	class and cluster levels},
+  journal = {ACM Transactions on Software Engineering and Methodology},
+  year = {2001},
+  volume = {10},
+  pages = {56--109},
+  number = {1},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Cheng1993,
+  author = {Kwang-Ting Cheng and A. S. Krishnakumar},
+  title = {Automatic Functional Test Generation Using the Extended Finite State
+	Machine Model},
+  booktitle = {DAC},
+  year = {1993},
+  pages = {86-91},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://doi.acm.org/10.1145/157485.164585},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Cheon2008,
+  author = {Yoonsik Cheon and Antonio Cortes and Martine Ceberio and Gary T.
+	Leavens},
+  title = {Integrating Random Testing with Constraints for Improved Efficiency
+	and Diversity},
+  booktitle = {Proceedings of the International Conference on Software Engineering
+	and Knowledge Engineering},
+  year = {2008},
+  month = {February},
+  organization = {Department of Computer Science, The University of Texas at El Paso},
+  note = {to appear},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Cimatti1999,
+  author = {Alessandro Cimatti and Edmund M. Clarke and Fausto Giunchiglia and
+	Marco Roveri},
+  title = {N{USMV}: {A} {N}ew {S}ymbolic {M}odel {V}erifier},
+  booktitle = {C{AV} '99: {P}roceedings of the 11th {I}nternational {C}onference
+	on {C}omputer {A}ided {V}erification},
+  year = {1999},
+  pages = {495--499},
+  address = {London, UK},
+  publisher = {Springer-Verlag},
+  isbn = {3-540-66202-2},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Claessen2002,
+  author = {Koen Claessen and John Hughes},
+  title = {Testing monadic code with QuickCheck},
+  journal = {SIGPLAN Notices},
+  year = {2002},
+  volume = {37},
+  pages = {47-59},
+  number = {12},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://doi.acm.org/10.1145/636517.636527},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Claessen2000,
+  author = {Koen Claessen and John Hughes},
+  title = {QuickCheck: a lightweight tool for random testing of Haskell programs},
+  booktitle = {ICFP},
+  year = {2000},
+  pages = {268-279},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://doi.acm.org/10.1145/351240.351266},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Claessen2000a,
+  author = {K. Claessen and J. Hughes},
+  title = {{Quickcheck}: a lightweight tool for random testing of {Haskell}
+	programs},
+  booktitle = {Fifth ACM SIGPLAN International Conference on Functional Programming},
+  year = {2000},
+  pages = {268--279},
+  publisher = {ACM Press},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Clarke2000,
+  author = {Clarke, Edmund and Grumberg, Orna and Jha, Somesh and Lu, Yuan and
+	Veith, Helmut},
+  title = {Counterexample-Guided Abstraction Refinement},
+  booktitle = {Computer Aided Verification, 12th International Conference},
+  year = {2000},
+  pages = {154--169},
+  journal = {Computer Aided Verification},
+  owner = {wkrenn},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1007/10722167_15}
+}
+
+@INPROCEEDINGS{Clarke2004,
+  author = { Clarke, Edmund and Kroening, Daniel and Lerda, Flavio },
+  title = { A Tool for Checking {ANSI-C} Programs },
+  booktitle = { Tools and Algorithms for the Construction and Analysis of Systems
+	(TACAS 2004) },
+  year = { 2004 },
+  editor = { Kurt Jensen and Andreas Podelski },
+  volume = { 2988 },
+  series = { Lecture Notes in Computer Science },
+  pages = { 168--176 },
+  publisher = { Springer },
+  isbn = { 3-540-21299-X },
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Clarke1982,
+  author = {Edmund M. Clarke and E. Allen Emerson},
+  title = {Design and Synthesis of Synchronization Skeletons Using Branching-Time
+	Temporal Logic},
+  booktitle = {Logic of Programs, Workshop},
+  year = {1982},
+  pages = {52--71},
+  address = {London, UK},
+  publisher = {Springer-Verlag},
+  isbn = {3-540-11212-X},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Clarke1976,
+  author = {Clarke, L. A. },
+  title = {A System to Generate Test Data and Symbolically Execute Programs},
+  journal = {IEEE Transactions on Software Engineering},
+  year = {1976},
+  volume = {2},
+  pages = {215--222},
+  number = {3},
+  abstract = {This paper describes a system that attempts to generate test data
+	for programs written in ANSI Fortran. Given a path, the system symbolically
+	executes the path and creates a set of constraints on the program's
+	input variables. If the set of constraints is linear, linear pro-
+	gramming techniques are employed to obtain a solution. A solution
+	to the set of constraints is test data that will drive execution
+	down the given path. If it can be determined that the set of constraints
+	is incon- sistent, then the given path is shown to be nonexecutable.
+	To increase the chance of detecting some of the more common programming
+	errors, artificial constraints are temporarily created that simulate
+	error condi- tions and then an attempt is made to solve each augmented
+	set of constraints. A symbolic representation of the program's output
+	vari- ables in terms of the program's input variables is also created.
+	The symbolic representation is in a human readable form that facilitates
+	error detection as weUl as being a possible aid in assertion generation
+	and automatic program documentation.},
+  address = {Los Alamitos, CA, USA},
+  citeulike-article-id = {2638013},
+  doi = {http://doi.ieeecomputersociety.org/10.1109/TSE.1976.233817},
+  keywords = {bibtex-import, execution, generationsymbolic, test, vector},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/01702368.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:45},
+  priority = {2},
+  publisher = {IEEE Computer Society},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/http://doi.ieeecomputersociety.org/10.1109/TSE.1976.233817}
+}
+
+@ARTICLE{Clarke1989,
+  author = {L. A. Clarke and A. Podgurski and D. J. Richardson and S. J. Zeil},
+  title = {A Formal Evaluation of Data Flow Path Selection Criteria},
+  journal = {IEEE Trans. Softw. Eng.},
+  year = {1989},
+  volume = {15},
+  pages = {1318--1332},
+  number = {11},
+  address = {Piscataway, NJ, USA},
+  doi = {http://dx.doi.org/10.1109/32.41326},
+  issn = {0098-5589},
+  owner = {harald},
+  publisher = {IEEE Press},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Cleaveland1991,
+  author = {R. Cleaveland and A. E. Zwarico},
+  title = {A Theory of Testing for Real-Time},
+  booktitle = {Proc.\ of the Sixth Annual IEEE Symposium on Logic in Computer Science},
+  year = {1991},
+  pages = {110-119},
+  address = {Amsterdam, The Netherlands},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Craggs2003,
+  author = {Ian Craggs and Manolis Sardis and Thierry Heuillard},
+  title = {AGEDIS Case Studies: Model-Based Testing in Industry},
+  booktitle = {Proceedings of the 1st European Conference on Model Driven Software
+	Engineering},
+  year = {2003},
+  pages = {106--117},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{D'Silva2008,
+  author = {D'Silva, Vijay and Kroening, Daniel and Weissenbacher, Georg },
+  title = {A Survey of Automated Techniques for Formal Software Verification},
+  journal = {A Survey of Automated Techniques for Formal Software Verification},
+  year = {2008},
+  abstract = {<p>The quality and the correctness of software is often the greatest
+	<br />concern in electronic systems. Formal verification tools can
+	provide a<br />guarantee that a design is free of specific flaws.
+	This paper surveys<br />algorithms that perform automatic, static
+	analysis of software to detect<br />programming errors or prove their
+	absence. The three techniques considered<br />are static analysis
+	with abstract domains, model checking, and bounded model<br />checking.
+	A short tutorial on these techniques is provided, highlighting<br
+	/>their differences when applied to practical problems. The paper
+	also surveys<br />the tools that are available implementing these
+	techniques, and describes<br />their merits and shortcomings.</p>},
+  citeulike-article-id = {2762806},
+  keywords = {mogentes},
+  owner = {harald},
+  posted-at = {2008-05-06 21:09:47},
+  priority = {2},
+  publisher = {IEEE},
+  timestamp = {2009.09.18},
+  url = {http://www.kroening.com/publications/view-publications-dkw2008.html}
+}
+
+@INPROCEEDINGS{Dan2004,
+  author = {Li Dan and Bernhard K. Aichernig},
+  title = {Combining Algebraic and Model-based Test Case Generation},
+  booktitle = {Proceedings of First International Colloquium on Theoretical Aspects
+	of Computing, Guiyang, China 20-24 September 2004},
+  year = {2004},
+  volume = {3407},
+  series = {Lecture Notes in Computer Science},
+  pages = {250--264},
+  publisher = {Springer-Verlag},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Dang2008,
+  author = {Dang, Thao and Nahhal, Tarik},
+  title = {Using Disparity to Enhance Test Generation for Hybrid Systems},
+  booktitle = {TestCom '08 / FATES '08: Proceedings of the 20th IFIP TC 6/WG 6.1
+	international conference on Testing of Software and Communicating
+	Systems},
+  year = {2008},
+  pages = {54--69},
+  address = {Berlin, Heidelberg},
+  publisher = {Springer-Verlag},
+  doi = {http://dx.doi.org/10.1007/978-3-540-68524-1_6},
+  isbn = {978-3-540-68514-2},
+  location = {Tokyo, Japan}
+}
+
+@ARTICLE{Dauchy1993,
+  author = {Pierre Dauchy and Marie-Claude Gaudel and Bruno Marre},
+  title = {Using algebraic specifications in software testing: A case study
+	on the software of an automatic subway},
+  journal = {Journal of Systems and Software},
+  year = {1993},
+  volume = {21},
+  pages = {229-244},
+  number = {3},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://dx.doi.org/10.1016/0164-1212(93)90025-S},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Daws1995,
+  author = {Conrado Daws and Alfredo Olivero and Sergio Yovine},
+  title = {Verifying ET-LOTOS programmes with KRONOS},
+  booktitle = {Proceedings of the 7th IFIP WG6.1 International Conference on Formal
+	Description Techniques VII},
+  year = {1995},
+  pages = {227--242},
+  address = {London, UK, UK},
+  publisher = {Chapman \& Hall, Ltd.},
+  isbn = {0-412-64450-9},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{DeJong2004,
+  author = {De Jong, Hidde},
+  title = {Qualitative simulation and related approaches for the analysis of
+	dynamic systems},
+  journal = {Knowl. Eng. Rev.},
+  year = {2004},
+  volume = {19},
+  pages = {93--132},
+  number = {2},
+  address = {New York, NY, USA},
+  doi = {http://dx.doi.org/10.1017/S0269888904000177},
+  issn = {0269-8889},
+  publisher = {Cambridge University Press}
+}
+
+@ARTICLE{DeMillo1978,
+  author = {Richard A. DeMillo and Richard J. Lipton and Frederick G. Sayward},
+  title = {Hints on {T}est {D}ata {S}election: {H}elp for the {P}racticing {P}rogrammer},
+  journal = {Computer},
+  year = {1978},
+  volume = {11},
+  pages = {34-41},
+  owner = {gordon},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Derksen2007,
+  author = {Derksen, Roger and van der Wouden, Huub and Heath, Paul},
+  title = {Testing The Heathrow Terminal 5 Baggage Handling System - Before
+	It Is Built},
+  year = {2007},
+  month = {November},
+  abstract = {London Heathrow Terminal 5 will open in March 2008. This new core
+	terminal building and two satellites will handle 30 million passengers
+	a year, and all of these passengers will expect their baggage to
+	accompany them on their flights. To achieve this, a new baggage handling
+	system is being constructed that will handle more than 70,000 bags
+	a day. Maintaining customer confidence in the reliability of the
+	baggage handling system is vital to the successful delivery of the
+	project. The challenge for the baggage control system designers was
+	how best to integrate and test the software systems of such a large
+	and complex system within a limited time to test the software in
+	its actual site environment. This article explains the vital role
+	that software emulation testing techniques played in factory integration
+	testing. The advantages and limitations of these techniques are covered
+	along with explanations of what can (and cannot) be achieved in the
+	factory environment.},
+  citeulike-article-id = {2802474},
+  keywords = {mogentes, testing},
+  owner = {harald},
+  posted-at = {2008-05-15 19:54:12},
+  priority = {3},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{DeRoever1999,
+  title = {Data Refinement: Model-Oriented Proof Methods and Their Comparison},
+  publisher = {Cambridge University Press},
+  year = {1999},
+  author = {DeRoever,, W. and Engelhardt,, Kai},
+  address = {New York, NY, USA},
+  isbn = {0521641705},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Dick1993a,
+  author = {Jeremy Dick and Alain Faivre},
+  title = {Automating the Generation and Sequencing of Test Cases from Model-Based
+	Specifications},
+  booktitle = {Proceedings of FME'93: Industrial-Strength Formal Methods, International
+	Symposium of Formal Methods Europe, April 1993, Odense, Denmark},
+  year = {1993},
+  editor = {J.C.P. Woodcock and P.G. Larsen},
+  pages = {268--284},
+  month = {April},
+  publisher = {Springer-Verlag},
+  libnum = {7},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Dick1993,
+  author = {Dick, Jeremy and Faivre, Alain },
+  title = {Automating the Generation and Sequencing of Test Cases from Model-Based
+	Specifications},
+  booktitle = {FME '93: Proceedings of the First International Symposium of Formal
+	Methods Europe on Industrial-Strength Formal Methods},
+  year = {1993},
+  pages = {268--284},
+  address = {London, UK},
+  publisher = {Springer-Verlag},
+  citeulike-article-id = {2649305},
+  isbn = {3540566627},
+  keywords = {model, mogentes, testing},
+  owner = {harald},
+  posted-at = {2008-04-10 14:43:12},
+  priority = {2},
+  timestamp = {2009.09.18},
+  url = {http://portal.acm.org/citation.cfm?id=647535.729387}
+}
+
+@BOOK{Dijkstra1990,
+  title = {Predicate Calculus and Program Semantics},
+  publisher = {Springer-Verlag},
+  year = {1990},
+  author = {E.W. Dijkstra and C.S. Scholten},
+  series = {Texts and Monographs in Computer Science},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Dill1990,
+  author = {D. L. Dill},
+  title = {Timing assumptions and verification of finite-state concurrent systems},
+  booktitle = {Proceedings of the international workshop on Automatic verification
+	methods for finite state systems},
+  year = {1990},
+  pages = {197--212},
+  address = {New York, NY, USA},
+  publisher = {Springer-Verlag New York, Inc.},
+  isbn = {0-387-52148-8},
+  location = {Grenoble, France},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Dong1994,
+  author = {R.K. Dong and Ph.G. Frankl},
+  title = {The {ASTOOT} approach to testing object-oriented programs},
+  journal = {ACM Transactions on Software Engineering and Methodology},
+  year = {1994},
+  volume = {3},
+  pages = {103--130},
+  number = {2},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Dowson1997,
+  author = {Mark Dowson},
+  title = {{The ARIANE 5 Software Failure}},
+  journal = {{ACM SIGSOFT Software Engineering Notes}},
+  year = {1997},
+  volume = {22},
+  pages = {84},
+  number = {2},
+  address = {New York, NY, USA},
+  file = {:home/elisabeth/Diplomarbeit/Literatur/PDFs/ariane5.pdf:PDF},
+  issn = {0163-5948},
+  publisher = {ACM},
+  url = {http://portal.acm.org/citation.cfm?id=251992}
+}
+
+@INPROCEEDINGS{Durrieu2004,
+  author = {Guy Durrieu and Odile Laurent and Christel Seguin and Virginie Wiels},
+  title = {Formal Proof and Test Case Generation for Critical Embedded Systems
+	Using Scade},
+  booktitle = {Building the Information Society, IFIP 18th World Computer Congress},
+  year = {2004},
+  editor = {Ren{\'e} Jacquart},
+  volume = {156/2004},
+  series = {IFIP International Federation for Information Processing},
+  pages = {499--504},
+  publisher = {Springer Boston},
+  doi = {10.1007/978-1-4020-8157-6_44},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@MISC{Dutertre2006,
+  author = {Dutertre, B. and de Moura, L.},
+  title = {The Yices SMT solver},
+  howpublished = {Tool paper at http://yices.csl.sri.com/tool-paper.pdf},
+  month = {August},
+  year = {2006},
+  citeulike-article-id = {2639925},
+  keywords = {sat-solvers},
+  organization = {SRI International},
+  posted-at = {2008-04-08 04:25:43},
+  priority = {2}
+}
+
+@INPROCEEDINGS{Emerson1982,
+  author = {E. Allen Emerson and Joseph Y. Halpern},
+  title = {Decision procedures and expressiveness in the temporal logic of branching
+	time},
+  booktitle = {STOC '82: Proceedings of the fourteenth annual ACM symposium on Theory
+	of computing},
+  year = {1982},
+  pages = {169--180},
+  address = {New York, NY, USA},
+  publisher = {ACM Press},
+  doi = {10.1145/800070.802190},
+  isbn = {0-89791-070-2},
+  location = {San Francisco, California, United States},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Emerson1987,
+  author = {E. Allen Emerson and Chin-Laung Lei},
+  title = {Modalities for model checking: branching time logic strikes back},
+  journal = {Sci. Comput. Program.},
+  year = {1987},
+  volume = {8},
+  pages = {275--306},
+  number = {3},
+  address = {Amsterdam, The Netherlands, The Netherlands},
+  doi = {http://dx.doi.org/10.1016/0167-6423(87)90036-0},
+  issn = {0167-6423},
+  owner = {harald},
+  publisher = {Elsevier North-Holland, Inc.},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Engels1997,
+  author = {Andr\'{e} Engels and Loe Feijs and Sjouke Mauw},
+  title = {Test Generation for Intelligent Networks Using ModelChecking},
+  booktitle = {Proceedings of the Third International Workshop on Tools and Algorithms
+	for the Construction and Analysis of Systems. (TACAS'97)},
+  year = {1997},
+  editor = {Ed Brinksma},
+  volume = {1217},
+  series = {Lecture Notes in Computer Science},
+  address = {Enschede, the Netherlands},
+  month = {April},
+  publisher = {Springer-Verlag},
+  optnote = {personal copy in Test 1},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Esposito2004,
+  author = {Esposito, J.M.},
+  title = {Randomized test case generation for hybrid systems: metric selection},
+  journal = {System Theory, 2004. Proceedings of the Thirty-Sixth Southeastern
+	Symposium on System Theory},
+  year = {2004},
+  pages = {236-240},
+  doi = {10.1109/SSST.2004.1295655},
+  keywords = {computational complexity, control system analysis, path planning,
+	randomised algorithms, reachability analysis control systems, hybrid
+	state space, hybrid systems, metric selection, randomized approach,
+	robotic path planning, test case generation},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@MISC{Farquhar1993,
+  author = {Adam Farquhar and Benjamin Kuipers and Jeff Rickel and David Throop
+	and The Qualitative Reasoning Group},
+  title = {{QSIM}: The Program and its Use},
+  month = {July},
+  year = {1993},
+  owner = {harald},
+  timestamp = {2010.08.11}
+}
+
+@INPROCEEDINGS{Floyd1967,
+  author = {Robert W. Floyd},
+  title = {Assigning meanings to programs},
+  booktitle = {{P}roc. {A}mer. {M}ath. {S}oc. {S}ymposia in {A}pplied {M}athematics},
+  year = {1967},
+  volume = {19},
+  pages = {19--32},
+  publisher = {Amer. Math. Soc.},
+  owner = {harald},
+  timestamp = {2009.09.18},
+  url = {http://www.ams.org/mathscinet-getitem?mr=235771}
+}
+
+@ARTICLE{Forbus1984,
+  author = {Kenneth D. Forbus},
+  title = {Qualitative Process Theory},
+  journal = {Artif. Intell.},
+  year = {1984},
+  volume = {24},
+  pages = {85-168},
+  number = {1-3},
+  bibsource = {DBLP, http://dblp.uni-trier.de}
+}
+
+@INPROCEEDINGS{Foster2007,
+  author = {Howard Foster and Wolfgang Emmerich and Jeff Kramer and Jeff Magee
+	and David S. Rosenblum and Sebasti{\'a}n Uchitel},
+  title = {Model Checking Service Compositions under Resource Constraints},
+  booktitle = {Proceedings of the 6th joint meeting of the European Software Engineering
+	Conference and the ACM SIGSOFT International Symposium on Foundations
+	of Software Engineering ({ESEC/SIGSOFT FSE})},
+  year = {2007},
+  editor = {Ivica Crnkovic and Antonia Bertolino},
+  pages = {225--234},
+  publisher = {ACM},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Frantzen2006,
+  author = {Lars Frantzen and Jan Tretmans and Tim A. C. Willemse},
+  title = {A Symbolic Framework for Model-Based Testing},
+  booktitle = {1st Combined International Workshops on Formal Approaches to Software
+	Testing and Runtime Verification},
+  year = {2006},
+  volume = {4262},
+  series = {LNCS},
+  pages = {40--54},
+  publisher = {Springer},
+  comment = {p,r},
+  ee = {http://dx.doi.org/10.1007/11940197_3},
+  file = {frantzen2006symbolic.pdf:frantzen2006symbolic.pdf:PDF},
+  owner = {martin},
+  timestamp = {2007.10.24}
+}
+
+@ARTICLE{Fraser2007a,
+  author = {Fraser, Gordon and Aichernig, Bernhard K. and Wotawa, Franz },
+  title = {Handling Model Changes: Regression Testing and Test-Suite Update
+	with Model-Checkers},
+  journal = {Electronic Notes in Theoretical Computer Science},
+  year = {2007},
+  volume = {190},
+  pages = {33--46},
+  number = {2},
+  abstract = {Several model-checker based methods to automated test-case generation
+	have been proposed recently. The performance and applicability largely
+	depends on the complexity of the model in use. For complex models,
+	the costs of creating a full test-suite can be significant. If the
+	model is changed, then in general the test-suite is completely regenerated.
+	However, only a subset of a test-suite might be invalidated by a
+	model change. Creating a full test-suite in such a case would therefore
+	waste time by unnecessarily recreating valid test-cases. This paper
+	investigates methods to reduce the effort of recreating test-suites
+	after a model is changed. This is also related to regression testing,
+	where the number of test-cases necessary after a change should be
+	minimized. This paper presents and evaluates methods to identify
+	obsolete test-cases, and to extend any given test-case generation
+	approach based on model-checkers in order to create test-cases for
+	test-suite update or regression testing.},
+  citeulike-article-id = {2637990},
+  keywords = {automated, bibtex-import, change, generation, model, model-checkers,
+	regression, test-case, testing, test-suite, tug, update, with},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/mbt07.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:41},
+  priority = {2},
+  timestamp = {2009.09.18},
+  url = {http://www.sciencedirect.com/science/article/B75H1-4PHSRDB-4/2/320e4bc91ad12d87ea9ded2f18cc69f9}
+}
+
+@INPROCEEDINGS{Fraser2008b,
+  author = {Gordon Fraser and Martin Weiglhofer and Franz Wotawa},
+  title = {Using Observer Automata to Select Test Cases for Test Purposes},
+  booktitle = {Proceedings of the 20th International Conference on Software Engineering
+	and Knowledge Engineering},
+  year = {2008},
+  note = {to appear},
+  comment = {a},
+  file = {fraser2008using.pdf:fraser2008using.pdf:PDF},
+  owner = {martin},
+  timestamp = {2008.05.20}
+}
+
+@INPROCEEDINGS{Fraser2008c,
+  author = {Gordon Fraser and Martin Weiglhofer and Franz Wotawa},
+  title = {Coverage Based Testing with Test Purposes},
+  booktitle = {Proceedings of the 8th International Conference on Quality Software},
+  year = {2008},
+  note = {to appear},
+  comment = {a},
+  owner = {martin},
+  timestamp = {2008.05.20}
+}
+
+@INPROCEEDINGS{Fraser2007,
+  author = {Fraser, Gordon and Wotawa, Franz},
+  title = {Test-Case Generation and Coverage Analysis for Nondeterministic Systems
+	Using Model-Checkers},
+  booktitle = {ICSEA '07: Proceedings of the International Conference on Software
+	Engineering Advances},
+  year = {2007},
+  pages = {45},
+  address = {Washington, DC, USA},
+  publisher = {IEEE Computer Society},
+  doi = {http://dx.doi.org/10.1109/ICSEA.2007.71},
+  isbn = {0-7695-2937-2},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Fraser2008,
+  author = {Gordon Fraser and Franz Wotawa and Paul E. Ammann},
+  title = {Testing with model checkers: a survey},
+  journal = {Software Testing, Verification and Reliability},
+  year = {2008},
+  month = {December},
+  note = {accepted for publication},
+  doi = {10.1002/stvr.402},
+  owner = {martin},
+  timestamp = {2009.05.15}
+}
+
+@INPROCEEDINGS{Friedman2002,
+  author = {G. Friedman and A. Hartman and K. Nagin and T. Shiran},
+  title = {Projected state machine coverage for software testing},
+  booktitle = {ISSTA},
+  year = {2002},
+  pages = {134-143},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://doi.acm.org/10.1145/566172.566192},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Futatsugi1995,
+  author = {K.~Futatsugi and J.A.~Goguen and J.P.~Jouannaud and J.~Meseguer},
+  title = {Principles of {OBJ2}},
+  booktitle = {Proceedings of the 12th ACM Symposium on Principles of Programming
+	Languages, New Orleans},
+  year = {1995},
+  pages = {52--66},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Gotz2009,
+  title = {iX Studie Modellbasiertes Testen},
+  publisher = {Heise Verlag},
+  year = {2009},
+  author = {Helmut G"{o}tz and Markus Nickolaus and Thomas Ro"sner and Knut Salomon},
+  owner = {wkrenn},
+  timestamp = {2009.09.17}
+}
+
+@TECHREPORT{Galler2008a,
+  author = {Galler, Stefan J. and K\"{o}nigshofer, Robert and Peischl, Bernhard
+	and Unterberger, Robert and Wotawa, Franz },
+  title = {Automatic Test Generation Tools for Java based on Design-by-Contract(tm):
+	A survey},
+  institution = {Competence Networt Softnet Austria},
+  year = {2008},
+  month = {May},
+  abstract = {Since testing counts for more than 40\% of total cost of software
+	development, automating the software testing process becomes more
+	and more important. Therefore, a more formal specification of the
+	expected behavior of software components is necessary. The Eiffel
+	programming language is the first programming language with built-in
+	formal specification of method pre-conditions, post-conditions and
+	class invariants, called Design-by-Contract. This technical report
+	should give an overview of currently available Design-by-Contract
+	specification languages for Java. The focus here is on the practical
+	usability of those languages in an real-world industrial project.},
+  citeulike-article-id = {2805308},
+  keywords = {java, mogentes, testing},
+  owner = {harald},
+  posted-at = {2008-05-16 14:59:10},
+  priority = {2},
+  timestamp = {2009.09.18}
+}
+
+@TECHREPORT{Galler2008,
+  author = {Galler, Stefan J. and Peischl, Bernhard and Wotawa, Franz},
+  title = {Formal Specification Languages for Design-by-Contract in Java: A
+	survey},
+  institution = {Competence Network Softnet Austria},
+  year = {2008},
+  key = {SNA-TR-2007-1P3},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Gannon1981,
+  author = {John Gannon and Paul McMullin and Richard Hamlet},
+  title = {Data abstraction implementation, specification and testing},
+  journal = {ACM Transactions on Programming Languages and Systems},
+  year = {1981},
+  volume = {3},
+  pages = {211--223},
+  number = {3},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Garavel2002,
+  author = {Hubert Garavel and Fr{\'e}d{\'e}ric Lang and Radu Mateescu},
+  title = {An overview of {CADP} 2001},
+  journal = {European Association for Software Science and Technology Newsletter},
+  year = {2002},
+  volume = {4},
+  pages = {13-24},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{697560,
+  author = {Gaudel, Marie-Claude},
+  title = {Testing Can Be Formal, Too},
+  booktitle = {TAPSOFT '95: Proceedings of the 6th International Joint Conference
+	CAAP/FASE on Theory and Practice of Software Development},
+  year = {1995},
+  pages = {82--96},
+  address = {London, UK},
+  publisher = {Springer-Verlag},
+  isbn = {3-540-59293-8}
+}
+
+@INPROCEEDINGS{Gaudel1995,
+  author = {Marie-Claude Gaudel},
+  title = {Testing can be formal too},
+  booktitle = {TAPSOFT'95: Theory and Practice of Software Development, 6th International
+	Joint Conference CAAP/FASE},
+  year = {1995},
+  volume = {915},
+  series = {Lecture Notes in Computer Science},
+  pages = {82--96},
+  month = {May},
+  publisher = {Springer-Verlag},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Gaudel2008,
+  author = {Marie-Claude Gaudel and Pascale Le Gall},
+  title = {Testing Data Types Implementations from Algebraic Specifications},
+  booktitle = {Formal Methods and Testing 2008},
+  year = {2008},
+  editor = {Robert M. Hierons and Jonathan P. Bowen and Mark Harman},
+  volume = {4949},
+  series = {LNCS},
+  pages = {209--239},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Gaudel1998,
+  author = {Marie-Claude Gaudel and Perry R.~James},
+  title = {Testing Algebraic Data Types and Processes: a Unifying Theory},
+  journal = {Formal Aspects of Computing},
+  year = {1998},
+  volume = {10},
+  pages = {436--451},
+  number = {5 \& 6},
+  libnum = {140},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Glymour1980,
+  title = {Theory and Evidence},
+  publisher = {Princeton University Press},
+  year = {1980},
+  author = {Clarke Glymour},
+  address = {New Jersey},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Glymour1980a,
+  author = {Clarke Glymour},
+  title = {Hypothetico-deductivism is hopeless},
+  journal = {Philosophy of science},
+  year = {1980},
+  volume = {47},
+  pages = {322--325},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Gnesi2004,
+  author = {Gnesi, Stefania and Latella, Diego and Massink, Mieke},
+  title = {Formal Test-Case Generation for {UML} Statecharts},
+  booktitle = {ICECCS '04: Proc. of the 9th IEEE Int. Conf. on Engineering Complex
+	Computer Systems Navigating Complexity in the e-Engineering Age},
+  year = {2004},
+  pages = {75--84},
+  publisher = {IEEE Computer Society}
+}
+
+@TECHREPORT{Godefroid2007,
+  author = {Godefroid, Patrice and Levin, Michael and Molnar, David },
+  title = {Automated Whitebox Fuzz Testing},
+  institution = {Microsoft Research},
+  year = {2007},
+  number = {MSR-TR-2007-58},
+  month = {May},
+  abstract = {{\\em Fuzz testing} is an effective technique for finding security
+	vulnerabilities in software. Traditionally, fuzz testing tools apply
+	random mutations to well-formed inputs and test the program on the
+	resulting values. We present an alternative {\\em whitebox fuzz testing}
+	approach inspired by recent advances in symbolic execution and dynamic
+	test generation. Our approach records an actual run of a program
+	under test on a well-formed input, symbolically evaluates the recorded
+	trace, and generates constraints capturing how the program uses its
+	inputs. The generated constraints are used to produce new inputs
+	which cause the program to follow different control paths. This process
+	is repeated with the help of a code-coverage maximizing heuristic
+	designed to find defects as fast as possible. We have implemented
+	this algorithm in SAGE (\\emph{Scalable, Automated, Guided Execution}),
+	a new tool employing x86 instruction-level tracing and emulation
+	for whitebox fuzzing of arbitrary file-reading Windows applications.
+	We describe key optimizations needed to make dynamic test generation
+	scale to large input files and long execution traces with hundreds
+	of millions of instructions. We then present detailed experiments
+	with several Windows applications. Notably, without any format-specific
+	knowledge, SAGE detects the MS07-017 ANI vulnerability, which was
+	missed by extensive blackbox fuzzing and static analysis tools. Furthermore,
+	while still in an early stage of development, SAGE has already discovered
+	20+ new bugs in large shipped Windows applications including image
+	processors, media players, and file decoders. Several of these bugs
+	are potentially exploitable memory access violations.},
+  citeulike-article-id = {2284715},
+  keywords = {bibtex-import},
+  owner = {harald},
+  posted-at = {2008-01-24 13:13:45},
+  priority = {0},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Gotlieb1998,
+  author = {Gotlieb, Arnaud and Botella, Bernard and Rueher, Michel },
+  title = {Automatic test data generation using constraint solving techniques},
+  journal = {SIGSOFT Softw. Eng. Notes},
+  year = {1998},
+  volume = {23},
+  pages = {53--62},
+  number = {2},
+  abstract = {Automatic test data generation leads to identify input values on which
+	a selected point in a procedure is ex- ecuted. This paper introduces
+	a new method for this problem based on constraint solving techniques.
+	First, we statically transform a procedure into a constraint system
+	by using well-known "Static Single Assignment" form and control-dependencies.
+	Second, we solve this system to check whether at least one feasible
+	control flow path going through the selected point exists and to
+	generate test data that correspond to one of these paths. The key
+	point of our approach is to take advantage of current advances in
+	constraint techniques when solving the generated constraint system.
+	Global constraints are used in a preliminary step to detect some
+	of the non fea- sible paths. Partial consistency techniques are employed
+	to reduce the domains of possible values of the test data. A prototype
+	implementation has been developped on a restricted subset of the
+	C language. Advantages of our approach are illustrated on a non-trivial
+	example.},
+  address = {New York, NY, USA},
+  citeulike-article-id = {2638008},
+  doi = {http://doi.acm.org/10.1145/271775.271790},
+  keywords = {bibtex-import, execution, generation, symbolic, test, vector},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/p53-gotlieb.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:44},
+  priority = {2},
+  publisher = {ACM},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1145/271775.271790}
+}
+
+@TECHREPORT{Grabowski1999,
+  author = {Jens Grabowski and Dieter Hogrefe},
+  title = {{The Standardization of Core INAP CS-2 by ETSI}},
+  institution = {Technical Report A-99-02, Medical University of L\"{u}beck, Schriftenreihe
+	der Institute f\"{u}r Mathematik/Informatik, L\"{u}beck, February
+	1999},
+  year = {1999},
+  month = feb,
+  keywords = {SDL, MSC, TTCN, ASN.1, conformance testing, automatic test generation,
+	standardization, ETSI, ITU-T},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Grieskamp2010,
+  author = {Wolfgang Grieskamp and Nicolas Kicillof and Keith Stobie and Victor
+	Braberman},
+  title = {Model-based quality assurance of protocol documentation: tools and
+	methodology},
+  journal = {Software Testing, Verification and Reliability (STVR)},
+  year = {2010},
+  owner = {harald},
+  timestamp = {2011.01.11}
+}
+
+@ARTICLE{Grieskamp2006,
+  author = {Wolfgang Grieskamp and Nicolas Kicillof and Nikolai Tillmann},
+  title = {Action Machines: a Framework for Encoding and Composing Partial Behaviors},
+  journal = {International Journal of Software Engineering and Knowledge Engineering},
+  year = {2006},
+  volume = {16},
+  pages = {705-726},
+  number = {5},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://dx.doi.org/10.1142/S0218194006002963},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Griesmayer2009,
+  author = {Andreas Griesmayer and Bernhard K. Aichernig and Einar Broch Johnsen
+	and Rudolf Schlatte},
+  title = {Dynamic Symbolic Execution for Testing Distributed Objects},
+  booktitle = {TAP},
+  year = {2009},
+  pages = {105-120},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://dx.doi.org/10.1007/978-3-642-02949-3_9}
+}
+
+@BOOK{Group1992,
+  title = {The RAISE Specification Language},
+  publisher = {Prentice-Hall},
+  year = {1992},
+  author = {The RAISE Language Group},
+  series = {The BCS Practitioners Series},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Group1995,
+  title = {The RAISE Development Method},
+  publisher = {Prentice-Hall},
+  year = {1995},
+  author = {The RAISE Method Group},
+  series = {The BCS Practitioners Series},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Gupta2000,
+  author = {Gupta, N. and Mathur, A. P. and Soffa, M. L. },
+  title = {Generating test data for branch coverage},
+  journal = {Automated Software Engineering, 2000. Proceedings ASE 2000. The Fifteenth
+	IEEE International Conference on},
+  year = {2000},
+  pages = {219--227},
+  abstract = {Branch coverage is an important criteria used during the structural
+	testing of programs. In this paper, we present a new program execution
+	based approach to generate input data that exercises a selected branch
+	in a program. The test data generation is initiated with an arbitrarily
+	chosen input from the input domain of the program. A new input is
+	derived from the initial input in an attempt to force execution through
+	any of the paths through the selected branch. The method dynamically
+	switches among the paths that reach the branch by refining the input.
+	Using a numerical iterative technique that attempts to generate an
+	input to exercise the branch, it dynamically selects Q path that
+	offers less resistance. We have implemented the technique and present
+	experimental results of its performance for some programs. Our results
+	show that our method is feasible and practical.},
+  citeulike-article-id = {2638009},
+  doi = {10.1109/ASE.2000.873666},
+  keywords = {bibtex-import, branch, coverage, generation, program, structural,
+	test, testing, vector},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/00873666.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:44},
+  priority = {2},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1109/ASE.2000.873666}
+}
+
+@ARTICLE{Gupta1998,
+  author = {Gupta, Neelam and Mathur, Aditya P. and Soffa, Mary L. },
+  title = {Automated test data generation using an iterative relaxation method},
+  journal = {SIGSOFT Softw. Eng. Notes},
+  year = {1998},
+  volume = {23},
+  pages = {231--244},
+  number = {6},
+  abstract = {An important problem that arises in path oriented testing is the generation
+	of test data that causes a program to follow a given path. In this
+	paper, we present a novel program execution based approach using
+	an iterative relaxation method to address the above problem. In this
+	method, test data generation is initiated with an arbitrarily chosen
+	input from a given domain. This input is then iteratively refined
+	to obtain an input on which all the branch predicates on the given
+	path evaluate to the desired outcome. In each iteration the program
+	statements relevant to the evaluation of each branch predicate on
+	the path are executed, and a set of linear constraints is derived.
+	The constraints are then solved to obtain the increments for the
+	input. These increments are added to the current input to obtain
+	the input for the next iteration. The relaxation technique used in
+	deriving the constraints provides feedback on the amount by which
+	each input variable should be adjusted for the branches on the path
+	to evaluate to the desired outcome.When the branch conditions on
+	a path are linear functions of input variables, our technique either
+	finds a solution for such paths in one iteration or it guarantees
+	that the path is infeasible. In contrast, existing execution based
+	approaches may require an unacceptably large number of iterations
+	for relatively long paths because they consider only one input variable
+	and one branch predicate at a time and use backtracking. When the
+	branch conditions on a path are nonlinear functions of input variables,
+	though it may take more then one iteration to derive a desired input,
+	the set of constraints to be solved in each iteration is linear and
+	is solved using Gaussian elimination. This makes our technique practical
+	and suitable for automation.},
+  address = {New York, NY, USA},
+  citeulike-article-id = {2638001},
+  doi = {http://doi.acm.org/10.1145/291252.288321},
+  keywords = {bibtex-import},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/p231-gupta.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:43},
+  priority = {2},
+  publisher = {ACM},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1145/291252.288321}
+}
+
+@ARTICLE{Gurevich2000,
+  author = {Yuri Gurevich},
+  title = {Sequential abstract-state machines capture sequential algorithms},
+  journal = {ACM Trans. Comput. Logic},
+  year = {2000},
+  volume = {1},
+  pages = {77--111},
+  number = {1},
+  address = {New York, NY, USA},
+  doi = {http://doi.acm.org/10.1145/343369.343384},
+  issn = {1529-3785},
+  owner = {harald},
+  publisher = {ACM},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Guttag1977,
+  author = {J.~Guttag},
+  title = {Abstract Data Types and the Development of Data Structures},
+  journal = {Communications of the ACM},
+  year = {1977},
+  volume = {20},
+  pages = {369--405},
+  number = {6},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Guttag1985,
+  author = {J.V.~Guttag and J.J.~Horning and J.M.~Wing},
+  title = {The {Larch} family of specification languages},
+  journal = {IEEE Software},
+  year = {1985},
+  volume = {2},
+  pages = {24--36},
+  number = {5},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Guttag1993,
+  title = {{Larch}: Languages and Tools for Formal Specification},
+  publisher = {Springer Verlag},
+  year = {1993},
+  author = {John V.~Guttag and James J.~Horning},
+  series = {Texts and Monographs in Computer Science},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Haeberer2001,
+  author = {A. M. Haeberer and T. S. E. Maibaum},
+  title = {{Scientific rigour, an answer to a pragmatic question: a linguistic
+	framework for software engineering}},
+  booktitle = {Proceedings of the 23rd International Conference on Software engineering,
+	Toronto, Ontario, Canada},
+  year = {2001},
+  pages = {463--472},
+  publisher = {IEEE Computer Society},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Halbwachs1991,
+  author = {N. Halbwachs and P. Caspi and P. Raymond and D. Pilaud},
+  title = {The synchronous data-flow programming language {LUSTRE}},
+  journal = {Proceedings of the IEEE},
+  year = {1991},
+  volume = {79},
+  pages = {1305--1320},
+  number = {9},
+  month = {September},
+  owner = {harald},
+  timestamp = {2009.09.18},
+  url = {citeseer.ist.psu.edu/halbwachs91synchronous.html}
+}
+
+@ARTICLE{Harder3-10May2003,
+  author = {Harder, M. and Mellen, J. and Ernst, M. D. },
+  title = {Improving test suites via operational abstraction},
+  journal = {Software Engineering, 2003. Proceedings. 25th International Conference
+	on},
+  year = {3-10 May 2003},
+  pages = {60--71},
+  abstract = {This paper presents the operational difference technique for generating,
+	augmenting, and minimizing test suites. The technique is analogous
+	to structural code coverage techniques, but it operates in the semantic
+	domain of program properties rather than the syntactic domain of
+	program text. The operational difference technique automatically
+	selects test cases; it assumes only the existence of a source of
+	test cases. The technique dynamically generates operational abstractions
+	(which describe observed behavior and are syntactically identical
+	to formal specifications)from test suite executions. Test suites
+	can be generated by adding cases until the operational abstraction
+	stops changing. The resulting test suites are as small, and detect
+	as many faults, as suites with 100 branch coverage, and are better
+	at detecting certain common faults. This paper also presents the
+	area and stacking techniques for comparing test suite generation
+	strategies; these techniques avoid bias due to test suite size.},
+  citeulike-article-id = {2638000},
+  doi = {10.1109/ICSE.2003.1201188},
+  keywords = {abstractions, bibtex-import, code, coverage, difference, domain, executions,
+	formal, generation, language, operational, program, programming,
+	semantics, specification, specifications, stacking, strategies, structural,
+	suite, syntactic, technique, techniques, test, testing, text, verification},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/improve-testsuite-icse2003.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:43},
+  priority = {2},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1109/ICSE.2003.1201188}
+}
+
+@ARTICLE{Harel1987,
+  author = {David Harel},
+  title = {Statecharts: {A} Visual Formalism for Complex Systems},
+  journal = {Science of Computer Programming},
+  year = {1987},
+  volume = {8},
+  pages = {231--274},
+  number = {3},
+  month = {June},
+  owner = {harald},
+  timestamp = {2009.09.18},
+  url = {citeseer.ist.psu.edu/harel87statecharts.html}
+}
+
+@ARTICLE{Harel1987a,
+  author = {David Harel},
+  title = {Statecharts: A visual formalism for complex systems},
+  journal = {Sci. Comput. Program.},
+  year = {1987},
+  volume = {8},
+  pages = {231--274},
+  number = {3},
+  address = {Amsterdam, The Netherlands, The Netherlands},
+  doi = {http://dx.doi.org/10.1016/0167-6423(87)90035-9},
+  issn = {0167-6423},
+  owner = {harald},
+  publisher = {Elsevier North-Holland, Inc.},
+  timestamp = {2009.09.18}
+}
+
+@TECHREPORT{Hartman2004,
+  author = {Alan Hartman},
+  title = {Final Project Report},
+  institution = {AGEDIS},
+  year = {2004},
+  month = {February},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Hartmann2000,
+  author = {Jean Hartmann and Claudio Imoberdorf and Michael Meisinger},
+  title = {UML-Based integration testing},
+  booktitle = {ISSTA},
+  year = {2000},
+  pages = {60-70},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://doi.acm.org/10.1145/347324.348872},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Hartmann2005,
+  author = {Jean Hartmann and Marlon Vieira and Herbert Foster and Axel Ruder},
+  title = {A UML-based approach to system testing},
+  journal = {ISSE},
+  year = {2005},
+  volume = {1},
+  pages = {12-24},
+  number = {1},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://dx.doi.org/10.1007/s11334-005-0006-0},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Hennessy1985,
+  author = {Matthew Hennessy and Robin Milner},
+  title = {Algebraic laws for nondeterminism and concurrency},
+  journal = {J. ACM},
+  year = {1985},
+  volume = {32},
+  pages = {137--161},
+  number = {1},
+  address = {New York, NY, USA},
+  doi = {10.1145/2455.2460},
+  issn = {0004-5411},
+  owner = {harald},
+  publisher = {ACM Press},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Henzinger1996,
+  author = {T. A. Henzinger},
+  title = {The theory of hybrid automata},
+  booktitle = {LICS '96: Proceedings of the 11th Annual IEEE Symposium on Logic
+	in Computer Science},
+  year = {1996},
+  pages = {278},
+  address = {Washington, DC, USA},
+  publisher = {IEEE Computer Society},
+  isbn = {0-8186-7463-6},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Henzinger1997,
+  author = {Henzinger, Thomas A. and Ho, Pei-Hsin and Wong-Toi, Howard},
+  title = {HYTECH: A Model Checker for Hybrid Systems},
+  booktitle = {CAV '97: Proceedings of the 9th International Conference on Computer
+	Aided Verification},
+  year = {1997},
+  pages = {460--463},
+  address = {London, UK},
+  publisher = {Springer-Verlag},
+  isbn = {3-540-63166-6}
+}
+
+@INPROCEEDINGS{Henzinger2000,
+  author = {Thomas A. Henzinger and Benjamin Horowitz and Rupak Majumdar and
+	Howard Wong-toi},
+  title = {Beyond HYTECH: Hybrid systems analysis using interval numerical methods},
+  booktitle = {in HSCC},
+  year = {2000},
+  pages = {130--144},
+  publisher = {Springer}
+}
+
+@INPROCEEDINGS{Henzinger2002,
+  author = {Henzinger, Thomas A. and Jhala, Ranjit and Majumdar, Rupak and Sutre,
+	Gr\'{e}goire },
+  title = {Lazy abstraction},
+  booktitle = {POPL '02: Proceedings of the 29th ACM SIGPLAN-SIGACT symposium on
+	Principles of programming languages},
+  year = {2002},
+  pages = {58--70},
+  address = {New York, NY, USA},
+  publisher = {ACM},
+  abstract = {One approach to model checking software is based on the abstract-check-refine
+	paradigm: build an abstract model, then check the desired property,
+	and if the check fails, refine the model and start over. We introduce
+	the concept of lazy abstraction to integrate and optimize the three
+	phases of the abstract-cheek-refine loop. Lazy abstraction continuously
+	builds and refines a single abstract model on demand, driven by the
+	model checker, so that different parts of the model may exhibit different
+	degrees of precision, namely just enough to verify the desired property.
+	We present an algorithm for model checking safety properties using
+	lazy abstraction and describe an implementation of the algorithm
+	applied to C programs. We also provide sufficient conditions for
+	the termination of the method.},
+  citeulike-article-id = {2638014},
+  doi = {http://doi.acm.org/10.1145/503272.503279},
+  keywords = {bibtex-import, blast},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/p58-henzinger.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:45},
+  priority = {2},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1145/503272.503279}
+}
+
+@INPROCEEDINGS{Henzinger1995,
+  author = {Henzinger, Thomas A. and Kopke, Peter W. and Puri, Anuj and Varaiya,
+	Pravin},
+  title = {What's decidable about hybrid automata?},
+  booktitle = {STOC '95: Proceedings of the twenty-seventh annual ACM symposium
+	on Theory of computing},
+  year = {1995},
+  pages = {373--382},
+  address = {New York, NY, USA},
+  publisher = {ACM},
+  doi = {http://doi.acm.org/10.1145/225058.225162},
+  isbn = {0-89791-718-9},
+  location = {Las Vegas, Nevada, United States}
+}
+
+@INPROCEEDINGS{Hessel2004,
+  author = {Anders Hessel and Paul Pettersson},
+  title = {A Test Case Generation Algorithm for Real-Time Systems},
+  booktitle = {QSIC '04: Proceedings of the Quality Software, Fourth International
+	Conference},
+  year = {2004},
+  pages = {268--273},
+  address = {Washington, DC, USA},
+  publisher = {IEEE Computer Society},
+  doi = {http://dx.doi.org/10.1109/QSIC.2004.5},
+  isbn = {0-7695-2207-6},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Hickey2004,
+  author = {Timothy J. Hickey and David K. Wittenberg},
+  title = {Rigorous Modeling of Hybrid Systems Using Interval Arithmetic Constraints},
+  booktitle = {HSCC},
+  year = {2004},
+  pages = {402-416},
+  owner = {harald},
+  timestamp = {2009.09.18},
+  url = {http://springerlink.metapress.com/openurl.asp?genre=article{\&}issn=0302-9743{\&}volume=2993{\&}spage=402}
+}
+
+@ARTICLE{Hierons2009,
+  author = {Robert M. Hierons and Kirill Bogdanov and Jonathan P. Bowen and Rance
+	Cleaveland and John Derrick and Jeremy Dick and Marian Gheorghe and
+	Mark Harman and Kalpesh Kapoor and Paul Krause and Gerald L{\"u}ttgen
+	and Anthony J. H. Simons and Sergiy A. Vilkomir and Martin R. Woodward
+	and Hussein Zedan},
+  title = {Using formal specifications to support testing},
+  journal = {ACM Computing Surveys},
+  year = {2009},
+  volume = {41},
+  number = {2},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://doi.acm.org/10.1145/1459352.1459354},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Hierons2008a,
+  author = {Hierons, Robert M. and Merayo, Mercedes G. and N, Manuel},
+  title = {Implementation Relations for the Distributed Test Architecture},
+  booktitle = {TestCom '08 / FATES '08: Proceedings of the 20th IFIP TC 6/WG 6.1
+	international conference on Testing of Software and Communicating
+	Systems},
+  year = {2008},
+  pages = {200--215},
+  address = {Berlin, Heidelberg},
+  publisher = {Springer-Verlag},
+  doi = {http://dx.doi.org/10.1007/978-3-540-68524-1_15},
+  isbn = {978-3-540-68514-2},
+  location = {Tokyo, Japan}
+}
+
+@BOOK{Hoare1985,
+  title = {Communicating Sequential Processes},
+  publisher = {Prentice-Hall},
+  year = {1985},
+  author = {C.A.R. Hoare},
+  series = {International Series in Computer Science},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Hoare1978,
+  author = {Hoare, CAR},
+  title = {{Communicating sequential processes}},
+  journal = {Communications of the ACM},
+  year = {1978},
+  volume = {21},
+  pages = {666--677},
+  number = {8},
+  owner = {harald},
+  publisher = {ACM Press New York, NY, USA},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Hoare1969,
+  author = {Hoare, C. A. R.},
+  title = {An Axiomatic Basis for Computer Programming},
+  journal = {Communications of the ACM},
+  year = {1969},
+  volume = {12},
+  pages = {576--580 and 583},
+  number = {10},
+  month = {October},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Hoare1998,
+  title = {Unifying Theories of Programming},
+  publisher = {Prentice-Hall International},
+  year = {1998},
+  author = {C.A.R.~Hoare and He Jifeng},
+  key = {HH98},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Holzer2008,
+  author = {Andreas Holzer and Christian Schallhart and Michael Tautschnig and
+	Helmut Veith},
+  title = {{FShell: Systematic Test Case Generation for Dynamic Analysis and
+	Measurement}},
+  booktitle = {Proceedings of the 20th International Conference on Computer Aided
+	Verification (CAV 2008)},
+  year = {2008},
+  volume = {5123},
+  series = {Lecture Notes in Computer Science},
+  pages = {209--213},
+  address = {Princeton, NJ, USA},
+  month = JUL,
+  publisher = {Springer},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Holzmann2004,
+  title = {{The Spin Model Checker: Primer and Reference Manual}},
+  publisher = {Addison-Wesley Professional},
+  year = {2004},
+  author = {Holzmann, G.J.},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Holzmann1997,
+  author = {Gerard J. Holzmann},
+  title = {{The Model Checker SPIN}},
+  journal = {IEEE Trans. Softw. Eng.},
+  year = {1997},
+  volume = {23},
+  pages = {279--295},
+  number = {5},
+  address = {Piscataway, NJ, USA},
+  doi = {10.1109/32.588521},
+  issn = {0098-5589},
+  owner = {harald},
+  publisher = {IEEE Press},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Hong2003,
+  author = {Hong, Hyoung S. and Cha, Sung D. and Lee, Insup and Sokolsky, Oleg
+	and Ural, Hasan},
+  title = {Data Flow Testing as Model Checking},
+  journal = {icse},
+  year = {2003},
+  volume = {00},
+  pages = {232},
+  abstract = {This paper presents a model checking-based approach to data flow testing.
+	We characterize data flow oriented coverage criteria in temporal
+	logic such that the problem of test generation is reduced to the
+	problem of finding witnesses for a set of temporal logic formulas.
+	The capability of model checkers to construct witnesses and counterexamples
+	allows test generation to be fully automatic. We discuss complexity
+	issues in minimal cost test generation and describe heurstic test
+	generation algorithms. We illustrate our approach using CTL as temporal
+	logic and SMV as model checker.},
+  address = {Los Alamitos, CA, USA},
+  citeulike-article-id = {2638002},
+  doi = {http://doi.ieeecomputersociety.org/10.1109/ICSE.2003.1201203},
+  keywords = {bibtex-import, coverage, criteria},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/03icse.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:43},
+  priority = {2},
+  publisher = {IEEE Computer Society},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/http://doi.ieeecomputersociety.org/10.1109/ICSE.2003.1201203}
+}
+
+@BOOK{Horebeek1993,
+  title = {Algebraic Specifications in Software Engineering, an Introduction},
+  publisher = {Springer Verlag},
+  year = {1993},
+  author = {Ivo Van Horebeek and Johan Lewi},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{HowdenSept.1976,
+  author = {Howden, W. E. },
+  title = {Reliability of the Path Analysis Testing Strategy},
+  journal = {Software Engineering, Transactions on},
+  year = {Sept. 1976},
+  volume = {SE-2},
+  pages = {208--215},
+  number = {3},
+  abstract = {A set of test data T for a program P is reliable if it reveals that
+	P contains an error whenever P is incorrect. If a set of tests T
+	is reliable and P produces the correct output for each element of
+	T then P is a correct program. Test data generation strategies are
+	procedures for generating sets of test data. A testing strategy is
+	reliable for a program P if it produces a reliable set of test data
+	for P. It is proved that an effective testing strategy which is reliable
+	for all programs cannot be constructed. A description of the path
+	analysis testing strategy is presented. In the path analysis strategy
+	data are generated which cause different paths in a program to be
+	executed. A method for analyzing the reliability of path testing
+	is introduced. The method is used to characterize certain classes
+	of programs and program errors for which the path analysis strategy
+	is reliable. Examples of published incorrect programs are included.},
+  citeulike-article-id = {2637999},
+  keywords = {analysissymbolic, bibtex-import, execution, path},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/01702367.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:42},
+  priority = {2},
+  timestamp = {2009.09.18}
+}
+
+@ELECTRONIC{ConferenceProtocol,
+  author = {http://fmt.cs.utwente.nl/ConfCase/v1.00/description/confprot.html},
+  title = {Conference Protocol},
+  url = {http://fmt.cs.utwente.nl/ConfCase/v1.00/description/confprot.html},
+  owner = {harald},
+  timestamp = {2009.06.22}
+}
+
+@ELECTRONIC{EventB,
+  author = {http://www.event-b.org/},
+  title = {Event-B},
+  url = {http://www.event-b.org/},
+  owner = {harald},
+  timestamp = {2009.06.22}
+}
+
+@ARTICLE{IEEE2Sep1998,
+  author = {IEEE},
+  title = {IEEE standard for information technology - requirements and guidelines
+	for test methods specifications and test method implementations for
+	measuring conformance to POSIX(R) standards},
+  journal = {IEEE Std 2003-1997},
+  year = {2 Sep 1998},
+  pages = {-},
+  keywords = {IEEE standards, Unix, application program interfaces, conformance
+	testing, formal specification, information technology, program testing,
+	software standardsAPI standards, IEEE Std 2003-1997, IEEE standard,
+	POSIX standards, application programming interface, assertion test,
+	conformance document, conformance measurement, conformance test procedure,
+	conformance test software, implementation under test, information
+	technology, options, specification standards, test method implementations,
+	test method specifications, test result code},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{IEEE1990,
+  author = {IEEE},
+  title = {{IEEE} Standard Glossary of Software Engineering Terminology},
+  journal = {IEEE Std 610.12-1990},
+  year = {1990},
+  month = Dec,
+  biburl = {http://www.bibsonomy.org/bibtex/2168c4ff010eecef4cce9d5b0030060ce/wiljami74},
+  keywords = {IEEE_Standard}
+}
+
+@MISC{ISO1997,
+  author = {ISO},
+  title = {Information processing systems --- {Open} systems interconnection
+	--- {Estelle} --- A formal description technique based on an extended
+	state transition model},
+  year = {1997},
+  address = {Geneva},
+  number = {9074},
+  organization = {International Organization for Standardization},
+  owner = {harald},
+  timestamp = {2009.09.18},
+  type = {IS}
+}
+
+@MISC{ISO1989,
+  author = {ISO},
+  title = {{ISO} 8807: Information processing systems -- Open Systems Interconnection
+	-- {LOTOS} -- A formal description technique based on the temporal
+	ordering of observational behaviour},
+  year = {1989},
+  comment = {r},
+  file = {iso1989lotos.pdf:iso1989lotos.pdf:PDF},
+  institution = {iso.ch},
+  owner = {martin},
+  timestamp = {2007.09.07}
+}
+
+@BOOK{ISO/IEC2002,
+  title = {Z formal specification notation -- Syntax, type system and semantics},
+  publisher = {ISO/IEC},
+  year = {2002},
+  author = {ISO/IEC},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@MISC{ITU-T2002,
+  author = {ITU-T},
+  title = {{Formal description techniques (FDT) -- Specification and Description
+	Language (SDL)}},
+  year = {2002},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{J'eron1999,
+  author = {J\'{e}ron, Thierry and Morel, Pierre},
+  title = {Test Generation Derived from Model-Checking},
+  booktitle = {CAV '99: Proceedings of the 11th International Conference on Computer
+	Aided Verification},
+  year = {1999},
+  pages = {108--121},
+  address = {London, UK},
+  publisher = {Springer-Verlag},
+  isbn = {3-540-66202-2}
+}
+
+@BOOK{Jackson2006,
+  title = {Software Abstractions: Logic, Language, and Analysis},
+  publisher = {The MIT Press},
+  year = {2006},
+  author = {Daniel Jackson},
+  isbn = {0262101149},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Jackson2000,
+  author = {Jackson, Daniel and Vaziri, Mandana },
+  title = {Finding bugs with a constraint solver},
+  journal = {SIGSOFT Softw. Eng. Notes},
+  year = {2000},
+  volume = {25},
+  pages = {14--25},
+  number = {5},
+  abstract = {A method for finding bugs in code is presented. For given small numbers
+	j and k, the code of a procedure is translated into a relational
+	formula whose models represent all execution traces that involve
+	at most j heap cells and k loop iterations. This formula is conjoined
+	with the negation of the procedure's specification. The models of
+	the resulting formula, obtained using a constraint solver, are counterexamples:
+	executions of the code that violate the specification. The method
+	can analyze millions of executions in seconds, and thus rapidly expose
+	quite subtle flaws. It can accommodate calls to procedures for which
+	specifications but no code is available. A range of standard properties
+	(such as absence of null pointer dereferences) can also be easily
+	checked, using predefined specifications.},
+  address = {New York, NY, USA},
+  citeulike-article-id = {2638006},
+  doi = {http://doi.acm.org/10.1145/347636.383378},
+  keywords = {bibtex-import, boundingsymbolic, execution, loop},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/p14-jackson.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:44},
+  priority = {2},
+  publisher = {ACM},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1145/347636.383378}
+}
+
+@ARTICLE{Jacobs2001,
+  author = {Bart Jacobs},
+  title = {Assertional and Behavioural Refinement in Coalgebraic Specification},
+  journal = {Electronic Notes in Theoretical Computer Science},
+  year = {2001},
+  volume = {47},
+  pages = {1--36},
+  libnum = {178},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Jard2005,
+  author = {Claude Jard and Thierry J{\'e}ron},
+  title = {{TGV}: theory, principles and algorithms},
+  journal = {International Journal on Software Tools for Technology Transfer},
+  year = {2005},
+  volume = {7},
+  pages = {297-315},
+  number = {4},
+  month = {August},
+  abstract = {This paper discusses the details of the tool TGV. TGV operates on
+	a Input/Output-Labeled Transition System (IOLTS) for the specification
+	and an IOLTS for a test purpose. On the construction of the intersection
+	of this IOLTS TGV generates a Test-Case Graph. This Test-Case Graph
+	is again an IOLTS. Based on the input/output conformance relation
+	the Test-Case Graph can be used to generate a verdict for a certain
+	Implementation under Test},
+  comment = {p,r},
+  file = {jard2005tgv.pdf:jard2005tgv.pdf:PDF},
+  filename = {./test\_generation/Jard-Jeron-05.ps},
+  keywords = {Testing, Conformance Test, Test generation, Input/Output Labeled Transition
+	System},
+  owner = {martin},
+  timestamp = {2007.07.27}
+}
+
+@INPROCEEDINGS{Jasper1994,
+  author = {Jasper, Robert and Brennan, Mike and Williamson, Keith and Currier,
+	Bill and Zimmerman, David },
+  title = {Test data generation and feasible path analysis},
+  booktitle = {ISSTA '94: Proceedings of the 1994 ACM SIGSOFT international symposium
+	on Software testing and analysis},
+  year = {1994},
+  pages = {95--107},
+  address = {New York, NY, USA},
+  publisher = {ACM},
+  abstract = {This paper describes techniques used by Test Specification and Determination
+	Tool (TSDT), an experimental prototype for analysis and testing of
+	critical applications written in Ada. Two problems dominate structural
+	testing of programs: exponential explosion in the number of execution
+	paths and feasible path determination, A path is feasible if there
+	exists some input that will cause the path to be traversed during
+	execution. We present techniques based on new representations combined
+	with automated theorem proving to deal with these problems, The paper
+	describes how these techniques can be used to determine the feasibility
+	of expressions containing references to Ada arrays. Finally, we present
+	algorithms specific to generating test data under the modified condition
+	decision coverage (MCDC) criterion. While we realize that many of
+	the problems we are attempting to solve are, in general, undecidable,
+	we are encouraged by preliminary results obtained from running TSDT
+	against vendor supplied code. Based on our results, we feel these
+	techniques can be applied to a broad enough section of Ada code to
+	make them cost effective.},
+  citeulike-article-id = {2638010},
+  doi = {http://doi.acm.org/10.1145/186258.187150},
+  keywords = {bibtex-import, execution, generationsymbolic, infeasibility, problemtest,
+	vector},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/p95-jasper.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:44},
+  priority = {2},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1145/186258.187150}
+}
+
+@ARTICLE{Jia2010,
+  author = {Yue Jia and Mark Harman},
+  title = {An Analysis and Survey of the Development of Mutation Testing},
+  journal = {IEEE Transactions on Software Engineering},
+  year = {2010},
+  volume = {99},
+  number = {PrePrints},
+  address = {Los Alamitos, CA, USA},
+  doi = {http://doi.ieeecomputersociety.org/10.1109/TSE.2010.62},
+  issn = {0098-5589},
+  publisher = {IEEE Computer Society}
+}
+
+@INPROCEEDINGS{Johnsen2004,
+  author = {Johnsen, Einar B. and Owe, Olaf },
+  title = {An Asynchronous Communication Model for Distributed Concurrent Objects},
+  booktitle = {SEFM '04: Proceedings of the Software Engineering and Formal Methods,
+	Second International Conference},
+  year = {2004},
+  pages = {188--197},
+  address = {Washington, DC, USA},
+  publisher = {IEEE Computer Society},
+  citeulike-article-id = {2653554},
+  doi = {http://dx.doi.org/10.1109/SEFM.2004.6},
+  owner = {harald},
+  posted-at = {2008-04-11 12:44:52},
+  priority = {3},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1109/SEFM.2004.6}
+}
+
+@BOOK{Jones1990,
+  title = {Systematic Software Development Using VDM},
+  publisher = {Prentice-Hall},
+  year = {1990},
+  author = {Cliff B. Jones},
+  series = {Series in Computer Science},
+  edition = {second},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Jr.1999,
+  title = {Model Checking},
+  publisher = {The MIT Press},
+  year = {1999},
+  author = {Edmund M. Clarke Jr. and Orna Grumberg and Doron A. Peled},
+  isbn = {0262032708}
+}
+
+@INPROCEEDINGS{Joebstl2010,
+  author = {Jöbstl, Elisabeth and Weiglhofer, Martin and Aichernig, Bernhard
+	K. and Wotawa, Franz},
+  title = {When {BDD}s Fail: Conformance Testing with Symbolic Execution and
+	{SMT} Solving},
+  booktitle = {Proceedings of the 2010 Third International Conference on Software
+	Testing, Verification and Validation},
+  year = {2010},
+  series = {ICST '10},
+  pages = {479--488},
+  address = {Washington, DC, USA},
+  publisher = {IEEE Computer Society},
+  acmid = {1828492},
+  doi = {http://dx.doi.org/10.1109/ICST.2010.48},
+  isbn = {978-0-7695-3990-4},
+  keywords = {model-based testing, symbolic execution, conformance testing, symbolic
+	input-output conformance, symbolic test case generation},
+  numpages = {10},
+  url = {http://dx.doi.org/10.1109/ICST.2010.48}
+}
+
+@TECHREPORT{K.L.McMillan1992,
+  author = {{K.L. McMillan}},
+  title = {The {SMV} system},
+  institution = {Carnegie-Mellon University},
+  year = {1992},
+  number = {CMU-CS-92-131},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Kansomkeat2003,
+  author = {Supaporn Kansomkeat and Wanchai Rivepiboon},
+  title = {Automated-generating test case using {UML} statechart diagrams},
+  booktitle = {Proc. of SAICSIT 2003},
+  year = {2003},
+  pages = {296--300}
+}
+
+@INPROCEEDINGS{Khurshid2003,
+  author = {Khurshid, Sarfraz and Pasareanu, Corina S. and Visser, Willem },
+  title = {Generalized Symbolic Execution for Model Checking and Testing},
+  booktitle = {TACAS},
+  year = {2003},
+  pages = {553--568},
+  abstract = {Modern software systems, which often are concurrent and manipulate
+	complex data structures must be extremely reliable. We present a
+	novel framework based on symbolic execution, for automated checking
+	of such systems. We provide a two-fold generalization of traditional
+	symbolic execution based approaches. First, we define a source to
+	source translation to instrument a program, which enables standard
+	model checkers to perform symbolic execution of the program. Second,
+	we give a novel symbolic execution algorithm that handles dynamically
+	allocated structures (e.g., lists and trees), method preconditions
+	(e.g., acyclicity), data (e.g., integers and strings) and concurrency.
+	The program instrumentation enables a model checker to automatically
+	explore different program heap configurations and manipulate logical
+	formulae on program data (using a decision procedure). We illustrate
+	two applications of our framework: checking correctness of multi-threaded
+	programs that take inputs from unbounded domains with complex structure
+	and generation of non-isomorphic test inputs that satisfy a testing
+	criterion. Our implementation for Java uses the Java PathFinder model
+	checker.},
+  citeulike-article-id = {2638007},
+  keywords = {bibtex-import, bounding, executionloop, generationsymbolic, test,
+	vector},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/GSE.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:44},
+  priority = {2},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Kicillof2007,
+  author = {Nicolas Kicillof and Wolfgang Grieskamp and Nikolai Tillmann and
+	Victor Braberman},
+  title = {Achieving both model and code coverage with automated gray-box testing},
+  booktitle = {A-MOST '07: Proceedings of the 3rd international workshop on Advances
+	in model-based testing},
+  year = {2007},
+  pages = {1--11},
+  address = {New York, NY, USA},
+  publisher = {ACM},
+  doi = {http://doi.acm.org/10.1145/1291535.1291536},
+  isbn = {978-1-59593-850-3},
+  location = {London, United Kingdom},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{King1976,
+  author = {King, James C. },
+  title = {Symbolic execution and program testing},
+  journal = {Commun. ACM},
+  year = {1976},
+  volume = {19},
+  pages = {385--394},
+  number = {7},
+  abstract = {This paper describes the symbolic execution of programs. Instead of
+	supplying the normal inputs to a program (e.g. numbers) one supplies
+	symbols representing arbitrary values. The execution proceeds as
+	in a normal execution except that values may he symbolic formulas
+	over the input symbols. The difficult, yet interesting issues arise
+	during the symbolic execution of conditional branch type statements.
+	A particular system called EFFIGY which provides symbolic execution
+	for program testing and debugging is also described, it interpretively
+	executes programs written in a simple PL/I style programming language.
+	It includes many standard debugging features, the ability to manage
+	and to prove things about symbolic expressions, a simple program
+	testing manager, and a program verifier. A brief discussion of the
+	relationship between symbolic execution and program proving is also
+	included.},
+  address = {New York, NY, USA},
+  citeulike-article-id = {2638012},
+  doi = {http://doi.acm.org/10.1145/360248.360252},
+  keywords = {bibtex-import, execution, generationsymbolic, test, vector},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/p385-king.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:45},
+  priority = {2},
+  publisher = {ACM},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1145/360248.360252}
+}
+
+@ARTICLE{Kleer1984,
+  author = {Johan De Kleer and John Seely Brown},
+  title = {A qualitative physics based on confluences},
+  journal = {Artif. Intell.},
+  year = {1984},
+  volume = {24},
+  pages = {7--83},
+  number = {1-3},
+  address = {Essex, UK},
+  doi = {http://dx.doi.org/10.1016/0004-3702(84)90037-7},
+  issn = {0004-3702},
+  owner = {harald},
+  publisher = {Elsevier Science Publishers Ltd.},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Kozen1983,
+  author = {Dexter Kozen},
+  title = {Results on the Propositional mu-Calculus.},
+  journal = {Theor. Comput. Sci.},
+  year = {1983},
+  volume = {27},
+  pages = {333-354},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Krenn2010,
+  author = {Willibald Krenn and Rupert Schlick and Bernhard K. Aichernig},
+  title = {Mapping {UML} to Labeled Transition Systems for Test-Case Generation
+	-- A Translation via Object-Oriented Action Systems},
+  booktitle = {Proc. of Formal Methods for Components and Objects (FMCO) 2009},
+  year = {2010},
+  volume = {6286},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  owner = {wkrenn},
+  timestamp = {2010.03.18}
+}
+
+@ARTICLE{Krichen2009,
+  author = {Krichen, Moez and Tripakis, Stavros},
+  title = {Conformance testing for real-time systems},
+  journal = {Form. Methods Syst. Des.},
+  year = {2009},
+  volume = {34},
+  pages = {238--304},
+  number = {3},
+  address = {Hingham, MA, USA},
+  doi = {http://dx.doi.org/10.1007/s10703-009-0065-1},
+  issn = {0925-9856},
+  publisher = {Kluwer Academic Publishers}
+}
+
+@BOOK{Kuipers1994,
+  title = {Qualitative Reasoning: Modeling and Simulation with Incomplete Knowledge},
+  publisher = {MIT Press},
+  year = {1994},
+  author = {Kuipers, Benjamin},
+  keywords = {QSIM},
+  owner = {harald},
+  priority = {0},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Larsen2005a,
+  author = {Kim G. Larsen and Marius Mikucionis and Brian Nielsen},
+  title = {Online Testing of Real-Time Systems Using UPPAAL: Status and Future
+	Work},
+  booktitle = {Perspectives of Model-Based Testing},
+  year = {2005},
+  editor = {Ed Brinksma and Wolfgang Grieskamp and Jan Tretmans},
+  number = {04371},
+  series = {Dagstuhl Seminar Proceedings},
+  publisher = {Internationales Begegnungs- und Forschungszentrum fuer Informatik
+	(IBFI), Schloss Dagstuhl, Germany},
+  note = {$<$http://drops.dagstuhl.de/opus/volltexte/2005/326$>$ [date of citation:
+	2005-01-01]},
+  issn = {1862-4405},
+  optaddress = {Dagstuhl, Germany},
+  optannote = {Keywords: Online testing, black-box testing, real-time systems, embedded
+	systems, symbolic state representation, relativized timed input/output
+	conformance, mo},
+  opturl = {http://drops.dagstuhl.de/opus/volltexte/2005/326 [date of citation:
+	2005-01-01]},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Larsen2005,
+  author = {Kim G. Larsen and Marius Mikucionis and Brian Nielsen and Arne Skou},
+  title = {Testing real-time embedded software using UPPAAL-TRON: an industrial
+	case study},
+  booktitle = {EMSOFT '05: Proceedings of the 5th ACM international conference on
+	Embedded software},
+  year = {2005},
+  pages = {299--306},
+  address = {New York, NY, USA},
+  publisher = {ACM},
+  doi = {http://doi.acm.org/10.1145/1086228.1086283},
+  isbn = {1-59593-091-4},
+  location = {Jersey City, NJ, USA},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{LaValle1999,
+  author = {Steven M. LaValle and James J. Kuffner Jr.},
+  title = {Randomized Kinodynamic Planning},
+  booktitle = {International Conference on Robotics and Automation},
+  year = {1999},
+  pages = {473-479},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INCOLLECTION{Leavens1999,
+  author = {Gary T. Leavens and Albert L. Baker and Clyde Ruby},
+  title = {{JML}: {A} Notation for Detailed Design},
+  booktitle = {Behavioral Specifications of Businesses and Systems},
+  publisher = {Kluwer Academic Publishers},
+  year = {1999},
+  editor = {Haim Kilov and Bernhard Rumpe and Ian Simmonds},
+  pages = {175--188},
+  owner = {harald},
+  timestamp = {2009.09.18},
+  url = {citeseer.ist.psu.edu/leavens99jml.html}
+}
+
+@ARTICLE{Lee1996,
+  author = {David Lee and Mihakus Yannakakis},
+  title = {Principles and Methods of Testing Finite State Machines -- A Survey},
+  journal = {Proceedings of the IEEE},
+  year = {1996},
+  volume = {84},
+  pages = {1090--1123},
+  number = {8},
+  month = {August},
+  abstract = {This paper reviews possible test generation techniques on finite state
+	machines. It discusses distinquishing sequences, seperating sequences,
+	intput/output sequences, seperating sequences and so on. It concludes
+	with a short view on other state machine representations such as
+	extended finite state machines and probabilistic state machines.},
+  file = {lee1996principles.pdf:lee1996principles.pdf:PDF},
+  filename = {./test\_generation/lee96principles.pdf},
+  keywords = {Testing, FSM, EFSM, PFSM, NFSM},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Lefebvre2006,
+  author = {Marie-Anne Lefebvre and Hervé Guéguen},
+  title = {Hybrid abstractions of affine systems},
+  journal = {Nonlinear Analysis},
+  year = {2006},
+  volume = {65},
+  pages = {1150 - 1167},
+  number = {6},
+  note = {Hybrid Systems and Applications (5)},
+  doi = {DOI: 10.1016/j.na.2005.12.016},
+  issn = {0362-546X},
+  keywords = {Hybrid systems},
+  url = {http://www.sciencedirect.com/science/article/B6V0Y-4JFGF71-2/2/9f7f4ee86fb16bf7f463a65950bc6feb}
+}
+
+@INPROCEEDINGS{Legeard2002,
+  author = {Bruno Legeard and Fabien Peureux and Mark Utting},
+  title = {Automated Boundary Testing from {Z} and {B}},
+  booktitle = {Proceedings of FME 2002: Formal Methods --- Getting IT Right, International
+	Symposium of Formal Methods Europe, July 2002, Copenhagen, Denmark},
+  year = {2002},
+  editor = {Lars-Henrik Eriksson and Peter A. Lindsay},
+  volume = {2391},
+  series = {Lecture Notes in Computer Science},
+  pages = {21--40},
+  publisher = {Springer-Verlag},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Leveson2004,
+  author = {Nancy G. Leveson},
+  title = {The role of software in spacecraft accidents},
+  journal = {AIAA Journal of Spacecraft and Rockets},
+  year = {2004},
+  volume = {41},
+  pages = {564--575}
+}
+
+@INPROCEEDINGS{Ma2006,
+  author = {Ma, Yu-Seung and Offutt, Jeff and Kwon, Yong-Rae},
+  title = {MuJava: a mutation system for java},
+  booktitle = {ICSE '06: Proceedings of the 28th international conference on Software
+	engineering},
+  year = {2006},
+  pages = {827--830},
+  address = {New York, NY, USA},
+  publisher = {ACM},
+  bdsk-url-1 = {http://doi.acm.org/10.1145/1134285.1134425},
+  doi = {http://doi.acm.org/10.1145/1134285.1134425},
+  isbn = {1-59593-375-1},
+  location = {Shanghai, China}
+}
+
+@INPROCEEDINGS{Maibaum2003,
+  author = {Tom Maibaum},
+  title = {In Memoriam {Armando Mart\'{i}n Haeberer}},
+  booktitle = {Formal Methods at the Crossroads: from Panacea to Foundational Support},
+  year = {2003},
+  editor = {Bernhard K.\ Aichernig and Tom Maibaum},
+  volume = {2757},
+  series = {Lecture Notes in Computer Science},
+  pages = {1--25},
+  publisher = {Springer-Verlag},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PHDTHESIS{Man2006,
+  author = {K.L. Man and R.R.H. Schiffelers},
+  title = {Formal Specification and Analysis of Hybrid Systems},
+  school = {Eindhoven University of Technology},
+  year = {2006},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Matiyasevich1993,
+  title = {Hilbert's tenth problem},
+  publisher = {MIT Press},
+  year = {1993},
+  author = {Matiyasevich, Yuri V.},
+  address = {Cambridge, MA, USA},
+  isbn = {0-262-13295-8}
+}
+
+@BOOK{McMillan1993,
+  title = {Symbolic Model Checking},
+  publisher = {Kluwer Academic Publishers},
+  year = {1993},
+  author = {Kenneth L. McMillan},
+  address = {Norwell, MA, USA},
+  isbn = {0792393805},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Memon2007,
+  author = {Atif M. Memon},
+  title = {An event-flow model of GUI-based applications for testing},
+  journal = {Softw. Test., Verif. Reliab.},
+  year = {2007},
+  volume = {17},
+  pages = {137-157},
+  number = {3},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://dx.doi.org/10.1002/stvr.364},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Meyer1997,
+  title = {Object-Oriented Software Construction},
+  publisher = {Prentice Hall Professional Technical Reference},
+  year = {1997},
+  author = {Bertrand Meyer},
+  abstract = {The developer of the acclaimed Eiffel programming language comes through
+	with one of the clearest and most informative books about computers
+	ever committed to paper. <i>Object-Oriented Software Construction</i>
+	is the gospel of object-oriented technology and it deserves to be
+	spread everywhere. Meyer opens with coverage of the need for an object-oriented
+	approach to software development, citing improved quality and development
+	speed as key advantages of the approach. He then explains all the
+	key criteria that define an object- oriented approach to a problem.
+	Meyer pays attention to techniques, such as classes, objects, memory
+	management, and more, returning to each technique and polishing his
+	readers' knowledge of it as he explains how to employ it "well."
+	In a section on advanced topics, Meyer explores interesting and relevant
+	topics, such as persistent objects stored in a database. He also
+	offers a sort of "Do and Don't" section in which he enumerates common
+	mistakes and ways to avoid them. Management information isn't the
+	main point of <i>Object-Oriented Software Construction</i>, but you'll
+	find some in its pages. Meyer concludes his tour de force with comparisons
+	of all the key object-oriented languages, including Java. He also
+	covers the potential of simulating object technology in non-object-oriented
+	languages, such as Pascal and Fortran. The companion CD-ROM includes
+	the full text of this book in hypertext form, as well as some tools
+	for designing object-oriented systems. If you program computers,
+	you need to read this book. <I>Recipient of the 1997 Jolt Award.</I>
+	<P>The developer of the acclaimed Eiffel programming language comes
+	through with one of the clearest and most informative books about
+	computers ever committed to paper. Object-Oriented Software Construction
+	is the gospel of object-oriented technology and it deserves to be
+	spread everywhere. Meyer opens with coverage of the need for an object-oriented
+	approach to software development, citing improved quality and development
+	speed as key advantages of the approach. He then explains all the
+	key criteria that define an object- oriented approach to a problem.
+	Meyer pays attention to techniques, such as classes, objects, memory
+	management, and more, returning to each technique and polishing his
+	readers' knowledge of it as he explains how to employ it "well."
+	In a section on advanced topics, Meyer explores interesting and relevant
+	topics, such as persistent objects stored in a database. He also
+	offers a sort of "Do and Don't" section in which he enumerates common
+	mistakes and ways to avoid them. Management information isn't the
+	main point of Object-Oriented Software Construction, but you'll find
+	some in its pages. Meyer concludes his tour de force with comparisons
+	of all the key object-oriented languages, including Java. He also
+	covers the potential of simulating object technology in non-object-oriented
+	languages, such as Pascal and Fortran. The companion CD-ROM includes
+	the full text of this book in hypertext form, as well as some tools
+	for designing object-oriented systems. If you program computers,
+	you need to read this book.},
+  isbn = {0-13-629155-4},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Milner1999,
+  title = {Communicating and Mobile Systems: the Pi-Calculus},
+  publisher = {{Cambridge University Press}},
+  year = {1999},
+  author = {Milner, Robin },
+  month = {June},
+  citeulike-article-id = {500640},
+  howpublished = {Paperback},
+  isbn = {0521658691},
+  keywords = {calculus, process},
+  owner = {harald},
+  priority = {3},
+  timestamp = {2009.09.18},
+  url = {http://www.amazon.ca/exec/obidos/redirect?tag=citeulike09-20\&amp;path=ASIN/0521658691}
+}
+
+@BOOK{Milner1982,
+  title = {{A Calculus of Communicating Systems}},
+  publisher = {Springer-Verlag New York, Inc. Secaucus, NJ, USA},
+  year = {1982},
+  author = {Milner, R.},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Morgan1990,
+  title = {Programming from Specifications},
+  publisher = {Prentice-Hall International},
+  year = {1990},
+  author = {Carroll C.\ Morgan},
+  series = {Series in Computer Science},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Mosses1999,
+  author = {Peter D.~Mosses},
+  title = {{CASL}: A guided tour of its design},
+  booktitle = {Proceedings of WADT'98},
+  year = {1999},
+  volume = {1589},
+  series = {Lecture Notes in Computer Science},
+  pages = {216--240},
+  publisher = {Springer-Verlag},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Moura2004,
+  author = {Leonardo de Moura and Sam Owre and Harald Rue{\ss} and John Rushbyand
+	N. Shankar and Maria Sorea and Ashish Tiwari},
+  title = {{SAL 2}},
+  booktitle = {Computer-Aided Verification, {CAV} 2004},
+  year = {2004},
+  editor = {Rajeev Alur and Doron Peled},
+  volume = {3114},
+  series = {Lecture Notes in Computer Science},
+  pages = {496--500},
+  address = {Boston, MA},
+  month = jul,
+  publisher = {Springer-Verlag},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Myers2004,
+  title = {{The Art of Software Testing}},
+  publisher = {Wiley},
+  year = {2004},
+  author = {Myers, G. J. },
+  citeulike-article-id = {2804765},
+  keywords = {fundamentals},
+  owner = {harald},
+  posted-at = {2008-05-16 10:32:55},
+  priority = {4},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Myers2004a,
+  title = {The Art of Software Testing},
+  publisher = {John Wiley \& Sons},
+  year = {2004},
+  author = {Myers, Glenford J. and Sandler, Corey},
+  isbn = {0471469122}
+}
+
+@INPROCEEDINGS{Nahhal2007,
+  author = {Tarik Nahhal and Thao Dang},
+  title = {Test Coverage for Continuous and Hybrid Systems},
+  booktitle = {Computer Aided Verification},
+  year = {2007},
+  pages = {449-462},
+  doi = {http://dx.doi.org/10.1007/978-3-540-73368-3_47},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Nicola1990,
+  author = {Rocco De Nicola and Frits Vaandrager},
+  title = {Action versus state based logics for transition systems},
+  booktitle = {Proceedings of the LITP spring school on theoretical computer science
+	on Semantics of systems of concurrent processes},
+  year = {1990},
+  pages = {407--419},
+  address = {New York, NY, USA},
+  publisher = {Springer-Verlag New York, Inc.},
+  isbn = {0-387-53479-2},
+  location = {La Roche Posay, France},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Nipkow2002,
+  title = {Isabelle/HOL - A Proof Assistant for Higher-Order Logic},
+  publisher = {Springer},
+  year = {2002},
+  author = {Tobias Nipkow and Lawrence C. Paulson and Markus Wenzel},
+  volume = {2283},
+  series = {Lecture Notes in Computer Science},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  isbn = {3-540-43376-7},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Offutt1996,
+  author = {Offutt, A.J. and Jie Pan},
+  title = {Detecting equivalent mutants and the feasible path problem},
+  year = {1996},
+  pages = {224 -236},
+  month = {jun.},
+  doi = {10.1109/CMPASS.1996.507890},
+  journal = {Computer Assurance, 1996. COMPASS '96, 'Systems Integrity. Software
+	Safety. Process Security'. Proceedings of the Eleventh Annual Conference
+	on},
+  keywords = {critical software;equivalent mutant programs;feasible path problem;high
+	reliability;infeasible constraints;mathematical constraint systems;mathematical
+	constraints;mutation testing;proof of concept implementation;software
+	unit testing;test criteria;program testing;safety-critical software;software
+	quality;}
+}
+
+@ARTICLE{Offutt1997,
+  author = {A. Jefferson Offutt and Jie Pan},
+  title = {Automatically Detecting Equivalent Mutants and Infeasible Paths},
+  journal = {Software Testing, Veri and Reliability},
+  year = {1997},
+  volume = {7},
+  pages = {165--192}
+}
+
+@ARTICLE{Oliveira2007,
+  author = {Marcel Oliveira and Ana Cavalcanti and Jim Woodcock},
+  title = {A Denotational Semantics for Circus},
+  journal = {Electr. Notes Theor. Comput. Sci.},
+  year = {2007},
+  volume = {187},
+  pages = {107-123},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://dx.doi.org/10.1016/j.entcs.2006.08.047},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PHDTHESIS{Oster2007,
+  author = {Norbert Oster},
+  title = {Automatische Generierung optimaler struktureller Testdaten f{\"u}r
+	objekt-orientierte Software mittels multi-objektiver Metaheuristiken
+	},
+  school = {Friedrich--Alexander University, Erlangen-N{\"u}rnberg},
+  year = {2007},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Ostrand1998,
+  author = {Thomas Ostrand and Aaron Anodide and Herbert Foster and Tarak Goradia},
+  title = {A visual test development environment for GUI systems},
+  journal = {SIGSOFT Softw. Eng. Notes},
+  year = {1998},
+  volume = {23},
+  pages = {82--92},
+  number = {2},
+  address = {New York, NY, USA},
+  doi = {http://doi.acm.org/10.1145/271775.271793},
+  issn = {0163-5948},
+  owner = {harald},
+  publisher = {ACM},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Ostrand1988,
+  author = {T. J. Ostrand and M. J. Balcer},
+  title = {The category-partition method for specifying and generating fuctional
+	tests},
+  journal = {Commun. ACM},
+  year = {1988},
+  volume = {31},
+  pages = {676--686},
+  number = {6},
+  address = {New York, NY, USA},
+  doi = {http://doi.acm.org/10.1145/62959.62964},
+  issn = {0001-0782},
+  owner = {harald},
+  publisher = {ACM},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Paradkar2005,
+  author = {Paradkar, Amit },
+  title = {Case studies on fault detection effectiveness of model based test
+	generation techniques},
+  booktitle = {A-MOST '05: Proceedings of the 1st international workshop on Advances
+	in model-based testing},
+  year = {2005},
+  pages = {1--7},
+  address = {New York, NY, USA},
+  publisher = {ACM},
+  abstract = {Model-based test generation (MBTG) is becoming an area of active research.
+	These techniques differ in terms of (1) modeling notations used,
+	and (2) the adequacy criteria used for test generation. This paper
+	(1) reviews different classes of MBTG techniques at a conceptual
+	level, and (2) reports results of two case studies comparing various
+	techniques in terms of their fault detection effectiveness. Our results
+	indicate that MBTG technique which employs mutation and explicitly
+	generates state verification sequences has better fault detection
+	effectiveness than those based on boundary values, and predicate
+	coverage criteria for transitions. Instead of a default adequacy
+	criteria, certain techniques allow the user to specify test objectives
+	in addition to the model. Our experience indicates that the task
+	of defining appropriate test objectives is not intuitive. Furthermore,
+	notations provided to describe such test objectives may have inadequate
+	expressive power. We posit the need for a suitable fault modeling
+	notation.},
+  citeulike-article-id = {2638015},
+  doi = {http://doi.acm.org/10.1145/1083274.1083286},
+  keywords = {bibtex-import},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/p12-paradkar.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:45},
+  priority = {2},
+  timestamp = {2009.09.18},
+  url = {http://doi.acm.org/10.1145/1083274.1083286}
+}
+
+@TECHREPORT{Paul2007,
+  author = {Paul},
+  title = {Testing with model checkers: A survey},
+  institution = {Competence Network Softnet Austria},
+  year = {2007},
+  number = {SNA-TR-2007-P2-04},
+  citeulike-article-id = {2637994},
+  keywords = {bibtex-import, tug},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/SNA-TR-2007-P2-04.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:41},
+  priority = {2},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Peischl2007,
+  author = {Peischl, Bernhard and Weiglhofer, Martin and Wotawa, Franz },
+  title = {Executing Abstract Test Cases},
+  booktitle = {In Proceedings of the Model-based Testing Workshop held in conjunction
+	with the 37th Annual Congress of the Gesellschaft fuer Informatik
+	(MOTES 2007)},
+  year = {2007},
+  pages = {421--426},
+  month = {September},
+  abstract = {This paper shows how to use an on-the-fly verification algo rithm,
+	that verifies the equivalence of labeled transition sys tems, for
+	the verification of the input output conformance (ioco) of input
+	output labeled transition systems. Since ioco is usually used for
+	testing there are several requirements on the input output labeled
+	transition system (IOLTS) that are used for test generation. We show
+	how to take care of these requirements during the on-the-fly verification.
+	Thus the presented approach can be applied to IOLTSs that do not
+	initially fulfill these requirements. Finally, we discuss the evaluation
+	of a prototype implementation on the datalink protocol.},
+  citeulike-article-id = {2637992},
+  keywords = {bibtex-import, tug},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/motes2007.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:41},
+  priority = {2},
+  timestamp = {2009.09.18}
+}
+
+@INBOOK{Peled2003,
+  title = {Model Checking and Testing Combined},
+  publisher = {Springer Berlin / Heidelberg},
+  year = {2003},
+  author = {Peled, Doron },
+  volume = {2719/2003},
+  series = {Lecture Notes in Computer Science},
+  month = {jan},
+  abstract = {Model checking is a technique for automatically checking properties
+	of models of systems. We present here several combinations of model
+	checking with testing techniques. This allows checking systems when
+	no model is given, when the model is inaccurate, or when only a part
+	of its description is given.},
+  citeulike-article-id = {2638004},
+  doi = {10.1007/3-540-45061-0\_5},
+  keywords = {bibtex-import, black-box, testing},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/peled-modcheckandtest.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:44},
+  priority = {2},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1007/3-540-45061-0\_5}
+}
+
+@INPROCEEDINGS{Peleska1996,
+  author = {Jan Peleska and Michael Siegel},
+  title = {From Testing Theory to Test Driver Implementation},
+  booktitle = {FME'96: Industrial Benefit and Advances in Formal Methods},
+  year = {1996},
+  editor = {Marie-Claude Gaudel and Jim Woodcock},
+  pages = {538--556},
+  month = {March},
+  publisher = {Springer-Verlag},
+  key = {Peleska\&96},
+  libnum = {6},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Petrenko2002,
+  author = {Alexandre Petrenko and Nina Yevtushenko},
+  title = {Queued Testing of Transition Systems with Inputs and Outputs},
+  booktitle = {Proceedings of the Workshop on Formal Approaches to Testing Of Software
+	(Fates'02), A Satellite Workshop of Concur'02},
+  year = {2002},
+  editor = {Rob Hierons and Thierry J\'{e}ron},
+  pages = {79--94},
+  address = {Brno, Czech Republic},
+  month = {August},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Platzer2008,
+  author = {Andr{\'e} Platzer},
+  title = {Differential Dynamic Logic for Hybrid Systems.},
+  journal = {Journal of Automated Reasoning},
+  year = {2008},
+  volume = {41},
+  pages = {143-189},
+  number = {2},
+  abstract = { Hybrid systems are models for complex physical systems and are defined
+	as dynamical systems with interacting discrete transitions and continuous
+	evolutions along differential equations. With the goal of developing
+	a theoretical and practical foundation for deductive verification
+	of hybrid systems, we introduce a dynamic logic for hybrid programs,
+	which is a program notation for hybrid systems. As a verification
+	technique that is suitable for automation, we introduce a free variable
+	proof calculus with a novel combination of real-valued free variables
+	and Skolemisation for lifting quantifier elimination for real arithmetic
+	to dynamic logic. The calculus is compositional, i.e., it reduces
+	properties of hybrid programs to properties of their parts. Our main
+	result proves that this calculus axiomatises the transition behaviour
+	of hybrid systems completely relative to differential equations.
+	In a case study with cooperating traffic agents of the European Train
+	Control System, we further show that our calculus is well-suited
+	for verifying realistic hybrid systems with parametric system dynamics.
+	},
+  doi = {10.1007/s10817-008-9103-8},
+  issn = {0168-7433},
+  keywords = {dynamic logic, differential equations, sequent calculus, axiomatisation,
+	automated theorem proving, verification of hybrid systems},
+  longjournal = {Journal of Automated Reasoning},
+  medjournal = {J. Autom. Reasoning}
+}
+
+@INCOLLECTION{Platzer2008a,
+  author = {Platzer, André and Quesel, Jan-David},
+  title = {KeYmaera: A Hybrid Theorem Prover for Hybrid Systems (System Description)},
+  booktitle = {Automated Reasoning},
+  publisher = {Springer Berlin, Heidelberg},
+  year = {2008},
+  editor = {Armando, Alessandro and Baumgartner, Peter and Dowek, Gilles},
+  volume = {5195},
+  series = {Lecture Notes in Computer Science},
+  pages = {171-178}
+}
+
+@INPROCEEDINGS{Platzer2008b,
+  author = {Platzer, Andr\'{e} and Quesel, Jan-David},
+  title = {Logical Verification and Systematic Parametric Analysis in Train
+	Control},
+  booktitle = {HSCC '08: Proceedings of the 11th international workshop on Hybrid
+	Systems},
+  year = {2008},
+  pages = {646--649},
+  address = {Berlin, Heidelberg},
+  publisher = {Springer-Verlag},
+  doi = {http://dx.doi.org/10.1007/978-3-540-78929-1_55},
+  isbn = {978-3-540-78928-4},
+  location = {St. Louis, MO, USA}
+}
+
+@INPROCEEDINGS{Pnueli1977,
+  author = {Amir Pnueli},
+  title = {The Temporal Logic of Programs},
+  booktitle = {18th Annual Symposium on Foundations of Computer Science, 31 October-2
+	November, Providence, Rhode Island, USA},
+  year = {1977},
+  pages = {46--57},
+  publisher = {IEEE},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Ronkko2003,
+  author = {Mauno R\"{o}nkk\"{o} and Anders P. Ravn and Kaisa Sere},
+  title = {Hybrid action systems},
+  journal = {Theor. Comput. Sci.},
+  year = {2003},
+  volume = {290},
+  pages = {937--973},
+  number = {1},
+  address = {Essex, UK},
+  doi = {http://dx.doi.org/10.1016/S0304-3975(02)00547-9},
+  issn = {0304-3975},
+  owner = {harald},
+  publisher = {Elsevier Science Publishers Ltd.},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Ronkko1999,
+  author = {R\"{o}nkk\"{o},, Mauno and Sere,, Kaisa},
+  title = {Refinement and Continuous Behaviour},
+  booktitle = {HSCC '99: Proceedings of the Second International Workshop on Hybrid
+	Systems},
+  year = {1999},
+  pages = {223--237},
+  address = {London, UK},
+  publisher = {Springer-Verlag},
+  isbn = {3-540-65734-7}
+}
+
+@BOOK{RAISELanguageGroup1995,
+  title = {The {RAISE} Development Method},
+  publisher = {Prentice Hall},
+  year = {1995},
+  author = {{RAISE Language Group}, The},
+  series = {BCS Practitioner Series},
+  annote = {\CRCS{D.2.1, 000427}},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{RamamoorthyDec.1976,
+  author = {Ramamoorthy, C. V. and Ho and Chen, W. T. },
+  title = {On the Automated Generation of Program Test Data},
+  journal = {Software Engineering, Transactions on},
+  year = {Dec. 1976},
+  volume = {SE-2},
+  pages = {293--300},
+  number = {4},
+  abstract = {Software validation through testing will continue to be a very important
+	tool for ensuring correctness of large scale software systems. Automation
+	of testing tools can greatly enhance their power and reduce testing
+	cost. In,this paper, techniques for automated test data generation
+	are discussed. Given a program graph, a set of paths are identified
+	to satisfy some given testing criteria. When a path or a program
+	segment is specified, symbolic execution is used for generating input
+	constraints which defme a set of inputs for executing this path or
+	segment. Problems encountered in symbolic execution are discussed.
+	A new approach for resolving array reference ambiguities and a procedure
+	for generating test inputs satisfying input constraints are proposed.
+	References to arrays are recorded in a table during symbolic execution
+	and ambiguities are resolved when test data are-generated to evaluate
+	the subscript expressions. The implementation of a test data generator
+	for Fortran programs incorporating these techniques is also described.},
+  citeulike-article-id = {2638011},
+  keywords = {ambiguity, array, bibtex-import, constraint, execution, generation,
+	path, reference, solver, symbolic, test, vector},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/01702386.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:45},
+  priority = {2},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Rapps1985,
+  author = {Sandra Rapps and Elaine J. Weyuker},
+  title = {Selecting Software Test Data Using Data Flow Information},
+  journal = {IEEE Trans. Software Eng.},
+  year = {1985},
+  volume = {11},
+  pages = {367-375},
+  number = {4},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@TECHREPORT{ReactiveSystems2003,
+  author = {{Reactive Systems}},
+  title = {Model-Based Testing and Validation with {Reactis}},
+  institution = {Reactive Systems, Inc.},
+  year = {2003},
+  key = {{Reactive Systems, Inc.}},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Richters1998,
+  author = {Richters, Mark and Gogolla, Martin},
+  title = {On Formalizing the UML Object Constraint Language OCL},
+  journal = {Conceptual Modeling --ER '98},
+  year = {1998},
+  pages = {449--464},
+  abstract = {We present a formal semantics for the Object Constraint Language (OCL)
+	which is part of the Unified Modeling Language (UML) - an emerging
+	standard language and notation for object-oriented analysis and design.
+	In context of information systems modeling, UML class diagrams can
+	be utilized for describing the overall structure, whereas additional
+	integrity constraints and queries are specified with OCL expressions.
+	By using OCL, constraints and queries can be specified in a formal
+	yet comprehensible way. However, the OCL itself is currently defined
+	only in a semi-formal way. Thus the semantics of constraints is in
+	general not precisely defined. Our approach gives precise meaning
+	to OCL concepts and to some central aspects of UML class models.
+	A formal semantics facilitates verification, validation and simulation
+	of models and helps to improve the quality of models and software
+	designs.},
+  date-added = {2008-05-27 02:43:14 +0200},
+  date-modified = {2008-05-27 02:43:14 +0200},
+  owner = {harald},
+  timestamp = {2009.09.18},
+  ty = {CHAPTER},
+  url = {http://www.springerlink.com/content/74bxqmgu9uted4fq}
+}
+
+@INPROCEEDINGS{Rokicki1994,
+  author = {Tomas Rokicki and Chris J. Myers},
+  title = {Automatic Verification of Timed Circuits},
+  booktitle = {CAV '94: Proceedings of the 6th International Conference on Computer
+	Aided Verification},
+  year = {1994},
+  pages = {468--480},
+  address = {London, UK},
+  publisher = {Springer-Verlag},
+  isbn = {3-540-58179-0},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@TECHREPORT{Ronkko1997,
+  author = {Ronkko, Mauno and Ravn, Anders P.},
+  title = {Switches and Jumps in Hybrid Action Systems},
+  year = {1997},
+  publisher = {Turku Centre for Computer Science},
+  source = {http://www.ncstrl.org:8900/ncstrl/servlet/search?formname=detail\&id=oai%3Ancstrlh%3Atucs_fi%3Ancstrl.tucs.fi%2F%2FTUCS-TR-152}
+}
+
+@BOOK{Roscoe1997,
+  title = {The Theory and Practice of Concurrency},
+  publisher = {Prentice Hall PTR},
+  year = {1997},
+  author = {Roscoe, A. W. and Hoare, C. A. R. and Bird, Richard},
+  address = {Upper Saddle River, NJ, USA},
+  isbn = {0136744095}
+}
+
+@BOOK{Rumbaugh2004,
+  title = {The Unified Modeling Language Reference Manual},
+  publisher = {Addison--Wesley},
+  year = {2004},
+  author = {James Rumbaugh and Ivar Jacobson and Grady Booch},
+  edition = {2nd},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Rumbaugh2004a,
+  title = {Unified Modeling Language Reference Manual, The (2nd Edition)},
+  publisher = {Pearson Higher Education},
+  year = {2004},
+  author = {Rumbaugh, James and Jacobson, Ivar and Booch, Grady},
+  isbn = {0321245628}
+}
+
+@BOOK{Russell2002,
+  title = {Artificial Intelligence: A Modern Approach (2nd Edition)},
+  publisher = {{Prentice Hall}},
+  year = {2002},
+  author = {Russell, Stuart J. and Norvig, Peter },
+  howpublished = {Hardcover},
+  isbn = {0137903952},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Say2003,
+  author = {Say, A. C. Cem and Akin, H. Levent},
+  title = {Sound and complete qualitative simulation is impossible},
+  journal = {Artif. Intell.},
+  year = {2003},
+  volume = {149},
+  pages = {251--266},
+  number = {2},
+  address = {Essex, UK},
+  doi = {http://dx.doi.org/10.1016/S0004-3702(03)00077-8},
+  issn = {0004-3702},
+  publisher = {Elsevier Science Publishers Ltd.}
+}
+
+@INPROCEEDINGS{Schlatte2008,
+  author = {Rudolf Schlatte and Bernhard Aichernig and Frank de Boer and Andreas
+	Griesmayer and Einar Broch Johnsen},
+  title = {Testing Concurrent Objects with Application-Specific Schedulers},
+  year = {2008},
+  series = {LNCS},
+  publisher = {Springer-Verlag},
+  note = {To be published in the proceedings for ICTAC 2008},
+  abstract = {In this paper, we propose a novel approach to testing executable models
+	of concurrent objects under application-specific scheduling regimes.
+	Method activations in concurrent objects are modelled as a composition
+	of symbolic automata; this composition expresses all possible interleavings
+	of actions. Scheduler specifications, also modelled as automata,
+	are used to constrain the system execution. Test purposes are expressed
+	as assertions on selected states of the system, and weakest precondition
+	calculation is used to derive the test cases from these test purposes.
+	Our new testing technique is based on the assumption that we have
+	full control over the (application-specific) scheduler, which is
+	the case in our executable models under test. Hence, the enforced
+	scheduling policy becomes an integral part of a test case. This tackles
+	the problem of testing non-deterministic behaviour due to scheduling.},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@TECHREPORT{Sekerinski1996,
+  author = {Sekerinski, Emil and Sere, Kaisa},
+  title = {A Theory of Prioritizing Composition},
+  year = {1996},
+  publisher = {Turku Centre for Computer Science},
+  source = {http://www.ncstrl.org:8900/ncstrl/servlet/search?formname=detail\&id=oai%3Ancstrlh%3Atucs_fi%3Ancstrl.tucs.fi%2F%2FTUCS-TR-5}
+}
+
+@INPROCEEDINGS{Sen2005a,
+  author = {Sen, Koushik and Marinov, Darko and Agha, Gul },
+  title = {CUTE: a concolic unit testing engine for C},
+  booktitle = {ESEC/FSE-13: Proceedings of the 10th European software engineering
+	conference held jointly with 13th ACM SIGSOFT international symposium
+	on Foundations of software engineering},
+  year = {2005},
+  pages = {263--272},
+  address = {New York, NY, USA},
+  publisher = {ACM},
+  abstract = {In unit testing, a program is decomposed into units which are collections
+	of functions. A part of unit can be tested by generating inputs for
+	a single entry function. The entry function may contain pointer arguments,
+	in which case the inputs to the unit are memory graphs. The paper
+	addresses the problem of automating unit testing with memory graphs
+	as inputs. The approach used builds on previous work combining symbolic
+	and concrete execution, and more specifically, using such a combination
+	to generate test inputs to explore all feasible execution paths.
+	The current work develops a method to represent and track constraints
+	that capture the behavior of a symbolic execution of a unit with
+	memory graphs as inputs. Moreover, an efficient constraint solver
+	is proposed to facilitate incremental generation of such test inputs.
+	Finally, CUTE, a tool implementing the method is described together
+	with the results of applying CUTE to real-world examples of C code.},
+  citeulike-article-id = {2236218},
+  doi = {10.1145/1081706.1081750},
+  isbn = {1595930140},
+  keywords = {c, concolic, testing},
+  owner = {harald},
+  posted-at = {2008-04-15 08:49:28},
+  priority = {2},
+  timestamp = {2009.09.18},
+  url = {http://portal.acm.org/citation.cfm?id=1081750}
+}
+
+@ARTICLE{Sims2007,
+  author = {Sims, S. and DuVarney, D.C.},
+  title = {{Experience report: the reactis validation tool}},
+  journal = {Proceedings of the 2007 ACM SIGPLAN international conference on Functional
+	programming},
+  year = {2007},
+  pages = {137--140},
+  owner = {harald},
+  publisher = {ACM Press New York, NY, USA},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Slaughter1998,
+  author = {Sandra A. Slaughter and Donald E. Harter and Mayuram S. Krishnan},
+  title = {Evaluating the cost of software quality},
+  journal = {Commun. ACM},
+  year = {1998},
+  volume = {41},
+  pages = {67--73},
+  number = {8},
+  address = {New York, NY, USA},
+  doi = {http://doi.acm.org/10.1145/280324.280335},
+  issn = {0001-0782},
+  owner = {harald},
+  publisher = {ACM},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Stewart1977,
+  title = {The Foundations of Mathematics},
+  publisher = {Oxford University Press},
+  year = {1977},
+  author = {Ian Stewart and David Tall},
+  owner = {harald},
+  timestamp = {2010.11.03}
+}
+
+@ARTICLE{TaiAug1996,
+  author = {Tai, Kuo C. },
+  title = {Theory of fault-based predicate testing for computer programs},
+  journal = {Software Engineering, Transactions on},
+  year = {Aug 1996},
+  volume = {22},
+  pages = {552--562},
+  number = {8},
+  abstract = {Predicates appear in both the specification and implementation of
+	a program. One approach to software testing, referred to as predicate
+	testing, is to require certain types of tests for a predicate. In
+	this paper, three fault-based testing criteria are defined for compound
+	predicates, which are predicates with one or more AND/OR operators.
+	BOR (boolean operator) testing requires a set of tests to guarantee
+	the detection of (single or multiple) boolean operator faults, including
+	incorrect AND/OR operators and missing/extra NOT operators. BRO (boolean
+	and relational operator) testing requires a set of tests to guarantee
+	the detection of boolean operator faults and relational operator
+	faults (i.e., incorrect relational operators). BRE (boolean and relational
+	expression) testing requires a set of tests to guarantee the detection
+	of boolean operator faults, relational operator faults, and a type
+	of fault involving arithmetical expressions. It is shown that for
+	a compound predicate with n, n>0, AND/OR operators, at most n+2 constraints
+	are needed for BOR testing and at most 2*n+3 constraints for BRO
+	or BRE testing, where each constraint specifies a restriction on
+	the value of each boolean variable or relational expression in the
+	predicate. Algorithms for generating a minimum set of constraints
+	for BOR, BRO, and BRE testing of a compound predicate are given,
+	and the feasibility problem for the generated constraints is discussed.
+	For boolean expressions that contain multiple occurrences of some
+	boolean variables, how to combine BOR testing with the meaningful
+	impact strategy (Weyuker et al., 1994) is described},
+  citeulike-article-id = {2637997},
+  doi = {10.1109/32.536956},
+  keywords = {arithmetical, bibtex-import, boolean, bor, bre, bro, compound, debugging,
+	expression, expressions, fault-based, faults, feasibility, formal,
+	functions, impact, implementation, meaningful, not, operator, operators,
+	predicate, predicates, problem, program, programming, relational,
+	specification, strategy, testing, theoryandor, variable},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:42},
+  priority = {2},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1109/32.536956}
+}
+
+@ARTICLE{Tai17-21May1993,
+  author = {Tai, K. C. },
+  title = {Predicate-based test generation for computer programs},
+  journal = {Software Engineering, 1993. Proceedings., 15th International Conference
+	on},
+  year = {17-21 May 1993},
+  pages = {267--276},
+  citeulike-article-id = {2637996},
+  doi = {10.1109/ICSE.1993.346037},
+  keywords = {and, andor, bibtex-import, boolean, compound, correctness, fault-based,
+	functions, operator, operators, predicates, program, relational,
+	simple, strategies, testing},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/00346037.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:42},
+  priority = {2},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1109/ICSE.1993.346037}
+}
+
+@INPROCEEDINGS{Tan2004,
+  author = {Li Tan and Oleg Sokolsky and Insup Lee},
+  title = {Specification-based Testing with Linear Temporal Logic},
+  booktitle = {Proceedings of IEEE International Conference on Information Reuse
+	and Integration (IRI'04)},
+  year = {2004},
+  pages = {493--498},
+  owner = {gordon},
+  timestamp = {2006.02.20}
+}
+
+@INPROCEEDINGS{Tiwari2002,
+  author = {Tiwari, Ashish and Khanna, Gaurav},
+  title = {Series of Abstractions for Hybrid Automata},
+  booktitle = {Hybrid Systems: Computation and Control},
+  year = {2002},
+  editor = {Tomlin, Claire and Greenstreet, Mark},
+  volume = {2289},
+  series = {Lecture Notes in Computer Science},
+  pages = {425-438},
+  publisher = {Springer Berlin, Heidelberg},
+  affiliation = {SRI International 333 Ravenswood Ave Menlo Park CA USA},
+  url = {http://dx.doi.org/10.1007/3-540-45873-5_36}
+}
+
+@ARTICLE{Tomlin1998,
+  author = {Tomlin, C. and Pappas, G.J. and Sastry, S.},
+  title = {Conflict resolution for air traffic management: a study in multiagent
+	hybrid systems},
+  journal = {Automatic Control, IEEE Transactions on},
+  year = {1998},
+  volume = {43},
+  pages = {509 -521},
+  number = {4},
+  month = apr,
+  doi = {10.1109/9.664154},
+  issn = {0018-9286}
+}
+
+@INPROCEEDINGS{Tretmans2008,
+  author = {Jan Tretmans},
+  title = {Model Based Testing with Labelled Transition Systems},
+  booktitle = {Formal Methods and Testing},
+  year = {2008},
+  editor = {R.M. Hierons and J.P. Bowen and M. Harman},
+  volume = {4949},
+  series = {Lecture Notes in Computer Science},
+  pages = {1--38},
+  publisher = {Springer},
+  comment = {p},
+  file = {tretmans2008model.pdf:tretmans2008model.pdf:PDF},
+  owner = {martin},
+  timestamp = {2008.03.13}
+}
+
+@INPROCEEDINGS{Tretmans1996,
+  author = {Tretmans, Jan },
+  title = {Test Generation with Inputs, Outputs, and Quiescence},
+  booktitle = {TACAs '96: Proceedings of the Second International Workshop on Tools
+	and Algorithms for Construction and Analysis of Systems},
+  year = {1996},
+  pages = {127--146},
+  address = {London, UK},
+  publisher = {Springer-Verlag},
+  citeulike-article-id = {1467403},
+  isbn = {3540610421},
+  keywords = {complete, exhaustive, ioconf, sound},
+  owner = {harald},
+  posted-at = {2008-04-07 15:37:05},
+  priority = {0},
+  timestamp = {2009.09.18},
+  url = {http://portal.acm.org/citation.cfm?id=693775}
+}
+
+@ARTICLE{Tretmans1996a,
+  author = {Jan Tretmans},
+  title = {Test Generation with Inputs, Outputs and Repetitive Quiescence.},
+  journal = {Software - Concepts and Tools},
+  year = {1996},
+  volume = {17},
+  pages = {103--120},
+  number = {3},
+  comment = {p,r},
+  file = {tretmans1996testgeneration.pdf:tretmans1996testgeneration.pdf:PDF},
+  keywords = {ioco},
+  owner = {martin},
+  timestamp = {2007.07.31}
+}
+
+@INPROCEEDINGS{Tretmans2003,
+  author = {Jan Tretmans and Ed Brinksma},
+  title = {{TorX}: Automated Model Based Testing},
+  booktitle = {Proceedings of the 1st European Conference on Model-Driven Software
+	Engineering},
+  year = {2003},
+  editor = {A. Hartman and K. Dussa-Zieger},
+  pages = {13--25},
+  address = {Nurnburg, Germany},
+  abstract = {Similar to the TGV-Tool, this tool relaies on the IOCO-Relation for
+	test generation. There are two main differences. The first one is
+	, that TorX does not produce a test case but sends Input-Sequences
+	directly to the IUT while construction the LTS. The second one is
+	that TorX does not use a test purpose but generates the test sequence
+	randomly.},
+  comment = {p,r},
+  file = {tretmans2003torx.pdf:tretmans2003torx.pdf:PDF},
+  filename = {./test\_generation/trej2003-torx.pdf},
+  keywords = {Testing, Conformance Test, Test generation, I/O LTS},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Utting2006,
+  title = {Practical Model-Based Testing: A Tools Approach},
+  publisher = {Morgan Kaufmann Publishers Inc.},
+  year = {2006},
+  author = {Utting, Mark and Legeard, Bruno },
+  address = {San Francisco, CA, USA},
+  citeulike-article-id = {2637985},
+  keywords = {bibtex-import, tug},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:40},
+  priority = {2},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Vanzin2006,
+  author = {Daniel D. Vanzin and Ivan L. Martins and Joao Bosco A. Pereira Filho},
+  title = {TDE UML Editor - A Success Development Case of a Software Extension},
+  booktitle = {ICGSE '06: Proceedings of the IEEE international conference on Global
+	Software Engineering},
+  year = {2006},
+  pages = {257--258},
+  address = {Washington, DC, USA},
+  publisher = {IEEE Computer Society},
+  isbn = {0-7695-2663-2},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Warmer1998,
+  title = {The {Object Constraint Language}: Precise Modeling with {UML}},
+  publisher = {Addison-Wesley},
+  year = {1998},
+  author = {Jos Warmer and Anneke Kleppe},
+  isbn = {0-201-37940-6},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Weiglhofer2008,
+  author = {Martin Weiglhofer and Franz Wotawa},
+  title = {Random vs. Scenario-Based vs. Fault-Based Testing -- An Industrial
+	Evaluation of Formal Black-Box Testing Methods},
+  booktitle = {Proceedings of the 3rd International Conference on Evaluation of
+	Novel Approaches to Software Engineering},
+  year = {2008},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@INPROCEEDINGS{Weiglhofer2008a,
+  author = {Martin Weiglhofer and Franz Wotawa},
+  title = {"{O}n the fly" input output conformance verification},
+  booktitle = {Proceedings of the IASTED International Conference on Software Engineering},
+  year = {2008},
+  address = {Innsbruck, Austria},
+  month = {February},
+  note = {To appear.},
+  comment = {a},
+  file = {weiglhofer2008onthefly.pdf:weiglhofer2008onthefly.pdf:PDF},
+  owner = {martin},
+  timestamp = {2007.10.09}
+}
+
+@INPROCEEDINGS{Wong2010,
+  author = {Wong, W.E. and Debroy, V. and Surampudi, A. and HyeonJeong Kim and
+	Siok, M.F.},
+  title = {Recent Catastrophic Accidents: Investigating How Software was Responsible},
+  booktitle = {Secure Software Integration and Reliability Improvement (SSIRI),
+	2010 Fourth International Conference on},
+  year = {2010},
+  pages = {14 -22},
+  month = june,
+  doi = {10.1109/SSIRI.2010.38},
+  keywords = {accident avoidance;causative factor;recent catastrophic accidents;safety-critical
+	software;safety-critical software;}
+}
+
+@INPROCEEDINGS{Wotawa2007,
+  author = {Franz Wotawa},
+  title = {Generating test-cases from qualitative knowledge -- Preliminary report},
+  booktitle = {Proceedings of the 21st Annual Workshop on Qualitative Reasoning},
+  year = {2007},
+  address = {Aberystwyth, U.K.},
+  month = {June},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Xie2007,
+  author = {Qing Xie and Atif M. Memon},
+  title = {Designing and comparing automated test oracles for GUI-based software
+	applications},
+  journal = {ACM Trans. Softw. Eng. Methodol.},
+  year = {2007},
+  volume = {16},
+  number = {1},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  ee = {http://doi.acm.org/10.1145/1189748.1189752},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@ARTICLE{Yates1989,
+  author = {Yates, D. and Malevris, N. },
+  title = {Reducing the effects of infeasible paths in branch testing},
+  journal = {SIGSOFT Softw. Eng. Notes},
+  year = {1989},
+  volume = {14},
+  pages = {48--54},
+  number = {8},
+  address = {New York, NY, USA},
+  citeulike-article-id = {2637995},
+  doi = {http://doi.acm.org/10.1145/75309.75315},
+  keywords = {bibtex-import},
+  local-url = {file://localhost/Users/michele/mogentes/bibliography/p48-yates.pdf},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:42},
+  priority = {2},
+  publisher = {ACM},
+  timestamp = {2009.09.18},
+  url = {http://dx.doi.org/10.1145/75309.75315}
+}
+
+@BOOK{Young2005,
+  title = {Software Testing and Analysis: Process, Principles and Techniques},
+  publisher = {John Wiley \& Sons},
+  year = {2005},
+  author = {Young, Michal and Pezze, Mauro },
+  citeulike-article-id = {2638003},
+  keywords = {bibtex-import, coverage, criteriainfeasibility, problem},
+  owner = {harald},
+  posted-at = {2008-04-07 16:23:44},
+  priority = {2},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Alur2003,
+  title = {Embedded Software, Third International Conference, EMSOFT 2003, Philadelphia,
+	PA, USA, October 13-15, 2003, Proceedings},
+  year = {2003},
+  editor = {Rajeev Alur and Insup Lee},
+  volume = {2855},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {EMSOFT},
+  isbn = {3-540-20223-4},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Arabnia2007,
+  title = {Proceedings of the 2007 International Conference on Software Engineering
+	Research {\&} Practice, SERP 2007, Volume II, June 25-28, 2007, Las
+	Vegas Nevada, USA},
+  year = {2007},
+  editor = {Hamid R. Arabnia and Hassan Reza},
+  publisher = {CSREA Press},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {Software Engineering Research and Practice},
+  isbn = {1-60132-034-5},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Avrunin2004,
+  title = {Proceedings of the ACM/SIGSOFT International Symposium on Software
+	Testing and Analysis, ISSTA 2004, Boston, Massachusetts, USA, July
+	11-14, 2004},
+  year = {2004},
+  editor = {George S. Avrunin and Gregg Rothermel},
+  publisher = {ACM},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {ISSTA},
+  isbn = {1-58113-820-2},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Ball2006a,
+  title = {Computer Aided Verification, 18th International Conference, CAV 2006,
+	Seattle, WA, USA, August 17-20, 2006, Proceedings},
+  year = {2006},
+  editor = {Thomas Ball and Robert B. Jones},
+  volume = {4144},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {CAV},
+  isbn = {3-540-37406-X},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Beckert2008,
+  title = {Tests and Proofs, Second International Conference, TAP 2008, Prato,
+	Italy, April 9-11, 2008. Proceedings},
+  year = {2008},
+  editor = {Bernhard Beckert and Reiner H{\"a}hnle},
+  volume = {4966},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {TAP},
+  isbn = {978-3-540-79123-2},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Bemporad2007,
+  title = {Hybrid Systems: Computation and Control, 10th International Workshop,
+	HSCC 2007, Pisa, Italy, April 3-5, 2007, Proceedings},
+  year = {2007},
+  editor = {Alberto Bemporad and Antonio Bicchi and Giorgio C. Buttazzo},
+  volume = {4416},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {HSCC},
+  isbn = {978-3-540-71492-7},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Berbers2006,
+  title = {Proceedings of the 2006 EuroSys Conference, Leuven, Belgium, April
+	18-21, 2006},
+  year = {2006},
+  editor = {Yolande Berbers and Willy Zwaenepoel},
+  publisher = {ACM},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {EuroSys},
+  isbn = {1-59593-322-0},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Bernardo2004,
+  title = {Formal Methods for the Design of Real-Time Systems, International
+	School on Formal Methods for the Design of Computer, Communication
+	and Software Systems, SFM-RT 2004, Bertinoro, Italy, September 13-18,
+	2004, Revised Lectures},
+  year = {2004},
+  editor = {Marco Bernardo and Flavio Corradini},
+  volume = {3185},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {SFM},
+  isbn = {3-540-23068-8},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Brim2007,
+  title = {Formal Methods: Applications and Technology, 11th International Workshop,
+	FMICS 2006 and 5th International Workshop PDMC 2006, Bonn, Germany,
+	August 26-27, and August 31, 2006, Revised Selected Papers},
+  year = {2007},
+  editor = {Lubos Brim and Boudewijn R. Haverkort and Martin Leucker and Jaco
+	van de Pol},
+  volume = {4346},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {FMICS/PDMC},
+  isbn = {978-3-540-70951-0},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Broy2005,
+  title = {Model-Based Testing of Reactive Systems},
+  year = {2005},
+  editor = {Manfred Broy and Bengt Jonsson and Joost-Pieter Katoen and Martin
+	Leucker and Alexander Pretschner},
+  volume = {3472},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {Model-Based Testing of Reactive Systems},
+  isbn = {3-540-26278-4},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Buxton1970,
+  title = {Software Engineering Techniques: Report of a conference sponsored
+	by the NATO Science Committee, Rome, Italy, 27-31 Oct. 1969, Brussels,
+	Scientific Affairs Division, NATO},
+  year = {1970},
+  editor = {Buxton, J. N. and Randell, B.}
+}
+
+@PROCEEDINGS{Cassez2001,
+  title = {Modeling and Verification of Parallel Processes, 4th Summer School,
+	MOVEP 2000, Nantes, France, June 19-23, 2000},
+  year = {2001},
+  editor = {Franck Cassez and Claude Jard and Brigitte Rozoy and Mark Dermot
+	Ryan},
+  volume = {2067},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {MOVEP},
+  isbn = {3-540-42787-2},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Chechik2009,
+  title = {Fundamental Approaches to Software Engineering, 12th International
+	Conference, FASE 2009, Held as Part of the Joint European Conferences
+	on Theory and Practice of Software, ETAPS 2009, York, UK, March 22-29,
+	2009. Proceedings},
+  year = {2009},
+  editor = {Marsha Chechik and Martin Wirsing},
+  volume = {5503},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {FASE},
+  ee = {http://dx.doi.org/10.1007/978-3-642-00593-0},
+  isbn = {978-3-642-00592-3},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Cin2005,
+  title = {Dependable Computing - EDCC-5, 5th European Dependable Computing
+	Conference, Budapest, Hungary, April 20-22, 2005, Proceedings},
+  year = {2005},
+  editor = {Mario Dal Cin and Mohamed Ka{\^a}niche and Andr{\'a}s Pataricza},
+  volume = {3463},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {EDCC},
+  isbn = {3-540-25723-3},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Damm2007,
+  title = {Computer Aided Verification, 19th International Conference, CAV 2007,
+	Berlin, Germany, July 3-7, 2007, Proceedings},
+  year = {2007},
+  editor = {Werner Damm and Holger Hermanns},
+  volume = {4590},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {CAV},
+  isbn = {978-3-540-73367-6},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{DangVan2002,
+  title = {Specification case studies in RAISE},
+  publisher = {Springer-Verlag},
+  year = {2002},
+  editor = {Dang Van, H. and George, C. and Janowski, T. and Moore, R. },
+  address = {London, UK},
+  isbn = {1-85233-359-6},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Dershowitz2003,
+  title = {Verification: Theory and Practice, Essays Dedicated to Zohar Manna
+	on the Occasion of His 64th Birthday},
+  year = {2003},
+  editor = {Nachum Dershowitz},
+  volume = {2772},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {Verification: Theory and Practice},
+  isbn = {3-540-21002-4},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Dacker2003,
+  title = {Proceedings of the 2003 ACM SIGPLAN Workshop on Erlang, Uppsala,
+	Sweden, August 29, 2003},
+  year = {2003},
+  editor = {Bjarne D{\"a}cker and Thomas Arts},
+  publisher = {ACM},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {Erlang Workshop},
+  isbn = {1-58113-772-9},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Fitzgerald2005,
+  title = {FM 2005: Formal Methods, International Symposium of Formal Methods
+	Europe, Newcastle, UK, July 18-22, 2005, Proceedings},
+  year = {2005},
+  editor = {John Fitzgerald and Ian J. Hayes and Andrzej Tarlecki},
+  volume = {3582},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {FM},
+  isbn = {3-540-27882-6},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Garavel2003,
+  title = {Tools and Algorithms for the Construction and Analysis of Systems,
+	9th International Conference, TACAS 2003, Held as Part of the Joint
+	European Conferences on Theory and Practice of Software, ETAPS 2003,
+	Warsaw, Poland, April 7-11, 2003, Proceedings},
+  year = {2003},
+  editor = {Hubert Garavel and John Hatcliff},
+  volume = {2619},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {TACAS},
+  isbn = {3-540-00898-5},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Grabowski2005,
+  title = {Formal Approaches to Software Testing, 4th International Workshop,
+	FATES 2004, Linz, Austria, September 21, 2004, Revised Selected Papers},
+  year = {2005},
+  editor = {Jens Grabowski and Brian Nielsen},
+  volume = {3395},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {FATES},
+  isbn = {3-540-25109-X},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Grieskamp2000,
+  title = {Integrated Formal Methods, Second International Conference, IFM 2000,
+	Dagstuhl Castle, Germany, November 1-3, 2000, Proceedings},
+  year = {2000},
+  editor = {Wolfgang Grieskamp and Thomas Santen and Bill Stoddart},
+  volume = {1945},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {IFM},
+  isbn = {3-540-41196-8},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Grieskamp2006a,
+  title = {Formal Approaches to Software Testing, 5th International Workshop,
+	FATES 2005, Edinburgh, UK, July 11, 2005, Revised Selected Papers},
+  year = {2006},
+  editor = {Wolfgang Grieskamp and Carsten Weise},
+  volume = {3997},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {FATES},
+  isbn = {3-540-34454-3},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Halbwachs2005,
+  title = {Tools and Algorithms for the Construction and Analysis of Systems,
+	11th International Conference, TACAS 2005, Held as Part of the Joint
+	European Conferences on Theory and Practice of Software, ETAPS 2005,
+	Edinburgh, UK, April 4-8, 2005, Proceedings},
+  year = {2005},
+  editor = {Nicolas Halbwachs and Lenore D. Zuck},
+  volume = {3440},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {TACAS},
+  isbn = {3-540-25333-5},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Havelund2006,
+  title = {Formal Approaches to Software Testing and Runtime Verification, First
+	Combined International Workshops, FATES 2006 and RV 2006, Seattle,
+	WA, USA, August 15-16, 2006, Revised Selected Papers},
+  year = {2006},
+  editor = {Klaus Havelund and Manuel N{\'u}{\~n}ez and Grigore Rosu and Burkhart
+	Wolff},
+  volume = {4262},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {FATES/RV},
+  isbn = {3-540-49699-8},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Hierons2008,
+  title = {Formal Methods and Testing, An Outcome of the FORTEST Network, Revised
+	Selected Papers},
+  year = {2008},
+  editor = {Robert M. Hierons and Jonathan P. Bowen and Mark Harman},
+  volume = {4949},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {Formal Methods and Testing},
+  isbn = {978-3-540-78916-1},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Juels2006,
+  title = {Proceedings of the 13th ACM Conference on Computer and Communications
+	Security, CCS 2006, Alexandria, VA, USA, Ioctober 30 - November 3,
+	2006},
+  year = {2006},
+  editor = {Ari Juels and Rebecca N. Wright and Sabrina De Capitani di Vimercati},
+  publisher = {ACM},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {ACM Conference on Computer and Communications Security},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Karras2007,
+  title = {International Conference on Software Engineering Theory and Practice,
+	SETP-07, Orlando, Florida, USA, July 9-12 2007},
+  year = {2007},
+  editor = {Dimitris A. Karras and Daming Wei and Jaroslav Zendulka},
+  publisher = {ISRST},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {SETP},
+  isbn = {978-0-9727412-6-2},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Katoen2002,
+  title = {Tools and Algorithms for the Construction and Analysis of Systems,
+	8th International Conference, TACAS 2002, Held as Part of the Joint
+	European Conference on Theory and Practice of Software, ETAPS 2002,
+	Grenoble, France, April 8-12, 2002, Proceedings},
+  year = {2002},
+  editor = {Joost-Pieter Katoen and Perdita Stevens},
+  volume = {2280},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {TACAS},
+  isbn = {3-540-43419-4},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Kaagstrom1998,
+  title = {Applied Parallel Computing, Large Scale Scientific and Industrial
+	Problems, 4th International Workshop, PARA '98, Ume{\aa}, Sweden,
+	June 14-17, 1998, Proceedings},
+  year = {1998},
+  editor = {Bo K{\aa}gstr{\"o}m and Jack Dongarra and Erik Elmroth and Jerzy
+	Wasniewski},
+  volume = {1541},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {PARA},
+  isbn = {3-540-65414-3},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Lamsweerde1991,
+  title = {ESEC '91, 3rd European Software Engineering Conference, Milan, Italy,
+	October 21-24, 1991, Proceedings},
+  year = {1991},
+  editor = {Axel van Lamsweerde and Alfonso Fugetta},
+  volume = {550},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {ESEC},
+  isbn = {3-540-54742-8},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Leucker2009,
+  title = {Theoretical Aspects of Computing - ICTAC 2009, 6th International
+	Colloquium, Kuala Lumpur, Malaysia, August 16-20, 2009. Proceedings},
+  year = {2009},
+  editor = {Martin Leucker and Carroll Morgan},
+  volume = {5684},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {ICTAC},
+  ee = {http://dx.doi.org/10.1007/978-3-642-03466-4},
+  isbn = {978-3-642-03465-7},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Misra2006,
+  title = {FM 2006: Formal Methods, 14th International Symposium on Formal Methods,
+	Hamilton, Canada, August 21-27, 2006, Proceedings},
+  year = {2006},
+  editor = {Jayadev Misra and Tobias Nipkow and Emil Sekerinski},
+  volume = {4085},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {FM},
+  isbn = {3-540-37215-6},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Mosses1995,
+  title = {TAPSOFT'95: Theory and Practice of Software Development, 6th International
+	Joint Conference CAAP/FASE, Aarhus, Denmark, May 22-26, 1995, Proceedings},
+  year = {1995},
+  editor = {Peter D. Mosses and Mogens Nielsen and Michael I. Schwartzbach},
+  volume = {915},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {TAPSOFT},
+  isbn = {3-540-59293-8},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Petrenko2007,
+  title = {Testing of Software and Communicating Systems, 19th IFIP TC6/WG6.1
+	International Conference, TestCom 2007, 7th International Workshop,
+	FATES 2007, Tallinn, Estonia, June 26-29, 2007, Proceedings},
+  year = {2007},
+  editor = {Alexandre Petrenko and Margus Veanes and Jan Tretmans and Wolfgang
+	Grieskamp},
+  volume = {4581},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {TestCom/FATES},
+  isbn = {978-3-540-73065-1},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Rafiq1994,
+  title = {Protocol Test Systems, VI, Proceedings of the IFIP TC6/WG6.1 Sixth
+	International Workshop on Protocol Test systems, Pau, France, 28-30
+	September, 1993},
+  year = {1994},
+  editor = {Omar Rafiq},
+  volume = {C-19},
+  series = {IFIP Transactions},
+  publisher = {North-Holland},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {Protocol Test Systems},
+  isbn = {0-444-81697-6},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Ramakrishnan2008,
+  title = {Tools and Algorithms for the Construction and Analysis of Systems,
+	14th International Conference, TACAS 2008, Held as Part of the Joint
+	European Conferences on Theory and Practice of Software, ETAPS 2008,
+	Budapest, Hungary, March 29-April 6, 2008. Proceedings},
+  year = {2008},
+  editor = {C. R. Ramakrishnan and Jakob Rehof},
+  volume = {4963},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {TACAS},
+  isbn = {978-3-540-78799-0},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Reed2001,
+  title = {SDL 2001: Meeting UML, 10th International SDL Forum Copenhagen, Denmark,
+	June 27-29, 2001, Proceedings},
+  year = {2001},
+  editor = {Rick Reed and Jeanne Reed},
+  volume = {2078},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {SDL Forum},
+  isbn = {3-540-42281-1},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Robby2008,
+  title = {30th International Conference on Software Engineering (ICSE 2008),
+	Leipzig, Germany, May 10-18, 2008, Companion Volume},
+  year = {2008},
+  editor = {Robby},
+  publisher = {ACM},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {ICSE Companion},
+  isbn = {978-1-60558-079-1},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Robby2008a,
+  title = {30th International Conference on Software Engineering (ICSE 2008),
+	Leipzig, Germany, May 10-18, 2008},
+  year = {2008},
+  editor = {Robby},
+  publisher = {ACM},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {ICSE},
+  isbn = {978-1-60558-079-1},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Sangiorgi1998,
+  title = {CONCUR '98: Concurrency Theory, 9th International Conference, Nice,
+	France, September 8-11, 1998, Proceedings},
+  year = {1998},
+  editor = {Davide Sangiorgi and Robert de Simone},
+  volume = {1466},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {CONCUR},
+  isbn = {3-540-64896-8},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Sarkar2005,
+  title = {Proceedings of the ACM SIGPLAN 2005 Conference on Programming Language
+	Design and Implementation, Chicago, IL, USA, June 12-15, 2005},
+  year = {2005},
+  editor = {Vivek Sarkar and Mary W. Hall},
+  publisher = {ACM},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {PLDI},
+  isbn = {1-59593-056-6},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Sherratt2003,
+  title = {Telecommunications and beyond: The Broader Applicability of SDL and
+	MSC, Third International Workshop, SAM 2002, Aberystwyth, UK, June
+	24-26, 2002. Revised Papers},
+  year = {2003},
+  editor = {Edel Sherratt},
+  volume = {2599},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {SAM},
+  isbn = {3-540-00877-2},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@BOOK{Tretmans2007,
+  title = {Tangram: Model-based integration and testing of complex high-tech
+	systems},
+  publisher = {Embedded Systems Institute, Eindhoven, The Netherlands},
+  year = {2007},
+  editor = {Jan Tretmans},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Uyar2006,
+  title = {Testing of Communicating Systems, 18th IFIP TC6/WG6.1 International
+	Conference, TestCom 2006, New York, NY, USA, May 16-18, 2006, Proceedings},
+  year = {2006},
+  editor = {M. {\"U}mit Uyar and Ali Y. Duale and Mariusz A. Fecko},
+  volume = {3964},
+  series = {Lecture Notes in Computer Science},
+  publisher = {Springer},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {TestCom},
+  isbn = {3-540-34184-6},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{Wermelinger2005,
+  title = {Proceedings of the 10th European Software Engineering Conference
+	held jointly with 13th ACM SIGSOFT International Symposium on Foundations
+	of Software Engineering, 2005, Lisbon, Portugal, September 5-9, 2005},
+  year = {2005},
+  editor = {Michel Wermelinger and Harald Gall},
+  publisher = {ACM},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {ESEC/SIGSOFT FSE},
+  isbn = {1-59593-014-0},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@MISC{,
+  title = {{T-VEC Tester for Simulink homepage}},
+  howpublished = {\url{http://www.t-vec.com/solutions/simulink.php}},
+  note = {(checked Aug 10, 2009)},
+  key = {t-vec-homepage},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@MISC{,
+  title = {{Simulink Design Verifier homepage}},
+  howpublished = {\url{http://www.mathworks.com/products/sldesignverifier/}},
+  note = {(checked Aug 10, 2009)},
+  key = {simulink-design-verifier-homepage},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@MISC{,
+  title = {{SCADE} product page},
+  howpublished = {\url{http://www.esterel-technologies.com/products/scade-suite/}},
+  note = {(checked Aug 10, 2009)},
+  key = {scade-homepage},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@MISC{,
+  title = {{MaTeLo Product Page}},
+  howpublished = {\url{http://www.all4tec.net/index.php/All4tec/matelo-product.html}},
+  note = {(checked Aug 5, 2009)},
+  key = {MaTeLo},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@MISC{,
+  title = {{BEACON Tester homepage}},
+  howpublished = {\url{http://www.adi.com/products\_be\_bss\_te.htm}},
+  note = {(checked Aug 10, 2009)},
+  key = {beacon-homepage},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@MISC{,
+  title = {{IBM Rational Tau product page}},
+  howpublished = {\url{http://www.telelogic.com/products/tau/}},
+  note = {(checked August 5, 2009)},
+  key = {tautoolset},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{2007,
+  title = {2007 IEEE Symposium on Security and Privacy (S{\&}P 2007), 20-23
+	May 2007, Oakland, California, USA},
+  year = {2007},
+  publisher = {IEEE Computer Society},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {IEEE Symposium on Security and Privacy},
+  key = {IEEE},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@MISC{2006,
+  title = {Standard ECMA--335, Common Language Infrastructure (CLI)},
+  month = {June},
+  year = {2006},
+  key = {ECMA},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{2006a,
+  title = {Proceedings of the Canadian Conference on Electrical and Computer
+	Engineering, CCECE 2007, May 7, 10, 2006, Ottawa Congress Centre,
+	Ottawa, Canada},
+  year = {2006},
+  publisher = {IEEE},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {CCECE},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{2004,
+  title = {10th IEEE Real-Time and Embedded Technology and Applications Symposium
+	(RTAS 2004), 25-28 May 2004, Toronto, Canada},
+  year = {2004},
+  publisher = {IEEE Computer Society},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {IEEE Real-Time and Embedded Technology and Applications Symposium},
+  isbn = {0-7695-2148-7},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{2003,
+  title = {3rd International Conference on Quality Software (QSIC 2003), 6-7
+	November 2003, Dallas, TX, USA},
+  year = {2003},
+  publisher = {IEEE Computer Society},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {QSIC},
+  isbn = {0-7695-2015-4},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{2002,
+  title = {8th International Conference on Engineering of Complex Computer Systems
+	(ICECCS 2002), 2-4 December 2002, Greenbelt, MD, USA},
+  year = {2002},
+  publisher = {IEEE Computer Society},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {ICECCS},
+  isbn = {0-7695-1757-9},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@PROCEEDINGS{1998,
+  title = {2nd Workshop on Industrial-Strength Formal Specification Techniques
+	(WIFT '98), October 20-23, 1998, Boca Raton, FL, USA},
+  year = {1998},
+  publisher = {IEEE Computer Society},
+  bibsource = {DBLP, http://dblp.uni-trier.de},
+  booktitle = {WIFT},
+  isbn = {0-7695-0081-1},
+  owner = {harald},
+  timestamp = {2009.09.18}
+}
+
+@comment{jabref-meta: selector_publisher:}
+
+@comment{jabref-meta: selector_author:}
+
+@comment{jabref-meta: selector_journal:}
+
+@comment{jabref-meta: selector_keywords:}
+
Index: branches/compiler/cSharp/ooasCompiler/src/Properties/AssemblyInfo.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/Properties/AssemblyInfo.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/Properties/AssemblyInfo.cs	(revision 3)
@@ -0,0 +1,57 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// Allgemeine Informationen über eine Assembly werden über die folgenden 
+// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
+// die mit einer Assembly verknüpft sind.
+[assembly: AssemblyTitle("Ulysses")]
+[assembly: AssemblyDescription("OO-Action System Testcase Generation")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("Graz University of Technology, AIT Austrian Institute of Technology")]
+[assembly: AssemblyProduct("Argos Parser")]
+[assembly: AssemblyCopyright("Copyright ©  2009, 2010, 2011, 2013 Willibald Krenn, Stefan Tiran")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar 
+// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von 
+// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
+[assembly: ComVisible(false)]
+
+// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
+[assembly: Guid("4b887855-8e5e-4bf1-afb8-cd61c3594c5d")]
+
+// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
+//
+//      Hauptversion
+//      Nebenversion 
+//      Buildnummer
+//      Revision
+//
+// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern 
+// übernehmen, indem Sie "*" eingeben:
+// [assembly: AssemblyVersion("1.0.*")]
+
+// argosmain.argosminor.grammarversion.buildnumber
+[assembly: AssemblyVersion("0.41.5.691")]
+
+//[assembly: AssemblyFileVersion("0.28.100.*")]
Index: branches/compiler/cSharp/ooasCompiler/src/codegen/CSharp/ooaCSharpCodeGen.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/codegen/CSharp/ooaCSharpCodeGen.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/codegen/CSharp/ooaCSharpCodeGen.cs	(revision 3)
@@ -0,0 +1,485 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+/*
+ * Limited C# code generation capabilities. Used for ooaObjectInstantiateVisitor to
+ * detect how many objects the system creates.
+*/
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TUG.Mogentes.Codegen;
+
+
+
+namespace TUG.Mogentes.Codegen.CSharp
+{
+
+    public sealed class CSharpIdentifier
+    {
+        public static string GetIdentifierString(string anIdentifier)
+        {
+            return String.Format("_{0}", anIdentifier);
+        }
+    }
+
+
+
+    public sealed class CSharpType : OoaTypeVisitor
+    {
+        private OoaCodeEmitter m_emitter = new OoaCodeEmitter();
+
+        private string GetIdentifierString(string anIdentifier)
+        {
+            return CSharpIdentifier.GetIdentifierString(anIdentifier);
+        }
+
+
+
+        public override void visit(CharType charType)
+        {
+            m_emitter.Append("int"); // ToDo: map to char?
+        }
+
+        public override void visit(IntType intType)
+        {
+            m_emitter.Append("int");
+        }
+
+        public override void visit(BoolType boolType)
+        {
+            m_emitter.Append("bool");
+        }
+
+        public override void visit(FloatType floatType)
+        {
+            m_emitter.Append("double");
+        }
+
+        public override void visit(EnumType enumType)
+        {
+            m_emitter.Append(GetIdentifierString(enumType.identifier.tokenText));
+        }
+
+        public override void visit(ListType listType)
+        {
+            m_emitter.Append("TUG.Mogentes.Codegen.CSharp.UlyssesList<object>");
+            //listType.innerType.Accept(this);
+            //m_emitter.Append(">");
+        }
+
+        public override void visit(MapType mapType)
+        {
+            //System.Collections.Generic.Dictionary
+            m_emitter.Append("UlyssesDictionary<object,object>");
+            //mapType.fromType.Accept(this);
+            //m_emitter.Append(",");
+            //mapType.toType.Accept(this);
+            //m_emitter.Append(">");
+        }
+
+        public override void visit(QrType qrType)
+        {
+            m_emitter.Append("UlyssesQualitativeValue");
+        }
+
+        public override void visit(TupleType tupleType)
+        {
+            // we map a tuple to a struct
+            m_emitter.Append(GetIdentifierString(tupleType.identifier.tokenText));
+        }
+        public override void visit(FunctionType functionType)
+        {
+            throw new NotImplementedException();
+        }
+        public override void visit(OoActionSystemType ooActionSystemType)
+        {
+            m_emitter.Append(GetIdentifierString(ooActionSystemType.identifier.tokenText));
+        }
+        public override void visit(OpaqueType opaqueType)
+        {
+            throw new NotImplementedException();
+        }
+
+
+        public override string ToString()
+        {
+            return m_emitter.ToString();
+        }
+    }
+
+
+
+    public sealed class CSharpExpression : OoaExpressionVisitor
+    {
+        private OoaCodeEmitter m_emitter = new OoaCodeEmitter();
+        private StringBuilder m_helpers;
+        private static List<ObjectConstructor> m_constructors = new List<ObjectConstructor>();
+
+        private string GetCSharpType(UlyssesType aType)
+        {
+            CSharpType sharptype = new CSharpType();
+            aType.Accept(sharptype);
+            return sharptype.ToString();
+        }
+        private string GetIdentifierString(string anIdentifier)
+        {
+            return CSharpIdentifier.GetIdentifierString(anIdentifier);
+        }
+
+        public static List<ObjectConstructor> constructors { get { return m_constructors; } }
+
+        // following calls must not happen
+        public override void visit(UnresolvedIdentifierExpression unresolvedIdentifierExpression)
+        {
+            System.Diagnostics.Debug.Assert(false);
+        }
+        public override void visit(CallExpression callExpression)
+        {
+            System.Diagnostics.Debug.Assert(false);
+        }
+
+
+        // we need to map all other things to C# constructs
+        private string OperatorString(Expression expression)
+        {
+            switch (expression.kind)
+            {
+                case ExpressionKind.abs:    // T_ABS:
+                case ExpressionKind.card:   // T_CARD:
+                case ExpressionKind.dom:    // T_DOM:
+                case ExpressionKind.range:  // T_RNG:
+                case ExpressionKind.merge:  // T_MERGE:
+                case ExpressionKind.len:    // T_LEN:
+                case ExpressionKind.elems:  // T_ELEMS:
+                case ExpressionKind.head:   // T_HEAD:
+                case ExpressionKind.tail:   // T_TAIL:
+                case ExpressionKind.conc:   // T_CONC:
+                case ExpressionKind.inds:   // T_INDS:
+                case ExpressionKind.dinter: // T_DINTER:
+                case ExpressionKind.dunion: // T_DUNION:
+                case ExpressionKind.domresby:   // T_DOMRESBY:
+                case ExpressionKind.domresto:   // T_DOMRESTO:
+                case ExpressionKind.rngresby:   // T_RNGRESBY:
+                case ExpressionKind.rngresto:   // T_RNGRESTO:
+                case ExpressionKind.inter:  // T_INTER:
+                case ExpressionKind.union:  // T_UNION:
+                case ExpressionKind.diff:   // T_DIFF:
+                case ExpressionKind.munion: // T_MUNION:
+                case ExpressionKind.seqmod_mapoverride: // T_SEQMOD_MAPOVERRIDE:
+                case ExpressionKind.subset:
+                case ExpressionKind.elemin:
+                case ExpressionKind.notelemin:
+                case ExpressionKind.implies:    // T_IMPLIES:
+                case ExpressionKind.biimplies:  // T_BIIMPLIES:
+                case ExpressionKind.Primed:
+                    throw new NotImplementedException();
+                case ExpressionKind.div:    // T_DIV:
+                    return "/";
+                case ExpressionKind.idiv:   // T_IDIV:
+                    return "/";
+                case ExpressionKind.mod:    // T_MOD:
+                    return "%";
+                case ExpressionKind.prod:   // T_PROD:
+                    return "*";
+                case ExpressionKind.sum:    // T_SUM:
+                    return "+";
+                case ExpressionKind.minus:  // T_MINUS:
+                    return "-";
+                case ExpressionKind.less:
+                    return "<";
+                case ExpressionKind.lessequal:
+                    return "<=";
+                case ExpressionKind.greater:
+                    return ">";
+                case ExpressionKind.greaterequal:
+                    return ">=";
+                case ExpressionKind.equal:
+                    return "==";
+                case ExpressionKind.notequal:
+                    return "!=";
+                case ExpressionKind.and:    // T_AND:
+                    return "&&";
+                case ExpressionKind.or:     // T_OR:
+                    return "||";
+                case ExpressionKind.not:
+                    return "!";
+
+                case ExpressionKind.Cast:
+                    CSharpType ctype = new CSharpType();
+                    expression.type.Accept(ctype);
+                    return String.Format("({0})", ctype.ToString()); ;
+
+                default:
+                    return Enum.GetName(typeof(ExpressionKind), expression.kind);
+            }
+        }
+        public override void visit<T>(ValueExpression<T> valueExpression)
+        {
+            if (valueExpression.value == null)
+                m_emitter.Append("null");
+            else if (valueExpression is ValueExpression<bool>)
+                m_emitter.Append(valueExpression.value.ToString().ToLower());
+            else
+                m_emitter.Append(valueExpression.value.ToString());
+        }
+        public override void visit(IdentifierExpression identifierExpression)
+        {
+            if (identifierExpression.identifier.kind == IdentifierKind.LandmarkIdentifier)
+            {
+                LandmarkIdentifier lmid = (LandmarkIdentifier)identifierExpression.identifier;
+                QrType qr = (QrType)lmid.type;
+                m_emitter.Append(qr.landmarks.IndexOf(lmid));
+                return;
+            }
+
+            if (identifierExpression.identifier.kind == IdentifierKind.EnumIdentifier)
+            {
+                m_emitter.Append(GetIdentifierString(((EnumIdentifier)identifierExpression.identifier).type.identifier.tokenText));
+                m_emitter.Append(".");
+            }
+
+            m_emitter.Append(GetIdentifierString(identifierExpression.identifier.tokenText));
+        }
+
+        public override void visit(TypeExpression typeExpression)
+        {
+            if (typeExpression.type.kind != TypeKind.QrType &&
+                typeExpression.type.kind != TypeKind.EnumeratedType)
+                m_emitter.Append(GetIdentifierString(typeExpression.type.identifier.tokenText));
+        }
+
+
+        public override void visit(ObjectConstructor objectConstructor)
+        {
+            int num = m_constructors.Count;
+            m_constructors.Add(objectConstructor);
+            if (objectConstructor.givenObjectName != null)
+                m_emitter.Append(String.Format("new {0}(this,{1},{2})", GetIdentifierString(objectConstructor.type.identifier.tokenText), num, objectConstructor.givenObjectName));
+            else
+                m_emitter.Append(String.Format("new {0}(this,{1})", GetIdentifierString(objectConstructor.type.identifier.tokenText), num));
+        }
+
+        public override void visit(ListConstructor listConstructor)
+        {
+            if (listConstructor.hasComprehension)
+            {
+                // we need a helper for this.
+                string helpername = String.Format("list_constr_helper_{0}", ((uint)listConstructor.GetHashCode()).ToString());
+                m_emitter.Append(String.Format("{0}(new TUG.Mogentes.Codegen.CSharp.UlyssesList<object>())",
+                    helpername));
+                OoaCodeEmitter helperEmitter = new OoaCodeEmitter();
+                helperEmitter.AppendLine(String.Format(
+                    "public TUG.Mogentes.Codegen.CSharp.UlyssesList<object> {0} (TUG.Mogentes.Codegen.CSharp.UlyssesList<object> newList){{",
+                     helpername));
+
+
+                foreach (var sym in listConstructor.comprehensionVariables.symbolList)
+                {
+                    CSharpType atype = new CSharpType();
+                    sym.type.Accept(atype);
+
+                    if (sym.type.IsNumeric())
+                        helperEmitter.AppendLine(String.Format("for ({0} {1} = {2}; {1} <= {3}; {1}++) {{",
+                             atype.ToString(), CSharpIdentifier.GetIdentifierString(sym.tokenText), UlyssesType.Low(sym.type), UlyssesType.High(sym.type)));
+                    else
+                        throw new NotImplementedException();
+                }
+
+                StringBuilder helperhelper = new StringBuilder();
+
+
+                string guardexpr = "true";
+                if (listConstructor.comprehension != null)
+                {
+                    CSharpExpression expr = new CSharpExpression(helperhelper);
+                    listConstructor.comprehension.Accept(expr);
+                    guardexpr = expr.ToString();
+                }
+
+                CSharpExpression expr2 = new CSharpExpression(helperhelper);
+                listConstructor.elements[0].Accept(expr2);
+
+                helperEmitter.AppendLine(String.Format("if ({0}) {{", guardexpr));
+                helperEmitter.AppendLine(String.Format("newList.Add({0});", expr2.ToString()));
+                helperEmitter.AppendLine("}");
+
+                foreach (var sym in listConstructor.comprehensionVariables.symbolList)
+                {
+                    helperEmitter.AppendLine("}");
+                }
+                helperEmitter.AppendLineIncIndent("return newList;");
+                helperEmitter.AppendLine("}");
+                m_helpers.Append(helperEmitter.ToString());
+                m_helpers.Append(helperhelper.ToString());
+            }
+            else
+            {
+                m_emitter.Append("new TUG.Mogentes.Codegen.CSharp.UlyssesList<object>(");
+                int i = 0;
+                if (listConstructor.elements.Count > 0)
+                {
+                    m_emitter.Append("new object[] { ");
+                    foreach (var x in listConstructor.elements)
+                    {
+                        if (i != 0)
+                            m_emitter.Append(",");
+                        else
+                            i++;
+                        x.Accept(this);
+                    }
+                    m_emitter.Append(" }");
+                }
+                m_emitter.Append(")");
+            }
+        }
+
+        public override void visit(SetConstructor setConstructor)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void visit(MapConstructor mapConstructor)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void visit(TupleConstructor tupleConstructor)
+        {
+            m_emitter.Append(String.Format("new {0}(", GetIdentifierString(tupleConstructor.tupleType.tokenText)));
+            int i = 0;
+            foreach (var arg in tupleConstructor.values)
+            {
+                if (i != 0)
+                    m_emitter.Append(",");
+                else
+                    i++;
+                arg.Accept(this);
+            }
+            m_emitter.Append(")");
+        }
+
+        public override void visit(QValConstructor qValConstructor)
+        {
+            StringBuilder helpers = new StringBuilder();
+
+            string landmarkOne = "null";
+            if (qValConstructor.value.Length >= 1 && qValConstructor.value[0] != null)
+            {
+                CSharpExpression lndmrk1 = new CSharpExpression(helpers);
+                qValConstructor.value[0].Accept(lndmrk1);
+                landmarkOne = lndmrk1.ToString();
+            }
+            string landmarkTwo = "null";
+            if (qValConstructor.value.Length >= 2 && qValConstructor.value[1] != null)
+            {
+                CSharpExpression lndmrk = new CSharpExpression(helpers);
+                qValConstructor.value[1].Accept(lndmrk);
+                landmarkTwo = lndmrk.ToString();
+            }
+            string derivation = "null";
+            if (qValConstructor.valueDeriv != QValDeriv.DonTCare)
+            {
+                derivation = Enum.Format(typeof(QValDeriv), qValConstructor.valueDeriv, "d");
+            }
+
+            m_helpers.Append(helpers.ToString());
+            m_emitter.Append(String.Format("new UlyssesQualitativeValue({0},{1},{2})", landmarkOne, landmarkTwo, derivation));
+        }
+
+        public override void visit(AccessExpression accessExpression)
+        {
+            if (accessExpression.left.type.kind != TypeKind.QrType &&
+                accessExpression.left.type.kind != TypeKind.EnumeratedType)
+            {
+                // enums and qr types are directly (statically) converted to nums...
+                VisitSub(accessExpression.left, accessExpression);
+                m_emitter.Append(".");
+            }
+            VisitSub(accessExpression.right, accessExpression);
+        }
+
+        public override void visit(BinaryOperator binaryOperator)
+        {
+            m_emitter.Append("(");
+            VisitSub(binaryOperator.left, binaryOperator);
+            m_emitter.Append(") ");
+            m_emitter.Append(OperatorString(binaryOperator));
+            m_emitter.Append(" (");
+            VisitSub(binaryOperator.right, binaryOperator);
+            m_emitter.Append(")");
+        }
+
+        public override void visit(TernaryOperator ternaryOperator)
+        {
+            m_emitter.Append("(");
+            VisitSub(ternaryOperator.left, ternaryOperator);
+            m_emitter.Append(" ? ");
+
+            VisitSub(ternaryOperator.mid, ternaryOperator);
+            m_emitter.Append(" : ");
+
+            VisitSub(ternaryOperator.right, ternaryOperator);
+            m_emitter.Append(")");
+        }
+        public override void visit(TupleMapAccessExpression tupleMapAccessExpression)
+        {
+            throw new NotImplementedException();
+            /*VisitSub(tupleMapAccessExpression.argument, tupleMapAccessExpression);
+            VisitSub(tupleMapAccessExpression.child, tupleMapAccessExpression);*/
+        }
+        public override void visit(ForallQuantifier quantifier)
+        {
+            throw new NotImplementedException();
+
+            /*foreach (var lvar in quantifier.symbols.symbolList)
+                VisitSub(lvar, quantifier);
+
+            VisitSub(quantifier.child, quantifier);*/
+        }
+        public override void visit(ExistsQuantifier quantifier)
+        {
+            throw new NotImplementedException();
+            /*foreach (var lvar in quantifier.symbols.symbolList)
+                VisitSub(lvar, quantifier);
+
+            VisitSub(quantifier.child, quantifier);*/
+        }
+        public override void visit(UnaryOperator unaryOperator)
+        {
+            m_emitter.Append(" ");
+            m_emitter.Append(OperatorString(unaryOperator));
+            m_emitter.Append("(");
+            VisitSub(unaryOperator.child, unaryOperator);
+            m_emitter.Append(")");
+        }
+
+        public override string ToString()
+        {
+            return m_emitter.ToString();
+        }
+
+        public CSharpExpression(StringBuilder helpers)
+            : base()
+        {
+            m_helpers = helpers;
+        }
+    }
+
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/codegen/CSharp/ooaCSharpInitVisitor.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/codegen/CSharp/ooaCSharpInitVisitor.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/codegen/CSharp/ooaCSharpInitVisitor.cs	(revision 3)
@@ -0,0 +1,354 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TUG.Mogentes;
+using TUG.Mogentes.Codegen.CSharp;
+
+
+namespace TUG.Mogentes.Codegen
+{
+
+    public sealed class OoaCSharpInitVisitor : OoaCompleteAstTraversalVisitor
+    {
+        private readonly string SimulationNameSpace = "TUG.Mogentes.Codegen.CSharp.Simulation";
+        private OoaCodeEmitter emitter;
+        private List<UlyssesType> hiddenTypesStillToEmit = new List<UlyssesType>();
+        private StringBuilder helpers = new StringBuilder();
+        private List<OoActionSystemType> autoConsList = new List<OoActionSystemType>();
+
+        private int m_maxObjectNameLength = 0;
+        private List<string> m_objectNames = new List<string>();
+        private List<OoActionSystemInstance> m_initialObjectWorkingSet = new List<OoActionSystemInstance>();
+
+
+
+        public int maxObjectNameLength { get { return m_maxObjectNameLength; } }
+        public List<string> objectNames { get { return m_objectNames; } }
+        public List<OoActionSystemInstance> initialObjectWorkingSet { get { return m_initialObjectWorkingSet; } }
+
+
+        public void Error(int line, int pos, string p)
+        {
+            ParserError error = new ParserError(m_ParserState.filename, line, pos, p);
+            m_ParserState.AddErrorMessage(error);
+        }
+
+
+        private void Error(OoActionSystemInstance id, string p)
+        {
+            int line = id.Type.identifier.line;
+            int pos = id.Type.identifier.column;
+
+            ParserError error = new ParserError(m_ParserState.filename, line, pos, p);
+            m_ParserState.AddErrorMessage(error);
+        }
+        private void Warning(OoActionSystemType atype, string p)
+        {
+            ParserWarning warn = new ParserWarning(m_ParserState.filename, atype.identifier.line,
+                atype.identifier.column, p);
+            m_ParserState.AddWarningMessage(warn);
+        }
+
+        private string GetIdentifierString(string anIdentifier)
+        {
+            return CSharpIdentifier.GetIdentifierString(anIdentifier);
+        }
+        private List<OoActionSystemType> AstTypeLookup = new List<OoActionSystemType>();
+
+        /// <summary>
+        /// here we are called when a new object has been created
+        /// </summary>
+        internal void visit(TUG.Mogentes.Codegen.CSharp.UlyssesActionSystemClass ulyssesActionSystemClass, int ConstrNum)
+        {
+            OoActionSystemType aParentType =
+                ulyssesActionSystemClass.parent != null ?
+                    AstTypeLookup[ulyssesActionSystemClass.parent._AstTypeLookupIndex] : null;
+            OoActionSystemType atype = AstTypeLookup[ulyssesActionSystemClass._AstTypeLookupIndex];
+            OoActionSystemInstance aParentInstance =
+                ulyssesActionSystemClass.parent != null ?
+                ulyssesActionSystemClass.parent.objectInstance : null;
+
+            C5.HashSet<UlyssesType> seenTypes = new C5.HashSet<UlyssesType>();
+            StringBuilder instantiationPath = new StringBuilder();
+            if (aParentInstance != null)
+            {
+                OoActionSystemInstance tmp = aParentInstance;
+                while (tmp != null)
+                {
+                    instantiationPath.Append(String.Format("<-{0}", tmp.Name));
+                    seenTypes.Add(tmp.Type);
+                    tmp = tmp.ParentObject;
+                }
+            }
+
+            UlyssesType tmpType = atype;
+            while (tmpType != null)
+            {
+                if (seenTypes.Contains(tmpType))
+                {
+                    throw new UlyssesCompileException(String.Format("Cycle in object creation. {0}", instantiationPath.ToString()));
+                }
+                else
+                    tmpType = ((OoActionSystemType)tmpType).baseType;
+            }
+
+            ulyssesActionSystemClass.objectInstance =
+                new OoActionSystemInstance(ulyssesActionSystemClass.objectName, atype, ulyssesActionSystemClass, aParentInstance);
+
+            // update max length of object name
+            m_maxObjectNameLength = ulyssesActionSystemClass.objectName.Length > m_maxObjectNameLength
+                ? ulyssesActionSystemClass.objectName.Length : m_maxObjectNameLength;
+
+            // add to list of object names
+            m_objectNames.Add(ulyssesActionSystemClass.objectName);
+
+            // add to global list of initial objects
+            m_initialObjectWorkingSet.Add(ulyssesActionSystemClass.objectInstance);
+
+            m_ParserState.AddMessage(new ParserMessage(m_ParserState.filename,
+                atype.identifier.line, atype.identifier.column, String.Format("Creating object: {0}", ulyssesActionSystemClass.objectName)));
+
+            atype.objects.Add(ulyssesActionSystemClass.objectInstance);
+            // also add the object to the base types
+            atype = atype.baseType;
+            while (atype != null)
+            {
+                atype.derivedObjects.Add(ulyssesActionSystemClass.objectInstance);
+                atype = atype.baseType;
+            }
+            atype = null;
+
+            if (ConstrNum >= 0)
+                CSharpExpression.constructors[ConstrNum].AddInstance(ulyssesActionSystemClass.objectInstance);
+        }
+        private string GetCSharpType(UlyssesType aType)
+        {
+            if (aType.isAnonymousType)
+                hiddenTypesStillToEmit.Add(aType);
+
+            CSharpType sharptype = new CSharpType();
+            aType.Accept(sharptype);
+            return sharptype.ToString();
+        }
+        private string GetCSharpExpression(Expression anExpression)
+        {
+            CSharpExpression sharpexpression = new CSharpExpression(helpers);
+            anExpression.Accept(sharpexpression);
+            return sharpexpression.ToString();
+        }
+
+        private void StartSimulation(string p)
+        {
+            try
+            {
+                // set reference
+                TUG.Mogentes.Codegen.CSharp.UlyssesActionSystemClass.objectInstantiator = this;
+                // compile
+                Uri path = new Uri(System.Reflection.Assembly.GetExecutingAssembly().CodeBase);
+                String[] RefAssemblies = { path.LocalPath };
+                System.Reflection.Assembly simulationCode = CSharpCodeCompiler.BuildAssembly(new string[] { p }, RefAssemblies);
+                // execute system initialization
+                CSharpCodeCompiler.ExecuteCode(simulationCode, SimulationNameSpace + ".SimulationCore", "Main", "Start", new object[] { });
+            }
+            catch (UlyssesCompileException e)
+            {
+                ParserError error = new ParserError("ObjectInstantiationVisitor.cs", 0, 0, e.Message);
+                m_ParserState.AddErrorMessage(error);
+            }
+        }
+
+        /// <summary>
+        /// generates C# code that describes initialization of the action systems
+        /// this is used to determine the initial working set of classes.
+        /// </summary>
+        private void Emit(OoActionSystemType ooActionSystemType)
+        {
+            List<AttributeIdentifier> initializers = new List<AttributeIdentifier>();
+            helpers = new StringBuilder();
+            if (ooActionSystemType.baseType == null)
+                emitter.AppendLineIncIndent(String.Format("public class {0} : TUG.Mogentes.Codegen.CSharp.UlyssesActionSystemClass {{", GetIdentifierString(ooActionSystemType.identifier.tokenText)));
+            else
+                emitter.AppendLineIncIndent(String.Format("public class {0} : {1} {{", GetIdentifierString(ooActionSystemType.identifier.tokenText), GetIdentifierString(ooActionSystemType.baseType.identifier.tokenText)));
+
+            foreach (var attr in ooActionSystemType.symbols.symbolList)
+            {
+                if (attr.kind == IdentifierKind.AttributeIdentifier)
+                {
+                    string staticdecl = ((AttributeIdentifier)attr).isStatic ? "static" : string.Empty;
+                    emitter.AppendLine(String.Format("public {2} {0} {1};", GetCSharpType(attr.type), GetIdentifierString(attr.tokenText), staticdecl));
+                    initializers.Add(((AttributeIdentifier)attr));
+                }
+            }
+
+            // emit internal constructor that initializes object
+            emitter.AppendLineIncIndent(String.Format("protected {0} (TUG.Mogentes.Codegen.CSharp.UlyssesActionSystemClass parent, int constrNum, int LookupIndex, string aGivenName): base(parent, constrNum, LookupIndex, aGivenName) {{", GetIdentifierString(ooActionSystemType.identifier.tokenText)));
+            foreach (var attr in initializers)
+                emitter.AppendLine(String.Format("{0} = {1};", GetIdentifierString(attr.tokenText), GetCSharpExpression(attr.initializer)));
+            emitter.AppendLineDecIndent("}");
+
+            // emit public constructor
+            emitter.AppendLineIncIndent(String.Format("public {0} (TUG.Mogentes.Codegen.CSharp.UlyssesActionSystemClass parent, int constrNum): this(parent, constrNum,{1}, String.Empty) {{}}", GetIdentifierString(ooActionSystemType.identifier.tokenText), AstTypeLookup.Count));
+
+            // emit public constructor with fixed name
+            emitter.AppendLineIncIndent(String.Format("public {0} (TUG.Mogentes.Codegen.CSharp.UlyssesActionSystemClass parent, int constrNum, string aName): this(parent, constrNum,{1}, aName) {{}}", GetIdentifierString(ooActionSystemType.identifier.tokenText), AstTypeLookup.Count));
+
+
+            AstTypeLookup.Add(ooActionSystemType);
+
+            // emit helpers
+            emitter.Append(helpers.ToString());
+
+            emitter.AppendLineDecIndent("}");
+
+            if (ooActionSystemType.autoConstruction)
+                autoConsList.Add(ooActionSystemType);
+        }
+
+        /// <summary>
+        /// Emits type definition for tuple 
+        /// </summary>
+        private void Emit(TupleType atupleType)
+        {
+            emitter.AppendLineIncIndent(String.Format("public class {0} {{", GetIdentifierString(atupleType.identifier.tokenText)));
+            int i = 0;
+            foreach (var it in atupleType.innerTypes)
+            {
+                emitter.AppendLine(String.Format("public {0} elem_{1};", GetCSharpType(it), i.ToString()));
+                i++;
+            }
+
+            emitter.AppendLine(" /*constr*/ ");
+            emitter.Append(String.Format("public {0} (", GetIdentifierString(atupleType.identifier.tokenText)));
+            i = 0;
+            foreach (var it in atupleType.innerTypes)
+            {
+                if (i != 0)
+                    emitter.Append(",");
+                emitter.Append(String.Format("{0} arg_{1}", GetCSharpType(it), i.ToString()));
+                i++;
+            }
+            emitter.AppendLineIncIndent(") {");
+            i = 0;
+            foreach (var it in atupleType.innerTypes)
+            {
+                emitter.AppendLine(String.Format("elem_{0} = arg_{0};", i.ToString()));
+                i++;
+            }
+            emitter.AppendLineDecIndent("}");
+
+            emitter.AppendLineDecIndent("}");
+        }
+
+        /// <summary>
+        /// Emits type definition for enum 
+        /// </summary>
+        private void Emit(EnumType anEnum)
+        {
+            emitter.Append(String.Format("public enum {0} {{", GetIdentifierString(anEnum.identifier.tokenText)));
+            int i = 0;
+            foreach (var it in anEnum.listOfEnumSymbols)
+            {
+                if (i != 0)
+                    emitter.Append(", ");
+                else
+                    i++;
+                emitter.Append(GetIdentifierString(it.tokenText));
+            }
+            emitter.AppendLine("}");
+        }
+
+        protected override void VisitAstElement(IAst element, IAst parent)
+        {
+            if (element.nodeType == AstNodeTypeEnum.type &&
+                ((UlyssesType)element).kind == TypeKind.OoActionSystemType)
+            {
+                OoActionSystemType asystem = (OoActionSystemType)element;
+                /*if (asystem.autoConstruction)
+                    CheckForRecursiveNew(asystem);*/
+                Emit((OoActionSystemType)element);
+            }
+            else if (element.nodeType == AstNodeTypeEnum.type &&
+                ((UlyssesType)element).kind == TypeKind.TupleType)
+            {
+                Emit((TupleType)element);
+            }
+            else if (element.nodeType == AstNodeTypeEnum.type &&
+                ((UlyssesType)element).kind == TypeKind.EnumeratedType)
+            {
+                Emit((EnumType)element);
+            }
+            else
+                base.VisitAstElement(element, parent);
+        }
+
+        public override void visit(MainModule mainModule)
+        {
+            CSharpExpression.constructors.Clear(); 
+            emitter.AppendLine("using System;");
+            emitter.AppendLine("using System.Collections.Generic;");
+            emitter.AppendLine("using System.Text;");
+            emitter.AppendLine("using TUG.Mogentes.Codegen.CSharp;");
+            emitter.AppendLine("");
+            emitter.AppendLineIncIndent(String.Format("namespace {0} {{", SimulationNameSpace));
+
+            base.visit(mainModule);
+
+            emitter.AppendLine(" /* == anonymous types == */ ");
+            foreach (var x in hiddenTypesStillToEmit)
+            {
+                // we only need to define tuples and enums..
+                if (x.kind == TypeKind.TupleType)
+                    Emit((TupleType)x);
+                else if (x.kind == TypeKind.EnumeratedType)
+                    Emit((EnumType)x);
+            }
+
+            emitter.AppendLine(" /* == create autocons objects == */ ");
+            emitter.AppendLineIncIndent("namespace SimulationCore {");
+            emitter.AppendLineIncIndent("public class Main {");
+            emitter.AppendLineIncIndent("public static void Start(){");
+
+            foreach (var x in autoConsList)
+                emitter.AppendLine(String.Format("new {0}(null,-1 /*autocons*/);", GetIdentifierString(x.identifier.tokenText)));
+
+            emitter.AppendLineDecIndent("}");
+            emitter.AppendLineDecIndent("}");
+            emitter.AppendLineDecIndent("}");
+
+            emitter.AppendLineDecIndent("}");
+
+            StartSimulation(emitter.ToString());
+        }
+
+
+        public override string ToString()
+        {
+            return emitter.ToString();
+        }
+
+        public OoaCSharpInitVisitor(ParserState state)
+            : base(state)
+        {
+            emitter = new OoaCodeEmitter();
+        }
+
+    }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/codegen/CSharp/ooaCSharpRuntime.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/codegen/CSharp/ooaCSharpRuntime.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/codegen/CSharp/ooaCSharpRuntime.cs	(revision 3)
@@ -0,0 +1,108 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TUG.Mogentes.Codegen;
+
+
+namespace TUG.Mogentes.Codegen.CSharp //Simulation.SimulationCore
+{
+    public class UlyssesList<T> : System.Collections.Generic.List<T>
+    {
+        public UlyssesList()
+            : base()
+        { }
+
+        public UlyssesList(T element)
+            :base()
+        {
+            if (element != null)
+                base.Add(element);
+        }
+
+        public UlyssesList(T[] elements)
+            : base()
+        {
+            if (elements != null)
+            {
+                base.AddRange(elements);
+            }
+        }
+    }
+
+    public class UlyssesQualitativeValue
+    {
+        public int? intervalLow;
+        public int? intervalHigh;
+        public int? derivation;
+
+        public UlyssesQualitativeValue(int? lowval, int? highval, int? deriv)
+        {
+            intervalLow = lowval;
+            intervalHigh = highval;
+            derivation = deriv;
+        }
+    }
+
+    public delegate void CallBack(UlyssesActionSystemClass self);
+
+
+    // class all instances in simulation inherit from
+    public class UlyssesActionSystemClass
+    {
+        public static OoaCSharpInitVisitor objectInstantiator;
+        public static C5.HashSet<String> givenObjectNames = new C5.HashSet<string>();
+
+        public string givenName;
+        public string objectName;
+        public int objectCreationCounter = 0;
+        public int _AstTypeLookupIndex = -1;
+        public UlyssesActionSystemClass parent = null;
+        public OoActionSystemInstance objectInstance = null;
+
+        public UlyssesActionSystemClass(UlyssesActionSystemClass aParent, int constrNum, int LookupIndex, string aGivenName)
+        {
+            parent = aParent;
+            _AstTypeLookupIndex = LookupIndex;
+            if (parent == null)
+                objectName = String.Format("{0}_root", this.GetType().Name);
+            else
+            {
+                objectName = String.Format("{0}_{1}_{2}", this.GetType().Name, parent.objectName, parent.objectCreationCounter);
+                parent.objectCreationCounter += 1;
+            }
+
+            if (aGivenName != String.Empty)
+            {
+                if (givenObjectNames.Contains(aGivenName))
+                {
+                    objectInstantiator.Error(0, 0, String.Format("Another object with name {0} exists.", aGivenName));
+                }
+                else
+                {
+                    objectName = aGivenName;
+                    givenObjectNames.Add(aGivenName);
+                }
+            }
+
+            objectInstantiator.visit(this, constrNum);
+        }
+    }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/codegen/Prolog/ooaPrologExpression.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/codegen/Prolog/ooaPrologExpression.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/codegen/Prolog/ooaPrologExpression.cs	(revision 3)
@@ -0,0 +1,828 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+/*
+ * Prolog Code Generator
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TUG.Mogentes.Codegen;
+
+
+namespace TUG.Mogentes.Codegen.Prolog
+{
+    public class OoaPrologExpression : OoaExpressionVisitor
+    {
+        public class Factory
+        {
+            public OoaPrologExpression create(OoaPrologIdentifier.Factory idFactory, OoaPrologType.Factory typeFactory) 
+            { return create(idFactory, typeFactory, false); }
+            public virtual OoaPrologExpression create(OoaPrologIdentifier.Factory idFactory, OoaPrologType.Factory typeFactory, bool lhs)
+            { return new OoaPrologExpression(idFactory, typeFactory, this, lhs); }
+        }
+
+        protected OoaCodeEmitter m_emitter = new OoaCodeEmitter();
+        protected List<string> m_tmpVars = new List<string>();
+        private bool m_LhsExpression = false;
+
+
+        public List<string> tmpVariables { get { return m_tmpVars; } }
+        public bool isLhsExpression { get { return m_LhsExpression; } }
+
+        private string GetPrologType(UlyssesType aType)
+        {
+            OoaPrologType pType = createTypeVisitor();
+            aType.Accept(pType);
+            return pType.ToString();
+        }
+
+        protected string GetIdentifierString(Identifier anIdentifier)
+        {
+            OoaPrologIdentifier pIdent = createIdentifierVisitor();
+            anIdentifier.Accept(pIdent);
+            return pIdent.ToString();
+        }
+
+
+        // following call must not happen
+        public override void visit(UnresolvedIdentifierExpression unresolvedIdentifierExpression)
+        {
+            System.Diagnostics.Debug.Assert(false);
+        }
+
+        // call of method that returns a value..
+        public override void visit(CallExpression callExpression)
+        {
+            // we handle only function calls within expressions here (must have non-void return!)
+            FunctionType funtype = (FunctionType)callExpression.child.type;
+            if (funtype.returnType == null)
+                throw new ArgumentException("Internal error: Function call in expression with return-type void!");
+
+            string callstatement = String.Empty;
+            StringBuilder parameter = new StringBuilder();
+
+            OoaPrologExpression prologexpr = createExpressionVisitor();
+            callExpression.child.Accept(prologexpr);
+
+            m_emitter.Append(prologexpr.ToString());
+            callstatement = prologexpr.tmpVariables[0];
+            int i = 0;
+            foreach (var arg in callExpression.arguments)
+            {
+                if (i != 0)
+                    parameter.Append(", ");
+                else
+                    i++;
+                OoaPrologExpression paramexpr = createExpressionVisitor();
+                arg.Accept(paramexpr);
+                m_emitter.Append(paramexpr.ToString());
+                parameter.Append(paramexpr.tmpVariables[0]);
+            }
+            if (parameter.Length > 0)
+                m_emitter.AppendLine(String.Format("{0}({1},{2}),", callstatement, parameter, NewTempVariable()));
+            else
+                m_emitter.AppendLine(String.Format("{0}({1}),", callstatement, NewTempVariable()));
+        }
+
+
+        // we need to map all other things to Prolog constructs
+        private string OperatorString(Expression expression, UlyssesType resultingType)
+        {
+            switch (expression.kind)
+            {
+                case ExpressionKind.abs:    // T_ABS:
+                case ExpressionKind.card:   // T_CARD:
+                case ExpressionKind.dom:    // T_DOM:
+                case ExpressionKind.range:  // T_RNG:
+                case ExpressionKind.merge:  // T_MERGE:
+                case ExpressionKind.elems:  // T_ELEMS:
+                case ExpressionKind.head:   // T_HEAD:
+                case ExpressionKind.tail:   // T_TAIL:
+                case ExpressionKind.conc:   // T_CONC:
+                case ExpressionKind.inds:   // T_INDS:
+                case ExpressionKind.dinter: // T_DINTER:
+                case ExpressionKind.dunion: // T_DUNION:
+                case ExpressionKind.domresby:   // T_DOMRESBY:
+                case ExpressionKind.domresto:   // T_DOMRESTO:
+                case ExpressionKind.rngresby:   // T_RNGRESBY:
+                case ExpressionKind.rngresto:   // T_RNGRESTO:
+                case ExpressionKind.inter:  // T_INTER:
+                case ExpressionKind.union:  // T_UNION:
+                case ExpressionKind.diff:   // T_DIFF:
+                case ExpressionKind.munion: // T_MUNION:
+                case ExpressionKind.seqmod_mapoverride: // T_SEQMOD_MAPOVERRIDE:
+                case ExpressionKind.subset:
+                case ExpressionKind.elemin:
+                case ExpressionKind.notelemin:
+                case ExpressionKind.implies:    // T_IMPLIES:
+                case ExpressionKind.biimplies:  // T_BIIMPLIES:
+                case ExpressionKind.Primed:
+                case ExpressionKind.len:    // T_LEN:
+                    throw new NotImplementedException();
+
+                case ExpressionKind.div:    // T_DIV:
+                    return "/";
+                case ExpressionKind.idiv:   // T_IDIV:
+                    return "/";
+                case ExpressionKind.mod:    // T_MOD:
+                    return "mod";
+                case ExpressionKind.prod:   // T_PROD:
+                    return "*";
+                case ExpressionKind.sum:    // T_SUM:
+                    return "+";
+                case ExpressionKind.minus:  // T_MINUS:
+                    return "-";
+                case ExpressionKind.less:
+                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? "<" : "#<";
+                case ExpressionKind.lessequal:
+                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? "=<" : "#=<";
+                case ExpressionKind.greater:
+                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? ">" : "#>";
+                case ExpressionKind.greaterequal:
+                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? ">=" : "#>=";
+                case ExpressionKind.equal:
+                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? "==" : "#=";
+                case ExpressionKind.notequal:
+                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? "\\=" : "#\\=";
+                case ExpressionKind.and:    // T_AND:
+                    throw new NotImplementedException(); // implemented in binaryoperator
+                case ExpressionKind.or:     // T_OR:
+                    throw new NotImplementedException(); // implemented in binaryoperator
+                case ExpressionKind.not:
+                    throw new NotImplementedException(); // implemented in binaryoperator
+
+                case ExpressionKind.Cast:
+                    return String.Empty;
+
+                default:
+                    return Enum.GetName(typeof(ExpressionKind), expression.kind);
+            }
+        }
+
+        protected bool isNumericBinary(Expression expression)
+        {
+            bool result = false;
+            if (expression is BinaryOperator)
+            {
+                result = ((BinaryOperator)expression).left.type.kind == TypeKind.IntType &&
+                    ((BinaryOperator)expression).right.type.kind == TypeKind.IntType;
+            }
+            else if (expression is UnaryOperator)
+            {
+                result = ((UnaryOperator)expression).child.type.kind == TypeKind.IntType;
+            }
+            else throw new NotImplementedException();
+            return result;
+        }
+
+        public override void visit<T>(ValueExpression<T> valueExpression)
+        {
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
+            string tmpVar = NewTempVariable();
+            m_emitter.Append(String.Format("{0} ", tmpVar));
+
+
+            if (valueExpression.value == null)
+                m_emitter.Append("= 'null'");
+            else if (valueExpression is ValueExpression<bool>)
+                m_emitter.Append((valueExpression as ValueExpression<bool>).value ? " #= true" : " #= fail");
+            else if (valueExpression is ValueExpression<char>)
+                m_emitter.Append(String.Format("#= '{0}'", valueExpression.ToString()));
+            else if (valueExpression is ValueExpression<int>)
+                m_emitter.Append(String.Format("#= {0}", valueExpression.ToString()));
+            else
+                m_emitter.Append(String.Format("= {0}", valueExpression.value.ToString()));
+
+            m_emitter.AppendLine(",");
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 1);
+        }
+
+        public override void visit(IdentifierExpression identifierExpression)
+        {
+            if (identifierExpression.identifier.kind == IdentifierKind.LandmarkIdentifier)
+            {
+                LandmarkIdentifier lmid = (LandmarkIdentifier)identifierExpression.identifier;
+                OoaPrologIdentifier pid = createIdentifierVisitor();
+                lmid.Accept(pid);
+                //m_emitter.Append(pid.ToString());
+                m_tmpVars.Add(pid.ToString());
+                return;
+            }
+            else if (identifierExpression.identifier.kind == IdentifierKind.EnumIdentifier)
+            {
+                EnumIdentifier enumid = (EnumIdentifier)identifierExpression.identifier;
+                EnumType enumType = (EnumType)enumid.type;
+                //m_emitter.Append(enumType.listOfEnumSymbols.IndexOf(enumid));
+                if (enumType is ValuedEnumType)
+                    m_emitter.AppendLine(String.Format("{0} #= {1},", NewTempVariable(), enumid.Value));
+                else
+                    m_emitter.AppendLine(String.Format("{0} #= {1},", NewTempVariable(), enumType.listOfEnumSymbols.IndexOf(enumid).ToString()));
+            }
+            else if (identifierExpression.isSelf)
+            {
+                m_emitter.AppendLine(String.Format("{0} = {1},", NewTempVariable(), GetIdentifierString(identifierExpression.identifier)));
+            }
+            /*else if (identifierExpression.identifier.kind == IdentifierKind.AttributeIdentifier)
+            {
+                m_emitter.AppendLine(String.Format("getVal({1},{0},_),", NewTempVariable(), GetIdentifierString(identifierExpression.identifier)));
+            }*/
+            else
+            {
+                //m_emitter.Append(GetIdentifierString(identifierExpression.identifier));
+                m_tmpVars.Add(GetIdentifierString(identifierExpression.identifier));
+            }
+        }
+
+        public override void visit(TypeExpression typeExpression)
+        {
+            if (typeExpression.type.kind != TypeKind.QrType &&
+                typeExpression.type.kind != TypeKind.EnumeratedType)
+            {
+                //m_emitter.Append(GetIdentifierString(typeExpression.type.identifier));
+                m_emitter.Append(GetIdentifierString(typeExpression.type.identifier));
+            }
+        }
+
+
+        public override void visit(ObjectConstructor objectConstructor)
+        {
+            if (objectConstructor.instances.Count > 1)
+                throw new NotImplementedException();
+
+            m_emitter.AppendLine(String.Format("{0} = '{1}',", NewTempVariable(), objectConstructor.instances[0].Name));
+
+            //m_emitter.Append(String.Format("new {0}(this)", GetIdentifierString(objectConstructor.type.identifier)));
+        }
+
+        public override void visit(ListConstructor listConstructor)
+        {
+            if (listConstructor.hasComprehension)
+            {
+                OoaPrologExpression compr = createExpressionVisitor();
+                listConstructor.comprehension.Accept(compr);
+                OoaPrologExpression elem = createExpressionVisitor();
+                listConstructor.elements[0].Accept(elem);
+
+                StringBuilder enumvars = new StringBuilder();
+                int i = 0;
+                foreach (var v in listConstructor.comprehensionVariables.symbolList)
+                {
+                    OoaPrologIdentifier ident = createIdentifierVisitor();
+                    v.Accept(ident);
+
+                    OoaPrologType identType = createTypeVisitor();
+                    v.type.Accept(identType);
+
+                    enumvars.Append(String.Format("{2} {0}: {1}", ident.ToString(), identType.ToString(), i == 0 ? String.Empty : ","));
+                    i++;
+                }
+
+                m_emitter.AppendLine("% listcomprehension");
+                m_emitter.AppendLine(String.Format("{0} = {{{1}:[{2}]:({3}{4},{5}{6})}}",
+                    NewTempVariable(), elem.tmpVariables[0], enumvars.ToString(), compr.ToString(), compr.tmpVariables[0],
+                    elem.ToString(), "1=1" /*elem.ToString() == String.Empty ? "1=1" : elem.tmpVariables[0]*/));
+            }
+            else
+            {
+                m_emitter.AppendLine("% make list");
+                m_emitter.AppendLine(String.Format("{0} = []", NewTempVariable()));
+
+                foreach (var expr in listConstructor.elements)
+                {
+                    m_emitter.Append(", ");
+
+                    OoaPrologExpression pVal = createExpressionVisitor();
+                    expr.Accept(pVal);
+                    m_emitter.Append(pVal.ToString());
+                    System.Diagnostics.Debug.Assert(pVal.tmpVariables.Count == 1);
+                    m_emitter.AppendLine(String.Format("ulyssesListConc({0},[{1}],{2})", m_tmpVars[0], pVal.tmpVariables[0], NewTempVariable()));
+                    m_tmpVars.RemoveAt(0);
+                }
+            }
+            m_emitter.Append(",");
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 1);
+        }
+
+        public override void visit(SetConstructor setConstructor)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void visit(MapConstructor mapConstructor)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void visit(TupleConstructor tupleConstructor)
+        {
+            if (tupleConstructor.isMatcher)
+            {
+                // being dealt with in binaryoperator (since we only allow tuple=MyTuple(a,b))
+                NewTempVariable();
+                return;
+            }
+            else
+            {
+                m_emitter.AppendLine("% make tuple");
+                m_emitter.AppendLine(String.Format("{0} = []", NewTempVariable()));
+
+                foreach (var expr in tupleConstructor.values)
+                {
+                    m_emitter.Append(", ");
+
+                    OoaPrologExpression pVal = createExpressionVisitor();
+                    expr.Accept(pVal);
+                    m_emitter.Append(pVal.ToString());
+                    System.Diagnostics.Debug.Assert(pVal.tmpVariables.Count == 1);
+                    m_emitter.AppendLine(String.Format("ulyssesListConc({0},[{1}],{2})", m_tmpVars[0], pVal.tmpVariables[0], NewTempVariable()));
+                    m_tmpVars.RemoveAt(0);
+                }
+                m_emitter.Append(",");
+                System.Diagnostics.Debug.Assert(m_tmpVars.Count == 1);
+            }
+        }
+
+        public override void visit(QValConstructor qValConstructor)
+        {
+            OoaPrologIdentifier pident = createIdentifierVisitor();
+            qValConstructor.type.identifier.Accept(pident);
+            StringBuilder qVal = new StringBuilder();
+            if (qValConstructor.value != null || qValConstructor.value.Length != 0)
+            {
+                OoaPrologExpression landmark1 = createExpressionVisitor();
+                qValConstructor.value[0].Accept(landmark1);
+                qVal.Append(landmark1.ToString());
+
+                if (qValConstructor.value.Length > 1)
+                {
+                    OoaPrologExpression landmark2 = createExpressionVisitor();
+                    qValConstructor.value[1].Accept(landmark2);
+                    qVal.Append("..");
+                    qVal.Append(landmark2.ToString());
+                }
+            }
+            else
+                qVal.Append("_");
+
+            string deriv = "_";
+            switch (qValConstructor.valueDeriv)
+            {
+                case QValDeriv.Dec:
+                    deriv = "dec";
+                    break;
+                case QValDeriv.Inc:
+                    deriv = "inc";
+                    break;
+                case QValDeriv.Steady:
+                    deriv = "std";
+                    break;
+
+            }
+            string tmpVar = NewTempVariable();
+            m_emitter.AppendLine(String.Format("{3} = ({0}:{1}/{2}),", pident.ToString(), qVal.ToString(), deriv, tmpVar));
+        }
+
+        public override void visit(AccessExpression accessExpression)
+        {
+            if (accessExpression.left.type.kind != TypeKind.QrType &&
+                accessExpression.left.type.kind != TypeKind.EnumeratedType &&
+                !(accessExpression.right.kind == ExpressionKind.Identifier &&
+                ((IdentifierExpression)accessExpression.right).identifier.kind == IdentifierKind.AttributeIdentifier))
+            {
+                System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
+                // enums and qr types are directly (statically) converted to nums...
+                VisitSub(accessExpression.left, accessExpression);
+                string leftresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
+
+                VisitSub(accessExpression.right, accessExpression);
+                string rightresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
+
+                m_tmpVars.Add(String.Format("{0}\\{1}", leftresult, rightresult));
+            }
+            else
+                VisitSub(accessExpression.right, accessExpression);
+        }
+
+        public override void visit(BinaryOperator binaryOperator)
+        {
+            OoaCodeEmitter origEmitter = m_emitter;
+
+
+            // eval stack must be empty
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
+            // traverse left
+            OoaCodeEmitter leftcode = new OoaCodeEmitter();
+            m_emitter = leftcode;
+            VisitSub(binaryOperator.left, binaryOperator);
+            string leftresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
+            // traverse right
+            OoaCodeEmitter rightcode = new OoaCodeEmitter();
+            m_emitter = rightcode;
+            VisitSub(binaryOperator.right, binaryOperator);
+            string rightresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
+            // eval stack must be empty
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
+
+            m_emitter = origEmitter;
+
+            // get tmp.var
+            string tmpVar = NewTempVariable();
+
+            switch (binaryOperator.kind)
+            {
+                case ExpressionKind.elemin:
+                    m_emitter.Append(leftcode.ToString());
+                    m_emitter.Append(rightcode.ToString());
+                    m_emitter.AppendLine(String.Format(" {0} = member({1},{2}),",
+                        tmpVar, leftresult, rightresult));
+                    break;
+                case ExpressionKind.and:    // T_AND:
+                    m_emitter.Append(leftcode.ToString());
+                    m_emitter.Append(rightcode.ToString());
+                    m_emitter.AppendLine(String.Format(" {0} = ({1} {2} {3}), ",
+                        tmpVar, leftresult, ",", rightresult));
+                    break;
+                case ExpressionKind.or:     // T_OR:
+                    m_emitter.Append(leftcode.ToString());
+                    m_emitter.Append(rightcode.ToString());
+                    m_emitter.AppendLine(String.Format(" {0} = ({1} {2} {3}), ",
+                        tmpVar, leftresult, ";", rightresult));
+                    break;
+
+                case ExpressionKind.implies:
+                    m_emitter.Append(leftcode.ToString());
+                    m_emitter.AppendLine(String.Format(" {0} = ({1} -> ({2}{3}); true), ", // {0} = (({1} -> ({2}{3}); true))
+                        tmpVar, leftresult, rightcode.ToString(), rightresult));
+                    break;
+
+                case ExpressionKind.equal:
+                    m_emitter.Append(leftcode.ToString());
+                    m_emitter.Append(rightcode.ToString());
+                    /*check if we have tupleconstructors as matchers*/
+                    TupleConstructor matcher = null;
+                    string aTuple = null;
+                    if (binaryOperator.left.kind == ExpressionKind.TupleConstr &&
+                        ((TupleConstructor)binaryOperator.left).isMatcher)
+                    {
+                        matcher = (TupleConstructor)binaryOperator.left;
+                        aTuple = rightresult;
+                    }
+                    else if (binaryOperator.right.kind == ExpressionKind.TupleConstr &&
+                        ((TupleConstructor)binaryOperator.right).isMatcher)
+                    {
+                        matcher = (TupleConstructor)binaryOperator.right;
+                        aTuple = leftresult;
+                    }
+
+                    if (matcher == null)
+                        m_emitter.AppendLine(String.Format(" {0} = ({1} {2} {3}), ",
+                            tmpVar, leftresult, OperatorString(binaryOperator, binaryOperator.left.type), rightresult));
+                    else
+                    {
+                        m_emitter.Append(String.Format("{0} = unify({1} = [", tmpVar, aTuple));
+                        int cntr = 0;
+                        foreach (var x in matcher.values)
+                        {
+                            if (cntr != 0)
+                                m_emitter.Append(", ");
+                            else
+                                cntr++;
+
+                            if (x.kind != ExpressionKind.Identifier)
+                                throw new ArgumentException();
+
+                            IdentifierExpression ident = (IdentifierExpression)x;
+                            OoaPrologIdentifier avisitor = createIdentifierVisitor();
+                            ident.Accept(avisitor);
+                            m_emitter.Append(avisitor.ToString());
+                        }
+                        m_emitter.AppendLine("]),");
+                    }
+                    break;
+
+
+
+                case ExpressionKind.conc:
+                    m_emitter.Append(leftcode.ToString());
+                    m_emitter.Append(rightcode.ToString());
+                    m_emitter.AppendLine(String.Format("ulyssesListConc({1},{2},{0}),", tmpVar, leftresult, rightresult));
+                    break;
+
+                default:
+                    m_emitter.Append(leftcode.ToString());
+                    m_emitter.Append(rightcode.ToString());
+                    if (binaryOperator.left.type.kind == TypeKind.QrType)
+                        m_emitter.Append("qEval");
+                    //m_emitter.Append("(");
+                    if (binaryOperator.type.kind == TypeKind.IntType)
+                        m_emitter.AppendLine(String.Format(" {0} #= ({1} {2} {3}), ",
+                            tmpVar, leftresult, OperatorString(binaryOperator, binaryOperator.left.type), rightresult));
+                    else
+                        m_emitter.AppendLine(String.Format(" {0} = ({1} {2} {3}), ",
+                            tmpVar, leftresult, OperatorString(binaryOperator, binaryOperator.left.type), rightresult));
+                    //m_emitter.Append(")");
+                    break;
+            }
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 1);
+        }
+
+        public override void visit(TernaryOperator ternaryOperator)
+        {
+            if (ternaryOperator.kind == ExpressionKind.conditional)
+            {
+                VisitSub(ternaryOperator.left, ternaryOperator);
+                string leftresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
+                VisitSub(ternaryOperator.mid, ternaryOperator);
+                string midresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
+                VisitSub(ternaryOperator.right, ternaryOperator);
+                string rightresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
+
+                string varname = NewTempVariable();
+
+                // (cond, expr #= var; #\ (cond), expr #= var)
+                m_emitter.Append("((");
+                m_emitter.Append(leftresult);
+                m_emitter.Append(", unify(");
+                m_emitter.Append(midresult);
+                m_emitter.Append(String.Format(" = {0}) );( call(\\+({1})), unify(", varname, leftresult));
+                m_emitter.Append(rightresult);
+                m_emitter.Append(String.Format(" = {0}) )),", varname));
+            }
+            else if (ternaryOperator.kind == ExpressionKind.foldRL)
+                throw new NotImplementedException();
+            else if (ternaryOperator.kind == ExpressionKind.foldLR)
+            {
+                VisitSub(ternaryOperator.mid, ternaryOperator);
+                string midresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
+                VisitSub(ternaryOperator.right, ternaryOperator);
+                string rightresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
+
+
+                int uniqueNumer = GetUniqueNumber();
+                m_emitter.Append(String.Format("fun_fold({0},{1},(_Elem_{2}, _In_{2}, Out_{2},(", midresult,
+                    rightresult, uniqueNumer));
+
+
+                // hack the current element and current result values to match the declaration above (change from __result, __elem)
+                CallExpression leftcall = (CallExpression)ternaryOperator.left;
+                IdentifierExpression elemId = (IdentifierExpression)leftcall.arguments[leftcall.arguments.Count - 1];
+                elemId.identifier.SetTokenText(String.Format("Elem_{0}", uniqueNumer));
+                IdentifierExpression currentResultId = (IdentifierExpression)leftcall.arguments[leftcall.arguments.Count - 2];
+                currentResultId.identifier.SetTokenText(String.Format("In_{0}", uniqueNumer));
+
+                VisitSub(leftcall, ternaryOperator);
+                string leftresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
+                string tmpresult = NewTempVariable();
+                m_emitter.Append(String.Format(" Out_{1} = {2})),{0}),", tmpresult, uniqueNumer, leftresult));
+            }
+
+
+
+            else
+                throw new NotImplementedException();
+        }
+
+        public override void visit(TupleMapAccessExpression tupleMapAccessExpression)
+        {
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
+            VisitSub(tupleMapAccessExpression.child, tupleMapAccessExpression);
+            string childresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
+
+            VisitSub(tupleMapAccessExpression.argument, tupleMapAccessExpression);
+            string accessresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
+
+            string tmpresult = NewTempVariable();
+
+            if (!m_LhsExpression)
+            {
+                switch (tupleMapAccessExpression.child.type.kind)
+                {
+                    case TypeKind.TupleType:
+                        m_emitter.AppendLine(String.Format("ulyssesTupleAccess({0},{1},{2}),", childresult, accessresult, tmpresult));
+                        break;
+                    case TypeKind.MapType:
+                        m_emitter.AppendLine(String.Format("ulyssesMapAccess({0},{1},{2}),", childresult, accessresult, tmpresult));
+                        break;
+                    case TypeKind.ListType:
+                        m_emitter.AppendLine(String.Format("ulyssesListAccess({0},{1},{2}),", childresult, accessresult, tmpresult));
+                        break;
+                    default:
+                        throw new NotImplementedException();
+                }
+                System.Diagnostics.Debug.Assert(m_tmpVars.Count == 1);
+            }
+            else
+            {
+                /*>>>>> See comment in ooaTypeCheckVisitor on method CheckPlace! <<<<<<<<<*/
+                switch (tupleMapAccessExpression.child.type.kind)
+                {
+                    case TypeKind.ListType:
+                        bool isAttribute;
+                        isAttribute = tupleMapAccessExpression.child.kind == ExpressionKind.Identifier &&
+                            ((IdentifierExpression)tupleMapAccessExpression.child).identifier.kind == IdentifierKind.AttributeIdentifier;
+
+                        isAttribute = isAttribute || tupleMapAccessExpression.child.kind == ExpressionKind.Access
+                            && ((AccessExpression)tupleMapAccessExpression.child).left.kind == ExpressionKind.Identifier
+                            && ((IdentifierExpression)((AccessExpression)tupleMapAccessExpression.child).left).isSelf
+                            && ((AccessExpression)tupleMapAccessExpression.child).right.kind == ExpressionKind.Identifier
+                            && ((IdentifierExpression)((AccessExpression)tupleMapAccessExpression.child).right).identifier.kind
+                                == IdentifierKind.AttributeIdentifier;
+
+
+                        tmpVarCntr++;
+                        string newlist = String.Format("RESVAR_{0}", tmpVarCntr);
+
+                        m_emitter.AppendLine(String.Format("ulyssesListWrite({0},{1},{2},{3}),", childresult, accessresult, tmpresult, newlist));
+
+                        if (isAttribute)
+                        { m_emitter.AppendLine(String.Format("{0} := {1},", childresult, newlist)); }
+                        else
+                        { throw new NotImplementedException(); }
+
+                        break;
+                    default:
+                        throw new NotImplementedException();
+                }
+
+
+            }
+        }
+
+
+        public override void visit(ForallQuantifier quantifier)
+        {
+            OoaPrologExpression pExpr = createExpressionVisitor();
+            quantifier.child.Accept(pExpr);
+
+            // TEMPXY = forall(enumerate1([var:type,...]),pred(var..))
+            StringBuilder Generator = new StringBuilder();
+            int i = 0;
+            foreach (var v in quantifier.symbols.symbolList)
+            {
+                OoaPrologIdentifier ident = createIdentifierVisitor();
+                v.Accept(ident);
+
+                OoaPrologType identType = createTypeVisitor();
+                v.type.Accept(identType);
+
+                Generator.Append(String.Format("{2} {0}: {1}", ident.ToString(), identType.ToString(), i == 0 ? String.Empty : ","));
+                i++;
+            }
+
+            m_emitter.AppendLine(String.Format("{0} = forall([{1}],({2}{3})),",
+            NewTempVariable(), Generator.ToString(), pExpr.ToString(), pExpr.tmpVariables[0]));
+        }
+
+
+
+        public override void visit(ExistsQuantifier quantifier)
+        {
+            OoaPrologExpression pExpr = createExpressionVisitor();
+            quantifier.child.Accept(pExpr);
+
+            // TEMPXY = exists(enumerate1([var:type,...]),pred(var..))
+            StringBuilder Generator = new StringBuilder();
+            int i = 0;
+            foreach (var v in quantifier.symbols.symbolList)
+            {
+                OoaPrologIdentifier ident = createIdentifierVisitor();
+                v.Accept(ident);
+
+                OoaPrologType identType = createTypeVisitor();
+                v.type.Accept(identType);
+
+                Generator.Append(String.Format("{2} {0}: {1}", ident.ToString(), identType.ToString(), i == 0 ? String.Empty : ","));
+                i++;
+            }
+
+            m_emitter.AppendLine(String.Format("{0} = exists([{1}],({2}{3})),",
+            NewTempVariable(), Generator.ToString(), pExpr.ToString(), pExpr.tmpVariables[0]));
+        }
+        public override void visit(UnaryOperator unaryOperator)
+        {
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
+            VisitSub(unaryOperator.child, unaryOperator);
+
+            if (unaryOperator.kind == ExpressionKind.Cast)
+                return;
+
+            string childresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
+
+            string tmpresult = NewTempVariable();
+
+            switch (unaryOperator.kind)
+            {
+                case ExpressionKind.head:
+                    m_emitter.AppendLine(String.Format("ulyssesListHead({1},{0}),", tmpresult, childresult));
+                    break;
+
+                case ExpressionKind.tail:
+                    m_emitter.AppendLine(String.Format("ulyssesListTail({1},{0}),", tmpresult, childresult));
+                    break;
+
+                case ExpressionKind.len:    // T_LEN:
+                    m_emitter.AppendLine(String.Format("ulyssesListLength({1},{0}),", tmpresult, childresult));
+                    break;
+
+                case ExpressionKind.not:
+
+                    if (unaryOperator.type.kind == TypeKind.IntType)
+                        m_emitter.Append(String.Format(" {0} #= call(\\+", tmpresult));
+                    else
+                        m_emitter.Append(String.Format(" {0} = call(\\+", tmpresult));
+                    m_emitter.Append("(");
+                    m_emitter.Append(childresult);
+                    m_emitter.AppendLine(")),");
+
+
+                    break;
+
+                case ExpressionKind.Cast:
+                    // todo
+                    break;
+
+                default:
+                    if (unaryOperator.type.kind == TypeKind.IntType)
+                        m_emitter.Append(String.Format(" {0} #= ({1}", tmpresult, OperatorString(unaryOperator, unaryOperator.child.type)));
+                    else
+                        m_emitter.Append(String.Format(" {0} = ({1}", tmpresult, OperatorString(unaryOperator, unaryOperator.child.type)));
+                    m_emitter.Append("(");
+                    m_emitter.Append(childresult);
+                    m_emitter.AppendLine(")),");
+                    break;
+            }
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 1);
+        }
+
+        public override string ToString()
+        {
+            return m_emitter.ToString();
+        }
+
+        protected OoaPrologType createTypeVisitor() { return m_typeFactory.create(m_idFactory); }
+        protected OoaPrologIdentifier createIdentifierVisitor() { return m_idFactory.create(); }
+        protected OoaPrologExpression createExpressionVisitor() { return m_exprFactory.create(m_idFactory, m_typeFactory); }
+
+        protected readonly OoaPrologIdentifier.Factory m_idFactory;
+        protected readonly OoaPrologType.Factory m_typeFactory;
+        protected readonly OoaPrologExpression.Factory m_exprFactory;
+
+        protected OoaPrologExpression(
+            OoaPrologIdentifier.Factory idFactory, 
+            OoaPrologType.Factory typeFactory,
+            OoaPrologExpression.Factory expressionFactory)
+            : this(idFactory, typeFactory, expressionFactory, false)
+        {
+        }
+
+        protected OoaPrologExpression(
+            OoaPrologIdentifier.Factory idFactory, 
+            OoaPrologType.Factory typeFactory, 
+            OoaPrologExpression.Factory expressionFactory,
+            bool isLHS)
+            : base()
+        {
+            m_LhsExpression = isLHS;
+            m_idFactory = idFactory;
+            m_typeFactory = typeFactory;
+            m_exprFactory = expressionFactory;
+        }
+
+
+        static int tmpVarCntr = 0;
+        public string NewTempVariable()
+        {
+            tmpVarCntr++;
+            string result = String.Format("TMPVAR_{0}", tmpVarCntr);
+            m_tmpVars.Add(result);
+            return result;
+        }
+
+        public int GetUniqueNumber()
+        {
+            tmpVarCntr++;
+            return tmpVarCntr;
+        }
+
+    }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/codegen/Prolog/ooaPrologIdentifier.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/codegen/Prolog/ooaPrologIdentifier.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/codegen/Prolog/ooaPrologIdentifier.cs	(revision 3)
@@ -0,0 +1,156 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+/*
+ * Prolog Code Generator
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TUG.Mogentes.Codegen;
+
+
+namespace TUG.Mogentes.Codegen.Prolog
+{
+    public sealed class OoaPrologIdentifier : OoaIdentifierVisitor
+    {
+        public class Factory
+        {
+            public OoaPrologIdentifier create() { return new OoaPrologIdentifier(); }
+        }
+
+
+        OoaCodeEmitter m_emitter;
+
+        private void AddTokenText(Identifier anId)
+        {
+            m_emitter.Append(anId.tokenText);
+        }
+
+
+        public override void visit(EnumIdentifier enumIdentifier)
+        {
+            System.Diagnostics.Debug.Assert(false); // handled in visit(IdentifierExpression identifierExpression)
+            //AddTokenText(enumIdentifier);
+        }
+
+        public override void visit(LandmarkIdentifier landmarkIdentifier)
+        {
+            AddTokenText(landmarkIdentifier);
+        }
+
+        public override void visit(AttributeIdentifier attributeIdentifier)
+        {
+            m_emitter.Append(String.Format("attr_{0}", attributeIdentifier.tokenText));
+        }
+
+        public override void visit(ExpressionVariableIdentifier expressionVariableIdentifier)
+        {
+            m_emitter.Append(String.Format("ExprVar_{0}", expressionVariableIdentifier));
+        }
+
+        public override void visit(ParameterIdentifier parameterIdentifier)
+        {
+            //m_emitter.Append(parameterIdentifier.tokenText.ToUpper());
+            if (parameterIdentifier.tokenText.Equals("result"))
+                m_emitter.Append("RESULT");
+            else
+                m_emitter.Append(String.Format("_{0}", parameterIdentifier.tokenText));
+        }
+
+        public override void visit(LocalVariableIdentifier localVariableIdentifier)
+        {
+            m_emitter.Append(String.Format("_{0}", localVariableIdentifier.tokenText));
+        }
+
+        public override void visit(TypeIdentifier typeIdentifier)
+        {
+            switch (typeIdentifier.type.kind)
+            {
+                case TypeKind.Any:          // not supported
+                case TypeKind.Null:         // must have some type
+                    throw new NotImplementedException();
+
+                case TypeKind.OpaqueType:   // must be resolved at this point in time
+                case TypeKind.FunctionType: // we do not support declaration of function types
+                    System.Diagnostics.Debug.Assert(false);
+                    throw new NotImplementedException();
+
+                case TypeKind.FloatType:
+                    FloatType afloat = (FloatType)typeIdentifier.type;
+                    m_emitter.Append(String.Format("float_{0}_{1}_{2}", afloat.low, afloat.high, afloat.precision));
+                    break;
+                case TypeKind.IntType:
+                    IntType intType = (IntType)typeIdentifier.type;
+                    m_emitter.Append(String.Format("{0}", intType.identifier.tokenText.ToLower()));
+                    break;
+
+                case TypeKind.BoolType:
+                    m_emitter.Append("bool");
+                    break;
+
+                case TypeKind.EnumeratedType:
+                    m_emitter.Append(String.Format("enum_{1}{0}", typeIdentifier.tokenText, typeIdentifier.prefix));
+                    break;
+
+                case TypeKind.TupleType:
+                    m_emitter.Append(String.Format("tuple_{1}{0}", typeIdentifier.tokenText, typeIdentifier.prefix));
+                    break;
+
+                case TypeKind.ListType:
+                    m_emitter.Append(String.Format("list_{1}{0}", typeIdentifier.tokenText, typeIdentifier.prefix));
+                    break;
+
+                case TypeKind.QrType:
+                case TypeKind.MapType:
+                    throw new NotImplementedException();
+
+                case TypeKind.OoActionSystemType:
+                    m_emitter.Append(String.Format("'{0}'", typeIdentifier.tokenText));
+                    //AddTokenText(typeIdentifier);
+                    break;
+
+                default:
+                    throw new NotImplementedException();
+            }
+
+        }
+
+        public override void visit(MethodIdentifier methodIdentifier)
+        {
+            m_emitter.Append(String.Format("'{0}'", methodIdentifier.tokenText));
+        }
+
+        public override void visit(NamedActionIdentifier namedActionIdentifier)
+        {
+            m_emitter.Append(String.Format("'{0}'", namedActionIdentifier.tokenText));
+        }
+
+
+        public override string ToString()
+        {
+            return m_emitter.ToString();
+        }
+
+        private OoaPrologIdentifier()
+        {
+            m_emitter = new OoaCodeEmitter();
+        }
+    }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/codegen/Prolog/ooaPrologStatement.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/codegen/Prolog/ooaPrologStatement.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/codegen/Prolog/ooaPrologStatement.cs	(revision 3)
@@ -0,0 +1,332 @@
+/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+/*
+ * Prolog Code Generator
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TUG.Mogentes.Codegen;
+
+
+namespace TUG.Mogentes.Codegen.Prolog
+{
+    public class OoaPrologStatement : OoaStatementVisitor
+    {
+        public class Factory
+        {
+            public virtual OoaPrologStatement create(
+                OoaPrologExpression.Factory exprFactory,
+                OoaPrologIdentifier.Factory idFactory,
+                OoaPrologType.Factory typeFactory) 
+            {
+                return new OoaPrologStatement(exprFactory, idFactory, typeFactory); 
+            }
+        }
+
+        protected OoaCodeEmitter m_emitter = new OoaCodeEmitter();
+
+        public override void visit(NondetBlock nondetBlock)
+        {
+            int y = 0;
+            foreach (var x in nondetBlock.statements)
+            {
+                if (y != 0)
+                    m_emitter.Append("; ");
+                else
+                    y++;
+                m_emitter.Append("(");
+                VisitSub(x, nondetBlock);
+                m_emitter.Append(")");
+            }
+        }
+
+        public override void visit(SeqBlock seqBlock)
+        {
+            int y = 0;
+            if (seqBlock.symbols.symbolList.Count > 0)
+            {
+                m_emitter.Append("([");
+                foreach (var sym in seqBlock.symbols.symbolList)
+                {
+                    if (y != 0)
+                        m_emitter.AppendLine(", ");
+                    else
+                        y++;
+
+                    OoaPrologType atype = createTypeVisitor();
+                    sym.type.Accept(atype);
+                    OoaPrologIdentifier anIdent = createIdentifierVisitor();
+                    sym.Accept(anIdent);
+                    m_emitter.Append(String.Format("{0}:{1}", anIdent.ToString(), atype.ToString()));
+                }
+                m_emitter.Append("]: ");
+            }
+
+            y = 0;
+            foreach (var x in seqBlock.statements)
+            {
+                if (y != 0)
+                    m_emitter.AppendLine(", ");
+                else
+                    y++;
+                m_emitter.Append("(");
+                VisitSub(x, seqBlock);
+                m_emitter.Append(")");
+            }
+
+            if (seqBlock.symbols.symbolList.Count > 0)
+                m_emitter.Append(")");
+        }
+
+        public override void visit(PrioBlock prioBlock)
+        {
+            int y = 0;
+            foreach (var x in prioBlock.statements)
+            {
+                if (y != 0)
+                    m_emitter.Append("// ");
+                else
+                    y++;
+                m_emitter.Append("(");
+                VisitSub(x, prioBlock);
+                m_emitter.Append(")");
+            }
+        }
+
+        public override void visit(GuardedCommand guardedCommand)
+        {
+            OoaPrologExpression expr = createExpressionVisitor();
+            guardedCommand.guard.Accept(expr);
+
+            m_emitter.AppendLineIncIndent(String.Format("({0}{2}) {1} ", expr.ToString(), guardedCommand.isQualitative ? "~>" : "=>", expr.tmpVariables[0]));
+            m_emitter.AppendLineIncIndent("(");
+            VisitSub(guardedCommand.body, guardedCommand);
+            m_emitter.DecIndent();
+            m_emitter.AppendLine("");
+            m_emitter.Append(")");
+        }
+
+        public override void visit(Assignment assignment)
+        {
+            if (assignment.nondetExpression != null)
+                throw new NotImplementedException();
+
+            LinkedListNode<Expression> aPlace = assignment.places.First;
+            LinkedListNode<Expression> aValue = assignment.values.First;
+            List<string> assignments = new List<string>();
+
+            while (aPlace != null)
+            {
+                OoaPrologExpression prologPlace = createExpressionVisitor(true);
+                aPlace.Value.Accept(prologPlace);
+                System.Diagnostics.Debug.Assert(prologPlace.tmpVariables.Count == 1);
+
+                OoaPrologExpression prologValue = createExpressionVisitor();
+                aValue.Value.Accept(prologValue);
+                System.Diagnostics.Debug.Assert(prologValue.tmpVariables.Count == 1);
+
+                m_emitter.Append(prologValue.ToString());
+
+                if (aPlace.Value.kind == ExpressionKind.Access &&
+                    ((AccessExpression)aPlace.Value).right.kind == ExpressionKind.Identifier &&
+                    ((IdentifierExpression)((AccessExpression)aPlace.Value).right).identifier.kind == IdentifierKind.AttributeIdentifier)
+                {
+                    //access to attribute is always 'self.XY'...
+                    assignments.Add(String.Format("{0} := {1}", prologPlace.tmpVariables[0], prologValue.tmpVariables[0]));
+                }
+                else
+                    if (prologPlace.tmpVariables[0] == "RESULT")
+                        assignments.Add(String.Format("unify( RESULT = {0})", prologValue.tmpVariables[0]));
+                    else if (aPlace.Value.type.kind == TypeKind.IntType)
+                        assignments.Add(String.Format("{0} #= {1}", prologPlace.tmpVariables[0], prologValue.tmpVariables[0]));
+                    else
+                        assignments.Add(String.Format("{0} = {1}", prologPlace.tmpVariables[0], prologValue.tmpVariables[0]));
+
+                if (prologPlace.ToString().Length > 0)
+                {
+                    string place = prologPlace.ToString();
+                    place = place.Trim();
+                    if (place.EndsWith(","))
+                        place = place.Substring(0, place.Length - 1);
+
+                    assignments.Add(place);
+                }
+
+                aPlace = aPlace.Next;
+                aValue = aValue.Next;
+            }
+
+            int pos = 0;
+            foreach (var s in assignments)
+            {
+                if (pos != 0)
+                    m_emitter.Append(",");
+                pos++;
+                m_emitter.Append(s);
+            }
+        }
+
+        public override void visit(Call call)
+        {
+            Expression ce = call.callExpression;
+            string callstatement = String.Empty;
+            StringBuilder parameter = new StringBuilder();
+            bool hideCall = false;
+
+            if (ce.kind == ExpressionKind.Identifier)
+                callstatement = ((IdentifierExpression)ce).identifier.tokenText;
+            else if (ce.kind == ExpressionKind.Call)
+            {
+                CallExpression parens = (CallExpression)ce;
+
+                OoaPrologExpression prologexpr = createExpressionVisitor();
+                parens.child.Accept(prologexpr);
+
+                if (parens.child.kind == ExpressionKind.Identifier &&
+                    ((IdentifierExpression)parens.child).identifier.kind == IdentifierKind.NamedActionIdentifier)
+                {
+                    // we need to hide internal actions
+                    NamedActionIdentifier namedactionid = (NamedActionIdentifier)((IdentifierExpression)parens.child).identifier;
+                    hideCall = ((FunctionType)namedactionid.type).functionType == FunctionTypeEnum.Internal;
+                }
+
+                m_emitter.Append(prologexpr.ToString());
+                callstatement = prologexpr.tmpVariables[0];
+                int i = 0;
+                foreach (var arg in parens.arguments)
+                {
+                    if (i != 0)
+                        parameter.Append(", ");
+                    else
+                        i++;
+                    OoaPrologExpression paramexpr = createExpressionVisitor();
+                    arg.Accept(paramexpr);
+                    m_emitter.Append(paramexpr.ToString());
+                    parameter.Append(paramexpr.tmpVariables[0]);
+                }
+            }
+            else
+                throw new NotImplementedException();
+            if (hideCall)
+                m_emitter.Append("i(");
+            if (parameter.Length > 0)
+                m_emitter.AppendLine(String.Format("{0}({1})", callstatement, parameter));
+            else
+                m_emitter.AppendLine(String.Format("{0}", callstatement, parameter));
+            if (hideCall)
+                m_emitter.Append(")");
+        }
+
+        public override void visit(SkipStatement skipStatement)
+        {
+            m_emitter.Append("skip");
+        }
+
+        public override void visit(AbortStatement abortStatement)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void visit(KillStatement killStatement)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void visit(QualitativeConstraintStatement qalitativeConstraintStatement)
+        {
+            if (qalitativeConstraintStatement.tag)
+            {
+                m_emitter.Append("% observable assignment in actionhead");
+                return;
+            }
+
+            OoaPrologIdentifier id1 = createIdentifierVisitor();
+            OoaPrologIdentifier id2 = createIdentifierVisitor();
+            OoaPrologIdentifier id3 = createIdentifierVisitor();
+
+
+            switch (qalitativeConstraintStatement.operation)
+            {
+                case QualitativeConstraintOperation.Deriv:
+                    qalitativeConstraintStatement.variable0.Accept(id1);
+                    qalitativeConstraintStatement.variable1.Accept(id2);
+                    m_emitter.Append(String.Format("{0} := dt {1}", id1.ToString(), id2.ToString()));
+                    break;
+                case QualitativeConstraintOperation.Diff:
+                    qalitativeConstraintStatement.variable0.Accept(id1);
+                    qalitativeConstraintStatement.variable1.Accept(id2);
+                    qalitativeConstraintStatement.variable2.Accept(id3);
+                    m_emitter.Append(String.Format("{0} := {1} - {2}", id1.ToString(), id2.ToString(), id3.ToString()));
+                    break;
+                case QualitativeConstraintOperation.Equal:
+                    qalitativeConstraintStatement.variable0.Accept(id1);
+                    qalitativeConstraintStatement.variable1.Accept(id2);
+                    m_emitter.Append(String.Format("{0} := {1}", id1.ToString(), id2.ToString()));
+                    break;
+
+                case QualitativeConstraintOperation.Prod:
+                    qalitativeConstraintStatement.variable0.Accept(id1);
+                    qalitativeConstraintStatement.variable1.Accept(id2);
+                    qalitativeConstraintStatement.variable2.Accept(id3);
+                    m_emitter.Append(String.Format("{0} := {1} * {2}", id1.ToString(), id2.ToString(), id3.ToString()));
+                    break;
+
+                case QualitativeConstraintOperation.Sum:
+                    qalitativeConstraintStatement.variable0.Accept(id1);
+                    qalitativeConstraintStatement.variable1.Accept(id2);
+                    qalitativeConstraintStatement.variable2.Accept(id3);
+                    m_emitter.Append(String.Format("{0} := {1} + {2}", id1.ToString(), id2.ToString(), id3.ToString()));
+                    break;
+
+                default:
+                    throw new NotImplementedException();
+            }
+        }
+
+
+        public override string ToString()
+        {
+            return m_emitter.ToString();
+        }
+
+        protected OoaPrologExpression createExpressionVisitor() { return m_exprFactory.create(m_idFactory, m_typeFactory); }
+        protected OoaPrologExpression createExpressionVisitor(bool lhs) { return m_exprFactory.create(m_idFactory, m_typeFactory, lhs); }
+        protected OoaPrologIdentifier createIdentifierVisitor() { return m_idFactory.create(); }
+        protected OoaPrologType createTypeVisitor() { return m_typeFactory.create(m_idFactory); }
+
+        private readonly OoaPrologExpression.Factory m_exprFactory;
+        private readonly OoaPrologIdentifier.Factory m_idFactory;
+        private readonly OoaPrologType.Factory m_typeFactory;
+
+        protected OoaPrologStatement(
+                OoaPrologExpression.Factory exprFactory,
+                OoaPrologIdentifier.Factory idFactory,
+                OoaPrologType.Factory typeFactory)
+            : base()
+        {
+            m_exprFactory = exprFactory;
+            m_idFactory = idFactory;
+            m_typeFactory = typeFactory;
+        }
+    }
+
+}
+
Index: branches/compiler/cSharp/ooasCompiler/src/codegen/Prolog/ooaPrologType.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/codegen/Prolog/ooaPrologType.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/codegen/Prolog/ooaPrologType.cs	(revision 3)
@@ -0,0 +1,302 @@
+/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+/*
+ * Prolog Code Generator
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TUG.Mogentes.Codegen;
+
+
+namespace TUG.Mogentes.Codegen.Prolog
+{
+    public class OoaPrologType : OoaTypeVisitor
+    {
+        public class Factory
+        {
+            public virtual OoaPrologType create(OoaPrologIdentifier.Factory idFactory) { return new OoaPrologType(idFactory); }
+        }
+
+        private static C5.HashBag<UlyssesType> definedTypes = new C5.HashBag<UlyssesType>();
+        public static StringBuilder typeDefinitions = new StringBuilder();
+
+        public static void EmitType(UlyssesType aType, OoaPrologIdentifier.Factory idFactory)
+        {
+            OoaPrologType ptype = new OoaPrologType(idFactory);
+            OoaCodeEmitter m_emitter = new OoaCodeEmitter();
+
+            if (definedTypes.Contains(aType))
+                return;
+
+            definedTypes.Add(aType);
+
+            switch (aType.kind)
+            {
+                case TypeKind.OoActionSystemType:
+                    aType.Accept(ptype);
+                    OoActionSystemType classtype = (OoActionSystemType)aType;
+                    // m_emitter.Append(String.Format("type( {0}, X) :- member(X,[ 'null'", ptype.ToString()));
+                    if (classtype.objects.Count == 0 && classtype.derivedObjects.Count == 0)
+                    {
+                        m_emitter.AppendLine(String.Format("type( {0}, nil).", ptype.ToString()));
+                    }
+                    else
+                    {
+                        m_emitter.Append(String.Format("type( {0}, X) :- member(X,[", ptype.ToString()));
+                        bool firste = true;
+                        foreach (var inst in classtype.objects)
+                        {
+                            if (firste)
+                                firste = false;
+                            else
+                                m_emitter.Append(", ");
+                            m_emitter.Append(String.Format("'{0}'", inst.Name));
+                        }
+                        firste = true;
+                        if (classtype.objects.Count > 0 && classtype.derivedObjects.Count > 0)
+                            m_emitter.Append(", ");
+                        foreach (var inst in classtype.derivedObjects)
+                        {
+                            if (firste)
+                                firste = false;
+                            else
+                                m_emitter.Append(", ");
+                            m_emitter.Append(String.Format("'{0}'", inst.Name));
+                        }
+                        m_emitter.AppendLine("]).");
+                    }
+                    break;
+                case TypeKind.EnumeratedType:
+                    aType.Accept(ptype);
+                    if (aType is ValuedEnumType)
+                    {
+                        ValuedEnumType venum = (ValuedEnumType)aType;
+                        m_emitter.Append(String.Format("type({0}, X) :- member(X,[", ptype.ToString()));
+                        bool nocomma = true;
+                        foreach (var val in venum.symbolTable.symbolList)
+                        {
+                            EnumIdentifier id = (EnumIdentifier)val;
+                            System.Diagnostics.Debug.Assert(id.HaveValue);
+                            if (nocomma)
+                                nocomma = false;
+                            else
+                                m_emitter.Append(", ");
+                            m_emitter.Append(id.Value);
+                        }
+                        m_emitter.AppendLine("]).");
+                    }
+                    else
+                    {
+                        EnumType enumtype = (EnumType)aType;
+                        m_emitter.AppendLine(String.Format("type( {0}, X) :- X in 0..{1}, labeling([],[X]).", ptype.ToString(), enumtype.listOfEnumSymbols.Count - 1));
+                    }
+                    break;
+                case TypeKind.IntType:
+                    aType.Accept(ptype);
+                    IntType inttype = (IntType)aType;
+                    m_emitter.AppendLine(String.Format("type( {0}, X) :- X in {1}..{2}, labeling([],[X]).", ptype.ToString(), inttype.rangeLow, inttype.rangeHigh));
+                    break;
+                case TypeKind.FloatType:
+                    throw new NotImplementedException();
+
+                case TypeKind.Any:
+                    break;
+
+                case TypeKind.ListType:
+                    ListType listType = (ListType)aType;
+                    aType.Accept(ptype);
+                    m_emitter.Append(String.Format("type( {0}, ", ptype.ToString()));
+                    m_emitter.Append("[");
+                    Boolean first = true;
+                    OoaPrologType pType = new OoaPrologType(idFactory);
+                    listType.innerType.Accept(pType);
+
+                    for (int i = 0; i < listType.maxNumberOfElements; i++)
+                    {
+                        if (!first)
+                        {
+                            m_emitter.Append(", ");
+                        }
+                        first = false;
+                        m_emitter.Append(pType.ToString());
+                    }
+                    m_emitter.AppendLine("]).");
+                    break;
+
+                case TypeKind.MapType:
+                    throw new NotImplementedException();
+
+                case TypeKind.FunctionType:
+                case TypeKind.OpaqueType:
+                case TypeKind.Null:
+                    throw new NotImplementedException(); // must not hit this
+
+                case TypeKind.TupleType:
+                    TupleType tupleType = (TupleType)aType;
+                    aType.Accept(ptype);
+                    m_emitter.Append(String.Format("type( {0}, ", ptype.ToString()));
+                    m_emitter.Append("[");
+                    first = true;
+
+                    foreach (var type in tupleType.innerTypes)
+                    {
+                        OoaPrologType iType = new OoaPrologType(idFactory);
+                        type.Accept(iType);
+
+                        if (!first)
+                        {
+                            m_emitter.Append(", ");
+                        }
+                        first = false;
+                        m_emitter.Append(iType.ToString());
+                    }
+                    m_emitter.AppendLine("]).");
+                    break;
+
+                case TypeKind.QrType:
+                    aType.Accept(ptype);
+                    QrType qrtype = (QrType)aType;
+
+                    StringBuilder landmarks = new StringBuilder();
+                    int cntr = 0;
+                    foreach (var s in qrtype.landmarks)
+                    {
+                        if (cntr != 0)
+                            landmarks.Append(", ");
+                        else
+                            cntr++;
+
+                        OoaPrologIdentifier identifierVisitor = idFactory.create();
+                        s.Accept(identifierVisitor);
+                        landmarks.Append(identifierVisitor.ToString());
+                    }
+                    m_emitter.AppendLine(String.Format("qspace( {0}, [{1}] ).", ptype.ToString(), landmarks.ToString()));
+                    break;
+                default:
+                    throw new NotImplementedException();
+            }
+            typeDefinitions.Append(m_emitter.ToString());
+        }
+
+
+        private OoaCodeEmitter m_emitter = new OoaCodeEmitter();
+        private OoaPrologIdentifier.Factory m_idFactory;
+
+        public override void visit(CharType charType)
+        {
+            m_emitter.Append("char");
+        }
+
+        public override void visit(IntType intType)
+        {
+            OoaPrologIdentifier id = m_idFactory.create();
+            intType.identifier.Accept(id);
+            EmitType(intType, m_idFactory);
+            m_emitter.Append(id.ToString());
+        }
+
+        public override void visit(BoolType boolType)
+        {
+            m_emitter.Append("bool");
+        }
+
+        public override void visit(FloatType floatType)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void visit(EnumType enumType)
+        {
+            OoaPrologIdentifier id = m_idFactory.create();
+            enumType.identifier.Accept(id);
+            EmitType(enumType, m_idFactory);
+            m_emitter.Append(id.ToString());
+        }
+
+        public override void visit(ListType listType)
+        {
+            OoaPrologIdentifier id = m_idFactory.create();
+            listType.identifier.Accept(id);
+            EmitType(listType, m_idFactory);
+            m_emitter.Append(id.ToString());
+
+        }
+
+        public override void visit(MapType mapType)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void visit(QrType qrType)
+        {
+            OoaPrologIdentifier id = m_idFactory.create();
+            qrType.identifier.Accept(id);
+            m_emitter.Append(id.ToString());
+            // m_emitter.Append(qrType.identifier.tokenText.ToLower());
+        }
+
+        public override void visit(TupleType tupleType)
+        {
+            OoaPrologIdentifier id = m_idFactory.create();
+            tupleType.identifier.Accept(id);
+            EmitType(tupleType, m_idFactory);
+            m_emitter.Append(id.ToString());
+        }
+
+        public override void visit(FunctionType functionType)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void visit(OoActionSystemType ooActionSystemType)
+        {
+            OoaPrologIdentifier id = m_idFactory.create();
+            ooActionSystemType.identifier.Accept(id);
+            m_emitter.Append(id.ToString());
+        }
+
+        public override void visit(OpaqueType opaqueType)
+        {
+            throw new NotImplementedException();
+        }
+
+
+        public override string ToString()
+        {
+            return m_emitter.ToString();
+        }
+
+        public virtual string GetInternalTypeDefinitions()
+        {
+            OoaCodeEmitter result = new OoaCodeEmitter();
+
+            result.AppendLine("type(bool, X) :- member(X,[fail,true]).");
+            result.AppendLine("type(char, X) :- X in 0..255, labeling([],[X]).");
+
+            return result.ToString();
+        }
+
+        protected OoaPrologType(OoaPrologIdentifier.Factory idFactory)
+        {
+            m_idFactory = idFactory;
+        }
+    }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/codegen/Prolog/ooaPrologVisitor.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/codegen/Prolog/ooaPrologVisitor.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/codegen/Prolog/ooaPrologVisitor.cs	(revision 3)
@@ -0,0 +1,482 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+/*
+ *  === Prolog Emitter ===
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TUG.Mogentes;
+using TUG.Mogentes.Codegen.Prolog;
+
+
+namespace TUG.Mogentes.Codegen
+{
+    public class OoaPrologVisitor : OoaCompleteAstTraversalVisitor
+    {
+        protected OoaCodeEmitter m_emitter;
+
+        private string PrologIdentifier(Identifier id)
+        {
+            OoaPrologIdentifier identifierVisitor = m_idFactory.create();
+            id.Accept(identifierVisitor);
+            return identifierVisitor.ToString();
+        }
+
+        protected void ExportMethodsAndActions(MainModule mainModule)
+        {
+            StringBuilder varActions = new StringBuilder();
+            m_emitter.AppendLine();
+            m_emitter.AppendLine("% action system");
+            m_emitter.AppendLineIncIndent("as :- ");
+
+            /* export methods */
+            m_emitter.AppendLine("methods (");
+            ExportMethods(mainModule);
+            m_emitter.AppendLine("), ");
+            m_emitter.AppendLine("actions (");
+            ExportNamedActions(mainModule, varActions);
+            m_emitter.AppendLine("), ");
+            m_emitter.AppendLine("dood (");
+
+            ExportDoOdBlock(mainModule.instance.doOdBlock, m_emitter);
+
+
+            m_emitter.AppendLine("), qdes (none)");
+            m_emitter.DecIndent();
+            m_emitter.AppendLine(".");
+            m_emitter.AppendLine("");
+
+            m_emitter.Append(varActions.ToString());
+        }
+
+        private void ExportMethods(MainModule mainModule)
+        {
+            int y = 0;
+            foreach (var x in mainModule.instance.symbols.symbolList)
+            {
+                if (x.kind == IdentifierKind.MethodIdentifier)
+                {
+                    if (y != 0)
+                        m_emitter.AppendLine(", ");
+                    else
+                        y++;
+
+                    MethodIdentifier theMethod = (MethodIdentifier)x;
+                    OoaPrologIdentifier pIdent = m_idFactory.create();
+                    theMethod.Accept(pIdent);
+
+                    /* method */
+                    StringBuilder parameter = new StringBuilder();
+                    if (theMethod.parameter.Count > 0 || ((FunctionType)theMethod.type).returnType != null)
+                    {
+                        parameter.Append("(");
+                        int z = 0;
+                        foreach (var param in theMethod.parameter)
+                        {
+                            if (z != 0)
+                            {
+                                parameter.Append(", ");
+                            }
+                            else
+                                z++;
+                            OoaPrologIdentifier pParamIdent = m_idFactory.create();
+                            param.Accept(pParamIdent);
+                            parameter.Append(pParamIdent.ToString());
+                        }
+
+
+                        if (((FunctionType)theMethod.type).returnType != null)
+                        {
+                            if (z != 0)
+                                parameter.Append(", ");
+                            parameter.Append("RESULT");
+                        }
+                        parameter.Append(")");
+                    }
+                    m_emitter.AppendLineIncIndent(String.Format("{0}{1} = (", pIdent.ToString(), parameter.ToString()));
+
+                    OoaPrologStatement pBody = createStatementVisitor();
+                    ((MethodIdentifier)x).body.Accept(pBody);
+                    m_emitter.Append(pBody.ToString());
+                    m_emitter.Append(")");
+                    m_emitter.DecIndent();
+                }
+            }
+            if (y == 0)
+                m_emitter.Append(" none ");
+        }
+
+        private void ExportNamedActions(MainModule mainModule, StringBuilder varActions)
+        {
+            int y = 0;
+            foreach (var x in mainModule.instance.symbols.symbolList)
+            {
+                if (x.kind == IdentifierKind.NamedActionIdentifier)
+                {
+                    if (y != 0)
+                        m_emitter.AppendLine(", ");
+                    else
+                        y++;
+                    NamedActionIdentifier action = (NamedActionIdentifier)x;
+                    OoaPrologIdentifier pIdent = m_idFactory.create();
+                    action.Accept(pIdent);
+
+                    if (((FunctionType)action.type).functionType != FunctionTypeEnum.Continuous)
+                    {
+                        /* discrete actions */
+                        StringBuilder parameter = new StringBuilder();
+                        StringBuilder parametertype = new StringBuilder();
+                        if (action.parameter.Count > 0)
+                        {
+                            parameter.Append("(");
+                            parametertype.Append("(");
+                            int z = 0;
+                            foreach (var param in action.parameter)
+                            {
+                                if (z != 0)
+                                {
+                                    parameter.Append(", ");
+                                    parametertype.Append(", ");
+                                }
+                                else
+                                    z++;
+                                OoaPrologIdentifier pParamIdent = m_idFactory.create();
+                                param.Accept(pParamIdent);
+                                parameter.Append(pParamIdent.ToString());
+
+                                OoaPrologType pParamType = createTypeVisitor();  // bugfix me!
+                                param.type.Accept(pParamType);
+                                parametertype.Append(pParamType.ToString());
+
+                            }
+                            parametertype.Append(")");
+                            parameter.Append(")");
+                        }
+                        //if (parametertype.Length > 0)
+                        //    varActions.AppendLine(String.Format("{0}{1}.", pIdent.ToString(), parametertype.ToString()));
+                        m_emitter.AppendLineIncIndent(String.Format("{0}{1}::", pIdent.ToString(), parameter.ToString()));
+                    }
+                    else
+                    {
+                        /* observable state vars outside... */
+                        StringBuilder parameter = new StringBuilder();
+                        int z = 0;
+                        foreach (var stmt in ((GuardedCommand)action.body.statements.First.Value).body.statements)
+                        {
+                            QualitativeConstraintStatement qstmt = (QualitativeConstraintStatement)stmt;
+                            if (qstmt.operation == QualitativeConstraintOperation.Equal
+                                && qstmt.variable1.kind == IdentifierKind.AttributeIdentifier
+                                && ((AttributeIdentifier)qstmt.variable1).isObservable)
+                            {
+                                if (z != 0)
+                                    parameter.Append(", ");
+                                else
+                                    z++;
+                                qstmt.tag = true;
+                                OoaPrologIdentifier pParamIdent1 = m_idFactory.create();
+                                OoaPrologIdentifier pParamIdent2 = m_idFactory.create();
+                                qstmt.variable0.Accept(pParamIdent1);
+                                qstmt.variable1.Accept(pParamIdent2);
+                                parameter.Append(String.Format("{0}({1})", pParamIdent2.ToString(), pParamIdent1.ToString()));
+                            }
+                        }
+                        m_emitter.AppendLineIncIndent(String.Format("[{0}]::", parameter.ToString()));
+                    }
+
+                    OoaPrologStatement pBody = createStatementVisitor();
+                    ((NamedActionIdentifier)x).body.Accept(pBody);
+                    m_emitter.Append(pBody.ToString());
+                    m_emitter.DecIndent();
+
+                }
+            }
+        }
+
+        private void ExportDoOdBlock(Block block, OoaCodeEmitter m_emitter)
+        {
+            OoaPrologStatement statement = createStatementVisitor();
+            block.Accept(statement);
+            m_emitter.Append(statement.ToString());
+        }
+
+        protected int ExportControllableActions(MainModule mainModule)
+        {
+            m_emitter.AppendLine("");
+            m_emitter.AppendLine("%emit controllable actions");
+            m_emitter.Append("input([");
+            int y = 0;
+            foreach (var x in mainModule.instance.symbols.symbolList)
+            {
+                if (x.kind == IdentifierKind.NamedActionIdentifier)
+                {
+                    if (((FunctionType)((NamedActionIdentifier)x).type).functionType == FunctionTypeEnum.Controllable)
+                    {
+                        if (y != 0)
+                            m_emitter.Append(", ");
+                        else
+                            y++;
+                        OoaPrologIdentifier pIdent = m_idFactory.create();
+
+                        ((NamedActionIdentifier)x).Accept(pIdent);
+                        m_emitter.Append(pIdent.ToString());
+                    }
+                }
+            }
+            m_emitter.AppendLine("]).");
+            return y;
+        }
+
+        protected int ExportObservableActions(MainModule mainModule)
+        {
+            m_emitter.AppendLine("");
+            m_emitter.AppendLine("%emit observable actions");
+            m_emitter.Append("output([");
+            int y = 0;
+            foreach (var x in mainModule.instance.symbols.symbolList)
+            {
+                if (x.kind == IdentifierKind.NamedActionIdentifier)
+                {
+                    if (((FunctionType)((NamedActionIdentifier)x).type).functionType == FunctionTypeEnum.Observable)
+                    {
+                        if (y != 0)
+                            m_emitter.Append(", ");
+                        else
+                            y++;
+                        OoaPrologIdentifier pIdent = m_idFactory.create();
+
+                        ((NamedActionIdentifier)x).Accept(pIdent);
+                        m_emitter.Append(pIdent.ToString());
+                    }
+                }
+            }
+            m_emitter.AppendLine("]).");
+            return y;
+        }
+
+        protected void ExportInitialState(MainModule mainModule)
+        {
+            m_emitter.AppendLine("");
+            m_emitter.AppendLine("%emit initial state");
+            List<string> initPreds = new List<string>();
+            List<string> initVars = new List<string>();
+            int y = 0;
+            foreach (var x in mainModule.instance.symbols.symbolList)
+            {
+                if (x.kind == IdentifierKind.AttributeIdentifier)
+                {
+                    OoaPrologExpression anExprVis = createExpressionVisitor();
+                    ((AttributeIdentifier)x).initializer.Accept(anExprVis);
+                    System.Diagnostics.Debug.Assert(anExprVis.tmpVariables.Count == 1);
+                    string initPredName = String.Format("attr_{0}_init({1})", x.tokenText, anExprVis.tmpVariables[0]);
+                    m_emitter.AppendLine(String.Format("{0} :- {1} 1=1.", initPredName, anExprVis.ToString()));
+                    initPreds.Add(initPredName);
+                    initVars.Add(anExprVis.tmpVariables[0]);
+                }
+            }
+
+
+            m_emitter.Append("init([");
+            y = 0;
+            foreach (var x in initVars)
+            {
+                if (y != 0)
+                    m_emitter.Append(",");
+                else
+                    y++;
+                m_emitter.Append(x);
+            }
+            m_emitter.Append("]) :-");
+            y = 0;
+            foreach (var x in initPreds)
+            {
+                if (y != 0)
+                    m_emitter.Append(",");
+                else
+                    y++;
+                m_emitter.Append(x);
+            }
+            m_emitter.AppendLine(".");
+        }
+
+        protected int ExportState(MainModule mainModule)
+        {
+            m_emitter.AppendLine("");
+            m_emitter.AppendLine("%emit state definition");
+            m_emitter.Append("state_def([");
+            int y = 0;
+            foreach (var x in mainModule.instance.symbols.symbolList)
+            {
+                if (x.kind == IdentifierKind.AttributeIdentifier)
+                {
+                    if (y != 0)
+                        m_emitter.Append(", ");
+                    else
+                        y++;
+                    OoaPrologIdentifier pid = m_idFactory.create();
+                    x.Accept(pid);
+                    m_emitter.Append(pid.ToString());
+                }
+            }
+            m_emitter.AppendLine("]).");
+            return y;
+        }
+
+        protected void ExportVariables(MainModule mainModule)
+        {
+            m_emitter.AppendLine("");
+            m_emitter.AppendLine("%emit type of state variables");
+            Dictionary<string, StringBuilder> varlist = new Dictionary<string, StringBuilder>();
+            foreach (var x in mainModule.instance.symbols.symbolList)
+            {
+                if (x.kind == IdentifierKind.AttributeIdentifier)
+                {
+                    OoaPrologIdentifier pid = m_idFactory.create();
+                    OoaPrologType ptype = createTypeVisitor();
+                    x.Accept(pid);
+                    x.type.Accept(ptype);
+
+                    string key = x.type.kind != TypeKind.QrType ? ptype.ToString() : "qvar";
+                    if (varlist.ContainsKey(key))
+                    {
+                        varlist[key].Append(String.Format(", {0}", pid.ToString()));
+                    }
+                    else
+                    {
+                        varlist.Add(key, new StringBuilder(String.Format("[{0}", pid.ToString())));
+                    }
+                }
+            }
+            foreach (var key in varlist.Keys)
+                m_emitter.AppendLine(String.Format("var({0}], {1}).", varlist[key], key));
+        }
+
+        protected void ExportTypes(MainModule mainModule)
+        {
+            foreach (var x in mainModule.symbolTable.symbolList)
+            {
+                if (x.kind == IdentifierKind.TypeIdentifier)
+                    OoaPrologType.EmitType(((TypeIdentifier)x).type, m_idFactory);
+            }
+        }
+
+
+        public override void visit(MainModule mainModule)
+        {
+            m_emitter.AppendLine("% Argos Generated");
+            m_emitter.AppendLine(String.Format("%{0}", Mogentes.Program.GetProgramVersion().ToString().Replace(Environment.NewLine, Environment.NewLine + "%")));
+            m_emitter.AppendLine("% Code-Gen Version: 0.2");
+            m_emitter.Append("%        Generated: "); m_emitter.AppendLine(System.DateTime.Now.ToString());
+            m_emitter.AppendLine("%------------------------------------------------------------------------");
+            m_emitter.AppendLine("");
+            String nameSpace = TUG.Mogentes.Program.Options.nameSpace;
+            m_emitter.AppendLine(":- module("+nameSpace+", [var/2, input/1, searchDepth/1, qspace/2]).");
+            m_emitter.AppendLine(":- use_module(library(file_systems)).");
+            m_emitter.AppendLine(":- use_module(library(process)).");
+            m_emitter.AppendLine(":- use_module(library(clpfd)).");
+            m_emitter.AppendLine(":- use_module(library(clpb)).");
+            m_emitter.AppendLine(":- use_module(library(lists)).");
+            m_emitter.AppendLine(":- use_module(library(avl)).");
+            m_emitter.AppendLine(":- use_module(library(ordsets)).");
+            m_emitter.AppendLine(":- use_module(library(system)).");
+            //m_emitter.AppendLine(":- use_module(library(gauge)).");
+            m_emitter.AppendLine(":- use_module(library(terms)).");
+            m_emitter.AppendLine(":- use_module(library(sets)).");
+            m_emitter.AppendLine(":- use_module(library(random)).");
+
+            m_emitter.AppendLine(":- use_module(ulysseslib, _, [ulyssesListHead/2, ulyssesListLength/2, ulyssesListTail/2, ulyssesListConc/3, ulyssesTupleAccess/3, ulyssesListAccess/3, ulyssesListWrite/4, ulyssesMapAccess/3]).");
+
+            m_emitter.AppendLine(":- public(as/0).");
+            m_emitter.AppendLine(":- dynamic(as/0).");
+            m_emitter.AppendLine(":- dynamic(qstate_init/1).");
+            m_emitter.AppendLine(":- dynamic(qstate_constraints/1).");
+            m_emitter.AppendLine(":- public(qstate_init/1).");
+            m_emitter.AppendLine(":- public(qstate_constraints/1).");
+
+            /*definition of search depth*/
+            m_emitter.AppendLine("");
+            m_emitter.AppendLine("% maximal search depth (change at will)");
+            m_emitter.AppendLine("searchDepth("+TUG.Mogentes.Program.Options.searchDepth+").");
+            m_emitter.AppendLine("");
+
+            /*definition of types*/
+            ExportTypes(mainModule);
+            /* variable definition */
+            ExportVariables(mainModule);
+
+            /* state definition */
+            ExportState(mainModule);
+            /* initial state */
+            ExportInitialState(mainModule);
+            /* input actions (controllables) */
+            ExportControllableActions(mainModule);
+            /* output actions (observables) */
+            ExportObservableActions(mainModule);
+            /* named actions */
+            ExportMethodsAndActions(mainModule);
+
+            /* all types */
+            m_emitter.AppendLine("%definition of types");
+            m_emitter.AppendLine(OoaPrologType.typeDefinitions.ToString());
+            m_emitter.AppendLine(createTypeVisitor().GetInternalTypeDefinitions());
+        }
+
+
+        public override string ToString()
+        {
+            return m_emitter.ToString();
+        }
+
+        protected OoaPrologIdentifier createIdentifierVisitor() { return m_idFactory.create(); }
+        protected OoaPrologType createTypeVisitor() { return m_typeFactory.create(m_idFactory); }
+        protected OoaPrologExpression createExpressionVisitor() { return m_exprFactory.create(m_idFactory, m_typeFactory); }
+        protected OoaPrologStatement createStatementVisitor() { return m_stmtFactory.create(m_exprFactory, m_idFactory, m_typeFactory); }
+
+        private readonly  OoaPrologExpression.Factory m_exprFactory;
+        private readonly OoaPrologIdentifier.Factory m_idFactory;
+        private readonly OoaPrologStatement.Factory m_stmtFactory;
+        private readonly OoaPrologType.Factory m_typeFactory;
+
+        protected OoaPrologVisitor(
+            ParserState aState, 
+            OoaPrologExpression.Factory exprFactory,
+            OoaPrologIdentifier.Factory idFactory,
+            OoaPrologStatement.Factory  stmtFactory,
+            OoaPrologType.Factory       tpeFactory) 
+            : base(aState)
+        {
+            m_emitter = new OoaCodeEmitter();
+            m_exprFactory = exprFactory;
+            m_idFactory = idFactory;
+            m_stmtFactory = stmtFactory;
+            m_typeFactory = tpeFactory;
+        }
+
+        public OoaPrologVisitor(ParserState aState)
+            : this(
+                aState,
+                new OoaPrologExpression.Factory(),
+                new OoaPrologIdentifier.Factory(),
+                new OoaPrologStatement.Factory(),
+                new OoaPrologType.Factory())
+        { }
+    }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/codegen/PrologSymbolic/ooaPrologSymbolicExpression.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/codegen/PrologSymbolic/ooaPrologSymbolicExpression.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/codegen/PrologSymbolic/ooaPrologSymbolicExpression.cs	(revision 3)
@@ -0,0 +1,379 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TUG.Mogentes.Codegen;
+using TUG.Mogentes.Codegen.Prolog;
+
+namespace TUG.Mogentes.Codegen.PrologSymbolic
+{
+    public class OoaPrologSymbolicExpression : OoaPrologExpression
+    {
+        new public class Factory : OoaPrologExpression.Factory
+        {
+            public override OoaPrologExpression create(OoaPrologIdentifier.Factory idFactory, OoaPrologType.Factory typeFactory, bool lhs)
+            { return new OoaPrologSymbolicExpression(idFactory, typeFactory, this, lhs); }
+        }
+        
+        /*Also treats bools and enums as ints..*/
+        new protected bool isNumericBinary(Expression expression)
+        {
+            bool result = false;
+            if (expression is BinaryOperator)
+            {
+                TypeKind leftKind = ((BinaryOperator)expression).left.type.kind;
+                TypeKind rightKind = ((BinaryOperator)expression).right.type.kind;
+                result = (leftKind == TypeKind.IntType || leftKind == TypeKind.BoolType || leftKind == TypeKind.EnumeratedType) &&
+                     (rightKind == TypeKind.IntType || rightKind == TypeKind.BoolType || rightKind == TypeKind.EnumeratedType);
+            }
+            else if (expression is UnaryOperator)
+            {
+                TypeKind childKind = ((UnaryOperator)expression).child.type.kind;
+                result = childKind == TypeKind.IntType || childKind == TypeKind.BoolType || childKind == TypeKind.EnumeratedType;
+            }
+            else throw new NotImplementedException();
+            return result;
+        }
+
+        // we need to map all other things to Prolog constructs
+        private string operatorString(Expression expression, UlyssesType resultingType)
+        {
+            switch (expression.kind)
+            {
+                case ExpressionKind.abs:    // T_ABS:
+                case ExpressionKind.card:   // T_CARD:
+                case ExpressionKind.dom:    // T_DOM:
+                case ExpressionKind.range:  // T_RNG:
+                case ExpressionKind.merge:  // T_MERGE:
+                case ExpressionKind.elems:  // T_ELEMS:
+                case ExpressionKind.head:   // T_HEAD:
+                case ExpressionKind.tail:   // T_TAIL:
+                case ExpressionKind.conc:   // T_CONC:
+                case ExpressionKind.inds:   // T_INDS:
+                case ExpressionKind.dinter: // T_DINTER:
+                case ExpressionKind.dunion: // T_DUNION:
+                case ExpressionKind.domresby:   // T_DOMRESBY:
+                case ExpressionKind.domresto:   // T_DOMRESTO:
+                case ExpressionKind.rngresby:   // T_RNGRESBY:
+                case ExpressionKind.rngresto:   // T_RNGRESTO:
+                case ExpressionKind.inter:  // T_INTER:
+                case ExpressionKind.union:  // T_UNION:
+                case ExpressionKind.diff:   // T_DIFF:
+                case ExpressionKind.munion: // T_MUNION:
+                case ExpressionKind.seqmod_mapoverride: // T_SEQMOD_MAPOVERRIDE:
+                case ExpressionKind.subset:
+                case ExpressionKind.elemin:
+                case ExpressionKind.notelemin:
+                case ExpressionKind.implies:    // T_IMPLIES:
+                case ExpressionKind.biimplies:  // T_BIIMPLIES:
+                case ExpressionKind.Primed:
+                case ExpressionKind.len:    // T_LEN:
+                    throw new NotImplementedException();
+
+                case ExpressionKind.div:    // T_DIV:
+                    return "/";
+                case ExpressionKind.idiv:   // T_IDIV:
+                    return "/";
+                case ExpressionKind.mod:    // T_MOD:
+                    return "mod";
+                case ExpressionKind.prod:   // T_PROD:
+                    return "*";
+                case ExpressionKind.sum:    // T_SUM:
+                    return "+";
+                case ExpressionKind.minus:  // T_MINUS:
+                    return "-";
+                case ExpressionKind.less:
+                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? "<" : "#<";
+                case ExpressionKind.lessequal:
+                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? "=<" : "#=<";
+                case ExpressionKind.greater:
+                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? ">" : "#>";
+                case ExpressionKind.greaterequal:
+                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? ">=" : "#>=";
+                case ExpressionKind.equal:
+                    return resultingType.kind == TypeKind.QrType ? "==" : "#=";
+                case ExpressionKind.notequal:
+                    return resultingType.kind == TypeKind.QrType || !isNumericBinary(expression) ? "\\=" : "#\\=";
+                case ExpressionKind.and:    // T_AND:
+                    throw new NotImplementedException(); // implemented in binaryoperator
+                case ExpressionKind.or:     // T_OR:
+                    throw new NotImplementedException(); // implemented in binaryoperator
+                case ExpressionKind.not:
+                    throw new NotImplementedException(); // implemented in binaryoperator
+
+                case ExpressionKind.Cast:
+                    return String.Empty;
+
+                default:
+                    return Enum.GetName(typeof(ExpressionKind), expression.kind);
+            }
+        }
+
+        public override void visit<T>(ValueExpression<T> valueExpression)
+        {
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
+            string tmpVar = NewTempVariable();
+            m_emitter.Append(String.Format("{0} ", tmpVar));
+
+
+            if (valueExpression.value == null)
+                m_emitter.Append("= 'null'");
+            else if (valueExpression is ValueExpression<bool>)
+                m_emitter.Append((valueExpression as ValueExpression<bool>).value ? " = true" : " = false");
+            else if (valueExpression is ValueExpression<char>)
+                m_emitter.Append(String.Format("= '{0}'", valueExpression.ToString()));
+            else if (valueExpression is ValueExpression<int>)
+                m_emitter.Append(String.Format("= {0}", valueExpression.ToString()));
+            else
+                m_emitter.Append(String.Format("= {0}", valueExpression.value.ToString()));
+
+            m_emitter.AppendLine(",");
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 1);
+        }
+
+        public override void visit(IdentifierExpression identifierExpression)
+        {
+            if (identifierExpression.identifier.kind == IdentifierKind.LandmarkIdentifier)
+            {
+                LandmarkIdentifier lmid = (LandmarkIdentifier)identifierExpression.identifier;
+                OoaPrologIdentifier pid = createIdentifierVisitor();
+                lmid.Accept(pid);
+                //m_emitter.Append(pid.ToString());
+                m_tmpVars.Add(pid.ToString());
+                return;
+            }
+            else if (identifierExpression.identifier.kind == IdentifierKind.EnumIdentifier)
+            {
+                EnumIdentifier enumid = (EnumIdentifier)identifierExpression.identifier;
+                EnumType enumType = (EnumType)enumid.type;
+                //m_emitter.Append(enumType.listOfEnumSymbols.IndexOf(enumid));
+                if (enumType is ValuedEnumType)
+                    m_emitter.AppendLine(String.Format("{0} = {1},", NewTempVariable(), enumid.Value));
+                else
+                    m_emitter.AppendLine(String.Format("{0} = {1},", NewTempVariable(), enumType.listOfEnumSymbols.IndexOf(enumid).ToString()));
+            }
+            else if (identifierExpression.isSelf)
+            {
+                m_emitter.AppendLine(String.Format("{0} = {1},", NewTempVariable(), GetIdentifierString(identifierExpression.identifier)));
+            }
+            /*else if (identifierExpression.identifier.kind == IdentifierKind.AttributeIdentifier)
+            {
+                m_emitter.AppendLine(String.Format("getVal({1},{0},_),", NewTempVariable(), GetIdentifierString(identifierExpression.identifier)));
+            }*/
+            else
+            {
+                //m_emitter.Append(GetIdentifierString(identifierExpression.identifier));
+                m_tmpVars.Add(GetIdentifierString(identifierExpression.identifier));
+            }
+        }
+
+        public override void visit(UnaryOperator unaryOperator)
+        {
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
+            VisitSub(unaryOperator.child, unaryOperator);
+
+            if (unaryOperator.kind == ExpressionKind.Cast)
+                return;
+
+            string childresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
+
+            string tmpresult = NewTempVariable();
+
+            switch (unaryOperator.kind)
+            {
+                case ExpressionKind.head:
+                    m_emitter.AppendLine(String.Format("ulyssesListHead({1},{0}),", tmpresult, childresult));
+                    break;
+
+                case ExpressionKind.tail:
+                    m_emitter.AppendLine(String.Format("ulyssesListTail({1},{0}),", tmpresult, childresult));
+                    break;
+
+                case ExpressionKind.len:    // T_LEN:
+                    m_emitter.AppendLine(String.Format("ulyssesListLength({1},{0}),", tmpresult, childresult));
+                    break;
+
+                case ExpressionKind.not:
+//                    if (unaryOperator.type.kind == TypeKind.IntType)
+//                        m_emitter.Append(String.Format(" {0} #= call(\\+", tmpresult));
+//                    else
+                        m_emitter.Append(String.Format(" {0} = ( #\\", tmpresult));
+                    m_emitter.Append("(");
+                    m_emitter.Append(childresult);
+                    m_emitter.AppendLine(")),");
+                    break;
+
+                case ExpressionKind.Cast:
+                    // todo
+                    break;
+
+                default:
+// do not use #= for assignments in the symbolic backend
+//                    if (unaryOperator.type.kind == TypeKind.IntType)
+//                        m_emitter.Append(String.Format(" {0} #= ({1}", tmpresult, operatorString(unaryOperator, unaryOperator.child.type)));
+//                    else
+                        m_emitter.Append(String.Format(" {0} = ({1}", tmpresult, operatorString(unaryOperator, unaryOperator.child.type)));
+                    m_emitter.Append("(");
+                    m_emitter.Append(childresult);
+                    m_emitter.AppendLine(")),");
+                    break;
+            }
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 1);
+        }
+
+        public override void visit(BinaryOperator binaryOperator)
+        {
+            // eval stack must be empty
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
+
+            OoaCodeEmitter origEmitter = m_emitter;
+            OoaCodeEmitter leftcode = new OoaCodeEmitter();
+            OoaCodeEmitter rightcode = new OoaCodeEmitter();
+
+
+            // traverse left
+            m_emitter = leftcode;
+            VisitSub(binaryOperator.left, binaryOperator);
+            string leftresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
+
+            // traverse right
+            m_emitter = rightcode;
+            VisitSub(binaryOperator.right, binaryOperator);
+            string rightresult = m_tmpVars[0]; m_tmpVars.RemoveAt(0);
+            // eval stack must be empty
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 0);
+
+            // restore original emitter and get tmp.var
+            m_emitter = origEmitter;
+            string tmpVar = NewTempVariable();
+
+            switch (binaryOperator.kind)
+            {
+                case ExpressionKind.elemin:
+                    m_emitter.Append(leftcode.ToString());
+                    m_emitter.Append(rightcode.ToString());
+                    m_emitter.AppendLine(String.Format(" {0} = member({1},{2}),",
+                        tmpVar, leftresult, rightresult));
+                    break;
+                case ExpressionKind.and:    // T_AND:
+                    m_emitter.Append(leftcode.ToString());
+                    m_emitter.Append(rightcode.ToString());
+                    m_emitter.AppendLine(String.Format(" {0} = ({1} {2} {3}), ",
+                        tmpVar, leftresult, "#/\\", rightresult));
+                    break;
+                case ExpressionKind.or:     // T_OR:
+                    m_emitter.Append(leftcode.ToString());
+                    m_emitter.Append(rightcode.ToString());
+                    m_emitter.AppendLine(String.Format(" {0} = ({1} {2} {3}), ",
+                        tmpVar, leftresult, "#\\/", rightresult));
+                    break;
+
+                case ExpressionKind.implies:
+                    m_emitter.Append(leftcode.ToString());
+                    m_emitter.AppendLine(String.Format(" {0} = ({1} -> ({2}{3}); true), ", // {0} = (({1} -> ({2}{3}); true))
+                        tmpVar, leftresult, rightcode.ToString(), rightresult));
+                    break;
+
+                case ExpressionKind.equal:
+                    m_emitter.Append(leftcode.ToString());
+                    m_emitter.Append(rightcode.ToString());
+                    /*check if we have tupleconstructors as matchers*/
+                    TupleConstructor matcher = null;
+                    string aTuple = null;
+                    if (binaryOperator.left.kind == ExpressionKind.TupleConstr &&
+                        ((TupleConstructor)binaryOperator.left).isMatcher)
+                    {
+                        matcher = (TupleConstructor)binaryOperator.left;
+                        aTuple = rightresult;
+                    }
+                    else if (binaryOperator.right.kind == ExpressionKind.TupleConstr &&
+                        ((TupleConstructor)binaryOperator.right).isMatcher)
+                    {
+                        matcher = (TupleConstructor)binaryOperator.right;
+                        aTuple = leftresult;
+                    }
+
+                    if (matcher == null)
+                        m_emitter.AppendLine(String.Format(" {0} = ({1} {2} {3}), ",
+                            tmpVar, leftresult, operatorString(binaryOperator, binaryOperator.left.type), rightresult));
+                    else
+                    {
+                        m_emitter.Append(String.Format("{0} = unify({1} = [", tmpVar, aTuple));
+                        int cntr = 0;
+                        foreach (var x in matcher.values)
+                        {
+                            if (cntr != 0)
+                                m_emitter.Append(", ");
+                            else
+                                cntr++;
+
+                            if (x.kind != ExpressionKind.Identifier)
+                                throw new ArgumentException();
+
+                            IdentifierExpression ident = (IdentifierExpression)x;
+                            OoaPrologIdentifier avisitor = createIdentifierVisitor();
+                            ident.Accept(avisitor);
+                            m_emitter.Append(avisitor.ToString());
+                        }
+                        m_emitter.AppendLine("]),");
+                    }
+                    break;
+
+
+
+                case ExpressionKind.conc:
+                    m_emitter.Append(leftcode.ToString());
+                    m_emitter.Append(rightcode.ToString());
+                    m_emitter.AppendLine(String.Format("ulyssesListConc({1},{2},{0}),", tmpVar, leftresult, rightresult));
+                    break;
+
+                default:
+                    m_emitter.Append(leftcode.ToString());
+                    m_emitter.Append(rightcode.ToString());
+                    if (binaryOperator.left.type.kind == TypeKind.QrType)
+                        m_emitter.Append("qEval");
+
+// do not use #= for assignments in the symbolic backend
+//                    if (binaryOperator.type.kind == TypeKind.IntType)
+//                        m_emitter.AppendLine(String.Format(" {0} #= ({1} {2} {3}), ",
+//                            tmpVar, leftresult, operatorString(binaryOperator, binaryOperator.left.type), rightresult));
+//                    else
+
+                        m_emitter.AppendLine(String.Format(" {0} = ({1} {2} {3}), ",
+                            tmpVar, leftresult, operatorString(binaryOperator, binaryOperator.left.type), rightresult));
+                    break;
+            }
+            System.Diagnostics.Debug.Assert(m_tmpVars.Count == 1);
+        }
+
+
+
+        protected OoaPrologSymbolicExpression(
+            OoaPrologIdentifier.Factory idFactory, 
+            OoaPrologType.Factory typeFactory, 
+            OoaPrologExpression.Factory expressionFactory,
+            bool lhs)
+            : base(idFactory, typeFactory, expressionFactory, lhs)
+        { }
+
+    }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/codegen/PrologSymbolic/ooaPrologSymbolicStatement.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/codegen/PrologSymbolic/ooaPrologSymbolicStatement.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/codegen/PrologSymbolic/ooaPrologSymbolicStatement.cs	(revision 3)
@@ -0,0 +1,145 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TUG.Mogentes.Codegen.Prolog;
+
+namespace TUG.Mogentes.Codegen.PrologSymbolic
+{    
+    public class OoaPrologSymbolicStatement : OoaPrologStatement
+    {
+        public new class Factory : OoaPrologStatement.Factory
+        {
+            public override OoaPrologStatement create(
+                OoaPrologExpression.Factory exprFactory,
+                OoaPrologIdentifier.Factory idFactory,
+                OoaPrologType.Factory typeFactory) 
+            {
+                return new OoaPrologSymbolicStatement(exprFactory, idFactory, typeFactory); 
+            }
+        }
+
+        public override void visit(Assignment assignment)
+        {
+            if (assignment.nondetExpression != null)
+                throw new NotImplementedException();
+
+            LinkedListNode<Expression> aPlace = assignment.places.First;
+            LinkedListNode<Expression> aValue = assignment.values.First;
+            List<string> assignments = new List<string>();
+
+            while (aPlace != null)
+            {
+                OoaPrologExpression prologPlace = createExpressionVisitor(true);
+                aPlace.Value.Accept(prologPlace);
+                System.Diagnostics.Debug.Assert(prologPlace.tmpVariables.Count == 1);
+
+                OoaPrologExpression prologValue = createExpressionVisitor();
+                aValue.Value.Accept(prologValue);
+                System.Diagnostics.Debug.Assert(prologValue.tmpVariables.Count == 1);
+
+                m_emitter.Append(prologValue.ToString());
+
+                if (aPlace.Value.kind == ExpressionKind.Access &&
+                    ((AccessExpression)aPlace.Value).right.kind == ExpressionKind.Identifier &&
+                    ((IdentifierExpression)((AccessExpression)aPlace.Value).right).identifier.kind == IdentifierKind.AttributeIdentifier)
+                {
+                    //access to attribute is always 'self.XY'...
+                    assignments.Add(String.Format("{0} := {1}", prologPlace.tmpVariables[0], prologValue.tmpVariables[0]));
+                }
+                else
+                    if (prologPlace.tmpVariables[0] == "RESULT")
+                        assignments.Add(String.Format("unify( RESULT = {0})", prologValue.tmpVariables[0]));
+//                    else if (aPlace.Value.type.kind == TypeKind.IntType)
+//                        assignments.Add(String.Format("{0} #= {1}", prologPlace.tmpVariables[0], prologValue.tmpVariables[0]));
+                    else
+                        assignments.Add(String.Format("{0} = {1}", prologPlace.tmpVariables[0], prologValue.tmpVariables[0]));
+
+                if (prologPlace.ToString().Length > 0)
+                {
+                    string place = prologPlace.ToString();
+                    place = place.Trim();
+                    if (place.EndsWith(","))
+                        place = place.Substring(0, place.Length - 1);
+
+                    assignments.Add(place);
+                }
+
+                aPlace = aPlace.Next;
+                aValue = aValue.Next;
+            }
+
+            int pos = 0;
+            foreach (var s in assignments)
+            {
+                if (pos != 0)
+                    m_emitter.Append(",");
+                pos++;
+                m_emitter.Append(s);
+            }
+        }
+
+        public override void visit(SeqBlock seqBlock)
+        {
+            int y = 0;
+            if (seqBlock.symbols.symbolList.Count > 0)
+            {
+                m_emitter.Append(" [");
+                foreach (Identifier sym in seqBlock.symbols.symbolList)
+                {
+                    if (y != 0)
+                        m_emitter.AppendLine(", ");
+                    else
+                        y++;
+
+                    OoaPrologType atype = createTypeVisitor();
+                    sym.type.Accept(atype);
+                    OoaPrologIdentifier anIdent = createIdentifierVisitor();
+                    sym.Accept(anIdent);
+                    m_emitter.Append(String.Format("{0}:{1}", anIdent.ToString(), atype.ToString()));
+                }
+                m_emitter.Append("]: ( ");
+            }
+
+            y = 0;
+            foreach (Statement x in seqBlock.statements)
+            {
+                if (y != 0)
+                    m_emitter.AppendLine(", ");
+                else
+                    y++;
+                m_emitter.Append("(");
+                VisitSub(x, seqBlock);
+                m_emitter.Append(")");
+            }
+            if (seqBlock.symbols.symbolList.Count > 0)
+                m_emitter.Append(")");
+        }
+
+
+        protected OoaPrologSymbolicStatement(
+                OoaPrologExpression.Factory exprFactory,
+                OoaPrologIdentifier.Factory idFactory,
+                OoaPrologType.Factory typeFactory)
+            : base(exprFactory, idFactory, typeFactory)
+        {
+        }
+    }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/codegen/PrologSymbolic/ooaPrologSymbolicType.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/codegen/PrologSymbolic/ooaPrologSymbolicType.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/codegen/PrologSymbolic/ooaPrologSymbolicType.cs	(revision 3)
@@ -0,0 +1,50 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TUG.Mogentes.Codegen;
+using TUG.Mogentes.Codegen.Prolog;
+
+namespace TUG.Mogentes.Codegen.PrologSymbolic
+{
+    class OoaPrologSymbolicType : OoaPrologType
+    {
+        new public class Factory : OoaPrologType.Factory
+        {
+            public override OoaPrologType create(OoaPrologIdentifier.Factory idFactory) 
+            { return new OoaPrologSymbolicType(idFactory); }
+        }
+
+        public override string GetInternalTypeDefinitions()
+        {
+            OoaCodeEmitter result = new OoaCodeEmitter();
+
+            result.AppendLine("type(bool, X) :- member(X, [true, false]).");
+            result.AppendLine("type(char, X) :- X in 0..255, labeling([],[X]).");
+
+            return result.ToString();
+        }
+
+        private OoaPrologSymbolicType(OoaPrologIdentifier.Factory idFactory)
+            : base(idFactory)
+        {
+        }
+    }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/codegen/PrologSymbolic/ooaPrologSymbolicVisitor.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/codegen/PrologSymbolic/ooaPrologSymbolicVisitor.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/codegen/PrologSymbolic/ooaPrologSymbolicVisitor.cs	(revision 3)
@@ -0,0 +1,101 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TUG.Mogentes;
+using TUG.Mogentes.Codegen.PrologSymbolic;
+using TUG.Mogentes.Codegen.Prolog;
+
+
+namespace TUG.Mogentes.Codegen.PrologSymbolic
+{
+
+    public sealed class OoaPrologSymbolicVisitor : OoaPrologVisitor
+    {
+        public override void visit(MainModule mainModule)
+        {
+            m_emitter.AppendLine("% Argos Generated");
+            m_emitter.AppendLine(String.Format("%{0}", Mogentes.Program.GetProgramVersion().ToString().Replace(Environment.NewLine, Environment.NewLine + "%")));
+            m_emitter.AppendLine("% Code-Gen Version: 0.3 symbolic");
+            m_emitter.Append("%        Generated: "); m_emitter.AppendLine(System.DateTime.Now.ToString());
+            m_emitter.AppendLine("%------------------------------------------------------------------------");
+            m_emitter.AppendLine("");
+            String nameSpace = TUG.Mogentes.Program.Options.nameSpace;
+            m_emitter.AppendLine(":- module(" + nameSpace + ", [var/2, input/1, searchDepth/1, qspace/2]).");
+            m_emitter.AppendLine(":- use_module(library(file_systems)).");
+            m_emitter.AppendLine(":- use_module(library(process)).");
+            m_emitter.AppendLine(":- use_module(library(clpfd)).");
+            m_emitter.AppendLine(":- use_module(library(clpb)).");
+            m_emitter.AppendLine(":- use_module(library(lists)).");
+            m_emitter.AppendLine(":- use_module(library(avl)).");
+            m_emitter.AppendLine(":- use_module(library(ordsets)).");
+            m_emitter.AppendLine(":- use_module(library(system)).");
+            m_emitter.AppendLine(":- use_module(library(gauge)).");
+            m_emitter.AppendLine(":- use_module(library(terms)).");
+            m_emitter.AppendLine(":- use_module(library(sets)).");
+            m_emitter.AppendLine(":- use_module(library(random)).");
+
+            m_emitter.AppendLine(":- public(as/0).");
+            m_emitter.AppendLine(":- dynamic(as/0).");
+            m_emitter.AppendLine(":- dynamic(qstate_init/1).");
+            m_emitter.AppendLine(":- dynamic(qstate_constraints/1).");
+            m_emitter.AppendLine(":- public(qstate_init/1).");
+            m_emitter.AppendLine(":- public(qstate_constraints/1).");
+            m_emitter.AppendLine(":- dynamic(type/2).");
+
+            /*definition of search depth*/
+            m_emitter.AppendLine("");
+            m_emitter.AppendLine("% maximal search depth (change at will)");
+            m_emitter.AppendLine("searchDepth(" + TUG.Mogentes.Program.Options.searchDepth + ").");
+            m_emitter.AppendLine("");
+
+            /*definition of types*/
+            ExportTypes(mainModule);
+            /* variable definition */
+            ExportVariables(mainModule);
+
+            /* state definition */
+            ExportState(mainModule);
+            /* initial state */
+            ExportInitialState(mainModule);
+            /* input actions (controllables) */
+            ExportControllableActions(mainModule);
+            /* output actions (observables) */
+            ExportObservableActions(mainModule);
+            /* named actions */
+            ExportMethodsAndActions(mainModule);
+
+            /* all types */
+            m_emitter.AppendLine("%definition of types");
+            m_emitter.AppendLine(OoaPrologType.typeDefinitions.ToString());
+            m_emitter.AppendLine(createTypeVisitor().GetInternalTypeDefinitions());
+        }
+
+
+        public OoaPrologSymbolicVisitor(ParserState aState)
+            : base(aState,
+                new OoaPrologSymbolicExpression.Factory(),
+                new OoaPrologIdentifier.Factory(),
+                new OoaPrologSymbolicStatement.Factory(),
+                new OoaPrologSymbolicType.Factory())
+        { }
+    }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/codegen/ooaCodeEmitter.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/codegen/ooaCodeEmitter.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/codegen/ooaCodeEmitter.cs	(revision 3)
@@ -0,0 +1,111 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TUG.Mogentes.Codegen
+{
+    /// <summary>
+    /// Class that is used as text buffer during code emission
+    /// </summary>
+    public class OoaCodeEmitter
+    {
+        private StringBuilder output;
+        private int indentLevel;
+        private int indentTabWidth;
+
+
+        public OoaCodeEmitter()
+        {
+            indentLevel = 0;
+            indentTabWidth = 4;
+            output = new StringBuilder();
+        }
+
+        public void Indent()
+        {
+            for (int i = 0; i < indentLevel * indentTabWidth; i++)
+                output.Append(" ");
+        }
+
+        public void Append(int num)
+        {
+            output.Append(num);
+        }
+
+        public void Append(string text)
+        {
+            output.Append(text);
+        }
+
+        public void AppendLineIncIndent(string text)
+        {
+            indentLevel++;
+            this.AppendLine(text);
+        }
+
+        public void AppendLineDecIndent(string text)
+        {
+            if (indentLevel > 0)
+            {
+                indentLevel--;
+                output.Remove(output.Length - indentTabWidth, indentTabWidth);
+            }
+            this.AppendLine(text);
+        }
+
+
+        public void AppendLine(string text)
+        {
+            output.AppendLine(text);
+            Indent();
+        }
+
+        public void AppendLine()
+        {
+            output.AppendLine();
+            Indent();
+        }
+
+
+
+        public void IncIndent()
+        {
+            indentLevel++;
+        }
+
+        public void DecIndent()
+        {
+            indentLevel--;
+        }
+
+        public void Clear()
+        {
+            output = new StringBuilder();
+        }
+
+
+        public override string ToString()
+        {
+            return output.ToString();
+        }
+
+    }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/codegen/prologCodeGenerator.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/codegen/prologCodeGenerator.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/codegen/prologCodeGenerator.cs	(revision 3)
@@ -0,0 +1,466 @@
+﻿
+/*
+ *  This is a quick'n dirty hack to see whether the internal data structures are sane enough to emit some
+ *  prolog code..
+ * 
+ * 
+ */
+
+
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TUG.Mogentes.Codegen
+{
+    class prologCodeGenerator : SyntaxTreeVisitor
+    {
+        protected int indentLevel = 0;
+        protected int indentTabWidth = 4;
+        protected bool writeTypes = true;
+        protected StringBuilder output = new StringBuilder();
+
+        protected Dictionary<NamedTypeSymbol, string> definedTypes = new Dictionary<NamedTypeSymbol, string>();
+
+        public void Append(string text)
+        {
+            output.Append(text);
+        }
+
+        public void Indent()
+        {
+            for (int i = 0; i < indentLevel * indentTabWidth; i++)
+                output.Append(" ");
+        }
+
+        public void AppendLine(string text)
+        {
+            output.AppendLine(text);
+            Indent();
+        }
+
+
+        public override string ToString()
+        {
+            return output.ToString();
+        }
+
+
+
+        public void visit<T>(CompositionList<T> compositionList, int stage) where T : SyntaxTree
+        {
+
+        }
+
+        public void visit(OoaType anObject, int stage)
+        {
+            if (stage != 0)
+                return;
+
+            // VARIABLES
+
+            List<string> varlist = new List<string>();
+            List<string> init = new List<string>();
+
+            AppendLine("");
+            AppendLine("% variable defs");
+            foreach (var sym in anObject.symbols.Values)
+            {
+                if (sym.GetType() == typeof(VariableSymbol))
+                {
+                    init.Add(((VariableSymbol)sym).initializer.ToString());
+
+                    Append("var([");
+                    Append(sym.tokenText);
+                    Append("],");
+
+                    varlist.Add(sym.tokenText);
+
+                    if (sym.type is OpaqueType)
+                    {
+                        Append(((OpaqueType)sym.type).referencedType.tokenText);
+                        AppendLine(").");
+                    }
+                    else
+                    {
+                        AppendLine("). % anonymous types not supported");
+                    }
+                }
+            }
+
+            /*define state vector*/
+            AppendLine("");
+            Append("state_def([");
+            int cntr = varlist.Count;
+            varlist.ForEach(i => { cntr--; Append(i); if (cntr > 0) Append(","); });
+            AppendLine("]).");
+
+            /*define start values (just a copy/paste of the initializer expressions)*/
+            AppendLine("");
+            Append("init([");
+            cntr = init.Count;
+            init.ForEach(i => { cntr--; Append(i); if (cntr > 0) Append(","); });
+            AppendLine("]).");
+
+
+            // ACTIONS
+            AppendLine("");
+            List<NamedActionSymbol> actions = new List<NamedActionSymbol>();
+            foreach (var sym in anObject.symbols.Values)
+            {
+                if (sym.GetType() == typeof(NamedActionSymbol))
+                    actions.Add((NamedActionSymbol)sym);
+            }
+
+            if (actions.Count > 0)
+            {
+                Append("as :- ");
+                cntr = actions.Count;
+                foreach (var na in actions)
+                {
+                    cntr--;
+                    Append(na.tokenText); Append(":");
+                    foreach (UlyssesStatement s in ((FunctionType)na.type).body)
+                    {
+                        if (s is GuardedCommandStatement)
+                        {
+                            Append("(");
+                            Append(((GuardedCommandStatement)s).guard.ToString());
+                            Append(") => (");
+                            bool first = true;
+                            foreach (UlyssesStatement sb in ((GuardedCommandStatement)s).body)
+                            {
+                                if (first)
+                                    first = false;
+                                else
+                                    Append(",");
+                                Append(sb.ToString());
+
+                            }
+                            Append(")");
+                        }
+                    }
+                    if (cntr > 0)
+                        AppendLine(",");
+                }
+                AppendLine(".");
+            }
+
+        }
+
+        public void visit(BoolType anObject, int stage)
+        {
+        }
+
+        public void visit(IntType intType, int p)
+        {
+        }
+
+        public void visit(FloatType floatType, int p)
+        {
+
+        }
+
+        public void visit(CharType charType, int p)
+        {
+
+        }
+
+        public void visit(EnumType enumType, int p)
+        {
+
+        }
+
+        public void visit(ListType listType, int p)
+        {
+
+        }
+
+        public void visit(MapType mapType, int p)
+        {
+
+        }
+
+        public void visit(TupleType tupleType, int p)
+        {
+
+        }
+
+        public void visit(OoaSystem ooaSystem, int stage)
+        {
+            if (stage == 0)
+            {
+                AppendLine(":- public(as/0).");
+                AppendLine(":- public(asM/0).");
+                AppendLine("");
+                AppendLine(":- dynamic(qstate_init/1).");
+                AppendLine(":- dynamic(qstate_constraints/1).");
+                AppendLine(":- public(qstate_constraints/1).");
+                AppendLine(":- public(qstate_init/1).");
+
+                AppendLine("");
+                AppendLine("% defintion of maximal search depth");
+                AppendLine("searchDepth(15).");
+                AppendLine("");
+            }
+            if (stage == 2)
+                writeTypes = false;
+
+        }
+
+        public bool visit(NamedTypeSymbol namedTypeSymbol, int p)
+        {
+            if (p != 0)
+                return writeTypes;
+
+            if (!definedTypes.ContainsKey(namedTypeSymbol))
+            {
+                definedTypes.Add(namedTypeSymbol, namedTypeSymbol.tokenText);
+                int i;
+                Type aType = namedTypeSymbol.type.GetType();
+                string atypedef = "type(" + namedTypeSymbol.tokenText + ",";
+                if (aType == typeof(IntType))
+                {
+                    IntType intType = (IntType)namedTypeSymbol.type;
+                    Append(atypedef);
+                    Append("X) :- "); Append("fd_domain(X,"); Append(intType.low.ToString()); Append(",");
+                    Append(intType.high.ToString()); Append("),");
+                    AppendLine("fd_labeling(X).");
+                }
+                else if (aType == typeof(EnumType))
+                {
+                    EnumType enumType = (EnumType)namedTypeSymbol.type;
+                    i = enumType.enumSymbols.Count;
+                    Append(atypedef);
+                    Append("[");
+                    foreach (var sym in enumType.enumSymbols)
+                    {
+                        i--;
+                        Append("'");
+                        Append(sym.tokenText);
+                        Append("'");
+                        if (i > 0)
+                            Append(",");
+                    }
+                    AppendLine("]).");
+
+                }
+                else if (aType == typeof(BoolType))
+                {
+                    AppendLine(" % bool not supported yet. ");
+                }
+                else if (aType == typeof(FloatType))
+                {
+                    AppendLine(" % float not supported yet. ");
+                }
+                else if (aType == typeof(CharType))
+                {
+                    AppendLine(" % char not supported yet. ");
+                }
+                else if (aType == typeof(ListType))
+                {
+                    AppendLine(" % list not supported yet. ");
+                }
+                else if (aType == typeof(MapType))
+                {
+                    AppendLine(" % map not supported yet. ");
+                }
+                else if (aType == typeof(TupleType))
+                {
+                    AppendLine(" % tuple not supported yet. ");
+                }
+            }
+            return writeTypes;
+        }
+
+        public bool visit(ParameterSymbol parameterSymbol, int p)
+        {
+            return true;
+        }
+
+        public bool visit(VariableSymbol variableSymbol, int p)
+        {
+            return true;
+        }
+
+        public bool visit(MethodSymbol methodSymbol, int p)
+        {
+
+
+
+            return true;
+        }
+
+        public void visit(EnumIdSymbol enumIdSymbol, int p)
+        {
+
+        }
+
+        public void visit(AbortStatement abortStatement, int p)
+        {
+
+        }
+
+        public void visit(SkipStatement skipStatement, int p)
+        {
+
+        }
+
+        public void visit(KillStatement killStatement, int p)
+        {
+
+        }
+
+        public void visit(GuardedCommandStatement guardedCommandStatement, int p)
+        {
+
+        }
+
+        public void visit(NamedActionInclusionStatement namedActionInclusionStatement, int p)
+        {
+
+        }
+
+        public void visit(MethodCallStatement methodCallStatement, int p)
+        {
+
+        }
+
+        public void visit(AssignmentStatement assignmentStatement, int p)
+        {
+
+        }
+
+        public void visit(LocalVarStatement localVarStatement, int p)
+        {
+
+        }
+
+        public void visit(ConstantChar constantChar, int p)
+        {
+
+        }
+
+        public void visit(ConstantInt constantInt, int p)
+        {
+
+        }
+
+        public void visit(ConstantFloat constantFloat, int p)
+        {
+
+        }
+
+        public void visit(ConstantNil constantNil, int p)
+        {
+
+        }
+
+        public void visit(ConstantBool constantBool, int p)
+        {
+
+        }
+
+        public void visit(ConstantList constantList, int p)
+        {
+
+        }
+
+        public void visit(ConstantSet constantSet, int p)
+        {
+
+        }
+
+        public void visit(ConstantMap constantMap, int p)
+        {
+
+        }
+
+        public void visit(UnaryOperator unaryOperator, int p)
+        {
+
+        }
+
+        public void visit(SetListUnaryOperator setListUnaryOperator, int p)
+        {
+
+        }
+
+        public void visit(MapUnaryOperator mapUnaryOperator, int p)
+        {
+
+        }
+
+        public void visit(BinaryOperator binaryOperator, int p)
+        {
+
+        }
+
+        public void visit(BoolBinaryOperator boolBinaryOperator, int p)
+        {
+
+        }
+
+        public void visit(NumericBinaryOperator numericBinaryOperator, int p)
+        {
+
+        }
+
+        public void visit(SetListBinaryOperator setListBinaryOperator, int p)
+        {
+
+        }
+
+        public void visit(MapBinaryOperator mapBinaryOperator, int p)
+        {
+
+        }
+
+        public void visit(QualifiedIdentifier qualifiedIdentifier, int p)
+        {
+
+        }
+
+        public void visit(Reference reference, int p)
+        {
+
+        }
+
+        public void visit(AccessExpression accessExpression, int p)
+        {
+
+        }
+
+        public void visit(ConditionalOperator conditionalOperator, int p)
+        {
+
+        }
+
+        public void visit(OpaqueType namedType, int p)
+        {
+
+        }
+
+        public bool visit(NamedActionSymbol namedActionSymbol, int p)
+        {
+            return true;
+        }
+
+
+        public void visit(ConstantTuple constantTuple, int p)
+        {
+        }
+
+
+        #region SyntaxTreeVisitor Member
+
+
+        public bool visit(FunctionType functionType, int p)
+        {
+            return true;
+        }
+
+        #endregion
+    }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/arrays/ArrayList.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/arrays/ArrayList.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/arrays/ArrayList.cs	(revision 3)
@@ -0,0 +1,2638 @@
+
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+#define HASHINDEXnot
+
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+namespace C5
+{
+  /// <summary>
+  /// A list collection based on a plain dynamic array data structure.
+  /// Expansion of the internal array is performed by doubling on demand. 
+  /// The internal array is only shrinked by the Clear method. 
+  ///
+  /// <i>When the FIFO property is set to false this class works fine as a stack of T.
+  /// When the FIFO property is set to true the class will function as a (FIFO) queue
+  /// but very inefficiently, use a LinkedList (<see cref="T:C5.LinkedList`1"/>) instead.</i>
+  /// </summary>
+  [Serializable]
+  public class ArrayList<T> : ArrayBase<T>, IList<T>, SCG.IList<T>
+#if HASHINDEX
+#else
+, IStack<T>, IQueue<T>
+#endif
+  {
+    #region Fields
+
+    /// <summary>
+    /// Has this list or view not been invalidated by some operation (by someone calling Dispose())
+    /// </summary>
+    bool isValid = true;
+
+    //TODO: wonder if we should save some memory on none-view situations by 
+    //      putting these three fields into a single ref field?
+    /// <summary>
+    /// The underlying list if we are a view, null else.
+    /// </summary>
+    ArrayList<T> underlying;
+    WeakViewList<ArrayList<T>> views;
+    WeakViewList<ArrayList<T>>.Node myWeakReference;
+
+    /// <summary>
+    /// The size of the underlying list.
+    /// </summary>
+    int underlyingsize { get { return (underlying ?? this).size; } }
+
+    /// <summary>
+    /// The underlying field of the FIFO property
+    /// </summary>
+    bool fIFO = false;
+
+#if HASHINDEX
+    HashSet<KeyValuePair<T, int>> itemIndex;
+#endif
+    #endregion
+    #region Events
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public override EventTypeEnum ListenableEvents { get { return underlying == null ? EventTypeEnum.All : EventTypeEnum.None; } }
+
+    /*
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public override event CollectionChangedHandler<T> CollectionChanged
+        {
+          add
+          {
+            if (underlying == null)
+              base.CollectionChanged += value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+          remove
+          {
+            if (underlying == null)
+              base.CollectionChanged -= value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public override event CollectionClearedHandler<T> CollectionCleared
+        {
+          add
+          {
+            if (underlying == null)
+              base.CollectionCleared += value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+          remove
+          {
+            if (underlying == null)
+              base.CollectionCleared -= value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public override event ItemsAddedHandler<T> ItemsAdded
+        {
+          add
+          {
+            if (underlying == null)
+              base.ItemsAdded += value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+          remove
+          {
+            if (underlying == null)
+              base.ItemsAdded -= value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public override event ItemInsertedHandler<T> ItemInserted
+        {
+          add
+          {
+            if (underlying == null)
+              base.ItemInserted += value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+          remove
+          {
+            if (underlying == null)
+              base.ItemInserted -= value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public override event ItemsRemovedHandler<T> ItemsRemoved
+        {
+          add
+          {
+            if (underlying == null)
+              base.ItemsRemoved += value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+          remove
+          {
+            if (underlying == null)
+              base.ItemsRemoved -= value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public override event ItemRemovedAtHandler<T> ItemRemovedAt
+        {
+          add
+          {
+            if (underlying == null)
+              base.ItemRemovedAt += value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+          remove
+          {
+            if (underlying == null)
+              base.ItemRemovedAt -= value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+        }
+
+          */
+
+    #endregion
+    #region Util
+
+    bool equals(T i1, T i2) { return itemequalityComparer.Equals(i1, i2); }
+
+    /// <summary>
+    /// Increment or decrement the private size fields
+    /// </summary>
+    /// <param name="delta">Increment (with sign)</param>
+    void addtosize(int delta)
+    {
+      size += delta;
+      if (underlying != null)
+        underlying.size += delta;
+    }
+
+    #region Array handling
+    /// <summary>
+    /// Double the size of the internal array.
+    /// </summary>
+    protected override void expand()
+    { expand(2 * array.Length, underlyingsize); }
+
+
+    /// <summary>
+    /// Expand the internal array, resetting the index of the first unused element.
+    /// </summary>
+    /// <param name="newcapacity">The new capacity (will be rouded upwards to a power of 2).</param>
+    /// <param name="newsize">The new count of </param>
+    protected override void expand(int newcapacity, int newsize)
+    {
+      if (underlying != null)
+        underlying.expand(newcapacity, newsize);
+      else
+      {
+        base.expand(newcapacity, newsize);
+        if (views != null)
+          foreach (ArrayList<T> v in views)
+            v.array = array;
+      }
+    }
+
+    #endregion
+
+    #region Checks
+    /// <summary>
+    /// Check if it is valid to perform updates and increment stamp if so.
+    /// </summary>
+    /// <exception cref="ViewDisposedException"> If check fails by this list being a disposed view.</exception>
+    /// <exception cref="ReadOnlyCollectionException"> If check fails by this being a read only list.</exception>
+    protected override void updatecheck()
+    {
+      validitycheck();
+      base.updatecheck();
+      if (underlying != null)
+        underlying.stamp++;
+    }
+
+
+    /// <summary>
+    /// Check if we are a view that the underlying list has only been updated through us.
+    /// <para>This method should be called from enumerators etc to guard against 
+    /// modification of the base collection.</para>
+    /// </summary>
+    /// <exception cref="ViewDisposedException"> if check fails.</exception>
+    void validitycheck()
+    {
+      if (!isValid)
+        throw new ViewDisposedException();
+    }
+
+
+    /// <summary>
+    /// Check that the list has not been updated since a particular time.
+    /// <para>To be used by enumerators and range </para>
+    /// </summary>
+    /// <exception cref="ViewDisposedException"> If check fails by this list being a disposed view.</exception>
+    /// <exception cref="CollectionModifiedException">If the list *has* beeen updated since that  time..</exception>
+    /// <param name="stamp">The stamp indicating the time.</param>
+    protected override void modifycheck(int stamp)
+    {
+      validitycheck();
+      if (this.stamp != stamp)
+        throw new CollectionModifiedException();
+    }
+
+    #endregion
+
+    #region Searching
+
+    /// <summary>
+    /// Internal version of IndexOf without modification checks.
+    /// </summary>
+    /// <param name="item">Item to look for</param>
+    /// <returns>The index of first occurrence</returns>
+    int indexOf(T item)
+    {
+#if HASHINDEX
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item);
+      if (itemIndex.Find(ref p) && p.Value >= offset && p.Value < offset + size)
+        return p.Value - offset;
+#else
+      for (int i = 0; i < size; i++)
+        if (equals(item, array[offset + i]))
+          return i;
+#endif
+      return ~size;
+    }
+
+    /// <summary>
+    /// Internal version of LastIndexOf without modification checks.
+    /// </summary>
+    /// <param name="item">Item to look for</param>
+    /// <returns>The index of last occurrence</returns>
+    int lastIndexOf(T item)
+    {
+#if HASHINDEX
+      return indexOf(item);
+#else
+      for (int i = size - 1; i >= 0; i--)
+        if (equals(item, array[offset + i]))
+          return i;
+      return ~size;
+#endif
+    }
+    #endregion
+
+    #region Inserting
+
+#if HASHINDEX
+    /// <summary>
+    /// Internal version of Insert with no modification checks.
+    /// </summary>
+    /// <exception cref="DuplicateNotAllowedException"> if item already in list.</exception>
+    /// <param name="i">Index to insert at</param>
+    /// <param name="item">Item to insert</param>
+#else
+    /// <summary>
+    /// Internal version of Insert with no modification checks.
+    /// </summary>
+    /// <param name="i">Index to insert at</param>
+    /// <param name="item">Item to insert</param>
+#endif
+    protected override void insert(int i, T item)
+    {
+#if HASHINDEX
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, offset + i);
+      if (itemIndex.FindOrAdd(ref p))
+        throw new DuplicateNotAllowedException("Item already in indexed list: " + item);
+#endif
+      baseinsert(i, item);
+#if HASHINDEX
+      reindex(i + offset + 1);
+#endif
+    }
+
+    private void baseinsert(int i, T item)
+    {
+      if (underlyingsize == array.Length)
+        expand();
+      i += offset;
+      if (i < underlyingsize)
+        Array.Copy(array, i, array, i + 1, underlyingsize - i);
+      array[i] = item;
+      addtosize(1);
+      fixViewsAfterInsert(1, i);
+    }
+    #endregion
+
+    #region Removing
+
+    /// <summary>
+    /// Internal version of RemoveAt with no modification checks.
+    /// </summary>
+    /// <param name="i">Index to remove at</param>
+    /// <returns>The removed item</returns>
+    T removeAt(int i)
+    {
+      i += offset;
+      fixViewsBeforeSingleRemove(i);
+      T retval = array[i];
+      addtosize(-1);
+      if (underlyingsize > i)
+        Array.Copy(array, i + 1, array, i, underlyingsize - i);
+      array[underlyingsize] = default(T);
+#if HASHINDEX
+      itemIndex.Remove(new KeyValuePair<T, int>(retval));
+      reindex(i);
+#endif
+      return retval;
+    }
+    #endregion
+
+    #region Indexing
+
+#if HASHINDEX
+    private void reindex(int start) { reindex(start, underlyingsize); }
+
+    private void reindex(int start, int end)
+    {
+      for (int j = start; j < end; j++)
+        itemIndex.UpdateOrAdd(new KeyValuePair<T, int>(array[j], j));
+    }
+#endif
+    #endregion
+
+    #region fixView utilities
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="added">The actual number of inserted nodes</param>
+    /// <param name="realInsertionIndex"></param>
+    void fixViewsAfterInsert(int added, int realInsertionIndex)
+    {
+      if (views != null)
+        foreach (ArrayList<T> view in views)
+        {
+          if (view != this)
+          {
+            if (view.offset < realInsertionIndex && view.offset + view.size > realInsertionIndex)
+              view.size += added;
+            if (view.offset > realInsertionIndex || (view.offset == realInsertionIndex && view.size > 0))
+              view.offset += added;
+          }
+        }
+    }
+
+    void fixViewsBeforeSingleRemove(int realRemovalIndex)
+    {
+      if (views != null)
+        foreach (ArrayList<T> view in views)
+        {
+          if (view != this)
+          {
+            if (view.offset <= realRemovalIndex && view.offset + view.size > realRemovalIndex)
+              view.size--;
+            if (view.offset > realRemovalIndex)
+              view.offset--;
+          }
+        }
+    }
+
+    /// <summary>
+    /// Fix offsets and sizes of other views before removing an interval from this 
+    /// </summary>
+    /// <param name="start">the start of the interval relative to the array/underlying</param>
+    /// <param name="count"></param>
+    void fixViewsBeforeRemove(int start, int count)
+    {
+      int clearend = start + count - 1;
+      if (views != null)
+        foreach (ArrayList<T> view in views)
+        {
+          if (view == this)
+            continue;
+          int viewoffset = view.offset, viewend = viewoffset + view.size - 1;
+          if (start < viewoffset)
+          {
+            if (clearend < viewoffset)
+              view.offset = viewoffset - count;
+            else
+            {
+              view.offset = start;
+              view.size = clearend < viewend ? viewend - clearend : 0;
+            }
+          }
+          else if (start <= viewend)
+            view.size = clearend <= viewend ? view.size - count : start - viewoffset;
+        }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="otherOffset"></param>
+    /// <param name="otherSize"></param>
+    /// <returns>The position of View(otherOffset, otherSize) wrt. this view</returns>
+    MutualViewPosition viewPosition(int otherOffset, int otherSize)
+    {
+      int end = offset + size, otherEnd = otherOffset + otherSize;
+      if (otherOffset >= end || otherEnd <= offset)
+        return MutualViewPosition.NonOverlapping;
+      if (size == 0 || (otherOffset <= offset && end <= otherEnd))
+        return MutualViewPosition.Contains;
+      if (otherSize == 0 || (offset <= otherOffset && otherEnd <= end))
+        return MutualViewPosition.ContainedIn;
+      return MutualViewPosition.Overlapping;
+    }
+
+    //TODO: make version that fits the new, more forgiving rules for disposing
+    void disposeOverlappingViews(bool reverse)
+    {
+      if (views != null)
+        foreach (ArrayList<T> view in views)
+        {
+          if (view != this)
+          {
+            switch (viewPosition(view.offset, view.size))
+            {
+              case MutualViewPosition.ContainedIn:
+                if (reverse)
+                  view.offset = 2 * offset + size - view.size - view.offset;
+                else
+                  view.Dispose();
+                break;
+              case MutualViewPosition.Overlapping:
+                view.Dispose();
+                break;
+              case MutualViewPosition.Contains:
+              case MutualViewPosition.NonOverlapping:
+                break;
+            }
+          }
+        }
+    }
+    #endregion
+
+    #endregion
+
+    #region Position, PositionComparer and ViewHandler nested types
+    class PositionComparer : SCG.IComparer<Position>
+    {
+      public int Compare(Position a, Position b)
+      {
+        return a.index.CompareTo(b.index);
+      }
+    }
+    /// <summary>
+    /// During RemoveAll, we need to cache the original endpoint indices of views (??? also for ArrayList?)
+    /// </summary>
+    struct Position
+    {
+      public readonly ArrayList<T> view;
+      public readonly int index;
+      public Position(ArrayList<T> view, bool left)
+      {
+        this.view = view;
+        index = left ? view.offset : view.offset + view.size - 1;
+      }
+      public Position(int index) { this.index = index; view = null; }
+    }
+
+    /// <summary>
+    /// Handle the update of (other) views during a multi-remove operation.
+    /// </summary>
+    struct ViewHandler
+    {
+      ArrayList<Position> leftEnds;
+      ArrayList<Position> rightEnds;
+      int leftEndIndex, rightEndIndex;
+      internal readonly int viewCount;
+      internal ViewHandler(ArrayList<T> list)
+      {
+        leftEndIndex = rightEndIndex = viewCount = 0;
+        leftEnds = rightEnds = null;
+        if (list.views != null)
+          foreach (ArrayList<T> v in list.views)
+            if (v != list)
+            {
+              if (leftEnds == null)
+              {
+                leftEnds = new ArrayList<Position>();
+                rightEnds = new ArrayList<Position>();
+              }
+              leftEnds.Add(new Position(v, true));
+              rightEnds.Add(new Position(v, false));
+            }
+        if (leftEnds == null)
+          return;
+        viewCount = leftEnds.Count;
+        leftEnds.Sort(new PositionComparer());
+        rightEnds.Sort(new PositionComparer());
+      }
+      /// <summary>
+      /// This is to be called with realindex pointing to the first node to be removed after a (stretch of) node that was not removed
+      /// </summary>
+      /// <param name="removed"></param>
+      /// <param name="realindex"></param>
+      internal void skipEndpoints(int removed, int realindex)
+      {
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex < viewCount && (endpoint = leftEnds[leftEndIndex]).index <= realindex)
+          {
+            ArrayList<T> view = endpoint.view;
+            view.offset = view.offset - removed;
+            view.size += removed;
+            leftEndIndex++;
+          }
+          while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).index < realindex)
+          {
+            endpoint.view.size -= removed;
+            rightEndIndex++;
+          }
+        }
+      }
+      internal void updateViewSizesAndCounts(int removed, int realindex)
+      {
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex < viewCount && (endpoint = leftEnds[leftEndIndex]).index <= realindex)
+          {
+            ArrayList<T> view = endpoint.view;
+            view.offset = view.Offset - removed;
+            view.size += removed;
+            leftEndIndex++;
+          }
+          while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).index < realindex)
+          {
+            endpoint.view.size -= removed;
+            rightEndIndex++;
+          }
+        }
+      }
+    }
+    #endregion
+
+    #region Constructors
+    /// <summary>
+    /// Create an array list with default item equalityComparer and initial capacity 8 items.
+    /// </summary>
+    public ArrayList() : this(8) { }
+
+
+    /// <summary>
+    /// Create an array list with external item equalityComparer and initial capacity 8 items.
+    /// </summary>
+    /// <param name="itemequalityComparer">The external item equalityComparer</param>
+    public ArrayList(SCG.IEqualityComparer<T> itemequalityComparer) : this(8, itemequalityComparer) { }
+
+
+    /// <summary>
+    /// Create an array list with default item equalityComparer and prescribed initial capacity.
+    /// </summary>
+    /// <param name="capacity">The prescribed capacity</param>
+    public ArrayList(int capacity) : this(capacity, EqualityComparer<T>.Default) { }
+
+
+    /// <summary>
+    /// Create an array list with external item equalityComparer and prescribed initial capacity.
+    /// </summary>
+    /// <param name="capacity">The prescribed capacity</param>
+    /// <param name="itemequalityComparer">The external item equalityComparer</param>
+    public ArrayList(int capacity, SCG.IEqualityComparer<T> itemequalityComparer)
+      : base(capacity, itemequalityComparer)
+    {
+#if HASHINDEX
+      itemIndex = new HashSet<KeyValuePair<T, int>>(new KeyValuePairEqualityComparer<T, int>(itemequalityComparer));
+#endif
+    }
+
+    #endregion
+
+    #region IList<T> Members
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+    /// <value>The first item in this list.</value>
+    [Tested]
+    public virtual T First
+    {
+      [Tested]
+      get
+      {
+        validitycheck();
+        if (size == 0)
+          throw new NoSuchItemException();
+
+        return array[offset];
+      }
+    }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+    /// <value>The last item in this list.</value>
+    [Tested]
+    public virtual T Last
+    {
+      [Tested]
+      get
+      {
+        validitycheck();
+        if (size == 0)
+          throw new NoSuchItemException();
+
+        return array[offset + size - 1];
+      }
+    }
+
+
+    /// <summary>
+    /// Since <code>Add(T item)</code> always add at the end of the list,
+    /// this describes if list has FIFO or LIFO semantics.
+    /// </summary>
+    /// <value>True if the <code>Remove()</code> operation removes from the
+    /// start of the list, false if it removes from the end. The default for a new array list is false.</value>
+    [Tested]
+    public virtual bool FIFO
+    {
+      [Tested]
+      get { validitycheck(); return fIFO; }
+      [Tested]
+      set { updatecheck(); fIFO = value; }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public virtual bool IsFixedSize
+    {
+      get { validitycheck(); return false; }
+    }
+
+
+#if HASHINDEX
+    /// <summary>
+    /// On this list, this indexer is read/write.
+    /// </summary>
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or
+    /// &gt;= the size of the collection.</exception>
+    /// <exception cref="DuplicateNotAllowedException"> By the get operation
+    /// if the item already is present somewhere else in the list.</exception>
+    /// <value>The index'th item of this list.</value>
+    /// <param name="index">The index of the item to fetch or store.</param>
+#else
+    /// <summary>
+    /// On this list, this indexer is read/write.
+    /// </summary>
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or
+    /// &gt;= the size of the collection.</exception>
+    /// <value>The index'th item of this list.</value>
+    /// <param name="index">The index of the item to fetch or store.</param>
+#endif
+    [Tested]
+    public virtual T this[int index]
+    {
+      [Tested]
+      get
+      {
+        validitycheck();
+        if (index < 0 || index >= size)
+          throw new IndexOutOfRangeException();
+
+        return array[offset + index];
+      }
+      [Tested]
+      set
+      {
+        updatecheck();
+        if (index < 0 || index >= size)
+          throw new IndexOutOfRangeException();
+        index += offset;
+        T item = array[index];
+#if HASHINDEX
+        KeyValuePair<T, int> p = new KeyValuePair<T, int>(value, index);
+        if (itemequalityComparer.Equals(value, item))
+        {
+          array[index] = value;
+          itemIndex.Update(p);
+        }
+        else if (!itemIndex.FindOrAdd(ref p))
+        {
+          itemIndex.Remove(new KeyValuePair<T, int>(item));
+          array[index] = value;
+        }
+        else
+          throw new DuplicateNotAllowedException("Item already in indexed list");
+#else
+        array[index] = value;
+#endif
+        (underlying ?? this).raiseForSetThis(index, value, item);
+      }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual Speed IndexingSpeed { get { return Speed.Constant; } }
+
+#if HASHINDEX
+    /// <summary>
+    /// Insert an item at a specific index location in this list. 
+    ///</summary>
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or
+    /// &gt; the size of the collection. </exception>
+    /// <exception cref="DuplicateNotAllowedException"> 
+    /// If the item is already present in the list.</exception>
+    /// <param name="index">The index at which to insert.</param>
+    /// <param name="item">The item to insert.</param>
+#else
+    /// <summary>
+    /// Insert an item at a specific index location in this list. 
+    ///</summary>
+    /// <exception cref="IndexOutOfRangeException"> if i is negative or
+    /// &gt; the size of the collection. </exception>
+    /// <param name="index">The index at which to insert.</param>
+    /// <param name="item">The item to insert.</param>
+#endif
+    [Tested]
+    public virtual void Insert(int index, T item)
+    {
+      updatecheck();
+      if (index < 0 || index > size)
+        throw new IndexOutOfRangeException();
+
+      insert(index, item);
+      (underlying ?? this).raiseForInsert(index + offset, item);
+    }
+
+    /// <summary>
+    /// Insert an item at the end of a compatible view, used as a pointer.
+    /// <para>The <code>pointer</code> must be a view on the same list as
+    /// <code>this</code> and the endpoitn of <code>pointer</code> must be
+    /// a valid insertion point of <code>this</code></para>
+    /// </summary>
+    /// <exception cref="IncompatibleViewException">If <code>pointer</code> 
+    /// is not a view on or the same list as <code>this</code></exception>
+    /// <exception cref="IndexOutOfRangeException"><b>??????</b> if the endpoint of 
+    ///  <code>pointer</code> is not inside <code>this</code></exception>
+    /// <exception cref="DuplicateNotAllowedException"> if the list has
+    /// <code>AllowsDuplicates==false</code> and the item is 
+    /// already in the list.</exception>
+    /// <param name="pointer"></param>
+    /// <param name="item"></param>
+    public void Insert(IList<T> pointer, T item)
+    {
+      if ((pointer == null) || ((pointer.Underlying ?? pointer) != (underlying ?? this)))
+        throw new IncompatibleViewException();
+      Insert(pointer.Offset + pointer.Count - Offset, item);
+    }
+
+#if HASHINDEX
+    /// <summary>
+    /// Insert into this list all items from an enumerable collection starting 
+    /// at a particular index.
+    /// </summary>
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or
+    /// &gt; the size of the collection.</exception>
+    /// <exception cref="DuplicateNotAllowedException"> If <code>items</code> 
+    /// contains duplicates or some item already  present in the list.</exception>
+    /// <param name="index">Index to start inserting at</param>
+    /// <param name="items">Items to insert</param>
+#else
+    /// <summary>
+    /// Insert into this list all items from an enumerable collection starting 
+    /// at a particular index.
+    /// </summary>
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or
+    /// &gt; the size of the collection.</exception>
+    /// <param name="index">Index to start inserting at</param>
+    /// <param name="items">Items to insert</param>
+    /// <typeparam name="U"></typeparam>
+#endif
+    [Tested]
+    public virtual void InsertAll<U>(int index, SCG.IEnumerable<U> items) where U : T
+    {
+      updatecheck();
+      if (index < 0 || index > size)
+        throw new IndexOutOfRangeException();
+      index += offset;
+      int toadd = EnumerableBase<U>.countItems(items);
+      if (toadd == 0)
+        return;
+      if (toadd + underlyingsize > array.Length)
+        expand(toadd + underlyingsize, underlyingsize);
+      if (underlyingsize > index)
+        Array.Copy(array, index, array, index + toadd, underlyingsize - index);
+      int i = index;
+      try
+      {
+
+        foreach (T item in items)
+        {
+#if HASHINDEX
+          KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, i);
+          if (itemIndex.FindOrAdd(ref p))
+            throw new DuplicateNotAllowedException("Item already in indexed list");
+#endif
+          array[i++] = item;
+        }
+      }
+      finally
+      {
+        int added = i - index;
+        if (added < toadd)
+        {
+          Array.Copy(array, index + toadd, array, i, underlyingsize - index);
+          Array.Clear(array, underlyingsize + added, toadd - added);
+        }
+        if (added > 0)
+        {
+          addtosize(added);
+#if HASHINDEX
+          reindex(i);
+#endif
+          fixViewsAfterInsert(added, index);
+          (underlying ?? this).raiseForInsertAll(index, added);
+        }
+      }
+    }
+    private void raiseForInsertAll(int index, int added)
+    {
+      if (ActiveEvents != 0)
+      {
+        if ((ActiveEvents & (EventTypeEnum.Added | EventTypeEnum.Inserted)) != 0)
+          for (int j = index; j < index + added; j++)
+          {
+            raiseItemInserted(array[j], j);
+            raiseItemsAdded(array[j], 1);
+          }
+        raiseCollectionChanged();
+      }
+    }
+
+#if HASHINDEX
+    /// <summary>
+    /// Insert an item at the front of this list;
+    /// </summary>
+    /// <exception cref="DuplicateNotAllowedException">If the item is already in the list</exception>
+    /// <param name="item">The item to insert.</param>
+#else
+    /// <summary>
+    /// Insert an item at the front of this list;
+    /// </summary>
+    /// <param name="item">The item to insert.</param>
+#endif
+    [Tested]
+    public virtual void InsertFirst(T item)
+    {
+      updatecheck();
+      insert(0, item);
+      (underlying ?? this).raiseForInsert(offset, item);
+    }
+
+
+#if HASHINDEX
+    /// <summary>
+    /// Insert an item at the back of this list.
+    /// </summary>
+    /// <exception cref="DuplicateNotAllowedException">If the item is already in the list</exception>
+    /// <param name="item">The item to insert.</param>
+#else
+    /// <summary>
+    /// Insert an item at the back of this list.
+    /// </summary>
+    /// <param name="item">The item to insert.</param>
+#endif
+    [Tested]
+    public virtual void InsertLast(T item)
+    {
+      updatecheck();
+      insert(size, item);
+      (underlying ?? this).raiseForInsert(size - 1 + offset, item);
+    }
+
+
+    //NOTE: if the filter throws an exception, no result will be returned.
+    /// <summary>
+    /// Create a new list consisting of the items of this list satisfying a 
+    /// certain predicate.
+    /// <para>The new list will be of type ArrayList</para>
+    /// </summary>
+    /// <param name="filter">The filter delegate defining the predicate.</param>
+    /// <returns>The new list.</returns>
+    [Tested]
+    public virtual IList<T> FindAll(Fun<T, bool> filter)
+    {
+      validitycheck();
+      int stamp = this.stamp;
+      ArrayList<T> res = new ArrayList<T>(itemequalityComparer);
+      int j = 0, rescap = res.array.Length;
+      for (int i = 0; i < size; i++)
+      {
+        T a = array[offset + i];
+        bool found = filter(a);
+        modifycheck(stamp);
+        if (found)
+        {
+          if (j == rescap) res.expand(rescap = 2 * rescap, j);
+          res.array[j++] = a;
+        }
+      }
+      res.size = j;
+#if HASHINDEX
+      res.reindex(0);
+#endif
+      return res;
+    }
+
+
+#if HASHINDEX
+    /// <summary>
+    /// Create a new list consisting of the results of mapping all items of this
+    /// list. The new list will use the default item equalityComparer for the item type V.
+    /// <para>The new list will be of type ArrayList</para>
+    /// </summary>
+    /// <exception cref="DuplicateNotAllowedException">If <code>mapper</code>
+    /// creates duplicates</exception>
+    /// <typeparam name="V">The type of items of the new list</typeparam>
+    /// <param name="mapper">The delegate defining the map.</param>
+    /// <returns>The new list.</returns>
+#else
+    /// <summary>
+    /// Create a new list consisting of the results of mapping all items of this
+    /// list. The new list will use the default item equalityComparer for the item type V.
+    /// <para>The new list will be of type ArrayList</para>
+    /// </summary>
+    /// <typeparam name="V">The type of items of the new list</typeparam>
+    /// <param name="mapper">The delegate defining the map.</param>
+    /// <returns>The new list.</returns>
+#endif
+    [Tested]
+    public virtual IList<V> Map<V>(Fun<T, V> mapper)
+    {
+      validitycheck();
+
+      ArrayList<V> res = new ArrayList<V>(size);
+
+      return map<V>(mapper, res);
+    }
+
+#if HASHINDEX
+    /// <summary>
+    /// Create a new list consisting of the results of mapping all items of this
+    /// list. The new list will use a specified item equalityComparer for the item type.
+    /// <para>The new list will be of type ArrayList</para>
+    /// </summary>
+    /// <exception cref="DuplicateNotAllowedException">If <code>mapper</code>
+    /// creates duplicates</exception>
+    /// <typeparam name="V">The type of items of the new list</typeparam>
+    /// <param name="mapper">The delegate defining the map.</param>
+    /// <param name="itemequalityComparer">The item equalityComparer to use for the new list</param>
+    /// <returns>The new list.</returns>
+#else
+    /// <summary>
+    /// Create a new list consisting of the results of mapping all items of this
+    /// list. The new list will use a specified item equalityComparer for the item type.
+    /// <para>The new list will be of type ArrayList</para>
+    /// </summary>
+    /// <typeparam name="V">The type of items of the new list</typeparam>
+    /// <param name="mapper">The delegate defining the map.</param>
+    /// <param name="itemequalityComparer">The item equalityComparer to use for the new list</param>
+    /// <returns>The new list.</returns>
+#endif
+    public virtual IList<V> Map<V>(Fun<T, V> mapper, SCG.IEqualityComparer<V> itemequalityComparer)
+    {
+      validitycheck();
+
+      ArrayList<V> res = new ArrayList<V>(size, itemequalityComparer);
+
+      return map<V>(mapper, res);
+    }
+
+    private IList<V> map<V>(Fun<T, V> mapper, ArrayList<V> res)
+    {
+      int stamp = this.stamp;
+      if (size > 0)
+        for (int i = 0; i < size; i++)
+        {
+          V mappeditem = mapper(array[offset + i]);
+          modifycheck(stamp);
+#if HASHINDEX
+          KeyValuePair<V, int> p = new KeyValuePair<V, int>(mappeditem, i);
+          if (res.itemIndex.FindOrAdd(ref p))
+            throw new ArgumentException("Mapped item already in indexed list");
+#endif
+          res.array[i] = mappeditem;
+        }
+      res.size = size;
+      return res;
+    }
+
+    /// <summary>
+    /// Remove one item from the list: from the front if <code>FIFO</code>
+    /// is true, else from the back.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public virtual T Remove()
+    {
+      updatecheck();
+      if (size == 0)
+        throw new NoSuchItemException("List is empty");
+
+      T item = removeAt(fIFO ? 0 : size - 1);
+      (underlying ?? this).raiseForRemove(item);
+      return item;
+    }
+
+    /// <summary>
+    /// Remove one item from the fromnt of the list.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public virtual T RemoveFirst()
+    {
+      updatecheck();
+      if (size == 0)
+        throw new NoSuchItemException("List is empty");
+
+      T item = removeAt(0);
+      (underlying ?? this).raiseForRemoveAt(offset, item);
+      return item;
+    }
+
+
+    /// <summary>
+    /// Remove one item from the back of the list.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public virtual T RemoveLast()
+    {
+      updatecheck();
+      if (size == 0)
+        throw new NoSuchItemException("List is empty");
+
+      T item = removeAt(size - 1);
+      (underlying ?? this).raiseForRemoveAt(size + offset, item);
+      return item;
+    }
+
+    /// <summary>
+    /// Create a list view on this list. 
+    /// </summary>
+    /// <exception cref="ArgumentOutOfRangeException"> if the start or count is negative
+    /// or the range does not fit within list.</exception>
+    /// <param name="start">The index in this list of the start of the view.</param>
+    /// <param name="count">The size of the view.</param>
+    /// <returns>The new list view.</returns>
+    [Tested]
+    public virtual IList<T> View(int start, int count)
+    {
+      validitycheck();
+      checkRange(start, count);
+      if (views == null)
+        views = new WeakViewList<ArrayList<T>>();
+      ArrayList<T> retval = (ArrayList<T>)MemberwiseClone();
+
+
+      retval.underlying = underlying != null ? underlying : this;
+      retval.offset = start + offset;
+      retval.size = count;
+      retval.myWeakReference = views.Add(retval);
+      return retval;
+    }
+
+    /// <summary>
+    /// Create a list view on this list containing the (first) occurrence of a particular item.
+    /// <para>Returns <code>null</code> if the item is not in this list.</para>
+    /// </summary>
+    /// <param name="item">The item to find.</param>
+    /// <returns>The new list view.</returns>
+    [Tested]
+    public virtual IList<T> ViewOf(T item)
+    {
+      int index = indexOf(item);
+      if (index < 0)
+        return null;
+      return View(index, 1);
+    }
+
+
+    /// <summary>
+    /// Create a list view on this list containing the last occurrence of a particular item. 
+    /// <para>Returns <code>null</code> if the item is not in this list.</para>
+    /// </summary>
+    /// <param name="item">The item to find.</param>
+    /// <returns>The new list view.</returns>
+    [Tested]
+    public virtual IList<T> LastViewOf(T item)
+    {
+      int index = lastIndexOf(item);
+      if (index < 0)
+        return null;
+      return View(index, 1);
+    }
+
+    /// <summary>
+    /// Null if this list is not a view.
+    /// </summary>
+    /// <value>Underlying list for view.</value>
+    [Tested]
+    public virtual IList<T> Underlying { [Tested]get { return underlying; } }
+
+
+    /// <summary>
+    /// </summary>
+    /// <value>Offset for this list view or 0 for an underlying list.</value>
+    [Tested]
+    public virtual int Offset { [Tested]get { return offset; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual bool IsValid { get { return isValid; } }
+
+    /// <summary>
+    /// Slide this list view along the underlying list.
+    /// </summary>
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>
+    /// <exception cref="ArgumentOutOfRangeException"> if the operation
+    /// would bring either end of the view outside the underlying list.</exception>
+    /// <param name="offset">The signed amount to slide: positive to slide
+    /// towards the end.</param>
+    [Tested]
+    public virtual IList<T> Slide(int offset)
+    {
+      if (!TrySlide(offset, size))
+        throw new ArgumentOutOfRangeException();
+      return this;
+    }
+
+
+    /// <summary>
+    /// Slide this list view along the underlying list, changing its size.
+    /// </summary>
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>
+    /// <exception cref="ArgumentOutOfRangeException"> if the operation
+    /// would bring either end of the view outside the underlying list.</exception>
+    /// <param name="offset">The signed amount to slide: positive to slide
+    /// towards the end.</param>
+    /// <param name="size">The new size of the view.</param>
+    [Tested]
+    public virtual IList<T> Slide(int offset, int size)
+    {
+      if (!TrySlide(offset, size))
+        throw new ArgumentOutOfRangeException();
+      return this;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>
+    /// <param name="offset"></param>
+    /// <returns></returns>
+    [Tested]
+    public virtual bool TrySlide(int offset)
+    {
+      return TrySlide(offset, size);
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>
+    /// <param name="offset"></param>
+    /// <param name="size"></param>
+    /// <returns></returns>
+    [Tested]
+    public virtual bool TrySlide(int offset, int size)
+    {
+      updatecheck();
+      if (underlying == null)
+        throw new NotAViewException("Not a view");
+
+      int newoffset = this.offset + offset;
+      int newsize = size;
+
+      if (newoffset < 0 || newsize < 0 || newoffset + newsize > underlyingsize)
+        return false;
+
+      this.offset = newoffset;
+      this.size = newsize;
+      return true;
+    }
+
+    /// <summary>
+    /// 
+    /// <para>Returns null if <code>otherView</code> is strictly to the left of this view</para>
+    /// </summary>
+    /// <param name="otherView"></param>
+    /// <exception cref="IncompatibleViewException">If otherView does not have the same underlying list as this</exception>
+    /// <returns></returns>
+    public virtual IList<T> Span(IList<T> otherView)
+    {
+      if ((otherView == null) || ((otherView.Underlying ?? otherView) != (underlying ?? this)))
+        throw new IncompatibleViewException();
+      if (otherView.Offset + otherView.Count - Offset < 0)
+        return null;
+      return (underlying ?? this).View(Offset, otherView.Offset + otherView.Count - Offset);
+    }
+
+    /// <summary>
+    /// Reverst the list so the items are in the opposite sequence order.
+    /// </summary>
+    [Tested]
+    public virtual void Reverse()
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      for (int i = 0, length = size / 2, end = offset + size - 1; i < length; i++)
+      {
+        T swap = array[offset + i];
+
+        array[offset + i] = array[end - i];
+        array[end - i] = swap;
+      }
+#if HASHINDEX
+      reindex(offset, offset + size);
+#endif
+      //TODO: be more forgiving wrt. disposing
+      disposeOverlappingViews(true);
+      (underlying ?? this).raiseCollectionChanged();
+    }
+
+    /// <summary>
+    /// Check if this list is sorted according to the default sorting order
+    /// for the item type T, as defined by the <see cref="T:C5.Comparer`1"/> class 
+    /// </summary>
+    /// <exception cref="NotComparableException">if T is not comparable</exception>
+    /// <returns>True if the list is sorted, else false.</returns>
+    [Tested]
+    public bool IsSorted() { return IsSorted(Comparer<T>.Default); }
+
+    /// <summary>
+    /// Check if this list is sorted according to a specific sorting order.
+    /// </summary>
+    /// <param name="c">The comparer defining the sorting order.</param>
+    /// <returns>True if the list is sorted, else false.</returns>
+    [Tested]
+    public virtual bool IsSorted(SCG.IComparer<T> c)
+    {
+      validitycheck();
+      for (int i = offset + 1, end = offset + size; i < end; i++)
+        if (c.Compare(array[i - 1], array[i]) > 0)
+          return false;
+
+      return true;
+    }
+
+    /// <summary>
+    /// Sort the items of the list according to the default sorting order
+    /// for the item type T, as defined by the Comparer[T] class 
+    /// (<see cref="T:C5.Comparer`1"/>).
+    /// </summary>
+    /// <exception cref="InvalidOperationException">if T is not comparable</exception>
+    public virtual void Sort()
+    {
+      Sort(Comparer<T>.Default);
+    }
+
+
+    /// <summary>
+    /// Sort the items of the list according to a specific sorting order.
+    /// </summary>
+    /// <param name="comparer">The comparer defining the sorting order.</param>
+    [Tested]
+    public virtual void Sort(SCG.IComparer<T> comparer)
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      Sorting.IntroSort<T>(array, offset, size, comparer);
+      disposeOverlappingViews(false);
+#if HASHINDEX
+      reindex(offset, offset + size);
+#endif
+      (underlying ?? this).raiseCollectionChanged();
+    }
+
+
+    /// <summary>
+    /// Randomly shuffle the items of this list. 
+    /// </summary>
+    public virtual void Shuffle() { Shuffle(new C5Random()); }
+
+
+    /// <summary>
+    /// Shuffle the items of this list according to a specific random source.
+    /// </summary>
+    /// <param name="rnd">The random source.</param>
+    public virtual void Shuffle(Random rnd)
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      for (int i = offset, top = offset + size, end = top - 1; i < end; i++)
+      {
+        int j = rnd.Next(i, top);
+        if (j != i)
+        {
+          T tmp = array[i];
+          array[i] = array[j];
+          array[j] = tmp;
+        }
+      }
+      disposeOverlappingViews(false);
+#if HASHINDEX
+      reindex(offset, offset + size);
+#endif
+      (underlying ?? this).raiseCollectionChanged();
+    }
+    #endregion
+
+    #region IIndexed<T> Members
+
+    /// <summary>
+    /// Search for an item in the list going forwrds from the start.
+    /// </summary>
+    /// <param name="item">Item to search for.</param>
+    /// <returns>Index of item from start.</returns>
+    [Tested]
+    public virtual int IndexOf(T item) { validitycheck(); return indexOf(item); }
+
+
+    /// <summary>
+    /// Search for an item in the list going backwords from the end.
+    /// </summary>
+    /// <param name="item">Item to search for.</param>
+    /// <returns>Index of item from the end.</returns>
+    [Tested]
+    public virtual int LastIndexOf(T item) { validitycheck(); return lastIndexOf(item); }
+
+
+    /// <summary>
+    /// Remove the item at a specific position of the list.
+    /// </summary>
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or
+    /// &gt;= the size of the collection.</exception>
+    /// <param name="index">The index of the item to remove.</param>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public virtual T RemoveAt(int index)
+    {
+      updatecheck();
+      if (index < 0 || index >= size)
+        throw new IndexOutOfRangeException("Index out of range for sequenced collection");
+
+      T item = removeAt(index);
+      (underlying ?? this).raiseForRemoveAt(offset + index, item);
+      return item;
+    }
+
+
+    /// <summary>
+    /// Remove all items in an index interval.
+    /// </summary>
+    /// <exception cref="ArgumentOutOfRangeException">If <code>start</code>
+    /// and <code>count</code> does not describe a valid interval in the list</exception> 
+    /// <param name="start">The index of the first item to remove.</param>
+    /// <param name="count">The number of items to remove.</param>
+    [Tested]
+    public virtual void RemoveInterval(int start, int count)
+    {
+      updatecheck();
+      if (count == 0)
+        return;
+      checkRange(start, count);
+      start += offset;
+      fixViewsBeforeRemove(start, count);
+#if HASHINDEX
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>();
+      for (int i = start, end = start + count; i < end; i++)
+      {
+        p.Key = array[i];
+        itemIndex.Remove(p);
+      }
+#endif
+      Array.Copy(array, start + count, array, start, underlyingsize - start - count);
+      addtosize(-count);
+      Array.Clear(array, underlyingsize, count);
+#if HASHINDEX
+      reindex(start);
+#endif
+      (underlying ?? this).raiseForRemoveInterval(start, count);
+    }
+    void raiseForRemoveInterval(int start, int count)
+    {
+      if (ActiveEvents != 0)
+      {
+        raiseCollectionCleared(size == 0, count, start);
+        raiseCollectionChanged();
+      }
+    }
+    #endregion
+
+    #region ICollection<T> Members
+
+    /// <summary>
+    /// The value is symbolic indicating the type of asymptotic complexity
+    /// in terms of the size of this collection (worst-case or amortized as
+    /// relevant).
+    /// </summary>
+    /// <value>Speed.Linear</value>
+    [Tested]
+    public virtual Speed ContainsSpeed
+    {
+      [Tested]
+      get
+      {
+#if HASHINDEX
+        return Speed.Constant;
+#else
+        return Speed.Linear;
+#endif
+      }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    [Tested]
+    public override int GetUnsequencedHashCode()
+    { validitycheck(); return base.GetUnsequencedHashCode(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="that"></param>
+    /// <returns></returns>
+    [Tested]
+    public override bool UnsequencedEquals(ICollection<T> that)
+    { validitycheck(); return base.UnsequencedEquals(that); }
+
+    /// <summary>
+    /// Check if this collection contains (an item equivalent to according to the
+    /// itemequalityComparer) a particular value.
+    /// </summary>
+    /// <param name="item">The value to check for.</param>
+    /// <returns>True if the items is in this collection.</returns>
+    [Tested]
+    public virtual bool Contains(T item)
+    { validitycheck(); return indexOf(item) >= 0; }
+
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, return in the ref argument (a
+    /// binary copy of) the actual value found.
+    /// </summary>
+    /// <param name="item">The value to look for.</param>
+    /// <returns>True if the items is in this collection.</returns>
+    [Tested]
+    public virtual bool Find(ref T item)
+    {
+      validitycheck();
+
+      int i;
+
+      if ((i = indexOf(item)) >= 0)
+      {
+        item = array[offset + i];
+        return true;
+      }
+
+      return false;
+    }
+
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// to with a binary copy of the supplied value. This will only update the first 
+    /// mathching item.
+    /// </summary>
+    /// <param name="item">Value to update.</param>
+    /// <returns>True if the item was found and hence updated.</returns>
+    [Tested]
+    public virtual bool Update(T item)
+    {
+      T olditem;
+      return Update(item, out olditem);
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public virtual bool Update(T item, out T olditem)
+    {
+      updatecheck();
+      int i;
+
+      if ((i = indexOf(item)) >= 0)
+      {
+        olditem = array[offset + i];
+        array[offset + i] = item;
+#if HASHINDEX
+        itemIndex.Update(new KeyValuePair<T, int>(item, offset + i));
+#endif
+        (underlying ?? this).raiseForUpdate(item, olditem);
+        return true;
+      }
+
+      olditem = default(T);
+      return false;
+    }
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, return in the ref argument (a
+    /// binary copy of) the actual value found. Else, add the item to the collection.
+    /// </summary>
+    /// <param name="item">The value to look for.</param>
+    /// <returns>True if the item was found (hence not added).</returns>
+    [Tested]
+    public virtual bool FindOrAdd(ref T item)
+    {
+      updatecheck();
+      if (Find(ref item))
+        return true;
+
+      Add(item);
+      return false;
+    }
+
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// to with a binary copy of the supplied value. This will only update the first 
+    /// mathching item.
+    /// </summary>
+    /// <param name="item">Value to update.</param>
+    /// <returns>True if the item was found and hence updated.</returns>
+    [Tested]
+    public virtual bool UpdateOrAdd(T item)
+    {
+      updatecheck();
+      if (Update(item))
+        return true;
+
+      Add(item);
+      return false;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public virtual bool UpdateOrAdd(T item, out T olditem)
+    {
+      updatecheck();
+      if (Update(item, out olditem))
+        return true;
+
+      Add(item);
+      olditem = default(T);
+      return false;
+    }
+
+    /// <summary>
+    /// Remove a particular item from this list. The item will be searched 
+    /// for from the end of the list if <code>FIFO == false</code> (the default), 
+    /// else from the start.
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    /// <returns>True if the item was found (and removed).</returns>
+    [Tested]
+    public virtual bool Remove(T item)
+    {
+      updatecheck();
+
+      int i = fIFO ? indexOf(item) : lastIndexOf(item);
+
+      if (i < 0)
+        return false;
+
+      T removeditem = removeAt(i);
+      (underlying ?? this).raiseForRemove(removeditem);
+      return true;
+    }
+
+
+    /// <summary>
+    /// Remove the first copy of a particular item from this collection if found.
+    /// If an item was removed, report a binary copy of the actual item removed in 
+    /// the argument. The item will be searched 
+    /// for from the end of the list if <code>FIFO == false</code> (the default), 
+    /// else from the start.
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    /// <param name="removeditem">The removed value.</param>
+    /// <returns>True if the item was found (and removed).</returns>
+    [Tested]
+    public virtual bool Remove(T item, out T removeditem)
+    {
+      updatecheck();
+
+      int i = fIFO ? indexOf(item) : lastIndexOf(item);
+
+      if (i < 0)
+      {
+        removeditem = default(T);
+        return false;
+      }
+
+      removeditem = removeAt(i);
+      (underlying ?? this).raiseForRemove(removeditem);
+      return true;
+    }
+
+
+    //TODO: remove from end or according to FIFO?
+    /// <summary>
+    /// Remove all items in another collection from this one, taking multiplicities into account.
+    /// Matching items will be removed from the front. Current implementation is not optimal.
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to remove.</param>
+    [Tested]
+    public virtual void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      //TODO: reactivate the old code for small sizes
+      HashBag<T> toremove = new HashBag<T>(itemequalityComparer);
+      toremove.AddAll(items);
+      if (toremove.Count == 0)
+        return;
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+      ViewHandler viewHandler = new ViewHandler(this);
+      int j = offset;
+      int removed = 0;
+      int i = offset, end = offset + size;
+#if HASHINDEX
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>();
+#endif
+      while (i < end)
+      {
+        T item;
+        //pass by a stretch of nodes
+        while (i < end && !toremove.Contains(item = array[i]))
+        {
+#if HASHINDEX
+          if (j < i)
+          {
+            p.Key = item;
+            p.Value = j;
+            itemIndex.Update(p);
+          }
+#endif
+          //if (j<i)
+          array[j] = item;
+          i++; j++;
+        }
+        viewHandler.skipEndpoints(removed, i);
+        //Remove a stretch of nodes
+        while (i < end && toremove.Remove(item = array[i]))
+        {
+#if HASHINDEX
+          p.Key = item;
+          itemIndex.Remove(p);
+#endif
+          if (mustFire)
+            raiseHandler.Remove(item);
+          removed++;
+          i++;
+          viewHandler.updateViewSizesAndCounts(removed, i);
+        }
+      }
+      if (removed == 0)
+        return;
+      viewHandler.updateViewSizesAndCounts(removed, underlyingsize);
+      Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);
+      addtosize(-removed);
+      Array.Clear(array, underlyingsize, removed);
+#if HASHINDEX
+      reindex(j);
+#endif
+      if (mustFire)
+        raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="predicate"></param>
+    void RemoveAll(Fun<T, bool> predicate)
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+      ViewHandler viewHandler = new ViewHandler(this);
+      int j = offset;
+      int removed = 0;
+      int i = offset, end = offset + size;
+#if HASHINDEX
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>();
+#endif
+      while (i < end)
+      {
+        T item;
+        //pass by a stretch of nodes
+        while (i < end && !predicate(item = array[i]))
+        {
+          updatecheck();
+#if HASHINDEX
+          if (j < i)
+          {
+            p.Key = item;
+            p.Value = j;
+            itemIndex.Update(p);
+          }
+#endif
+          //if (j<i)
+          array[j] = item;
+          i++; j++;
+        }
+        updatecheck();
+        viewHandler.skipEndpoints(removed, i);
+        //Remove a stretch of nodes
+        while (i < end && predicate(item = array[i]))
+        {
+          updatecheck();
+#if HASHINDEX
+          p.Key = item;
+          itemIndex.Remove(p);
+#endif
+          if (mustFire)
+            raiseHandler.Remove(item);
+          removed++;
+          i++;
+          viewHandler.updateViewSizesAndCounts(removed, i);
+        }
+        updatecheck();
+      }
+      if (removed == 0)
+        return;
+      viewHandler.updateViewSizesAndCounts(removed, underlyingsize);
+      Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);
+      addtosize(-removed);
+      Array.Clear(array, underlyingsize, removed);
+#if HASHINDEX
+      reindex(j);
+#endif
+      if (mustFire)
+        raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// Remove all items from this collection, resetting internal array size.
+    /// </summary>
+    [Tested]
+    public override void Clear()
+    {
+      if (underlying == null)
+      {
+        updatecheck();
+        if (size == 0)
+          return;
+        int oldsize = size;
+        fixViewsBeforeRemove(0, size);
+#if HASHINDEX
+        itemIndex.Clear();
+#endif
+        array = new T[8];
+        size = 0;
+        (underlying ?? this).raiseForRemoveInterval(offset, oldsize);
+      }
+      else
+        RemoveInterval(0, size);
+    }
+
+    /// <summary>
+    /// Remove all items not in some other collection from this one, taking multiplicities into account.
+    /// Items are retained front first.  
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to retain.</param>
+    [Tested]
+    public virtual void RetainAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      HashBag<T> toretain = new HashBag<T>(itemequalityComparer);
+      toretain.AddAll(items);
+      if (toretain.Count == 0)
+      {
+        Clear();
+        return;
+      }
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+      ViewHandler viewHandler = new ViewHandler(this);
+      int j = offset;
+      int removed = 0;
+      int i = offset, end = offset + size;
+#if HASHINDEX
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>();
+#endif
+      while (i < end)
+      {
+        T item;
+        //pass by a stretch of nodes
+        while (i < end && toretain.Remove(item = array[i]))
+        {
+#if HASHINDEX
+          if (j < i)
+          {
+            p.Key = item;
+            p.Value = j;
+            itemIndex.Update(p);
+          }
+#endif
+          //if (j<i)
+          array[j] = item;
+          i++; j++;
+        }
+        viewHandler.skipEndpoints(removed, i);
+        //Remove a stretch of nodes
+        while (i < end && !toretain.Contains(item = array[i]))
+        {
+#if HASHINDEX
+          p.Key = item;
+          itemIndex.Remove(p);
+#endif
+          if (mustFire)
+            raiseHandler.Remove(item);
+          removed++;
+          i++;
+          viewHandler.updateViewSizesAndCounts(removed, i);
+        }
+      }
+      if (removed == 0)
+        return;
+      viewHandler.updateViewSizesAndCounts(removed, underlyingsize);
+      Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);
+      addtosize(-removed);
+      Array.Clear(array, underlyingsize, removed);
+#if HASHINDEX
+      reindex(j);
+#endif
+      raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="predicate"></param>
+    void RetainAll(Fun<T, bool> predicate)
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+      ViewHandler viewHandler = new ViewHandler(this);
+      int j = offset;
+      int removed = 0;
+      int i = offset, end = offset + size;
+#if HASHINDEX
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>();
+#endif
+      while (i < end)
+      {
+        T item;
+        //pass by a stretch of nodes
+        while (i < end && predicate(item = array[i]))
+        {
+          updatecheck();
+#if HASHINDEX
+          if (j < i)
+          {
+            p.Key = item;
+            p.Value = j;
+            itemIndex.Update(p);
+          }
+#endif
+          //if (j<i)
+          array[j] = item;
+          i++; j++;
+        }
+        updatecheck();
+        viewHandler.skipEndpoints(removed, i);
+        //Remove a stretch of nodes
+        while (i < end && !predicate(item = array[i]))
+        {
+          updatecheck();
+#if HASHINDEX
+          p.Key = item;
+          itemIndex.Remove(p);
+#endif
+          if (mustFire)
+            raiseHandler.Remove(item);
+          removed++;
+          i++;
+          viewHandler.updateViewSizesAndCounts(removed, i);
+        }
+        updatecheck();
+      }
+      if (removed == 0)
+        return;
+      viewHandler.updateViewSizesAndCounts(removed, underlyingsize);
+      Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);
+      addtosize(-removed);
+      Array.Clear(array, underlyingsize, removed);
+#if HASHINDEX
+      reindex(j);
+#endif
+      raiseHandler.Raise();
+    }
+
+
+    /// <summary>
+    /// Check if this collection contains all the values in another collection,
+    /// taking multiplicities into account.
+    /// Current implementation is not optimal.
+    /// </summary>
+    /// <param name="items">The </param>
+    /// <typeparam name="U"></typeparam>
+    /// <returns>True if all values in <code>items</code>is in this collection.</returns>
+    [Tested]
+    public virtual bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      validitycheck();
+#if HASHINDEX
+      foreach (T item in items)
+        if (indexOf(item) < 0)
+          return false;
+
+      return true;
+#else
+      //TODO: use aux hash bag to obtain linear time procedure
+      HashBag<T> tomatch = new HashBag<T>(itemequalityComparer);
+      tomatch.AddAll(items);
+      if (tomatch.Count == 0)
+        return true;
+      for (int i = offset, end = offset + size; i < end; i++)
+      {
+        tomatch.Remove(array[i]);
+        if (tomatch.Count == 0)
+          return true;
+      }
+      return false;
+#endif
+    }
+
+
+    /// <summary>
+    /// Count the number of items of the collection equal to a particular value.
+    /// Returns 0 if and only if the value is not in the collection.
+    /// </summary>
+    /// <param name="item">The value to count.</param>
+    /// <returns>The number of copies found.</returns>
+    [Tested]
+    public virtual int ContainsCount(T item)
+    {
+      validitycheck();
+#if HASHINDEX
+      return indexOf(item) >= 0 ? 1 : 0;
+#else
+      int count = 0;
+      for (int i = 0; i < size; i++)
+        if (equals(item, array[offset + i]))
+          count++;
+      return count;
+#endif
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<T> UniqueItems()
+    {
+#if HASHINDEX
+      return this;
+#else
+      HashBag<T> hashbag = new HashBag<T>(itemequalityComparer);
+      hashbag.AddAll(this);
+      return hashbag.UniqueItems();
+#endif
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities()
+    {
+#if HASHINDEX
+      return new MultiplicityOne<T>(this);
+#else
+      HashBag<T> hashbag = new HashBag<T>(itemequalityComparer);
+      hashbag.AddAll(this);
+      return hashbag.ItemMultiplicities();
+#endif
+    }
+
+
+
+
+
+    /// <summary>
+    /// Remove all items equal to a given one.
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    [Tested]
+    public virtual void RemoveAllCopies(T item)
+    {
+#if HASHINDEX
+      Remove(item);
+#else
+      updatecheck();
+      if (size == 0)
+        return;
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+      ViewHandler viewHandler = new ViewHandler(this);
+      int j = offset;
+      int removed = 0;
+      int i = offset, end = offset + size;
+      while (i < end)
+      {
+        //pass by a stretch of nodes
+        while (i < end && !equals(item, array[i]))
+          array[j++] = array[i++];
+        viewHandler.skipEndpoints(removed, i);
+        //Remove a stretch of nodes
+        while (i < end && equals(item, array[i]))
+        {
+          if (mustFire)
+            raiseHandler.Remove(array[i]);
+          removed++;
+          i++;
+          viewHandler.updateViewSizesAndCounts(removed, i);
+        }
+      }
+      if (removed == 0)
+        return;
+      viewHandler.updateViewSizesAndCounts(removed, underlyingsize);
+      Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);
+      addtosize(-removed);
+      Array.Clear(array, underlyingsize, removed);
+      raiseHandler.Raise();
+#endif
+    }
+
+
+    //TODO: check views
+    /// <summary>
+    /// Check the integrity of the internal data structures of this array list.
+    /// </summary>
+    /// <returns>True if check does not fail.</returns>
+    [Tested]
+    public override bool Check()
+    {
+      bool retval = true;
+
+      if (underlyingsize > array.Length)
+      {
+        Console.WriteLine("underlyingsize ({0}) > array.Length ({1})", size, array.Length);
+        return false;
+      }
+
+      if (offset + size > underlyingsize)
+      {
+        Console.WriteLine("offset({0})+size({1}) > underlyingsize ({2})", offset, size, underlyingsize);
+        return false;
+      }
+
+      if (offset < 0)
+      {
+        Console.WriteLine("offset({0}) < 0", offset);
+        return false;
+      }
+
+      for (int i = 0; i < underlyingsize; i++)
+      {
+        if ((object)(array[i]) == null)
+        {
+          Console.WriteLine("Bad element: null at (base)index {0}", i);
+          retval = false;
+        }
+      }
+
+      for (int i = underlyingsize, length = array.Length; i < length; i++)
+      {
+        if (!equals(array[i], default(T)))
+        {
+          Console.WriteLine("Bad element: != default(T) at (base)index {0}", i);
+          retval = false;
+        }
+      }
+
+      {
+        ArrayList<T> u = underlying ?? this;
+        if (u.views != null)
+          foreach (ArrayList<T> v in u.views)
+          {
+            if (u.array != v.array)
+            {
+              Console.WriteLine("View from {0} of length has different base array than the underlying list", v.offset, v.size);
+              retval = false;
+            }
+          }
+      }
+
+
+#if HASHINDEX
+      if (underlyingsize != itemIndex.Count)
+      {
+        Console.WriteLine("size ({0})!= index.Count ({1})", size, itemIndex.Count);
+        retval = false;
+      }
+
+      for (int i = 0; i < underlyingsize; i++)
+      {
+        KeyValuePair<T, int> p = new KeyValuePair<T, int>(array[i]);
+
+        if (!itemIndex.Find(ref p))
+        {
+          Console.WriteLine("Item {1} at {0} not in hashindex", i, array[i]);
+          retval = false;
+        }
+
+        if (p.Value != i)
+        {
+          Console.WriteLine("Item {1} at {0} has hashindex {2}", i, array[i], p.Value);
+          retval = false;
+        }
+      }
+#endif
+      return retval;
+    }
+
+    #endregion
+
+    #region IExtensible<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>True, indicating array list has bag semantics.</value>
+    [Tested]
+    public virtual bool AllowsDuplicates
+    {
+      [Tested]
+      get
+      {
+#if HASHINDEX
+        return false;
+#else
+        return true;
+#endif
+      }
+    }
+
+    /// <summary>
+    /// By convention this is true for any collection with set semantics.
+    /// </summary>
+    /// <value>True if only one representative of a group of equal items 
+    /// is kept in the collection together with the total count.</value>
+    public virtual bool DuplicatesByCounting
+    {
+      get
+      {
+#if HASHINDEX
+        return true;
+#else
+        return false;
+#endif
+      }
+    }
+
+    /// <summary>
+    /// Add an item to end of this list.
+    /// </summary>
+    /// <param name="item">The item to add.</param>
+    /// <returns>True</returns>
+    [Tested]
+    public virtual bool Add(T item)
+    {
+      updatecheck();
+#if HASHINDEX
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, size + offset);
+      if (itemIndex.FindOrAdd(ref p))
+        return false;
+#endif
+      baseinsert(size, item);
+#if HASHINDEX
+      reindex(size + offset);
+#endif
+      (underlying ?? this).raiseForAdd(item);
+      return true;
+    }
+
+
+    /// <summary>
+    /// Add the elements from another collection to this collection.
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items"></param>
+    [Tested]
+    public virtual void AddAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      updatecheck();
+      int toadd = EnumerableBase<U>.countItems(items);
+      if (toadd == 0)
+        return;
+
+      if (toadd + underlyingsize > array.Length)
+        expand(toadd + underlyingsize, underlyingsize);
+
+      int i = size + offset;
+      if (underlyingsize > i)
+        Array.Copy(array, i, array, i + toadd, underlyingsize - i);
+      try
+      {
+        foreach (T item in items)
+        {
+#if HASHINDEX
+          KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, i);
+          if (itemIndex.FindOrAdd(ref p))
+            continue;
+#endif
+          array[i++] = item;
+        }
+      }
+      finally
+      {
+        int added = i - size - offset;
+        if (added < toadd)
+        {
+          Array.Copy(array, size + offset + toadd, array, i, underlyingsize - size - offset);
+          Array.Clear(array, underlyingsize + added, toadd - added);
+        }
+        if (added > 0)
+        {
+          addtosize(added);
+#if HASHINDEX
+          reindex(i);
+#endif
+          fixViewsAfterInsert(added, i - added);
+          (underlying ?? this).raiseForAddAll(i - added, added);
+        }
+      }
+    }
+    private void raiseForAddAll(int start, int added)
+    {
+      if ((ActiveEvents & EventTypeEnum.Added) != 0)
+        for (int i = start, end = start + added; i < end; i++)
+          raiseItemsAdded(array[i], 1);
+      raiseCollectionChanged();
+    }
+
+    #endregion
+
+    #region IDirectedEnumerable<T> Members
+
+    /// <summary>
+    /// Create a collection containing the same items as this collection, but
+    /// whose enumerator will enumerate the items backwards. The new collection
+    /// will become invalid if the original is modified. Method typicaly used as in
+    /// <code>foreach (T x in coll.Backwards()) {...}</code>
+    /// </summary>
+    /// <returns>The backwards collection.</returns>
+    [Tested]
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
+
+    #endregion
+
+    #region ICollectionValue<T> Members
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>The number of items in this collection</value>
+    [Tested]
+    public override int Count { [Tested]get { validitycheck(); return size; } }
+    #endregion
+
+    #region IEnumerable<T> Members
+    //TODO: make tests of all calls on a disposed view throws the right exception! (Which should be C5.InvalidListViewException)
+    /// <summary>
+    /// Create an enumerator for the collection
+    /// </summary>
+    /// <returns>The enumerator</returns>
+    [Tested]
+    public override SCG.IEnumerator<T> GetEnumerator()
+    {
+      validitycheck();
+      return base.GetEnumerator();
+    }
+    #endregion
+
+#if HASHINDEX
+#else
+    #region IStack<T> Members
+
+    /// <summary>
+    /// Push an item to the top of the stack.
+    /// </summary>
+    /// <param name="item">The item</param>
+    [Tested]
+    public virtual void Push(T item)
+    {
+      InsertLast(item);
+    }
+
+    /// <summary>
+    /// Pop the item at the top of the stack from the stack.
+    /// </summary>
+    /// <returns>The popped item.</returns>
+    [Tested]
+    public virtual T Pop()
+    {
+      return RemoveLast();
+    }
+
+    #endregion
+
+    #region IQueue<T> Members
+
+    /// <summary>
+    /// Enqueue an item at the back of the queue. 
+    /// </summary>
+    /// <param name="item">The item</param>
+    [Tested]
+    public virtual void Enqueue(T item)
+    {
+      InsertLast(item);
+    }
+
+    /// <summary>
+    /// Dequeue an item from the front of the queue.
+    /// </summary>
+    /// <returns>The item</returns>
+    [Tested]
+    public virtual T Dequeue()
+    {
+      return RemoveFirst();
+    }
+
+    #endregion
+#endif
+    #region IDisposable Members
+
+    /// <summary>
+    /// Invalidate this list. If a view, just invalidate the view. 
+    /// If not a view, invalidate the list and all views on it.
+    /// </summary>
+    public virtual void Dispose()
+    {
+      Dispose(false);
+    }
+
+    void Dispose(bool disposingUnderlying)
+    {
+      if (isValid)
+      {
+        if (underlying != null)
+        {
+          isValid = false;
+          if (!disposingUnderlying && views != null)
+            views.Remove(myWeakReference);
+          underlying = null;
+          views = null;
+          myWeakReference = null;
+        }
+        else
+        {
+          //isValid = false;
+          if (views != null)
+            foreach (ArrayList<T> view in views)
+              view.Dispose(true);
+          Clear();
+        }
+      }
+    }
+
+    #endregion
+
+    #region ICloneable Members
+
+    /// <summary>
+    /// Make a shallow copy of this ArrayList.
+    /// </summary>
+    /// <returns></returns>
+    public virtual object Clone()
+    {
+      ArrayList<T> clone = new ArrayList<T>(size, itemequalityComparer);
+      clone.AddAll(this);
+      return clone;
+    }
+
+    #endregion
+
+    #region ISerializable Members
+    /*
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="info"></param>
+    /// <param name="context"></param>
+    public ArrayList(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) :
+      this(info.GetInt32("sz"),(SCG.IEqualityComparer<T>)(info.GetValue("eq",typeof(SCG.IEqualityComparer<T>))))
+    {
+      size = info.GetInt32("sz");
+      for (int i = 0; i < size; i++)
+      {
+        array[i] = (T)(info.GetValue("elem" + i,typeof(T)));
+      }
+#if HASHINDEX
+      reindex(0);
+#endif      
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="info"></param>
+    /// <param name="context"></param>
+    public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
+    {
+      info.AddValue("sz", size);
+      info.AddValue("eq", EqualityComparer);
+      for (int i = 0; i < size; i++)
+			{
+        info.AddValue("elem" + i, array[i + offset]);
+      }
+    }
+*/
+    #endregion
+
+    #region System.Collections.Generic.IList<T> Members
+
+    void System.Collections.Generic.IList<T>.RemoveAt(int index)
+    {
+      RemoveAt(index);
+    }
+
+    void System.Collections.Generic.ICollection<T>.Add(T item)
+    {
+      Add(item);
+    }
+
+    #endregion
+
+    #region System.Collections.ICollection Members
+
+    bool System.Collections.ICollection.IsSynchronized
+    {
+      get { return false; }
+    }
+
+    [Obsolete]
+    Object System.Collections.ICollection.SyncRoot
+    {
+      get { return underlying != null ? ((System.Collections.ICollection)underlying).SyncRoot : array; }
+    }
+
+    void System.Collections.ICollection.CopyTo(Array arr, int index)
+    {
+      if (index < 0 || index + Count > arr.Length)
+        throw new ArgumentOutOfRangeException();
+
+      foreach (T item in this)
+        arr.SetValue(item, index++);
+    }
+
+    #endregion
+
+    #region System.Collections.IList Members
+
+    Object System.Collections.IList.this[int index]
+    {
+      get { return this[index]; }
+      set { this[index] = (T)value; }
+    }
+
+    int System.Collections.IList.Add(Object o)
+    {
+      bool added = Add((T)o);
+      // What position to report if item not added? SC.IList.Add doesn't say
+      return added ? Count - 1 : -1;
+    }
+
+    bool System.Collections.IList.Contains(Object o)
+    {
+      return Contains((T)o);
+    }
+
+    int System.Collections.IList.IndexOf(Object o)
+    {
+      return Math.Max(-1, IndexOf((T)o));
+    }
+
+    void System.Collections.IList.Insert(int index, Object o)
+    {
+      Insert(index, (T)o);
+    }
+
+    void System.Collections.IList.Remove(Object o)
+    {
+      Remove((T)o);
+    }
+
+    void System.Collections.IList.RemoveAt(int index)
+    {
+      RemoveAt(index);
+    }
+
+    #endregion
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/arrays/CircularQueue.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/arrays/CircularQueue.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/arrays/CircularQueue.cs	(revision 3)
@@ -0,0 +1,335 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+namespace C5
+{
+  /// <summary>
+  /// 
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  public class CircularQueue<T> : SequencedBase<T>, IQueue<T>, IStack<T>
+  {
+    #region Fields
+    /*
+        Invariant: the itemes in the queue ar the elements from front upwards, 
+        possibly wrapping around at the end of array, to back.
+
+        if front<=back then size = back - front + 1;
+        else size = array.Length + back - front + 1;
+
+        */
+    int front, back;
+    /// <summary>
+    /// The internal container array is doubled when necessary, but never shrinked.
+    /// </summary>
+    T[] array;
+    bool forwards = true, original = true;
+    #endregion
+
+    #region Events
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public override EventTypeEnum ListenableEvents { get { return EventTypeEnum.Basic; } }
+
+    #endregion
+
+    #region Util
+    void expand()
+    {
+      int newlength = 2 * array.Length;
+      T[] newarray = new T[newlength];
+
+      if (front <= back)
+        Array.Copy(array, front, newarray, 0, size);
+      else
+      {
+        int half = array.Length - front;
+        Array.Copy(array, front, newarray, 0, half);
+        Array.Copy(array, 0, newarray, half, size - half);
+      }
+
+      front = 0;
+      back = size;
+      array = newarray;
+    }
+
+    #endregion
+
+    #region Constructors
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public CircularQueue() : this(8) { }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="capacity"></param>
+    public CircularQueue(int capacity)
+      : base(EqualityComparer<T>.Default)
+    {
+      int newlength = 8;
+      while (newlength < capacity) newlength *= 2;
+      array = new T[newlength];
+    }
+
+    #endregion
+
+    #region IQueue<T> Members
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual bool AllowsDuplicates { get { return true; } }
+
+    /// <summary>
+    /// Get the i'th item in the queue. The front of the queue is at index 0.
+    /// </summary>
+    /// <param name="i"></param>
+    /// <returns></returns>
+    public virtual T this[int i]
+    {
+      get
+      {
+        if (i < 0 || i >= size)
+          throw new IndexOutOfRangeException();
+        i = i + front;
+        //Bug fix by Steve Wallace 2006/02/10
+        return array[i >= array.Length ? i - array.Length : i];
+      }
+    }
+
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    [Tested]
+    public virtual void Enqueue(T item)
+    {
+      if (!original)
+        throw new ReadOnlyCollectionException();
+      stamp++;
+      if (size == array.Length - 1) expand();
+      size++;
+      int oldback = back++;
+      if (back == array.Length) back = 0;
+      array[oldback] = item;
+      if (ActiveEvents != 0)
+        raiseForAdd(item);
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    [Tested]
+    public virtual T Dequeue()
+    {
+      if (!original)
+        throw new ReadOnlyCollectionException("Object is a non-updatable clone");
+      stamp++;
+      if (size == 0)
+        throw new NoSuchItemException();
+      size--;
+      int oldfront = front++;
+      if (front == array.Length) front = 0;
+      T retval = array[oldfront];
+      array[oldfront] = default(T);
+      if (ActiveEvents != 0)
+        raiseForRemove(retval);
+      return retval;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    public void Push(T item) //== Enqueue
+    {
+      if (!original)
+        throw new ReadOnlyCollectionException();
+      stamp++;
+      if (size == array.Length - 1) expand();
+      size++;
+      int oldback = back++;
+      if (back == array.Length) back = 0;
+      array[oldback] = item;
+      if (ActiveEvents != 0)
+        raiseForAdd(item);
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public T Pop()
+    {
+      if (!original)
+        throw new ReadOnlyCollectionException("Object is a non-updatable clone");
+      stamp++;
+      if (size == 0)
+        throw new NoSuchItemException();
+      size--;
+      back--;
+      if (back == -1) back = array.Length - 1;
+      T retval = array[back];
+      array[back] = default(T);
+      if (ActiveEvents != 0)
+        raiseForRemove(retval);
+      return retval;
+    }
+    #endregion
+
+    #region ICollectionValue<T> Members
+
+    //TODO: implement these with Array.Copy instead of relying on XxxBase:
+    /*
+        public void CopyTo(T[] a, int i)
+        {
+        }
+
+        public T[] ToArray()
+        {
+        }*/
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    [Tested]
+    public override T Choose()
+    {
+      if (size == 0)
+        throw new NoSuchItemException();
+      return array[front];
+    }
+
+    #endregion
+
+    #region IEnumerable<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override SCG.IEnumerator<T> GetEnumerator()
+    {
+      int stamp = this.stamp;
+      if (forwards)
+      {
+        int position = front;
+        int end = front <= back ? back : array.Length;
+        while (position < end)
+        {
+          if (stamp != this.stamp)
+            throw new CollectionModifiedException();
+          yield return array[position++];
+        }
+        if (front > back)
+        {
+          position = 0;
+          while (position < back)
+          {
+            if (stamp != this.stamp)
+              throw new CollectionModifiedException();
+            yield return array[position++];
+          }
+        }
+      }
+      else
+      {
+        int position = back - 1;
+        int end = front <= back ? front : 0;
+        while (position >= end)
+        {
+          if (stamp != this.stamp)
+            throw new CollectionModifiedException();
+          yield return array[position--];
+        }
+        if (front > back)
+        {
+          position = array.Length - 1;
+          while (position >= front)
+          {
+            if (stamp != this.stamp)
+              throw new CollectionModifiedException();
+            yield return array[position--];
+          }
+        }
+      }
+    }
+
+    #endregion
+
+    #region IDirectedCollectionValue<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override IDirectedCollectionValue<T> Backwards()
+    {
+      CircularQueue<T> retval = (CircularQueue<T>)MemberwiseClone();
+      retval.original = false;
+      retval.forwards = !forwards;
+      return retval;
+    }
+
+    #endregion
+
+    #region IDirectedEnumerable<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
+    {
+      return Backwards();
+    }
+
+    #endregion
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual bool Check()
+    {
+      if (front < 0 || front >= array.Length || back < 0 || back >= array.Length ||
+          (front <= back && size != back - front) || (front > back && size != array.Length + back - front))
+      {
+        Console.WriteLine("Bad combination of (front,back,size,array.Length): ({0},{1},{2},{3})",
+            front, back, size, array.Length);
+        return false;
+      }
+      return true;
+    }
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/arrays/HashedArrayList.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/arrays/HashedArrayList.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/arrays/HashedArrayList.cs	(revision 3)
@@ -0,0 +1,2638 @@
+
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+#define HASHINDEX
+
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+namespace C5
+{
+  /// <summary>
+  /// A list collection based on a plain dynamic array data structure.
+  /// Expansion of the internal array is performed by doubling on demand. 
+  /// The internal array is only shrinked by the Clear method. 
+  ///
+  /// <i>When the FIFO property is set to false this class works fine as a stack of T.
+  /// When the FIFO property is set to true the class will function as a (FIFO) queue
+  /// but very inefficiently, use a LinkedList (<see cref="T:C5.LinkedList`1"/>) instead.</i>
+  /// </summary>
+  [Serializable]
+  public class HashedArrayList<T> : ArrayBase<T>, IList<T>, SCG.IList<T>
+#if HASHINDEX
+#else
+, IStack<T>, IQueue<T>
+#endif
+  {
+    #region Fields
+
+    /// <summary>
+    /// Has this list or view not been invalidated by some operation (by someone calling Dispose())
+    /// </summary>
+    bool isValid = true;
+
+    //TODO: wonder if we should save some memory on none-view situations by 
+    //      putting these three fields into a single ref field?
+    /// <summary>
+    /// The underlying list if we are a view, null else.
+    /// </summary>
+    HashedArrayList<T> underlying;
+    WeakViewList<HashedArrayList<T>> views;
+    WeakViewList<HashedArrayList<T>>.Node myWeakReference;
+
+    /// <summary>
+    /// The size of the underlying list.
+    /// </summary>
+    int underlyingsize { get { return (underlying ?? this).size; } }
+
+    /// <summary>
+    /// The underlying field of the FIFO property
+    /// </summary>
+    bool fIFO = false;
+
+#if HASHINDEX
+    HashSet<KeyValuePair<T, int>> itemIndex;
+#endif
+    #endregion
+    #region Events
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public override EventTypeEnum ListenableEvents { get { return underlying == null ? EventTypeEnum.All : EventTypeEnum.None; } }
+
+    /*
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public override event CollectionChangedHandler<T> CollectionChanged
+        {
+          add
+          {
+            if (underlying == null)
+              base.CollectionChanged += value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+          remove
+          {
+            if (underlying == null)
+              base.CollectionChanged -= value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public override event CollectionClearedHandler<T> CollectionCleared
+        {
+          add
+          {
+            if (underlying == null)
+              base.CollectionCleared += value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+          remove
+          {
+            if (underlying == null)
+              base.CollectionCleared -= value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public override event ItemsAddedHandler<T> ItemsAdded
+        {
+          add
+          {
+            if (underlying == null)
+              base.ItemsAdded += value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+          remove
+          {
+            if (underlying == null)
+              base.ItemsAdded -= value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public override event ItemInsertedHandler<T> ItemInserted
+        {
+          add
+          {
+            if (underlying == null)
+              base.ItemInserted += value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+          remove
+          {
+            if (underlying == null)
+              base.ItemInserted -= value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public override event ItemsRemovedHandler<T> ItemsRemoved
+        {
+          add
+          {
+            if (underlying == null)
+              base.ItemsRemoved += value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+          remove
+          {
+            if (underlying == null)
+              base.ItemsRemoved -= value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        /// <value></value>
+        public override event ItemRemovedAtHandler<T> ItemRemovedAt
+        {
+          add
+          {
+            if (underlying == null)
+              base.ItemRemovedAt += value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+          remove
+          {
+            if (underlying == null)
+              base.ItemRemovedAt -= value;
+            else
+              throw new UnlistenableEventException("Can't listen to a view");
+          }
+        }
+
+          */
+
+    #endregion
+    #region Util
+
+    bool equals(T i1, T i2) { return itemequalityComparer.Equals(i1, i2); }
+
+    /// <summary>
+    /// Increment or decrement the private size fields
+    /// </summary>
+    /// <param name="delta">Increment (with sign)</param>
+    void addtosize(int delta)
+    {
+      size += delta;
+      if (underlying != null)
+        underlying.size += delta;
+    }
+
+    #region Array handling
+    /// <summary>
+    /// Double the size of the internal array.
+    /// </summary>
+    protected override void expand()
+    { expand(2 * array.Length, underlyingsize); }
+
+
+    /// <summary>
+    /// Expand the internal array, resetting the index of the first unused element.
+    /// </summary>
+    /// <param name="newcapacity">The new capacity (will be rouded upwards to a power of 2).</param>
+    /// <param name="newsize">The new count of </param>
+    protected override void expand(int newcapacity, int newsize)
+    {
+      if (underlying != null)
+        underlying.expand(newcapacity, newsize);
+      else
+      {
+        base.expand(newcapacity, newsize);
+        if (views != null)
+          foreach (HashedArrayList<T> v in views)
+            v.array = array;
+      }
+    }
+
+    #endregion
+
+    #region Checks
+    /// <summary>
+    /// Check if it is valid to perform updates and increment stamp if so.
+    /// </summary>
+    /// <exception cref="ViewDisposedException"> If check fails by this list being a disposed view.</exception>
+    /// <exception cref="ReadOnlyCollectionException"> If check fails by this being a read only list.</exception>
+    protected override void updatecheck()
+    {
+      validitycheck();
+      base.updatecheck();
+      if (underlying != null)
+        underlying.stamp++;
+    }
+
+
+    /// <summary>
+    /// Check if we are a view that the underlying list has only been updated through us.
+    /// <para>This method should be called from enumerators etc to guard against 
+    /// modification of the base collection.</para>
+    /// </summary>
+    /// <exception cref="ViewDisposedException"> if check fails.</exception>
+    void validitycheck()
+    {
+      if (!isValid)
+        throw new ViewDisposedException();
+    }
+
+
+    /// <summary>
+    /// Check that the list has not been updated since a particular time.
+    /// <para>To be used by enumerators and range </para>
+    /// </summary>
+    /// <exception cref="ViewDisposedException"> If check fails by this list being a disposed view.</exception>
+    /// <exception cref="CollectionModifiedException">If the list *has* beeen updated since that  time..</exception>
+    /// <param name="stamp">The stamp indicating the time.</param>
+    protected override void modifycheck(int stamp)
+    {
+      validitycheck();
+      if (this.stamp != stamp)
+        throw new CollectionModifiedException();
+    }
+
+    #endregion
+
+    #region Searching
+
+    /// <summary>
+    /// Internal version of IndexOf without modification checks.
+    /// </summary>
+    /// <param name="item">Item to look for</param>
+    /// <returns>The index of first occurrence</returns>
+    int indexOf(T item)
+    {
+#if HASHINDEX
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item);
+      if (itemIndex.Find(ref p) && p.Value >= offset && p.Value < offset + size)
+        return p.Value - offset;
+#else
+      for (int i = 0; i < size; i++)
+        if (equals(item, array[offset + i]))
+          return i;
+#endif
+      return ~size;
+    }
+
+    /// <summary>
+    /// Internal version of LastIndexOf without modification checks.
+    /// </summary>
+    /// <param name="item">Item to look for</param>
+    /// <returns>The index of last occurrence</returns>
+    int lastIndexOf(T item)
+    {
+#if HASHINDEX
+      return indexOf(item);
+#else
+      for (int i = size - 1; i >= 0; i--)
+        if (equals(item, array[offset + i]))
+          return i;
+      return ~size;
+#endif
+    }
+    #endregion
+
+    #region Inserting
+
+#if HASHINDEX
+    /// <summary>
+    /// Internal version of Insert with no modification checks.
+    /// </summary>
+    /// <exception cref="DuplicateNotAllowedException"> if item already in list.</exception>
+    /// <param name="i">Index to insert at</param>
+    /// <param name="item">Item to insert</param>
+#else
+    /// <summary>
+    /// Internal version of Insert with no modification checks.
+    /// </summary>
+    /// <param name="i">Index to insert at</param>
+    /// <param name="item">Item to insert</param>
+#endif
+    protected override void insert(int i, T item)
+    {
+#if HASHINDEX
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, offset + i);
+      if (itemIndex.FindOrAdd(ref p))
+        throw new DuplicateNotAllowedException("Item already in indexed list: " + item);
+#endif
+      baseinsert(i, item);
+#if HASHINDEX
+      reindex(i + offset + 1);
+#endif
+    }
+
+    private void baseinsert(int i, T item)
+    {
+      if (underlyingsize == array.Length)
+        expand();
+      i += offset;
+      if (i < underlyingsize)
+        Array.Copy(array, i, array, i + 1, underlyingsize - i);
+      array[i] = item;
+      addtosize(1);
+      fixViewsAfterInsert(1, i);
+    }
+    #endregion
+
+    #region Removing
+
+    /// <summary>
+    /// Internal version of RemoveAt with no modification checks.
+    /// </summary>
+    /// <param name="i">Index to remove at</param>
+    /// <returns>The removed item</returns>
+    T removeAt(int i)
+    {
+      i += offset;
+      fixViewsBeforeSingleRemove(i);
+      T retval = array[i];
+      addtosize(-1);
+      if (underlyingsize > i)
+        Array.Copy(array, i + 1, array, i, underlyingsize - i);
+      array[underlyingsize] = default(T);
+#if HASHINDEX
+      itemIndex.Remove(new KeyValuePair<T, int>(retval));
+      reindex(i);
+#endif
+      return retval;
+    }
+    #endregion
+
+    #region Indexing
+
+#if HASHINDEX
+    private void reindex(int start) { reindex(start, underlyingsize); }
+
+    private void reindex(int start, int end)
+    {
+      for (int j = start; j < end; j++)
+        itemIndex.UpdateOrAdd(new KeyValuePair<T, int>(array[j], j));
+    }
+#endif
+    #endregion
+
+    #region fixView utilities
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="added">The actual number of inserted nodes</param>
+    /// <param name="realInsertionIndex"></param>
+    void fixViewsAfterInsert(int added, int realInsertionIndex)
+    {
+      if (views != null)
+        foreach (HashedArrayList<T> view in views)
+        {
+          if (view != this)
+          {
+            if (view.offset < realInsertionIndex && view.offset + view.size > realInsertionIndex)
+              view.size += added;
+            if (view.offset > realInsertionIndex || (view.offset == realInsertionIndex && view.size > 0))
+              view.offset += added;
+          }
+        }
+    }
+
+    void fixViewsBeforeSingleRemove(int realRemovalIndex)
+    {
+      if (views != null)
+        foreach (HashedArrayList<T> view in views)
+        {
+          if (view != this)
+          {
+            if (view.offset <= realRemovalIndex && view.offset + view.size > realRemovalIndex)
+              view.size--;
+            if (view.offset > realRemovalIndex)
+              view.offset--;
+          }
+        }
+    }
+
+    /// <summary>
+    /// Fix offsets and sizes of other views before removing an interval from this 
+    /// </summary>
+    /// <param name="start">the start of the interval relative to the array/underlying</param>
+    /// <param name="count"></param>
+    void fixViewsBeforeRemove(int start, int count)
+    {
+      int clearend = start + count - 1;
+      if (views != null)
+        foreach (HashedArrayList<T> view in views)
+        {
+          if (view == this)
+            continue;
+          int viewoffset = view.offset, viewend = viewoffset + view.size - 1;
+          if (start < viewoffset)
+          {
+            if (clearend < viewoffset)
+              view.offset = viewoffset - count;
+            else
+            {
+              view.offset = start;
+              view.size = clearend < viewend ? viewend - clearend : 0;
+            }
+          }
+          else if (start <= viewend)
+            view.size = clearend <= viewend ? view.size - count : start - viewoffset;
+        }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="otherOffset"></param>
+    /// <param name="otherSize"></param>
+    /// <returns>The position of View(otherOffset, otherSize) wrt. this view</returns>
+    MutualViewPosition viewPosition(int otherOffset, int otherSize)
+    {
+      int end = offset + size, otherEnd = otherOffset + otherSize;
+      if (otherOffset >= end || otherEnd <= offset)
+        return MutualViewPosition.NonOverlapping;
+      if (size == 0 || (otherOffset <= offset && end <= otherEnd))
+        return MutualViewPosition.Contains;
+      if (otherSize == 0 || (offset <= otherOffset && otherEnd <= end))
+        return MutualViewPosition.ContainedIn;
+      return MutualViewPosition.Overlapping;
+    }
+
+    //TODO: make version that fits the new, more forgiving rules for disposing
+    void disposeOverlappingViews(bool reverse)
+    {
+      if (views != null)
+        foreach (HashedArrayList<T> view in views)
+        {
+          if (view != this)
+          {
+            switch (viewPosition(view.offset, view.size))
+            {
+              case MutualViewPosition.ContainedIn:
+                if (reverse)
+                  view.offset = 2 * offset + size - view.size - view.offset;
+                else
+                  view.Dispose();
+                break;
+              case MutualViewPosition.Overlapping:
+                view.Dispose();
+                break;
+              case MutualViewPosition.Contains:
+              case MutualViewPosition.NonOverlapping:
+                break;
+            }
+          }
+        }
+    }
+    #endregion
+
+    #endregion
+
+    #region Position, PositionComparer and ViewHandler nested types
+    class PositionComparer : SCG.IComparer<Position>
+    {
+      public int Compare(Position a, Position b)
+      {
+        return a.index.CompareTo(b.index);
+      }
+    }
+    /// <summary>
+    /// During RemoveAll, we need to cache the original endpoint indices of views (??? also for HashedArrayList?)
+    /// </summary>
+    struct Position
+    {
+      public readonly HashedArrayList<T> view;
+      public readonly int index;
+      public Position(HashedArrayList<T> view, bool left)
+      {
+        this.view = view;
+        index = left ? view.offset : view.offset + view.size - 1;
+      }
+      public Position(int index) { this.index = index; view = null; }
+    }
+
+    /// <summary>
+    /// Handle the update of (other) views during a multi-remove operation.
+    /// </summary>
+    struct ViewHandler
+    {
+      HashedArrayList<Position> leftEnds;
+      HashedArrayList<Position> rightEnds;
+      int leftEndIndex, rightEndIndex;
+      internal readonly int viewCount;
+      internal ViewHandler(HashedArrayList<T> list)
+      {
+        leftEndIndex = rightEndIndex = viewCount = 0;
+        leftEnds = rightEnds = null;
+        if (list.views != null)
+          foreach (HashedArrayList<T> v in list.views)
+            if (v != list)
+            {
+              if (leftEnds == null)
+              {
+                leftEnds = new HashedArrayList<Position>();
+                rightEnds = new HashedArrayList<Position>();
+              }
+              leftEnds.Add(new Position(v, true));
+              rightEnds.Add(new Position(v, false));
+            }
+        if (leftEnds == null)
+          return;
+        viewCount = leftEnds.Count;
+        leftEnds.Sort(new PositionComparer());
+        rightEnds.Sort(new PositionComparer());
+      }
+      /// <summary>
+      /// This is to be called with realindex pointing to the first node to be removed after a (stretch of) node that was not removed
+      /// </summary>
+      /// <param name="removed"></param>
+      /// <param name="realindex"></param>
+      internal void skipEndpoints(int removed, int realindex)
+      {
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex < viewCount && (endpoint = leftEnds[leftEndIndex]).index <= realindex)
+          {
+            HashedArrayList<T> view = endpoint.view;
+            view.offset = view.offset - removed;
+            view.size += removed;
+            leftEndIndex++;
+          }
+          while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).index < realindex)
+          {
+            endpoint.view.size -= removed;
+            rightEndIndex++;
+          }
+        }
+      }
+      internal void updateViewSizesAndCounts(int removed, int realindex)
+      {
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex < viewCount && (endpoint = leftEnds[leftEndIndex]).index <= realindex)
+          {
+            HashedArrayList<T> view = endpoint.view;
+            view.offset = view.Offset - removed;
+            view.size += removed;
+            leftEndIndex++;
+          }
+          while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).index < realindex)
+          {
+            endpoint.view.size -= removed;
+            rightEndIndex++;
+          }
+        }
+      }
+    }
+    #endregion
+
+    #region Constructors
+    /// <summary>
+    /// Create an array list with default item equalityComparer and initial capacity 8 items.
+    /// </summary>
+    public HashedArrayList() : this(8) { }
+
+
+    /// <summary>
+    /// Create an array list with external item equalityComparer and initial capacity 8 items.
+    /// </summary>
+    /// <param name="itemequalityComparer">The external item equalityComparer</param>
+    public HashedArrayList(SCG.IEqualityComparer<T> itemequalityComparer) : this(8, itemequalityComparer) { }
+
+
+    /// <summary>
+    /// Create an array list with default item equalityComparer and prescribed initial capacity.
+    /// </summary>
+    /// <param name="capacity">The prescribed capacity</param>
+    public HashedArrayList(int capacity) : this(capacity, EqualityComparer<T>.Default) { }
+
+
+    /// <summary>
+    /// Create an array list with external item equalityComparer and prescribed initial capacity.
+    /// </summary>
+    /// <param name="capacity">The prescribed capacity</param>
+    /// <param name="itemequalityComparer">The external item equalityComparer</param>
+    public HashedArrayList(int capacity, SCG.IEqualityComparer<T> itemequalityComparer)
+      : base(capacity, itemequalityComparer)
+    {
+#if HASHINDEX
+      itemIndex = new HashSet<KeyValuePair<T, int>>(new KeyValuePairEqualityComparer<T, int>(itemequalityComparer));
+#endif
+    }
+
+    #endregion
+
+    #region IList<T> Members
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+    /// <value>The first item in this list.</value>
+    [Tested]
+    public virtual T First
+    {
+      [Tested]
+      get
+      {
+        validitycheck();
+        if (size == 0)
+          throw new NoSuchItemException();
+
+        return array[offset];
+      }
+    }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+    /// <value>The last item in this list.</value>
+    [Tested]
+    public virtual T Last
+    {
+      [Tested]
+      get
+      {
+        validitycheck();
+        if (size == 0)
+          throw new NoSuchItemException();
+
+        return array[offset + size - 1];
+      }
+    }
+
+
+    /// <summary>
+    /// Since <code>Add(T item)</code> always add at the end of the list,
+    /// this describes if list has FIFO or LIFO semantics.
+    /// </summary>
+    /// <value>True if the <code>Remove()</code> operation removes from the
+    /// start of the list, false if it removes from the end. The default for a new array list is false.</value>
+    [Tested]
+    public virtual bool FIFO
+    {
+      [Tested]
+      get { validitycheck(); return fIFO; }
+      [Tested]
+      set { updatecheck(); fIFO = value; }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public virtual bool IsFixedSize
+    {
+      get { validitycheck(); return false; }
+    }
+
+
+#if HASHINDEX
+    /// <summary>
+    /// On this list, this indexer is read/write.
+    /// </summary>
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or
+    /// &gt;= the size of the collection.</exception>
+    /// <exception cref="DuplicateNotAllowedException"> By the get operation
+    /// if the item already is present somewhere else in the list.</exception>
+    /// <value>The index'th item of this list.</value>
+    /// <param name="index">The index of the item to fetch or store.</param>
+#else
+    /// <summary>
+    /// On this list, this indexer is read/write.
+    /// </summary>
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or
+    /// &gt;= the size of the collection.</exception>
+    /// <value>The index'th item of this list.</value>
+    /// <param name="index">The index of the item to fetch or store.</param>
+#endif
+    [Tested]
+    public virtual T this[int index]
+    {
+      [Tested]
+      get
+      {
+        validitycheck();
+        if (index < 0 || index >= size)
+          throw new IndexOutOfRangeException();
+
+        return array[offset + index];
+      }
+      [Tested]
+      set
+      {
+        updatecheck();
+        if (index < 0 || index >= size)
+          throw new IndexOutOfRangeException();
+        index += offset;
+        T item = array[index];
+#if HASHINDEX
+        KeyValuePair<T, int> p = new KeyValuePair<T, int>(value, index);
+        if (itemequalityComparer.Equals(value, item))
+        {
+          array[index] = value;
+          itemIndex.Update(p);
+        }
+        else if (!itemIndex.FindOrAdd(ref p))
+        {
+          itemIndex.Remove(new KeyValuePair<T, int>(item));
+          array[index] = value;
+        }
+        else
+          throw new DuplicateNotAllowedException("Item already in indexed list");
+#else
+        array[index] = value;
+#endif
+        (underlying ?? this).raiseForSetThis(index, value, item);
+      }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual Speed IndexingSpeed { get { return Speed.Constant; } }
+
+#if HASHINDEX
+    /// <summary>
+    /// Insert an item at a specific index location in this list. 
+    ///</summary>
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or
+    /// &gt; the size of the collection. </exception>
+    /// <exception cref="DuplicateNotAllowedException"> 
+    /// If the item is already present in the list.</exception>
+    /// <param name="index">The index at which to insert.</param>
+    /// <param name="item">The item to insert.</param>
+#else
+    /// <summary>
+    /// Insert an item at a specific index location in this list. 
+    ///</summary>
+    /// <exception cref="IndexOutOfRangeException"> if i is negative or
+    /// &gt; the size of the collection. </exception>
+    /// <param name="index">The index at which to insert.</param>
+    /// <param name="item">The item to insert.</param>
+#endif
+    [Tested]
+    public virtual void Insert(int index, T item)
+    {
+      updatecheck();
+      if (index < 0 || index > size)
+        throw new IndexOutOfRangeException();
+
+      insert(index, item);
+      (underlying ?? this).raiseForInsert(index + offset, item);
+    }
+
+    /// <summary>
+    /// Insert an item at the end of a compatible view, used as a pointer.
+    /// <para>The <code>pointer</code> must be a view on the same list as
+    /// <code>this</code> and the endpoitn of <code>pointer</code> must be
+    /// a valid insertion point of <code>this</code></para>
+    /// </summary>
+    /// <exception cref="IncompatibleViewException">If <code>pointer</code> 
+    /// is not a view on or the same list as <code>this</code></exception>
+    /// <exception cref="IndexOutOfRangeException"><b>??????</b> if the endpoint of 
+    ///  <code>pointer</code> is not inside <code>this</code></exception>
+    /// <exception cref="DuplicateNotAllowedException"> if the list has
+    /// <code>AllowsDuplicates==false</code> and the item is 
+    /// already in the list.</exception>
+    /// <param name="pointer"></param>
+    /// <param name="item"></param>
+    public void Insert(IList<T> pointer, T item)
+    {
+      if ((pointer == null) || ((pointer.Underlying ?? pointer) != (underlying ?? this)))
+        throw new IncompatibleViewException();
+      Insert(pointer.Offset + pointer.Count - Offset, item);
+    }
+
+#if HASHINDEX
+    /// <summary>
+    /// Insert into this list all items from an enumerable collection starting 
+    /// at a particular index.
+    /// </summary>
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or
+    /// &gt; the size of the collection.</exception>
+    /// <exception cref="DuplicateNotAllowedException"> If <code>items</code> 
+    /// contains duplicates or some item already  present in the list.</exception>
+    /// <param name="index">Index to start inserting at</param>
+    /// <param name="items">Items to insert</param>
+#else
+    /// <summary>
+    /// Insert into this list all items from an enumerable collection starting 
+    /// at a particular index.
+    /// </summary>
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or
+    /// &gt; the size of the collection.</exception>
+    /// <param name="index">Index to start inserting at</param>
+    /// <param name="items">Items to insert</param>
+    /// <typeparam name="U"></typeparam>
+#endif
+    [Tested]
+    public virtual void InsertAll<U>(int index, SCG.IEnumerable<U> items) where U : T
+    {
+      updatecheck();
+      if (index < 0 || index > size)
+        throw new IndexOutOfRangeException();
+      index += offset;
+      int toadd = EnumerableBase<U>.countItems(items);
+      if (toadd == 0)
+        return;
+      if (toadd + underlyingsize > array.Length)
+        expand(toadd + underlyingsize, underlyingsize);
+      if (underlyingsize > index)
+        Array.Copy(array, index, array, index + toadd, underlyingsize - index);
+      int i = index;
+      try
+      {
+
+        foreach (T item in items)
+        {
+#if HASHINDEX
+          KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, i);
+          if (itemIndex.FindOrAdd(ref p))
+            throw new DuplicateNotAllowedException("Item already in indexed list");
+#endif
+          array[i++] = item;
+        }
+      }
+      finally
+      {
+        int added = i - index;
+        if (added < toadd)
+        {
+          Array.Copy(array, index + toadd, array, i, underlyingsize - index);
+          Array.Clear(array, underlyingsize + added, toadd - added);
+        }
+        if (added > 0)
+        {
+          addtosize(added);
+#if HASHINDEX
+          reindex(i);
+#endif
+          fixViewsAfterInsert(added, index);
+          (underlying ?? this).raiseForInsertAll(index, added);
+        }
+      }
+    }
+    private void raiseForInsertAll(int index, int added)
+    {
+      if (ActiveEvents != 0)
+      {
+        if ((ActiveEvents & (EventTypeEnum.Added | EventTypeEnum.Inserted)) != 0)
+          for (int j = index; j < index + added; j++)
+          {
+            raiseItemInserted(array[j], j);
+            raiseItemsAdded(array[j], 1);
+          }
+        raiseCollectionChanged();
+      }
+    }
+
+#if HASHINDEX
+    /// <summary>
+    /// Insert an item at the front of this list;
+    /// </summary>
+    /// <exception cref="DuplicateNotAllowedException">If the item is already in the list</exception>
+    /// <param name="item">The item to insert.</param>
+#else
+    /// <summary>
+    /// Insert an item at the front of this list;
+    /// </summary>
+    /// <param name="item">The item to insert.</param>
+#endif
+    [Tested]
+    public virtual void InsertFirst(T item)
+    {
+      updatecheck();
+      insert(0, item);
+      (underlying ?? this).raiseForInsert(offset, item);
+    }
+
+
+#if HASHINDEX
+    /// <summary>
+    /// Insert an item at the back of this list.
+    /// </summary>
+    /// <exception cref="DuplicateNotAllowedException">If the item is already in the list</exception>
+    /// <param name="item">The item to insert.</param>
+#else
+    /// <summary>
+    /// Insert an item at the back of this list.
+    /// </summary>
+    /// <param name="item">The item to insert.</param>
+#endif
+    [Tested]
+    public virtual void InsertLast(T item)
+    {
+      updatecheck();
+      insert(size, item);
+      (underlying ?? this).raiseForInsert(size - 1 + offset, item);
+    }
+
+
+    //NOTE: if the filter throws an exception, no result will be returned.
+    /// <summary>
+    /// Create a new list consisting of the items of this list satisfying a 
+    /// certain predicate.
+    /// <para>The new list will be of type HashedArrayList</para>
+    /// </summary>
+    /// <param name="filter">The filter delegate defining the predicate.</param>
+    /// <returns>The new list.</returns>
+    [Tested]
+    public virtual IList<T> FindAll(Fun<T, bool> filter)
+    {
+      validitycheck();
+      int stamp = this.stamp;
+      HashedArrayList<T> res = new HashedArrayList<T>(itemequalityComparer);
+      int j = 0, rescap = res.array.Length;
+      for (int i = 0; i < size; i++)
+      {
+        T a = array[offset + i];
+        bool found = filter(a);
+        modifycheck(stamp);
+        if (found)
+        {
+          if (j == rescap) res.expand(rescap = 2 * rescap, j);
+          res.array[j++] = a;
+        }
+      }
+      res.size = j;
+#if HASHINDEX
+      res.reindex(0);
+#endif
+      return res;
+    }
+
+
+#if HASHINDEX
+    /// <summary>
+    /// Create a new list consisting of the results of mapping all items of this
+    /// list. The new list will use the default item equalityComparer for the item type V.
+    /// <para>The new list will be of type HashedArrayList</para>
+    /// </summary>
+    /// <exception cref="DuplicateNotAllowedException">If <code>mapper</code>
+    /// creates duplicates</exception>
+    /// <typeparam name="V">The type of items of the new list</typeparam>
+    /// <param name="mapper">The delegate defining the map.</param>
+    /// <returns>The new list.</returns>
+#else
+    /// <summary>
+    /// Create a new list consisting of the results of mapping all items of this
+    /// list. The new list will use the default item equalityComparer for the item type V.
+    /// <para>The new list will be of type HashedArrayList</para>
+    /// </summary>
+    /// <typeparam name="V">The type of items of the new list</typeparam>
+    /// <param name="mapper">The delegate defining the map.</param>
+    /// <returns>The new list.</returns>
+#endif
+    [Tested]
+    public virtual IList<V> Map<V>(Fun<T, V> mapper)
+    {
+      validitycheck();
+
+      HashedArrayList<V> res = new HashedArrayList<V>(size);
+
+      return map<V>(mapper, res);
+    }
+
+#if HASHINDEX
+    /// <summary>
+    /// Create a new list consisting of the results of mapping all items of this
+    /// list. The new list will use a specified item equalityComparer for the item type.
+    /// <para>The new list will be of type HashedArrayList</para>
+    /// </summary>
+    /// <exception cref="DuplicateNotAllowedException">If <code>mapper</code>
+    /// creates duplicates</exception>
+    /// <typeparam name="V">The type of items of the new list</typeparam>
+    /// <param name="mapper">The delegate defining the map.</param>
+    /// <param name="itemequalityComparer">The item equalityComparer to use for the new list</param>
+    /// <returns>The new list.</returns>
+#else
+    /// <summary>
+    /// Create a new list consisting of the results of mapping all items of this
+    /// list. The new list will use a specified item equalityComparer for the item type.
+    /// <para>The new list will be of type HashedArrayList</para>
+    /// </summary>
+    /// <typeparam name="V">The type of items of the new list</typeparam>
+    /// <param name="mapper">The delegate defining the map.</param>
+    /// <param name="itemequalityComparer">The item equalityComparer to use for the new list</param>
+    /// <returns>The new list.</returns>
+#endif
+    public virtual IList<V> Map<V>(Fun<T, V> mapper, SCG.IEqualityComparer<V> itemequalityComparer)
+    {
+      validitycheck();
+
+      HashedArrayList<V> res = new HashedArrayList<V>(size, itemequalityComparer);
+
+      return map<V>(mapper, res);
+    }
+
+    private IList<V> map<V>(Fun<T, V> mapper, HashedArrayList<V> res)
+    {
+      int stamp = this.stamp;
+      if (size > 0)
+        for (int i = 0; i < size; i++)
+        {
+          V mappeditem = mapper(array[offset + i]);
+          modifycheck(stamp);
+#if HASHINDEX
+          KeyValuePair<V, int> p = new KeyValuePair<V, int>(mappeditem, i);
+          if (res.itemIndex.FindOrAdd(ref p))
+            throw new ArgumentException("Mapped item already in indexed list");
+#endif
+          res.array[i] = mappeditem;
+        }
+      res.size = size;
+      return res;
+    }
+
+    /// <summary>
+    /// Remove one item from the list: from the front if <code>FIFO</code>
+    /// is true, else from the back.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public virtual T Remove()
+    {
+      updatecheck();
+      if (size == 0)
+        throw new NoSuchItemException("List is empty");
+
+      T item = removeAt(fIFO ? 0 : size - 1);
+      (underlying ?? this).raiseForRemove(item);
+      return item;
+    }
+
+    /// <summary>
+    /// Remove one item from the fromnt of the list.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public virtual T RemoveFirst()
+    {
+      updatecheck();
+      if (size == 0)
+        throw new NoSuchItemException("List is empty");
+
+      T item = removeAt(0);
+      (underlying ?? this).raiseForRemoveAt(offset, item);
+      return item;
+    }
+
+
+    /// <summary>
+    /// Remove one item from the back of the list.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public virtual T RemoveLast()
+    {
+      updatecheck();
+      if (size == 0)
+        throw new NoSuchItemException("List is empty");
+
+      T item = removeAt(size - 1);
+      (underlying ?? this).raiseForRemoveAt(size + offset, item);
+      return item;
+    }
+
+    /// <summary>
+    /// Create a list view on this list. 
+    /// </summary>
+    /// <exception cref="ArgumentOutOfRangeException"> if the start or count is negative
+    /// or the range does not fit within list.</exception>
+    /// <param name="start">The index in this list of the start of the view.</param>
+    /// <param name="count">The size of the view.</param>
+    /// <returns>The new list view.</returns>
+    [Tested]
+    public virtual IList<T> View(int start, int count)
+    {
+      validitycheck();
+      checkRange(start, count);
+      if (views == null)
+        views = new WeakViewList<HashedArrayList<T>>();
+      HashedArrayList<T> retval = (HashedArrayList<T>)MemberwiseClone();
+
+
+      retval.underlying = underlying != null ? underlying : this;
+      retval.offset = start + offset;
+      retval.size = count;
+      retval.myWeakReference = views.Add(retval);
+      return retval;
+    }
+
+    /// <summary>
+    /// Create a list view on this list containing the (first) occurrence of a particular item.
+    /// <para>Returns <code>null</code> if the item is not in this list.</para>
+    /// </summary>
+    /// <param name="item">The item to find.</param>
+    /// <returns>The new list view.</returns>
+    [Tested]
+    public virtual IList<T> ViewOf(T item)
+    {
+      int index = indexOf(item);
+      if (index < 0)
+        return null;
+      return View(index, 1);
+    }
+
+
+    /// <summary>
+    /// Create a list view on this list containing the last occurrence of a particular item. 
+    /// <para>Returns <code>null</code> if the item is not in this list.</para>
+    /// </summary>
+    /// <param name="item">The item to find.</param>
+    /// <returns>The new list view.</returns>
+    [Tested]
+    public virtual IList<T> LastViewOf(T item)
+    {
+      int index = lastIndexOf(item);
+      if (index < 0)
+        return null;
+      return View(index, 1);
+    }
+
+    /// <summary>
+    /// Null if this list is not a view.
+    /// </summary>
+    /// <value>Underlying list for view.</value>
+    [Tested]
+    public virtual IList<T> Underlying { [Tested]get { return underlying; } }
+
+
+    /// <summary>
+    /// </summary>
+    /// <value>Offset for this list view or 0 for an underlying list.</value>
+    [Tested]
+    public virtual int Offset { [Tested]get { return offset; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual bool IsValid { get { return isValid; } }
+
+    /// <summary>
+    /// Slide this list view along the underlying list.
+    /// </summary>
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>
+    /// <exception cref="ArgumentOutOfRangeException"> if the operation
+    /// would bring either end of the view outside the underlying list.</exception>
+    /// <param name="offset">The signed amount to slide: positive to slide
+    /// towards the end.</param>
+    [Tested]
+    public virtual IList<T> Slide(int offset)
+    {
+      if (!TrySlide(offset, size))
+        throw new ArgumentOutOfRangeException();
+      return this;
+    }
+
+
+    /// <summary>
+    /// Slide this list view along the underlying list, changing its size.
+    /// </summary>
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>
+    /// <exception cref="ArgumentOutOfRangeException"> if the operation
+    /// would bring either end of the view outside the underlying list.</exception>
+    /// <param name="offset">The signed amount to slide: positive to slide
+    /// towards the end.</param>
+    /// <param name="size">The new size of the view.</param>
+    [Tested]
+    public virtual IList<T> Slide(int offset, int size)
+    {
+      if (!TrySlide(offset, size))
+        throw new ArgumentOutOfRangeException();
+      return this;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>
+    /// <param name="offset"></param>
+    /// <returns></returns>
+    [Tested]
+    public virtual bool TrySlide(int offset)
+    {
+      return TrySlide(offset, size);
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>
+    /// <param name="offset"></param>
+    /// <param name="size"></param>
+    /// <returns></returns>
+    [Tested]
+    public virtual bool TrySlide(int offset, int size)
+    {
+      updatecheck();
+      if (underlying == null)
+        throw new NotAViewException("Not a view");
+
+      int newoffset = this.offset + offset;
+      int newsize = size;
+
+      if (newoffset < 0 || newsize < 0 || newoffset + newsize > underlyingsize)
+        return false;
+
+      this.offset = newoffset;
+      this.size = newsize;
+      return true;
+    }
+
+    /// <summary>
+    /// 
+    /// <para>Returns null if <code>otherView</code> is strictly to the left of this view</para>
+    /// </summary>
+    /// <param name="otherView"></param>
+    /// <exception cref="IncompatibleViewException">If otherView does not have the same underlying list as this</exception>
+    /// <returns></returns>
+    public virtual IList<T> Span(IList<T> otherView)
+    {
+      if ((otherView == null) || ((otherView.Underlying ?? otherView) != (underlying ?? this)))
+        throw new IncompatibleViewException();
+      if (otherView.Offset + otherView.Count - Offset < 0)
+        return null;
+      return (underlying ?? this).View(Offset, otherView.Offset + otherView.Count - Offset);
+    }
+
+    /// <summary>
+    /// Reverst the list so the items are in the opposite sequence order.
+    /// </summary>
+    [Tested]
+    public virtual void Reverse()
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      for (int i = 0, length = size / 2, end = offset + size - 1; i < length; i++)
+      {
+        T swap = array[offset + i];
+
+        array[offset + i] = array[end - i];
+        array[end - i] = swap;
+      }
+#if HASHINDEX
+      reindex(offset, offset + size);
+#endif
+      //TODO: be more forgiving wrt. disposing
+      disposeOverlappingViews(true);
+      (underlying ?? this).raiseCollectionChanged();
+    }
+
+    /// <summary>
+    /// Check if this list is sorted according to the default sorting order
+    /// for the item type T, as defined by the <see cref="T:C5.Comparer`1"/> class 
+    /// </summary>
+    /// <exception cref="NotComparableException">if T is not comparable</exception>
+    /// <returns>True if the list is sorted, else false.</returns>
+    [Tested]
+    public bool IsSorted() { return IsSorted(Comparer<T>.Default); }
+
+    /// <summary>
+    /// Check if this list is sorted according to a specific sorting order.
+    /// </summary>
+    /// <param name="c">The comparer defining the sorting order.</param>
+    /// <returns>True if the list is sorted, else false.</returns>
+    [Tested]
+    public virtual bool IsSorted(SCG.IComparer<T> c)
+    {
+      validitycheck();
+      for (int i = offset + 1, end = offset + size; i < end; i++)
+        if (c.Compare(array[i - 1], array[i]) > 0)
+          return false;
+
+      return true;
+    }
+
+    /// <summary>
+    /// Sort the items of the list according to the default sorting order
+    /// for the item type T, as defined by the Comparer[T] class 
+    /// (<see cref="T:C5.Comparer`1"/>).
+    /// </summary>
+    /// <exception cref="InvalidOperationException">if T is not comparable</exception>
+    public virtual void Sort()
+    {
+      Sort(Comparer<T>.Default);
+    }
+
+
+    /// <summary>
+    /// Sort the items of the list according to a specific sorting order.
+    /// </summary>
+    /// <param name="comparer">The comparer defining the sorting order.</param>
+    [Tested]
+    public virtual void Sort(SCG.IComparer<T> comparer)
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      Sorting.IntroSort<T>(array, offset, size, comparer);
+      disposeOverlappingViews(false);
+#if HASHINDEX
+      reindex(offset, offset + size);
+#endif
+      (underlying ?? this).raiseCollectionChanged();
+    }
+
+
+    /// <summary>
+    /// Randomly shuffle the items of this list. 
+    /// </summary>
+    public virtual void Shuffle() { Shuffle(new C5Random()); }
+
+
+    /// <summary>
+    /// Shuffle the items of this list according to a specific random source.
+    /// </summary>
+    /// <param name="rnd">The random source.</param>
+    public virtual void Shuffle(Random rnd)
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      for (int i = offset, top = offset + size, end = top - 1; i < end; i++)
+      {
+        int j = rnd.Next(i, top);
+        if (j != i)
+        {
+          T tmp = array[i];
+          array[i] = array[j];
+          array[j] = tmp;
+        }
+      }
+      disposeOverlappingViews(false);
+#if HASHINDEX
+      reindex(offset, offset + size);
+#endif
+      (underlying ?? this).raiseCollectionChanged();
+    }
+    #endregion
+
+    #region IIndexed<T> Members
+
+    /// <summary>
+    /// Search for an item in the list going forwrds from the start.
+    /// </summary>
+    /// <param name="item">Item to search for.</param>
+    /// <returns>Index of item from start.</returns>
+    [Tested]
+    public virtual int IndexOf(T item) { validitycheck(); return indexOf(item); }
+
+
+    /// <summary>
+    /// Search for an item in the list going backwords from the end.
+    /// </summary>
+    /// <param name="item">Item to search for.</param>
+    /// <returns>Index of item from the end.</returns>
+    [Tested]
+    public virtual int LastIndexOf(T item) { validitycheck(); return lastIndexOf(item); }
+
+
+    /// <summary>
+    /// Remove the item at a specific position of the list.
+    /// </summary>
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or
+    /// &gt;= the size of the collection.</exception>
+    /// <param name="index">The index of the item to remove.</param>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public virtual T RemoveAt(int index)
+    {
+      updatecheck();
+      if (index < 0 || index >= size)
+        throw new IndexOutOfRangeException("Index out of range for sequenced collection");
+
+      T item = removeAt(index);
+      (underlying ?? this).raiseForRemoveAt(offset + index, item);
+      return item;
+    }
+
+
+    /// <summary>
+    /// Remove all items in an index interval.
+    /// </summary>
+    /// <exception cref="ArgumentOutOfRangeException">If <code>start</code>
+    /// and <code>count</code> does not describe a valid interval in the list</exception> 
+    /// <param name="start">The index of the first item to remove.</param>
+    /// <param name="count">The number of items to remove.</param>
+    [Tested]
+    public virtual void RemoveInterval(int start, int count)
+    {
+      updatecheck();
+      if (count == 0)
+        return;
+      checkRange(start, count);
+      start += offset;
+      fixViewsBeforeRemove(start, count);
+#if HASHINDEX
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>();
+      for (int i = start, end = start + count; i < end; i++)
+      {
+        p.Key = array[i];
+        itemIndex.Remove(p);
+      }
+#endif
+      Array.Copy(array, start + count, array, start, underlyingsize - start - count);
+      addtosize(-count);
+      Array.Clear(array, underlyingsize, count);
+#if HASHINDEX
+      reindex(start);
+#endif
+      (underlying ?? this).raiseForRemoveInterval(start, count);
+    }
+    void raiseForRemoveInterval(int start, int count)
+    {
+      if (ActiveEvents != 0)
+      {
+        raiseCollectionCleared(size == 0, count, start);
+        raiseCollectionChanged();
+      }
+    }
+    #endregion
+
+    #region ICollection<T> Members
+
+    /// <summary>
+    /// The value is symbolic indicating the type of asymptotic complexity
+    /// in terms of the size of this collection (worst-case or amortized as
+    /// relevant).
+    /// </summary>
+    /// <value>Speed.Linear</value>
+    [Tested]
+    public virtual Speed ContainsSpeed
+    {
+      [Tested]
+      get
+      {
+#if HASHINDEX
+        return Speed.Constant;
+#else
+        return Speed.Linear;
+#endif
+      }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    [Tested]
+    public override int GetUnsequencedHashCode()
+    { validitycheck(); return base.GetUnsequencedHashCode(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="that"></param>
+    /// <returns></returns>
+    [Tested]
+    public override bool UnsequencedEquals(ICollection<T> that)
+    { validitycheck(); return base.UnsequencedEquals(that); }
+
+    /// <summary>
+    /// Check if this collection contains (an item equivalent to according to the
+    /// itemequalityComparer) a particular value.
+    /// </summary>
+    /// <param name="item">The value to check for.</param>
+    /// <returns>True if the items is in this collection.</returns>
+    [Tested]
+    public virtual bool Contains(T item)
+    { validitycheck(); return indexOf(item) >= 0; }
+
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, return in the ref argument (a
+    /// binary copy of) the actual value found.
+    /// </summary>
+    /// <param name="item">The value to look for.</param>
+    /// <returns>True if the items is in this collection.</returns>
+    [Tested]
+    public virtual bool Find(ref T item)
+    {
+      validitycheck();
+
+      int i;
+
+      if ((i = indexOf(item)) >= 0)
+      {
+        item = array[offset + i];
+        return true;
+      }
+
+      return false;
+    }
+
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// to with a binary copy of the supplied value. This will only update the first 
+    /// mathching item.
+    /// </summary>
+    /// <param name="item">Value to update.</param>
+    /// <returns>True if the item was found and hence updated.</returns>
+    [Tested]
+    public virtual bool Update(T item)
+    {
+      T olditem;
+      return Update(item, out olditem);
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public virtual bool Update(T item, out T olditem)
+    {
+      updatecheck();
+      int i;
+
+      if ((i = indexOf(item)) >= 0)
+      {
+        olditem = array[offset + i];
+        array[offset + i] = item;
+#if HASHINDEX
+        itemIndex.Update(new KeyValuePair<T, int>(item, offset + i));
+#endif
+        (underlying ?? this).raiseForUpdate(item, olditem);
+        return true;
+      }
+
+      olditem = default(T);
+      return false;
+    }
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, return in the ref argument (a
+    /// binary copy of) the actual value found. Else, add the item to the collection.
+    /// </summary>
+    /// <param name="item">The value to look for.</param>
+    /// <returns>True if the item was found (hence not added).</returns>
+    [Tested]
+    public virtual bool FindOrAdd(ref T item)
+    {
+      updatecheck();
+      if (Find(ref item))
+        return true;
+
+      Add(item);
+      return false;
+    }
+
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// to with a binary copy of the supplied value. This will only update the first 
+    /// mathching item.
+    /// </summary>
+    /// <param name="item">Value to update.</param>
+    /// <returns>True if the item was found and hence updated.</returns>
+    [Tested]
+    public virtual bool UpdateOrAdd(T item)
+    {
+      updatecheck();
+      if (Update(item))
+        return true;
+
+      Add(item);
+      return false;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public virtual bool UpdateOrAdd(T item, out T olditem)
+    {
+      updatecheck();
+      if (Update(item, out olditem))
+        return true;
+
+      Add(item);
+      olditem = default(T);
+      return false;
+    }
+
+    /// <summary>
+    /// Remove a particular item from this list. The item will be searched 
+    /// for from the end of the list if <code>FIFO == false</code> (the default), 
+    /// else from the start.
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    /// <returns>True if the item was found (and removed).</returns>
+    [Tested]
+    public virtual bool Remove(T item)
+    {
+      updatecheck();
+
+      int i = fIFO ? indexOf(item) : lastIndexOf(item);
+
+      if (i < 0)
+        return false;
+
+      T removeditem = removeAt(i);
+      (underlying ?? this).raiseForRemove(removeditem);
+      return true;
+    }
+
+
+    /// <summary>
+    /// Remove the first copy of a particular item from this collection if found.
+    /// If an item was removed, report a binary copy of the actual item removed in 
+    /// the argument. The item will be searched 
+    /// for from the end of the list if <code>FIFO == false</code> (the default), 
+    /// else from the start.
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    /// <param name="removeditem">The removed value.</param>
+    /// <returns>True if the item was found (and removed).</returns>
+    [Tested]
+    public virtual bool Remove(T item, out T removeditem)
+    {
+      updatecheck();
+
+      int i = fIFO ? indexOf(item) : lastIndexOf(item);
+
+      if (i < 0)
+      {
+        removeditem = default(T);
+        return false;
+      }
+
+      removeditem = removeAt(i);
+      (underlying ?? this).raiseForRemove(removeditem);
+      return true;
+    }
+
+
+    //TODO: remove from end or according to FIFO?
+    /// <summary>
+    /// Remove all items in another collection from this one, taking multiplicities into account.
+    /// Matching items will be removed from the front. Current implementation is not optimal.
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to remove.</param>
+    [Tested]
+    public virtual void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      //TODO: reactivate the old code for small sizes
+      HashBag<T> toremove = new HashBag<T>(itemequalityComparer);
+      toremove.AddAll(items);
+      if (toremove.Count == 0)
+        return;
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+      ViewHandler viewHandler = new ViewHandler(this);
+      int j = offset;
+      int removed = 0;
+      int i = offset, end = offset + size;
+#if HASHINDEX
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>();
+#endif
+      while (i < end)
+      {
+        T item;
+        //pass by a stretch of nodes
+        while (i < end && !toremove.Contains(item = array[i]))
+        {
+#if HASHINDEX
+          if (j < i)
+          {
+            p.Key = item;
+            p.Value = j;
+            itemIndex.Update(p);
+          }
+#endif
+          //if (j<i)
+          array[j] = item;
+          i++; j++;
+        }
+        viewHandler.skipEndpoints(removed, i);
+        //Remove a stretch of nodes
+        while (i < end && toremove.Remove(item = array[i]))
+        {
+#if HASHINDEX
+          p.Key = item;
+          itemIndex.Remove(p);
+#endif
+          if (mustFire)
+            raiseHandler.Remove(item);
+          removed++;
+          i++;
+          viewHandler.updateViewSizesAndCounts(removed, i);
+        }
+      }
+      if (removed == 0)
+        return;
+      viewHandler.updateViewSizesAndCounts(removed, underlyingsize);
+      Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);
+      addtosize(-removed);
+      Array.Clear(array, underlyingsize, removed);
+#if HASHINDEX
+      reindex(j);
+#endif
+      if (mustFire)
+        raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="predicate"></param>
+    void RemoveAll(Fun<T, bool> predicate)
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+      ViewHandler viewHandler = new ViewHandler(this);
+      int j = offset;
+      int removed = 0;
+      int i = offset, end = offset + size;
+#if HASHINDEX
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>();
+#endif
+      while (i < end)
+      {
+        T item;
+        //pass by a stretch of nodes
+        while (i < end && !predicate(item = array[i]))
+        {
+          updatecheck();
+#if HASHINDEX
+          if (j < i)
+          {
+            p.Key = item;
+            p.Value = j;
+            itemIndex.Update(p);
+          }
+#endif
+          //if (j<i)
+          array[j] = item;
+          i++; j++;
+        }
+        updatecheck();
+        viewHandler.skipEndpoints(removed, i);
+        //Remove a stretch of nodes
+        while (i < end && predicate(item = array[i]))
+        {
+          updatecheck();
+#if HASHINDEX
+          p.Key = item;
+          itemIndex.Remove(p);
+#endif
+          if (mustFire)
+            raiseHandler.Remove(item);
+          removed++;
+          i++;
+          viewHandler.updateViewSizesAndCounts(removed, i);
+        }
+        updatecheck();
+      }
+      if (removed == 0)
+        return;
+      viewHandler.updateViewSizesAndCounts(removed, underlyingsize);
+      Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);
+      addtosize(-removed);
+      Array.Clear(array, underlyingsize, removed);
+#if HASHINDEX
+      reindex(j);
+#endif
+      if (mustFire)
+        raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// Remove all items from this collection, resetting internal array size.
+    /// </summary>
+    [Tested]
+    public override void Clear()
+    {
+      if (underlying == null)
+      {
+        updatecheck();
+        if (size == 0)
+          return;
+        int oldsize = size;
+        fixViewsBeforeRemove(0, size);
+#if HASHINDEX
+        itemIndex.Clear();
+#endif
+        array = new T[8];
+        size = 0;
+        (underlying ?? this).raiseForRemoveInterval(offset, oldsize);
+      }
+      else
+        RemoveInterval(0, size);
+    }
+
+    /// <summary>
+    /// Remove all items not in some other collection from this one, taking multiplicities into account.
+    /// Items are retained front first.  
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to retain.</param>
+    [Tested]
+    public virtual void RetainAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      HashBag<T> toretain = new HashBag<T>(itemequalityComparer);
+      toretain.AddAll(items);
+      if (toretain.Count == 0)
+      {
+        Clear();
+        return;
+      }
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+      ViewHandler viewHandler = new ViewHandler(this);
+      int j = offset;
+      int removed = 0;
+      int i = offset, end = offset + size;
+#if HASHINDEX
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>();
+#endif
+      while (i < end)
+      {
+        T item;
+        //pass by a stretch of nodes
+        while (i < end && toretain.Remove(item = array[i]))
+        {
+#if HASHINDEX
+          if (j < i)
+          {
+            p.Key = item;
+            p.Value = j;
+            itemIndex.Update(p);
+          }
+#endif
+          //if (j<i)
+          array[j] = item;
+          i++; j++;
+        }
+        viewHandler.skipEndpoints(removed, i);
+        //Remove a stretch of nodes
+        while (i < end && !toretain.Contains(item = array[i]))
+        {
+#if HASHINDEX
+          p.Key = item;
+          itemIndex.Remove(p);
+#endif
+          if (mustFire)
+            raiseHandler.Remove(item);
+          removed++;
+          i++;
+          viewHandler.updateViewSizesAndCounts(removed, i);
+        }
+      }
+      if (removed == 0)
+        return;
+      viewHandler.updateViewSizesAndCounts(removed, underlyingsize);
+      Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);
+      addtosize(-removed);
+      Array.Clear(array, underlyingsize, removed);
+#if HASHINDEX
+      reindex(j);
+#endif
+      raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="predicate"></param>
+    void RetainAll(Fun<T, bool> predicate)
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+      ViewHandler viewHandler = new ViewHandler(this);
+      int j = offset;
+      int removed = 0;
+      int i = offset, end = offset + size;
+#if HASHINDEX
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>();
+#endif
+      while (i < end)
+      {
+        T item;
+        //pass by a stretch of nodes
+        while (i < end && predicate(item = array[i]))
+        {
+          updatecheck();
+#if HASHINDEX
+          if (j < i)
+          {
+            p.Key = item;
+            p.Value = j;
+            itemIndex.Update(p);
+          }
+#endif
+          //if (j<i)
+          array[j] = item;
+          i++; j++;
+        }
+        updatecheck();
+        viewHandler.skipEndpoints(removed, i);
+        //Remove a stretch of nodes
+        while (i < end && !predicate(item = array[i]))
+        {
+          updatecheck();
+#if HASHINDEX
+          p.Key = item;
+          itemIndex.Remove(p);
+#endif
+          if (mustFire)
+            raiseHandler.Remove(item);
+          removed++;
+          i++;
+          viewHandler.updateViewSizesAndCounts(removed, i);
+        }
+        updatecheck();
+      }
+      if (removed == 0)
+        return;
+      viewHandler.updateViewSizesAndCounts(removed, underlyingsize);
+      Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);
+      addtosize(-removed);
+      Array.Clear(array, underlyingsize, removed);
+#if HASHINDEX
+      reindex(j);
+#endif
+      raiseHandler.Raise();
+    }
+
+
+    /// <summary>
+    /// Check if this collection contains all the values in another collection,
+    /// taking multiplicities into account.
+    /// Current implementation is not optimal.
+    /// </summary>
+    /// <param name="items">The </param>
+    /// <typeparam name="U"></typeparam>
+    /// <returns>True if all values in <code>items</code>is in this collection.</returns>
+    [Tested]
+    public virtual bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      validitycheck();
+#if HASHINDEX
+      foreach (T item in items)
+        if (indexOf(item) < 0)
+          return false;
+
+      return true;
+#else
+      //TODO: use aux hash bag to obtain linear time procedure
+      HashBag<T> tomatch = new HashBag<T>(itemequalityComparer);
+      tomatch.AddAll(items);
+      if (tomatch.Count == 0)
+        return true;
+      for (int i = offset, end = offset + size; i < end; i++)
+      {
+        tomatch.Remove(array[i]);
+        if (tomatch.Count == 0)
+          return true;
+      }
+      return false;
+#endif
+    }
+
+
+    /// <summary>
+    /// Count the number of items of the collection equal to a particular value.
+    /// Returns 0 if and only if the value is not in the collection.
+    /// </summary>
+    /// <param name="item">The value to count.</param>
+    /// <returns>The number of copies found.</returns>
+    [Tested]
+    public virtual int ContainsCount(T item)
+    {
+      validitycheck();
+#if HASHINDEX
+      return indexOf(item) >= 0 ? 1 : 0;
+#else
+      int count = 0;
+      for (int i = 0; i < size; i++)
+        if (equals(item, array[offset + i]))
+          count++;
+      return count;
+#endif
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<T> UniqueItems()
+    {
+#if HASHINDEX
+      return this;
+#else
+      HashBag<T> hashbag = new HashBag<T>(itemequalityComparer);
+      hashbag.AddAll(this);
+      return hashbag.UniqueItems();
+#endif
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities()
+    {
+#if HASHINDEX
+      return new MultiplicityOne<T>(this);
+#else
+      HashBag<T> hashbag = new HashBag<T>(itemequalityComparer);
+      hashbag.AddAll(this);
+      return hashbag.ItemMultiplicities();
+#endif
+    }
+
+
+
+
+
+    /// <summary>
+    /// Remove all items equal to a given one.
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    [Tested]
+    public virtual void RemoveAllCopies(T item)
+    {
+#if HASHINDEX
+      Remove(item);
+#else
+      updatecheck();
+      if (size == 0)
+        return;
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+      ViewHandler viewHandler = new ViewHandler(this);
+      int j = offset;
+      int removed = 0;
+      int i = offset, end = offset + size;
+      while (i < end)
+      {
+        //pass by a stretch of nodes
+        while (i < end && !equals(item, array[i]))
+          array[j++] = array[i++];
+        viewHandler.skipEndpoints(removed, i);
+        //Remove a stretch of nodes
+        while (i < end && equals(item, array[i]))
+        {
+          if (mustFire)
+            raiseHandler.Remove(array[i]);
+          removed++;
+          i++;
+          viewHandler.updateViewSizesAndCounts(removed, i);
+        }
+      }
+      if (removed == 0)
+        return;
+      viewHandler.updateViewSizesAndCounts(removed, underlyingsize);
+      Array.Copy(array, offset + size, array, j, underlyingsize - offset - size);
+      addtosize(-removed);
+      Array.Clear(array, underlyingsize, removed);
+      raiseHandler.Raise();
+#endif
+    }
+
+
+    //TODO: check views
+    /// <summary>
+    /// Check the integrity of the internal data structures of this array list.
+    /// </summary>
+    /// <returns>True if check does not fail.</returns>
+    [Tested]
+    public override bool Check()
+    {
+      bool retval = true;
+
+      if (underlyingsize > array.Length)
+      {
+        Console.WriteLine("underlyingsize ({0}) > array.Length ({1})", size, array.Length);
+        return false;
+      }
+
+      if (offset + size > underlyingsize)
+      {
+        Console.WriteLine("offset({0})+size({1}) > underlyingsize ({2})", offset, size, underlyingsize);
+        return false;
+      }
+
+      if (offset < 0)
+      {
+        Console.WriteLine("offset({0}) < 0", offset);
+        return false;
+      }
+
+      for (int i = 0; i < underlyingsize; i++)
+      {
+        if ((object)(array[i]) == null)
+        {
+          Console.WriteLine("Bad element: null at (base)index {0}", i);
+          retval = false;
+        }
+      }
+
+      for (int i = underlyingsize, length = array.Length; i < length; i++)
+      {
+        if (!equals(array[i], default(T)))
+        {
+          Console.WriteLine("Bad element: != default(T) at (base)index {0}", i);
+          retval = false;
+        }
+      }
+
+      {
+        HashedArrayList<T> u = underlying ?? this;
+        if (u.views != null)
+          foreach (HashedArrayList<T> v in u.views)
+          {
+            if (u.array != v.array)
+            {
+              Console.WriteLine("View from {0} of length has different base array than the underlying list", v.offset, v.size);
+              retval = false;
+            }
+          }
+      }
+
+
+#if HASHINDEX
+      if (underlyingsize != itemIndex.Count)
+      {
+        Console.WriteLine("size ({0})!= index.Count ({1})", size, itemIndex.Count);
+        retval = false;
+      }
+
+      for (int i = 0; i < underlyingsize; i++)
+      {
+        KeyValuePair<T, int> p = new KeyValuePair<T, int>(array[i]);
+
+        if (!itemIndex.Find(ref p))
+        {
+          Console.WriteLine("Item {1} at {0} not in hashindex", i, array[i]);
+          retval = false;
+        }
+
+        if (p.Value != i)
+        {
+          Console.WriteLine("Item {1} at {0} has hashindex {2}", i, array[i], p.Value);
+          retval = false;
+        }
+      }
+#endif
+      return retval;
+    }
+
+    #endregion
+
+    #region IExtensible<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>True, indicating array list has bag semantics.</value>
+    [Tested]
+    public virtual bool AllowsDuplicates
+    {
+      [Tested]
+      get
+      {
+#if HASHINDEX
+        return false;
+#else
+        return true;
+#endif
+      }
+    }
+
+    /// <summary>
+    /// By convention this is true for any collection with set semantics.
+    /// </summary>
+    /// <value>True if only one representative of a group of equal items 
+    /// is kept in the collection together with the total count.</value>
+    public virtual bool DuplicatesByCounting
+    {
+      get
+      {
+#if HASHINDEX
+        return true;
+#else
+        return false;
+#endif
+      }
+    }
+
+    /// <summary>
+    /// Add an item to end of this list.
+    /// </summary>
+    /// <param name="item">The item to add.</param>
+    /// <returns>True</returns>
+    [Tested]
+    public virtual bool Add(T item)
+    {
+      updatecheck();
+#if HASHINDEX
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, size + offset);
+      if (itemIndex.FindOrAdd(ref p))
+        return false;
+#endif
+      baseinsert(size, item);
+#if HASHINDEX
+      reindex(size + offset);
+#endif
+      (underlying ?? this).raiseForAdd(item);
+      return true;
+    }
+
+
+    /// <summary>
+    /// Add the elements from another collection to this collection.
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items"></param>
+    [Tested]
+    public virtual void AddAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      updatecheck();
+      int toadd = EnumerableBase<U>.countItems(items);
+      if (toadd == 0)
+        return;
+
+      if (toadd + underlyingsize > array.Length)
+        expand(toadd + underlyingsize, underlyingsize);
+
+      int i = size + offset;
+      if (underlyingsize > i)
+        Array.Copy(array, i, array, i + toadd, underlyingsize - i);
+      try
+      {
+        foreach (T item in items)
+        {
+#if HASHINDEX
+          KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, i);
+          if (itemIndex.FindOrAdd(ref p))
+            continue;
+#endif
+          array[i++] = item;
+        }
+      }
+      finally
+      {
+        int added = i - size - offset;
+        if (added < toadd)
+        {
+          Array.Copy(array, size + offset + toadd, array, i, underlyingsize - size - offset);
+          Array.Clear(array, underlyingsize + added, toadd - added);
+        }
+        if (added > 0)
+        {
+          addtosize(added);
+#if HASHINDEX
+          reindex(i);
+#endif
+          fixViewsAfterInsert(added, i - added);
+          (underlying ?? this).raiseForAddAll(i - added, added);
+        }
+      }
+    }
+    private void raiseForAddAll(int start, int added)
+    {
+      if ((ActiveEvents & EventTypeEnum.Added) != 0)
+        for (int i = start, end = start + added; i < end; i++)
+          raiseItemsAdded(array[i], 1);
+      raiseCollectionChanged();
+    }
+
+    #endregion
+
+    #region IDirectedEnumerable<T> Members
+
+    /// <summary>
+    /// Create a collection containing the same items as this collection, but
+    /// whose enumerator will enumerate the items backwards. The new collection
+    /// will become invalid if the original is modified. Method typicaly used as in
+    /// <code>foreach (T x in coll.Backwards()) {...}</code>
+    /// </summary>
+    /// <returns>The backwards collection.</returns>
+    [Tested]
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
+
+    #endregion
+
+    #region ICollectionValue<T> Members
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>The number of items in this collection</value>
+    [Tested]
+    public override int Count { [Tested]get { validitycheck(); return size; } }
+    #endregion
+
+    #region IEnumerable<T> Members
+    //TODO: make tests of all calls on a disposed view throws the right exception! (Which should be C5.InvalidListViewException)
+    /// <summary>
+    /// Create an enumerator for the collection
+    /// </summary>
+    /// <returns>The enumerator</returns>
+    [Tested]
+    public override SCG.IEnumerator<T> GetEnumerator()
+    {
+      validitycheck();
+      return base.GetEnumerator();
+    }
+    #endregion
+
+#if HASHINDEX
+#else
+    #region IStack<T> Members
+
+    /// <summary>
+    /// Push an item to the top of the stack.
+    /// </summary>
+    /// <param name="item">The item</param>
+    [Tested]
+    public virtual void Push(T item)
+    {
+      InsertLast(item);
+    }
+
+    /// <summary>
+    /// Pop the item at the top of the stack from the stack.
+    /// </summary>
+    /// <returns>The popped item.</returns>
+    [Tested]
+    public virtual T Pop()
+    {
+      return RemoveLast();
+    }
+
+    #endregion
+
+    #region IQueue<T> Members
+
+    /// <summary>
+    /// Enqueue an item at the back of the queue. 
+    /// </summary>
+    /// <param name="item">The item</param>
+    [Tested]
+    public virtual void Enqueue(T item)
+    {
+      InsertLast(item);
+    }
+
+    /// <summary>
+    /// Dequeue an item from the front of the queue.
+    /// </summary>
+    /// <returns>The item</returns>
+    [Tested]
+    public virtual T Dequeue()
+    {
+      return RemoveFirst();
+    }
+
+    #endregion
+#endif
+    #region IDisposable Members
+
+    /// <summary>
+    /// Invalidate this list. If a view, just invalidate the view. 
+    /// If not a view, invalidate the list and all views on it.
+    /// </summary>
+    public virtual void Dispose()
+    {
+      Dispose(false);
+    }
+
+    void Dispose(bool disposingUnderlying)
+    {
+      if (isValid)
+      {
+        if (underlying != null)
+        {
+          isValid = false;
+          if (!disposingUnderlying && views != null)
+            views.Remove(myWeakReference);
+          underlying = null;
+          views = null;
+          myWeakReference = null;
+        }
+        else
+        {
+          //isValid = false;
+          if (views != null)
+            foreach (HashedArrayList<T> view in views)
+              view.Dispose(true);
+          Clear();
+        }
+      }
+    }
+
+    #endregion
+
+    #region ICloneable Members
+
+    /// <summary>
+    /// Make a shallow copy of this HashedArrayList.
+    /// </summary>
+    /// <returns></returns>
+    public virtual object Clone()
+    {
+      HashedArrayList<T> clone = new HashedArrayList<T>(size, itemequalityComparer);
+      clone.AddAll(this);
+      return clone;
+    }
+
+    #endregion
+
+    #region ISerializable Members
+    /*
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="info"></param>
+    /// <param name="context"></param>
+    public HashedArrayList(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) :
+      this(info.GetInt32("sz"),(SCG.IEqualityComparer<T>)(info.GetValue("eq",typeof(SCG.IEqualityComparer<T>))))
+    {
+      size = info.GetInt32("sz");
+      for (int i = 0; i < size; i++)
+      {
+        array[i] = (T)(info.GetValue("elem" + i,typeof(T)));
+      }
+#if HASHINDEX
+      reindex(0);
+#endif      
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="info"></param>
+    /// <param name="context"></param>
+    public void GetObjectData(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context)
+    {
+      info.AddValue("sz", size);
+      info.AddValue("eq", EqualityComparer);
+      for (int i = 0; i < size; i++)
+			{
+        info.AddValue("elem" + i, array[i + offset]);
+      }
+    }
+*/
+    #endregion
+
+    #region System.Collections.Generic.IList<T> Members
+
+    void System.Collections.Generic.IList<T>.RemoveAt(int index)
+    {
+      RemoveAt(index);
+    }
+
+    void System.Collections.Generic.ICollection<T>.Add(T item)
+    {
+      Add(item);
+    }
+
+    #endregion
+
+    #region System.Collections.ICollection Members
+
+    bool System.Collections.ICollection.IsSynchronized
+    {
+      get { return false; }
+    }
+
+    [Obsolete]
+    Object System.Collections.ICollection.SyncRoot
+    {
+      get { return underlying != null ? ((System.Collections.ICollection)underlying).SyncRoot : array; }
+    }
+
+    void System.Collections.ICollection.CopyTo(Array arr, int index)
+    {
+      if (index < 0 || index + Count > arr.Length)
+        throw new ArgumentOutOfRangeException();
+
+      foreach (T item in this)
+        arr.SetValue(item, index++);
+    }
+
+    #endregion
+
+    #region System.Collections.IList Members
+
+    Object System.Collections.IList.this[int index]
+    {
+      get { return this[index]; }
+      set { this[index] = (T)value; }
+    }
+
+    int System.Collections.IList.Add(Object o)
+    {
+      bool added = Add((T)o);
+      // What position to report if item not added? SC.IList.Add doesn't say
+      return added ? Count - 1 : -1;
+    }
+
+    bool System.Collections.IList.Contains(Object o)
+    {
+      return Contains((T)o);
+    }
+
+    int System.Collections.IList.IndexOf(Object o)
+    {
+      return Math.Max(-1, IndexOf((T)o));
+    }
+
+    void System.Collections.IList.Insert(int index, Object o)
+    {
+      Insert(index, (T)o);
+    }
+
+    void System.Collections.IList.Remove(Object o)
+    {
+      Remove((T)o);
+    }
+
+    void System.Collections.IList.RemoveAt(int index)
+    {
+      RemoveAt(index);
+    }
+
+    #endregion
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/arrays/SortedArray.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/arrays/SortedArray.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/arrays/SortedArray.cs	(revision 3)
@@ -0,0 +1,1476 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+namespace C5
+{
+  /// <summary>
+  /// A collection class implementing a sorted dynamic array data structure.
+  /// </summary>
+  [Serializable]
+  public class SortedArray<T> : ArrayBase<T>, IIndexedSorted<T>
+  {
+    #region Features
+    /// <summary>
+    /// A debugging artifact. To be removed.
+    /// </summary>
+    [Flags]
+    public enum Feature : short
+    {
+      /// <summary>
+      /// A debugging artifact. To be removed.
+      /// </summary>
+      Standard = 0
+    }
+
+
+    static Feature features = Feature.Standard;
+
+
+    /// <summary>
+    /// A debugging artifact. To be removed.
+    /// </summary>
+    /// <value></value>
+    public static Feature Features { get { return features; } }
+
+    #endregion
+
+    #region Events
+
+    /// <summary>
+    ///
+    /// </summary>
+    /// <value></value>
+    public override EventTypeEnum ListenableEvents { get { return EventTypeEnum.Basic; } }
+
+    #endregion
+
+    #region Fields
+
+    SCG.IComparer<T> comparer;
+
+    #endregion
+
+    #region Util
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item">The item to search for</param>
+    /// <param name="mid">The least index, mid, for which array[mid] >= item</param>
+    /// <returns>True if item found</returns>
+    private bool binarySearch(T item, out int mid)
+    {
+      int bot = 0, top = size;
+
+      mid = top / 2;
+      while (top > bot)
+      {
+        int c;
+
+        if ((c = comparer.Compare(array[mid], item)) == 0)
+          return true;
+
+        if (c > 0)
+        { top = mid; }
+        else
+        { bot = mid + 1; }
+
+        mid = (bot + top) / 2;
+      }
+
+      return false;
+    }
+
+    private int indexOf(T item)
+    {
+      int ind;
+
+      if (binarySearch(item, out ind))
+        return ind;
+
+      return ~ind;
+    }
+
+    #endregion
+
+    #region Constructors
+
+    /// <summary>
+    /// Create a dynamic sorted array with a natural comparer
+    /// (and item equalityComparer,  assumed compatible)
+    /// </summary>
+    /// <exception cref="NotComparableException">If <code>T</code> is not comparable.
+    /// </exception>
+    public SortedArray() : this(8) { }
+
+
+    /// <summary>
+    /// Create a dynamic sorted array with a natural comparer 
+    /// (and item equalityComparer,  assumed compatible)
+    /// and prescribed initial capacity.
+    /// </summary>
+    /// <exception cref="NotComparableException">If <code>T</code> is not comparable.
+    /// </exception>
+    /// <param name="capacity">The capacity</param>
+    public SortedArray(int capacity)
+      : this(capacity, Comparer<T>.Default, EqualityComparer<T>.Default) { }
+
+
+    /// <summary>
+    /// Create a dynamic sorted array with an external comparer.
+    /// <para>The itemequalityComparer will be compatible 
+    /// <see cref="T:C5.ComparerZeroHashCodeEqualityComparer`1"/> since the 
+    /// default equalityComparer for T (<see cref="P:C5.EqualityComparer`1.Default"/>)
+    /// is unlikely to be compatible with the external comparer. This makes the
+    /// array inadequate for use as item in a collection of unsequenced or sequenced sets or bags
+    /// (<see cref="T:C5.ICollection`1"/> and <see cref="T:C5.ISequenced`1"/>)
+    /// </para>
+    /// </summary>
+    /// <param name="comparer">The comparer</param>
+    public SortedArray(SCG.IComparer<T> comparer)
+      : this(8, comparer) { }
+
+    /// <summary>
+    /// Create a dynamic sorted array with an external comparer
+    /// and prescribed initial capacity.
+    /// <para>The itemequalityComparer will be a compatible 
+    /// <see cref="T:C5.ComparerZeroHashCodeEqualityComparer`1"/> since the 
+    /// default equalityComparer for T (<see cref="P:C5.EqualityComparer`1.Default"/>)
+    /// is unlikely to be compatible with the external comparer. This makes the
+    /// sorted array inadequate for use as item in a collection of unsequenced or sequenced sets or bags
+    /// (<see cref="T:C5.ICollection`1"/> and <see cref="T:C5.ISequenced`1"/>)
+    /// </para>
+    /// </summary>
+    /// <param name="capacity">The capacity</param>
+    /// <param name="comparer">The comparer</param>
+    public SortedArray(int capacity, SCG.IComparer<T> comparer)
+      : this(capacity, comparer, new ComparerZeroHashCodeEqualityComparer<T>(comparer)) { }
+
+    /// <summary>
+    /// Create a dynamic sorted array with an external comparer, an external item equalityComparer
+    /// and prescribed initial capacity. This is the constructor to use if the collection 
+    /// will be used as item in a hash table based collection.
+    /// </summary>
+    /// <param name="capacity">The capacity</param>
+    /// <param name="comparer">The item comparer</param>
+    /// <param name="equalityComparer">The item equalityComparer (assumed compatible)</param>
+    public SortedArray(int capacity, SCG.IComparer<T> comparer, SCG.IEqualityComparer<T> equalityComparer)
+      : base(capacity, equalityComparer)
+    {
+      if (comparer == null)
+        throw new NullReferenceException("Comparer cannot be null");
+      this.comparer = comparer;
+    }
+
+    #endregion
+
+    #region IIndexedSorted<T> Members
+
+    /// <summary>
+    /// Determine the number of items at or above a supplied threshold.
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive)</param>
+    /// <returns>The number of matcing items.</returns>
+    [Tested]
+    public int CountFrom(T bot)
+    {
+      int lo;
+
+      binarySearch(bot, out lo);
+      return size - lo;
+    }
+
+
+    /// <summary>
+    /// Determine the number of items between two supplied thresholds.
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive)</param>
+    /// <param name="top">The upper bound (exclusive)</param>
+    /// <returns>The number of matcing items.</returns>
+    [Tested]
+    public int CountFromTo(T bot, T top)
+    {
+      int lo, hi;
+
+      binarySearch(bot, out lo);
+      binarySearch(top, out hi);
+      return hi > lo ? hi - lo : 0;
+    }
+
+
+    /// <summary>
+    /// Determine the number of items below a supplied threshold.
+    /// </summary>
+    /// <param name="top">The upper bound (exclusive)</param>
+    /// <returns>The number of matcing items.</returns>
+    [Tested]
+    public int CountTo(T top)
+    {
+      int hi;
+
+      binarySearch(top, out hi);
+      return hi;
+    }
+
+
+    /// <summary>
+    /// Query this sorted collection for items greater than or equal to a supplied value.
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive).</param>
+    /// <returns>The result directed collection.</returns>
+    [Tested]
+    public IDirectedCollectionValue<T> RangeFrom(T bot)
+    {
+      int lo;
+
+      binarySearch(bot, out lo);
+      return new Range(this, lo, size - lo, true);
+    }
+
+
+    /// <summary>
+    /// Query this sorted collection for items between two supplied values.
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive).</param>
+    /// <param name="top">The upper bound (exclusive).</param>
+    /// <returns>The result directed collection.</returns>
+    [Tested]
+    public IDirectedCollectionValue<T> RangeFromTo(T bot, T top)
+    {
+      int lo, hi;
+
+      binarySearch(bot, out lo);
+      binarySearch(top, out hi);
+
+      int sz = hi - lo;
+
+      return new Range(this, lo, sz, true);
+    }
+
+
+    /// <summary>
+    /// Query this sorted collection for items less than a supplied value.
+    /// </summary>
+    /// <param name="top">The upper bound (exclusive).</param>
+    /// <returns>The result directed collection.</returns>
+    [Tested]
+    public IDirectedCollectionValue<T> RangeTo(T top)
+    {
+      int hi;
+
+      binarySearch(top, out hi);
+      return new Range(this, 0, hi, true);
+    }
+
+
+    /// <summary>
+    /// Create a new indexed sorted collection consisting of the items of this
+    /// indexed sorted collection satisfying a certain predicate.
+    /// </summary>
+    /// <param name="f">The filter delegate defining the predicate.</param>
+    /// <returns>The new indexed sorted collection.</returns>
+    [Tested]
+    public IIndexedSorted<T> FindAll(Fun<T, bool> f)
+    {
+      SortedArray<T> res = new SortedArray<T>(comparer);
+      int j = 0, rescap = res.array.Length;
+
+      for (int i = 0; i < size; i++)
+      {
+        T a = array[i];
+
+        if (f(a))
+        {
+          if (j == rescap) res.expand(rescap = 2 * rescap, j);
+
+          res.array[j++] = a;
+        }
+      }
+
+      res.size = j;
+      return res;
+    }
+
+
+    /// <summary>
+    /// Create a new indexed sorted collection consisting of the results of
+    /// mapping all items of this list.
+    /// <exception cref="ArgumentException"/> if the map is not increasing over 
+    /// the items of this collection (with respect to the two given comparison 
+    /// relations).
+    /// </summary>
+    /// <param name="m">The delegate definging the map.</param>
+    /// <param name="c">The comparion relation to use for the result.</param>
+    /// <returns>The new sorted collection.</returns>
+    [Tested]
+    public IIndexedSorted<V> Map<V>(Fun<T, V> m, SCG.IComparer<V> c)
+    {
+      SortedArray<V> res = new SortedArray<V>(size, c);
+
+      if (size > 0)
+      {
+        V oldv = res.array[0] = m(array[0]), newv;
+
+        for (int i = 1; i < size; i++)
+        {
+          if (c.Compare(oldv, newv = res.array[i] = m(array[i])) >= 0)
+            throw new ArgumentException("mapper not monotonic");
+
+          oldv = newv;
+        }
+      }
+
+      res.size = size;
+      return res;
+    }
+
+    #endregion
+
+    #region ISorted<T> Members
+
+    /// <summary>
+    /// Find the strict predecessor of item in the sorted array,
+    /// that is, the greatest item in the collection smaller than the item.
+    /// </summary>
+    /// <param name="item">The item to find the predecessor for.</param>
+    /// <param name="res">The predecessor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a predecessor; otherwise false.</returns>
+    public bool TryPredecessor(T item, out T res)
+    {
+        int lo;
+        binarySearch(item, out lo);
+        if (lo == 0)
+        {
+            res = default(T);
+            return false;
+        }
+        else
+        {
+            res = array[lo - 1];
+            return true;
+        }
+    }
+
+
+    /// <summary>
+    /// Find the strict successor of item in the sorted array,
+    /// that is, the least item in the collection greater than the supplied value.
+    /// </summary>
+    /// <param name="item">The item to find the successor for.</param>
+    /// <param name="res">The successor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a successor; otherwise false.</returns>
+    public bool TrySuccessor(T item, out T res)
+    {
+        int hi;
+        if (binarySearch(item, out hi)) 
+            hi++;
+        if (hi >= size)
+        {
+            res = default(T);
+            return false;
+        } else {
+            res = array[hi];
+            return true;
+        }
+    }
+
+
+    /// <summary>
+    /// Find the weak predecessor of item in the sorted array,
+    /// that is, the greatest item in the collection smaller than or equal to the item.
+    /// </summary>
+    /// <param name="item">The item to find the weak predecessor for.</param>
+    /// <param name="res">The weak predecessor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a weak predecessor; otherwise false.</returns>
+    public bool TryWeakPredecessor(T item, out T res)
+    {
+        int lo;
+
+        if (!binarySearch(item, out lo)) 
+            lo--;
+
+        if (lo < 0)
+        {
+            res = default(T);
+            return false;
+        }
+        else
+        {
+            res = array[lo];
+            return true;
+        }
+    }
+
+
+    /// <summary>
+    /// Find the weak successor of item in the sorted array,
+    /// that is, the least item in the collection greater than or equal to the supplied value.
+    /// </summary>
+    /// <param name="item">The item to find the weak successor for.</param>
+    /// <param name="res">The weak successor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a weak successor; otherwise false.</returns>
+    public bool TryWeakSuccessor(T item, out T res)
+    {
+        int hi;
+
+        binarySearch(item, out hi);
+        if (hi >= size)
+        {
+            res = default(T);
+            return false;
+        }
+        else
+        {
+            res = array[hi];
+            return true;
+        }
+    }
+
+
+    /// <summary>
+    /// Find the strict predecessor in the sorted collection of a particular value,
+    /// i.e. the largest item in the collection less than the supplied value.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such element exists (the
+    /// supplied  value is less than or equal to the minimum of this collection.)</exception>
+    /// <param name="item">The item to find the predecessor for.</param>
+    /// <returns>The predecessor.</returns>
+    [Tested]
+    public T Predecessor(T item)
+    {
+      int lo;
+
+      binarySearch(item, out lo);
+      if (lo == 0)
+        throw new NoSuchItemException();
+
+      return array[lo - 1];
+    }
+
+
+    /// <summary>
+    /// Find the strict successor in the sorted collection of a particular value,
+    /// i.e. the least item in the collection greater than the supplied value.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such element exists (the
+    /// supplied  value is greater than or equal to the maximum of this collection.)</exception>
+    /// <param name="item">The item to find the successor for.</param>
+    /// <returns>The successor.</returns>
+    [Tested]
+    public T Successor(T item)
+    {
+      int hi;
+
+      if (binarySearch(item, out hi)) hi++;
+
+      if (hi >= size)
+        throw new NoSuchItemException();
+
+      return array[hi];
+    }
+
+
+    /// <summary>
+    /// Find the weak predecessor in the sorted collection of a particular value,
+    /// i.e. the largest item in the collection less than or equal to the supplied value.
+    /// <exception cref="NoSuchItemException"/> if no such element exists (the
+    /// supplied  value is less than the minimum of this collection.)
+    /// </summary>
+    /// <param name="item">The item to find the weak predecessor for.</param>
+    /// <returns>The weak predecessor.</returns>
+    [Tested]
+    public T WeakPredecessor(T item)
+    {
+      int lo;
+
+      if (!binarySearch(item, out lo)) lo--;
+
+      if (lo < 0)
+        throw new NoSuchItemException();
+
+      return array[lo];
+    }
+
+
+    /// <summary>
+    /// Find the weak successor in the sorted collection of a particular value,
+    /// i.e. the least item in the collection greater than or equal to the supplied value.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such element exists (the
+    /// supplied  value is greater than the maximum of this collection.)</exception>
+    /// <param name="item">The item to find the weak successor for.</param>
+    /// <returns>The weak successor.</returns>
+    [Tested]
+    public T WeakSuccessor(T item)
+    {
+      int hi;
+
+      binarySearch(item, out hi);
+      if (hi >= size)
+        throw new NoSuchItemException();
+
+      return array[hi];
+    }
+
+
+    /// <summary>
+    /// Perform a search in the sorted collection for the ranges in which a
+    /// non-increasing (i.e. weakly decrerasing) function from the item type to 
+    /// <code>int</code> is
+    /// negative, zero respectively positive. If the supplied cut function is
+    /// not non-increasing, the result of this call is undefined.
+    /// </summary>
+    /// <param name="c">The cut function <code>T</code> to <code>int</code>, given
+    /// as an <code>IComparable&lt;T&gt;</code> object, where the cut function is
+    /// the <code>c.CompareTo(T that)</code> method.</param>
+    /// <param name="low">Returns the largest item in the collection, where the
+    /// cut function is positive (if any).</param>
+    /// <param name="lowIsValid">True if the cut function is positive somewhere
+    /// on this collection.</param>
+    /// <param name="high">Returns the least item in the collection, where the
+    /// cut function is negative (if any).</param>
+    /// <param name="highIsValid">True if the cut function is negative somewhere
+    /// on this collection.</param>
+    /// <returns></returns>
+    [Tested]
+    public bool Cut(IComparable<T> c, out T low, out bool lowIsValid, out T high, out bool highIsValid)
+    {
+      int lbest = -1, rbest = size;
+
+      low = default(T);
+      lowIsValid = false;
+      high = default(T);
+      highIsValid = false;
+
+      int bot = 0, top = size, mid, comp = -1, sol;
+
+      mid = top / 2;
+      while (top > bot)
+      {
+        if ((comp = c.CompareTo(array[mid])) == 0)
+          break;
+
+        if (comp < 0)
+        { rbest = top = mid; }
+        else
+        { lbest = mid; bot = mid + 1; }
+
+        mid = (bot + top) / 2;
+      }
+
+      if (comp != 0)
+      {
+        if (lbest >= 0) { lowIsValid = true; low = array[lbest]; }
+
+        if (rbest < size) { highIsValid = true; high = array[rbest]; }
+
+        return false;
+      }
+
+      sol = mid;
+      bot = sol - 1;
+
+      //Invariant: c.Compare(array[x]) < 0  when rbest <= x < size 
+      //           c.Compare(array[x]) >= 0 when x < bot)
+      //(Assuming c.Compare monotonic)
+      while (rbest > bot)
+      {
+        mid = (bot + rbest) / 2;
+        if (c.CompareTo(array[mid]) < 0)
+        { rbest = mid; }
+        else
+        { bot = mid + 1; }
+      }
+
+      if (rbest < size) { highIsValid = true; high = array[rbest]; }
+
+      top = sol + 1;
+
+      //Invariant: c.Compare(array[x]) > 0  when 0 <= x <= lbest
+      //           c.Compare(array[x]) <= 0 when x>top)
+      //(Assuming c.Compare monotonic)
+      while (top > lbest)
+      {
+        mid = (lbest + top + 1) / 2;
+        if (c.CompareTo(array[mid]) > 0)
+        { lbest = mid; }
+        else
+        { top = mid - 1; }
+      }
+
+      if (lbest >= 0) { lowIsValid = true; low = array[lbest]; }
+
+      return true;
+    }
+
+
+    IDirectedEnumerable<T> ISorted<T>.RangeFrom(T bot)
+    { return RangeFrom(bot); }
+
+
+    IDirectedEnumerable<T> ISorted<T>.RangeFromTo(T bot, T top)
+    { return RangeFromTo(bot, top); }
+
+
+    IDirectedEnumerable<T> ISorted<T>.RangeTo(T top)
+    { return RangeTo(top); }
+
+
+    /// <summary>
+    /// Create a directed collection with the same items as this collection.
+    /// </summary>
+    /// <returns>The result directed collection.</returns>
+    [Tested]
+    public IDirectedCollectionValue<T> RangeAll()
+    { return new Range(this, 0, size, true); }
+
+
+    /// <summary>
+    /// Add all the items from another collection with an enumeration order that 
+    /// is increasing in the items.
+    /// <exception cref="ArgumentException"/> if the enumerated items turns out
+    /// not to be in increasing order.
+    /// </summary>
+    /// <param name="items">The collection to add.</param>
+    /// <typeparam name="U"></typeparam>
+    [Tested]
+    public void AddSorted<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      //Unless items have <=1 elements we would expect it to be
+      //too expensive to do repeated inserts, thus:
+      updatecheck();
+
+      int j = 0, i = 0, c = -1, itemcount = EnumerableBase<U>.countItems(items), numAdded = 0;
+      SortedArray<T> res = new SortedArray<T>(size + itemcount, comparer);
+      T lastitem = default(T);
+      T[] addedItems = new T[itemcount];
+
+      foreach (T item in items)
+      {
+        while (i < size && (c = comparer.Compare(array[i], item)) <= 0)
+        {
+          lastitem = res.array[j++] = array[i++];
+          if (c == 0)
+            goto next;
+        }
+
+        if (j > 0 && comparer.Compare(lastitem, item) >= 0)
+          throw new ArgumentException("Argument not sorted");
+
+        addedItems[numAdded++] = lastitem = res.array[j++] = item;
+      next:
+        c = -1;
+      }
+
+      while (i < size) res.array[j++] = array[i++];
+
+      size = j;
+      array = res.array;
+      raiseForAddAll(addedItems, numAdded);
+    }
+
+
+    /// <summary>
+    /// Remove all items of this collection above or at a supplied threshold.
+    /// </summary>
+    /// <param name="low">The lower threshold (inclusive).</param>
+    [Tested]
+    public void RemoveRangeFrom(T low)
+    {
+      int lowind;
+
+      binarySearch(low, out lowind);
+      if (lowind == size)
+        return;
+
+      T[] removed = new T[size - lowind];
+      Array.Copy(array, lowind, removed, 0, removed.Length);
+      Array.Reverse(removed);
+
+      Array.Clear(array, lowind, size - lowind);
+      size = lowind;
+
+      raiseForRemoveRange(removed);
+    }
+
+
+    /// <summary>
+    /// Remove all items of this collection between two supplied thresholds.
+    /// </summary>
+    /// <param name="low">The lower threshold (inclusive).</param>
+    /// <param name="hi">The upper threshold (exclusive).</param>
+    [Tested]
+    public void RemoveRangeFromTo(T low, T hi)
+    {
+      int lowind, highind;
+
+      binarySearch(low, out lowind);
+      binarySearch(hi, out highind);
+      if (highind <= lowind)
+        return;
+
+      T[] removed = new T[highind - lowind];
+      Array.Copy(array, lowind, removed, 0, removed.Length);
+      Array.Reverse(removed);
+
+      Array.Copy(array, highind, array, lowind, size - highind);
+      Array.Clear(array, size - highind + lowind, highind - lowind);
+      size -= highind - lowind;
+
+      raiseForRemoveRange(removed);
+    }
+
+
+    /// <summary>
+    /// Remove all items of this collection below a supplied threshold.
+    /// </summary>
+    /// <param name="hi">The upper threshold (exclusive).</param>
+    [Tested]
+    public void RemoveRangeTo(T hi)
+    {
+      int highind;
+
+      binarySearch(hi, out highind);
+      if (highind == 0)
+        return;
+
+      T[] removed = new T[highind];
+      Array.Copy(array, 0, removed, 0, removed.Length);
+
+      Array.Copy(array, highind, array, 0, size - highind);
+      Array.Clear(array, size - highind, highind);
+      size = size - highind;
+
+      raiseForRemoveRange(removed);
+    }
+
+    private void raiseForRemoveRange(T[] removed)
+    {
+       foreach(T item in removed)
+         raiseItemsRemoved(item, 1);
+
+       if(removed.Length > 0)
+         raiseCollectionChanged();
+    }
+
+    #endregion
+
+    #region ICollection<T> Members
+    /// <summary>
+    /// The value is symbolic indicating the type of asymptotic complexity
+    /// in terms of the size of this collection (worst-case).
+    /// </summary>
+    /// <value>Speed.Log</value>
+    [Tested]
+    public Speed ContainsSpeed { [Tested]get { return Speed.Log; } }
+
+    /// <summary>
+    /// Remove all items from this collection, resetting internal array size.
+    /// </summary>
+    [Tested]
+    override public void Clear()
+    {
+      int oldCount = size;
+      base.Clear();
+      if(oldCount > 0)
+      {
+        raiseCollectionCleared(true, oldCount);
+        raiseCollectionChanged();
+      }
+    }
+
+    /// <summary>
+    /// Check if this collection contains (an item equivalent according to the
+    /// itemequalityComparer) to a particular value.
+    /// </summary>
+    /// <param name="item">The value to check for.</param>
+    /// <returns>True if the items is in this collection.</returns>
+    [Tested]
+    public bool Contains(T item)
+    {
+      int ind;
+
+      return binarySearch(item, out ind);
+    }
+
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, return in the ref argument (a
+    /// binary copy of) the actual value found.
+    /// </summary>
+    /// <param name="item">The value to look for.</param>
+    /// <returns>True if the items is in this collection.</returns>
+    [Tested]
+    public bool Find(ref T item)
+    {
+      int ind;
+
+      if (binarySearch(item, out ind))
+      {
+        item = array[ind];
+        return true;
+      }
+
+      return false;
+    }
+
+
+    //This should probably just be bool Add(ref T item); !!!
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, return in the ref argument (a
+    /// binary copy of) the actual value found. Else, add the item to the collection.
+    /// </summary>
+    /// <param name="item">The value to look for.</param>
+    /// <returns>True if the item was added (hence not found).</returns>
+    [Tested]
+    public bool FindOrAdd(ref T item)
+    {
+      updatecheck();
+
+      int ind;
+
+      if (binarySearch(item, out ind))
+      {
+        item = array[ind];
+        return true;
+      }
+
+      if (size == array.Length) expand();
+
+      Array.Copy(array, ind, array, ind + 1, size - ind);
+      array[ind] = item;
+      size++;
+      raiseForAdd(item);
+      return false;
+    }
+
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// to with a binary copy of the supplied value. If the collection has bag semantics,
+    /// it is implementation dependent if this updates all equivalent copies in
+    /// the collection or just one.
+    /// </summary>
+    /// <param name="item">Value to update.</param>
+    /// <returns>True if the item was found and hence updated.</returns>
+    [Tested]
+    public bool Update(T item)
+    { T olditem; return Update(item, out olditem); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public bool Update(T item, out T olditem)
+    {
+      updatecheck();
+
+      int ind;
+
+      if (binarySearch(item, out ind))
+      {
+        olditem = array[ind];
+        array[ind] = item;
+        raiseForUpdate(item, olditem);
+        return true;
+      }
+
+      olditem = default(T);
+      return false;
+    }
+
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// to with a binary copy of the supplied value; else add the value to the collection. 
+    /// </summary>
+    /// <param name="item">Value to add or update.</param>
+    /// <returns>True if the item was found and updated (hence not added).</returns>
+    [Tested]
+    public bool UpdateOrAdd(T item)
+    { T olditem; return UpdateOrAdd(item, out olditem); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public bool UpdateOrAdd(T item, out T olditem)
+    {
+      updatecheck();
+
+      int ind;
+
+      if (binarySearch(item, out ind))
+      {
+        olditem = array[ind];
+        array[ind] = item;
+        raiseForUpdate(item, olditem);
+        return true;
+      }
+
+      if (size == array.Length) expand();
+
+      Array.Copy(array, ind, array, ind + 1, size - ind);
+      array[ind] = item;
+      size++;
+      olditem = default(T);
+      raiseForAdd(item);
+      return false;
+    }
+
+
+    /// <summary>
+    /// Remove a particular item from this collection. If the collection has bag
+    /// semantics only one copy equivalent to the supplied item is removed. 
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    /// <returns>True if the item was found (and removed).</returns>
+    [Tested]
+    public bool Remove(T item)
+    {
+      int ind;
+
+      updatecheck();
+      if (binarySearch(item, out ind))
+      {
+        T removeditem = array[ind];
+        Array.Copy(array, ind + 1, array, ind, size - ind - 1);
+        array[--size] = default(T);
+        raiseForRemove(removeditem);
+        return true;
+      }
+
+      return false;
+    }
+
+
+    /// <summary>
+    /// Remove a particular item from this collection if found. If the collection
+    /// has bag semantics only one copy equivalent to the supplied item is removed,
+    /// which one is implementation dependent. 
+    /// If an item was removed, report a binary copy of the actual item removed in 
+    /// the argument.
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    /// <param name="removeditem">The removed value.</param>
+    /// <returns>True if the item was found (and removed).</returns>
+    [Tested]
+    public bool Remove(T item, out T removeditem)
+    {
+      int ind;
+
+      updatecheck();
+      if (binarySearch(item, out ind))
+      {
+        removeditem = array[ind];
+        Array.Copy(array, ind + 1, array, ind, size - ind - 1);
+        array[--size] = default(T);
+        raiseForRemove(removeditem);
+        return true;
+      }
+
+      removeditem = default(T);
+      return false;
+    }
+
+
+    /// <summary>
+    /// Remove all items in another collection from this one. 
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to remove.</param>
+    [Tested]
+    public void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      //This is O(m*logn) with n bits extra storage
+      //(Not better to collect the m items and sort them)
+      updatecheck();
+        
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(this);
+      bool mustFire = raiseHandler.MustFire;
+
+      int[] toremove = new int[(size >> 5) + 1];
+      int ind, j = 0;
+
+      foreach (T item in items)
+        if (binarySearch(item, out ind))
+          toremove[ind >> 5] |= 1 << (ind & 31);
+
+      for (int i = 0; i < size; i++)
+        if ((toremove[i >> 5] & (1 << (i & 31))) == 0)
+          array[j++] = array[i];
+        else if (mustFire)
+          raiseHandler.Remove(array[i]);
+
+      Array.Clear(array, j, size - j);
+      size = j;
+      if (mustFire)
+        raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// Remove all items not in some other collection from this one. 
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to retain.</param>
+    [Tested]
+    public void RetainAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      //This is O(m*logn) with n bits extra storage
+      //(Not better to collect the m items and sort them)
+      updatecheck();
+
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(this);
+      bool mustFire = raiseHandler.MustFire;
+
+      int[] toretain = new int[(size >> 5) + 1];
+      int ind, j = 0;
+
+      foreach (T item in items)
+        if (binarySearch(item, out ind))
+          toretain[ind >> 5] |= 1 << (ind & 31);
+
+      for (int i = 0; i < size; i++)
+        if ((toretain[i >> 5] & (1 << (i & 31))) != 0)
+          array[j++] = array[i];
+        else if (mustFire)
+          raiseHandler.Remove(array[i]);
+
+      Array.Clear(array, j, size - j);
+      size = j;
+      if (mustFire)
+        raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// Check if this collection contains all the values in another collection.
+    /// Multiplicities are not taken into account.
+    /// </summary>
+    /// <param name="items">The </param>
+    /// <typeparam name="U"></typeparam>
+    /// <returns>True if all values in <code>items</code>is in this collection.</returns>
+    [Tested]
+    public bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      int tmp;
+
+      foreach (T item in items)
+        if (!binarySearch(item, out tmp))
+          return false;
+
+      return true;
+    }
+
+
+    /// <summary>
+    /// Count the number of items of the collection equal to a particular value.
+    /// Returns 0 if and only if the value is not in the collection.
+    /// </summary>
+    /// <param name="item">The value to count.</param>
+    /// <returns>The number of copies found (0 or 1).</returns>
+    [Tested]
+    public int ContainsCount(T item)
+    {
+      int tmp;
+
+      return binarySearch(item, out tmp) ? 1 : 0;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<T> UniqueItems() { return this; }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities()
+    {
+      return new MultiplicityOne<T>(this);
+    }
+
+    /// <summary>
+    /// Remove all (0 or 1) items equivalent to a given value.
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    [Tested]
+    public void RemoveAllCopies(T item) { Remove(item); }
+
+
+    /// <summary>
+    /// Check the integrity of the internal data structures of this collection.
+    /// Only avaliable in DEBUG builds???
+    /// </summary>
+    /// <returns>True if check does not fail.</returns>
+    [Tested]
+    public override bool Check()
+    {
+      bool retval = true;
+
+      if (size > array.Length)
+      {
+        Console.WriteLine("Bad size ({0}) > array.Length ({1})", size, array.Length);
+        return false;
+      }
+
+      for (int i = 0; i < size; i++)
+      {
+        if ((object)(array[i]) == null)
+        {
+          Console.WriteLine("Bad element: null at index {0}", i);
+          return false;
+        }
+
+        if (i > 0 && comparer.Compare(array[i], array[i - 1]) <= 0)
+        {
+          Console.WriteLine("Inversion at index {0}", i);
+          retval = false;
+        }
+      }
+
+      return retval;
+    }
+
+    #endregion
+
+    #region IExtensible<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>False since this collection has set semantics</value>
+    [Tested]
+    public bool AllowsDuplicates { [Tested]get { return false; } }
+
+    /// <summary>
+    /// By convention this is true for any collection with set semantics.
+    /// </summary>
+    /// <value>True if only one representative of a group of equal items 
+    /// is kept in the collection together with the total count.</value>
+    public virtual bool DuplicatesByCounting { get { return true; } }
+
+    /// <summary>
+    /// Add an item to this collection if possible. If this collection has set
+    /// semantics, the item will be added if not already in the collection. If
+    /// bag semantics, the item will always be added.
+    /// </summary>
+    /// <param name="item">The item to add.</param>
+    /// <returns>True if item was added.</returns>
+    [Tested]
+    public bool Add(T item)
+    {
+      updatecheck();
+
+      int ind;
+
+      if (binarySearch(item, out ind)) return false;
+
+      insert(ind, item);
+      raiseForAdd(item);
+      return true;
+    }
+
+    /// <summary>
+    /// Add an item to this collection if possible. 
+    /// </summary>
+    /// <param name="item">The item to add.</param>
+    [Tested]
+    void SCG.ICollection<T>.Add(T item)
+    {
+        Add(item);
+    }
+
+
+    /// <summary>
+    /// Add the elements from another collection with a more specialized item type 
+    /// to this collection. Since this
+    /// collection has set semantics, only items not already in the collection
+    /// will be added.
+    /// </summary>
+    /// <typeparam name="U">The type of items to add</typeparam>
+    /// <param name="items">The items to add</param>
+    [Tested]
+    public void AddAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      int toadd = EnumerableBase<U>.countItems(items), newsize = array.Length;
+
+      while (newsize < size + toadd) { newsize *= 2; }
+
+      T[] newarr = new T[newsize];
+
+      toadd = 0;
+      foreach (T item in items) newarr[size + toadd++] = item;
+
+      Sorting.IntroSort<T>(newarr, size, toadd, comparer);
+
+      int j = 0, i = 0, numAdded = 0;
+      T lastitem = default(T);
+      T[] addedItems = new T[toadd];
+
+      //The following eliminates duplicates (including duplicates in input)
+      //while merging the old and new collection
+      for (int k = size, klimit = size + toadd; k < klimit; k++)
+      {
+        while (i < size && comparer.Compare(array[i], newarr[k]) <= 0)
+          lastitem = newarr[j++] = array[i++];
+
+        if (j == 0 || comparer.Compare(lastitem, newarr[k]) < 0)
+          addedItems[numAdded++] = lastitem = newarr[j++] = newarr[k];
+      }
+
+      while (i < size) newarr[j++] = array[i++];
+
+      Array.Clear(newarr, j, size + toadd - j);
+      size = j;
+      array = newarr;
+
+      raiseForAddAll(addedItems, numAdded);
+    }
+
+    private void raiseForAddAll(T[] addedItems, int numAdded)
+    {
+      if ((ActiveEvents & EventTypeEnum.Added) != 0)
+        for(int i = 0 ;i < numAdded; i += 1)
+          raiseItemsAdded(addedItems[i], 1);
+      if (numAdded > 0)
+        raiseCollectionChanged();
+    }
+
+    #endregion
+
+    #region IPriorityQueue<T> Members
+
+    /// <summary>
+    /// Find the current least item of this priority queue.
+    /// </summary>
+    /// <returns>The least item.</returns>
+    [Tested]
+    public T FindMin()
+    {
+      if (size == 0)
+        throw new NoSuchItemException();
+
+      return array[0];
+    }
+
+    /// <summary>
+    /// Remove the least item from this  priority queue.
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public T DeleteMin()
+    {
+      updatecheck();
+      if (size == 0)
+        throw new NoSuchItemException();
+
+      T retval = array[0];
+
+      size--;
+      Array.Copy(array, 1, array, 0, size);
+      array[size] = default(T);
+      raiseForRemove(retval);
+      return retval;
+    }
+
+
+    /// <summary>
+    /// Find the current largest item of this priority queue.
+    /// </summary>
+    /// <returns>The largest item.</returns>
+    [Tested]
+    public T FindMax()
+    {
+      if (size == 0)
+        throw new NoSuchItemException();
+
+      return array[size - 1];
+    }
+
+
+    /// <summary>
+    /// Remove the largest item from this  priority queue.
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public T DeleteMax()
+    {
+      updatecheck();
+      if (size == 0)
+        throw new NoSuchItemException();
+
+      T retval = array[size - 1];
+
+      size--;
+      array[size] = default(T);
+      raiseForRemove(retval);
+      return retval;
+    }
+
+    /// <summary>
+    /// The comparer object supplied at creation time for this collection
+    /// </summary>
+    /// <value>The comparer</value>
+    public SCG.IComparer<T> Comparer { get { return comparer; } }
+
+    #endregion
+
+    #region IIndexed<T> Members
+
+    /// <summary>
+    /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+    /// &gt;= the size of the collection.
+    /// </summary>
+    /// <value>The i'th item of this list.</value>
+    /// <param name="i">the index to lookup</param>
+    [Tested]
+    public T this[int i]
+    {
+      [Tested]
+      get
+      {
+        if (i < 0 || i >= size)
+          throw new IndexOutOfRangeException();
+
+        return array[i];
+      }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual Speed IndexingSpeed { get { return Speed.Constant; } }
+
+    /// <summary>
+    /// Searches for an item in the list going forwrds from the start.
+    /// </summary>
+    /// <param name="item">Item to search for.</param>
+    /// <returns>Index of item from start.</returns>
+    [Tested]
+    public int IndexOf(T item) { return indexOf(item); }
+
+
+    /// <summary>
+    /// Searches for an item in the list going backwords from the end.
+    /// </summary>
+    /// <param name="item">Item to search for.</param>
+    /// <returns>Index of of item from the end.</returns>
+    [Tested]
+    public int LastIndexOf(T item) { return indexOf(item); }
+
+
+    /// <summary>
+    /// Remove the item at a specific position of the list.
+    /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+    /// &gt;= the size of the collection.
+    /// </summary>
+    /// <param name="i">The index of the item to remove.</param>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public T RemoveAt(int i)
+    {
+      if (i < 0 || i >= size)
+        throw new IndexOutOfRangeException("Index out of range for sequenced collectionvalue");
+
+      updatecheck();
+
+      T retval = array[i];
+
+      size--;
+      Array.Copy(array, i + 1, array, i, size - i);
+      array[size] = default(T);
+      raiseForRemoveAt(i, retval);
+      return retval;
+    }
+
+    /// <summary>
+    /// Remove all items in an index interval.
+    /// <exception cref="IndexOutOfRangeException"/>???. 
+    /// </summary>
+    /// <param name="start">The index of the first item to remove.</param>
+    /// <param name="count">The number of items to remove.</param>
+    [Tested]
+    public void RemoveInterval(int start, int count)
+    {
+      updatecheck();
+      checkRange(start, count);
+      Array.Copy(array, start + count, array, start, size - start - count);
+      size -= count;
+      Array.Clear(array, size, count);
+      raiseForRemoveInterval(start, count);
+    }
+
+    private void raiseForRemoveInterval(int start, int count)
+    {
+      if (ActiveEvents != 0 && count > 0)
+      {
+        raiseCollectionCleared(size == 0, count);
+        raiseCollectionChanged();
+      }
+    }
+
+    #endregion
+
+    #region IDirectedEnumerable<T> Members
+
+    /// <summary>
+    /// Create a collection containing the same items as this collection, but
+    /// whose enumerator will enumerate the items backwards. The new collection
+    /// will become invalid if the original is modified. Method typicaly used as in
+    /// <code>foreach (T x in coll.Backwards()) {...}</code>
+    /// </summary>
+    /// <returns>The backwards collection.</returns>
+    [Tested]
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
+    { return Backwards(); }
+
+    #endregion
+
+    #region ICloneable Members
+
+    /// <summary>
+    /// Make a shallow copy of this SortedArray.
+    /// </summary>
+    /// <returns></returns>
+    public virtual object Clone()
+    {
+      SortedArray<T> clone = new SortedArray<T>(size, comparer, itemequalityComparer);
+      clone.AddSorted(this);
+      return clone;
+    }
+
+    #endregion
+
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/hashing/HashBag.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/hashing/HashBag.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/hashing/HashBag.cs	(revision 3)
@@ -0,0 +1,688 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+
+namespace C5
+{
+  /// <summary>
+  /// A bag collection based on a hash table of (item,count) pairs. 
+  /// </summary>
+  [Serializable]
+  public class HashBag<T> : CollectionBase<T>, ICollection<T>
+  {
+    #region Fields
+    HashSet<KeyValuePair<T, int>> dict;
+    #endregion
+
+    #region Events
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public override EventTypeEnum ListenableEvents { get { return EventTypeEnum.Basic; } }
+
+    #endregion
+
+    #region Constructors
+    /// <summary>
+    /// Create a hash bag with the deafult item equalityComparer.
+    /// </summary>
+    public HashBag() : this(EqualityComparer<T>.Default) { }
+
+    /// <summary>
+    /// Create a hash bag with an external item equalityComparer.
+    /// </summary>
+    /// <param name="itemequalityComparer">The external item equalityComparer.</param>
+    public HashBag(SCG.IEqualityComparer<T> itemequalityComparer)
+      : base(itemequalityComparer)
+    {
+      dict = new HashSet<KeyValuePair<T, int>>(new KeyValuePairEqualityComparer<T, int>(itemequalityComparer));
+    }
+
+    /// <summary>
+    /// Create a hash bag with external item equalityComparer, prescribed initial table size and default fill threshold (66%)
+    /// </summary>
+    /// <param name="capacity">Initial table size (rounded to power of 2, at least 16)</param>
+    /// <param name="itemequalityComparer">The external item equalityComparer</param>
+    public HashBag(int capacity, SCG.IEqualityComparer<T> itemequalityComparer)
+      : base(itemequalityComparer)
+    {
+      dict = new HashSet<KeyValuePair<T, int>>(capacity, new KeyValuePairEqualityComparer<T, int>(itemequalityComparer));
+    }
+
+
+    /// <summary>
+    /// Create a hash bag with external item equalityComparer, prescribed initial table size and fill threshold.
+    /// </summary>
+    /// <param name="capacity">Initial table size (rounded to power of 2, at least 16)</param>
+    /// <param name="fill">Fill threshold (valid range 10% to 90%)</param>
+    /// <param name="itemequalityComparer">The external item equalityComparer</param>
+    public HashBag(int capacity, double fill, SCG.IEqualityComparer<T> itemequalityComparer)
+      : base(itemequalityComparer)
+    {
+      dict = new HashSet<KeyValuePair<T, int>>(capacity, fill, new KeyValuePairEqualityComparer<T, int>(itemequalityComparer));
+    }
+
+    #endregion
+
+    #region IEditableCollection<T> Members
+
+    /// <summary>
+    /// The complexity of the Contains operation
+    /// </summary>
+    /// <value>Always returns Speed.Constant</value>
+    [Tested]
+    public virtual Speed ContainsSpeed { [Tested]get { return Speed.Constant; } }
+
+    /// <summary>
+    /// Check if an item is in the bag 
+    /// </summary>
+    /// <param name="item">The item to look for</param>
+    /// <returns>True if bag contains item</returns>
+    [Tested]
+    public virtual bool Contains(T item)
+    { return dict.Contains(new KeyValuePair<T, int>(item, 0)); }
+
+
+    /// <summary>
+    /// Check if an item (collection equal to a given one) is in the bag and
+    /// if so report the actual item object found.
+    /// </summary>
+    /// <param name="item">On entry, the item to look for.
+    /// On exit the item found, if any</param>
+    /// <returns>True if bag contains item</returns>
+    [Tested]
+    public virtual bool Find(ref T item)
+    {
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 0);
+
+      if (dict.Find(ref p))
+      {
+        item = p.Key;
+        return true;
+      }
+
+      return false;
+    }
+
+
+    /// <summary>
+    /// Check if an item (collection equal to a given one) is in the bag and
+    /// if so replace the item object in the bag with the supplied one.
+    /// </summary>
+    /// <param name="item">The item object to update with</param>
+    /// <returns>True if item was found (and updated)</returns>
+    [Tested]
+    public virtual bool Update(T item)
+    { T olditem = default(T); return Update(item, out olditem); }
+
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public virtual bool Update(T item, out T olditem)
+    {
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 0);
+
+      updatecheck();
+
+      //Note: we cannot just do dict.Update: we have to lookup the count before we 
+      //know what to update with. There is of course a way around if we use the 
+      //implementation of hashset -which we do not want to do.
+      //The hashbag is moreover mainly a proof of concept
+      if (dict.Find(ref p))
+      {
+        olditem = p.Key;
+        p.Key = item;
+        dict.Update(p);
+        if (ActiveEvents != 0)
+          raiseForUpdate(item, olditem, p.Value);
+        return true;
+      }
+
+      olditem = default(T);
+      return false;
+    }
+
+
+    /// <summary>
+    /// Check if an item (collection equal to a given one) is in the bag.
+    /// If found, report the actual item object in the bag,
+    /// else add the supplied one.
+    /// </summary>
+    /// <param name="item">On entry, the item to look for or add.
+    /// On exit the actual object found, if any.</param>
+    /// <returns>True if item was found</returns>
+    [Tested]
+    public virtual bool FindOrAdd(ref T item)
+    {
+      updatecheck();
+      if (Find(ref item))
+        return true;
+
+      Add(item);
+      return false;
+    }
+
+
+    /// <summary>
+    /// Check if an item (collection equal to a supplied one) is in the bag and
+    /// if so replace the item object in the set with the supplied one; else
+    /// add the supplied one.
+    /// </summary>
+    /// <param name="item">The item to look for and update or add</param>
+    /// <returns>True if item was updated</returns>
+    [Tested]
+    public virtual bool UpdateOrAdd(T item)
+    {
+      updatecheck();
+      if (Update(item))
+        return true;
+
+      Add(item);
+      return false;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public virtual bool UpdateOrAdd(T item, out T olditem)
+    {
+      updatecheck();
+      if (Update(item, out olditem))
+        return true;
+
+      Add(item);
+      return false;
+    }
+
+    /// <summary>
+    /// Remove one copy af an item from the bag
+    /// </summary>
+    /// <param name="item">The item to remove</param>
+    /// <returns>True if item was (found and) removed </returns>
+    [Tested]
+    public virtual bool Remove(T item)
+    {
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 0);
+
+      updatecheck();
+      if (dict.Find(ref p))
+      {
+        size--;
+        if (p.Value == 1)
+          dict.Remove(p);
+        else
+        {
+          p.Value--;
+          dict.Update(p);
+        }
+        if (ActiveEvents != 0)
+          raiseForRemove(p.Key);
+        return true;
+      }
+
+      return false;
+    }
+
+
+    /// <summary>
+    /// Remove one copy of an item from the bag, reporting the actual matching item object.
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    /// <param name="removeditem">The removed value.</param>
+    /// <returns>True if item was found.</returns>
+    [Tested]
+    public virtual bool Remove(T item, out T removeditem)
+    {
+      updatecheck();
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 0);
+      if (dict.Find(ref p))
+      {
+        removeditem = p.Key;
+        size--;
+        if (p.Value == 1)
+          dict.Remove(p);
+        else
+        {
+          p.Value--;
+          dict.Update(p);
+        }
+        if (ActiveEvents != 0)
+          raiseForRemove(removeditem);
+
+        return true;
+      }
+
+      removeditem = default(T);
+      return false;
+    }
+
+    /// <summary>
+    /// Remove all items in a supplied collection from this bag, counting multiplicities.
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to remove.</param>
+    [Tested]
+    public virtual void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+#warning Improve if items is a counting bag
+      updatecheck();
+      bool mustRaise = (ActiveEvents & (EventTypeEnum.Changed | EventTypeEnum.Removed)) != 0;
+      RaiseForRemoveAllHandler raiseHandler = mustRaise ? new RaiseForRemoveAllHandler(this) : null;
+      foreach (U item in items)
+      {
+        KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 0);
+        if (dict.Find(ref p))
+        {
+          size--;
+          if (p.Value == 1)
+            dict.Remove(p);
+          else
+          {
+            p.Value--;
+            dict.Update(p);
+          }
+          if (mustRaise)
+            raiseHandler.Remove(p.Key);
+        }
+      }
+      if (mustRaise)
+        raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// Remove all items from the bag, resetting internal table to initial size.
+    /// </summary>
+    [Tested]
+    public virtual void Clear()
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      dict.Clear();
+      int oldsize = size;
+      size = 0;
+      if ((ActiveEvents & EventTypeEnum.Cleared) != 0)
+        raiseCollectionCleared(true, oldsize);
+      if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+        raiseCollectionChanged();
+    }
+
+
+    /// <summary>
+    /// Remove all items *not* in a supplied collection from this bag,
+    /// counting multiplicities.
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to retain</param>
+    [Tested]
+    public virtual void RetainAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      updatecheck();
+
+      HashBag<T> res = new HashBag<T>(itemequalityComparer);
+
+      foreach (U item in items)
+      {
+        KeyValuePair<T, int> p = new KeyValuePair<T, int>(item);
+        if (dict.Find(ref p))
+        {
+          KeyValuePair<T, int> q = p;
+          if (res.dict.Find(ref q))
+          {
+            if (q.Value < p.Value)
+            {
+              q.Value++;
+              res.dict.Update(q);
+              res.size++;
+            }
+          }
+          else
+          {
+            q.Value = 1;
+            res.dict.Add(q);
+            res.size++;
+          }
+        }
+      }
+
+      if (size == res.size)
+        return;
+
+      CircularQueue<T> wasRemoved = null;
+      if ((ActiveEvents & EventTypeEnum.Removed) != 0)
+      {
+        wasRemoved = new CircularQueue<T>();
+        foreach (KeyValuePair<T, int> p in dict)
+        {
+          int removed = p.Value - res.ContainsCount(p.Key);
+          if (removed > 0)
+#warning We could send bag events here easily using a CircularQueue of (should?)
+            for (int i = 0; i < removed; i++)
+              wasRemoved.Enqueue(p.Key);
+        }
+      }
+      dict = res.dict;
+      size = res.size;
+
+      if ((ActiveEvents & EventTypeEnum.Removed) != 0)
+        raiseForRemoveAll(wasRemoved);
+      else if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+        raiseCollectionChanged();
+    }
+
+    /// <summary>
+    /// Check if all items in a supplied collection is in this bag
+    /// (counting multiplicities). 
+    /// </summary>
+    /// <param name="items">The items to look for.</param>
+    /// <typeparam name="U"></typeparam>
+    /// <returns>True if all items are found.</returns>
+    [Tested]
+    public virtual bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      HashBag<T> res = new HashBag<T>(itemequalityComparer);
+
+      foreach (T item in items)
+        if (res.ContainsCount(item) < ContainsCount(item))
+          res.Add(item);
+        else
+          return false;
+
+      return true;
+    }
+
+
+    /// <summary>
+    /// Create an array containing all items in this bag (in enumeration order).
+    /// </summary>
+    /// <returns>The array</returns>
+    [Tested]
+    public override T[] ToArray()
+    {
+      T[] res = new T[size];
+      int ind = 0;
+
+      foreach (KeyValuePair<T, int> p in dict)
+        for (int i = 0; i < p.Value; i++)
+          res[ind++] = p.Key;
+
+      return res;
+    }
+
+
+    /// <summary>
+    /// Count the number of times an item is in this set.
+    /// </summary>
+    /// <param name="item">The item to look for.</param>
+    /// <returns>The count</returns>
+    [Tested]
+    public virtual int ContainsCount(T item)
+    {
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 0);
+
+      if (dict.Find(ref p))
+        return p.Value;
+
+      return 0;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<T> UniqueItems() { return new DropMultiplicity<T>(dict); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities()
+    {
+      return new GuardedCollectionValue<KeyValuePair<T, int>>(dict);
+    }
+
+    /// <summary>
+    /// Remove all copies of item from this set.
+    /// </summary>
+    /// <param name="item">The item to remove</param>
+    [Tested]
+    public virtual void RemoveAllCopies(T item)
+    {
+      updatecheck();
+
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 0);
+
+      if (dict.Find(ref p))
+      {
+        size -= p.Value;
+        dict.Remove(p);
+        if ((ActiveEvents & EventTypeEnum.Removed) != 0)
+          raiseItemsRemoved(p.Key, p.Value);
+        if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+          raiseCollectionChanged();
+      }
+    }
+
+    #endregion
+
+    #region ICollection<T> Members
+
+
+    /// <summary>
+    /// Copy the items of this bag to part of an array.
+    /// <exception cref="ArgumentOutOfRangeException"/> if i is negative.
+    /// <exception cref="ArgumentException"/> if the array does not have room for the items.
+    /// </summary>
+    /// <param name="array">The array to copy to</param>
+    /// <param name="index">The starting index.</param>
+    [Tested]
+    public override void CopyTo(T[] array, int index)
+    {
+      if (index < 0 || index + Count > array.Length)
+        throw new ArgumentOutOfRangeException();
+
+      foreach (KeyValuePair<T, int> p in dict)
+        for (int j = 0; j < p.Value; j++)
+          array[index++] = p.Key;
+    }
+
+    #endregion
+
+    #region IExtensible<T> Members
+
+    /// <summary>
+    /// Report if this is a set collection.
+    /// </summary>
+    /// <value>Always true</value>
+    [Tested]
+    public virtual bool AllowsDuplicates { [Tested] get { return true; } }
+
+    /// <summary>
+    /// By convention this is true for any collection with set semantics.
+    /// </summary>
+    /// <value>True if only one representative of a group of equal items 
+    /// is kept in the collection together with the total count.</value>
+    public virtual bool DuplicatesByCounting { get { return true; } }
+
+    /// <summary>
+    /// Add an item to this bag.
+    /// </summary>
+    /// <param name="item">The item to add.</param>
+    /// <returns>Always true</returns>
+    [Tested]
+    public virtual bool Add(T item)
+    {
+      updatecheck();
+      add(ref item);
+      if (ActiveEvents != 0)
+        raiseForAdd(item);
+      return true;
+    }
+
+    /// <summary>
+    /// Add an item to this bag.
+    /// </summary>
+    /// <param name="item">The item to add.</param>
+    [Tested]
+    void SCG.ICollection<T>.Add(T item)
+    {
+        Add(item);
+    }
+
+    private void add(ref T item)
+    {
+      KeyValuePair<T, int> p = new KeyValuePair<T, int>(item, 1);
+      if (dict.Find(ref p))
+      {
+        p.Value++;
+        dict.Update(p);
+        item = p.Key;
+      }
+      else
+        dict.Add(p);
+      size++;
+    }
+
+    /// <summary>
+    /// Add the elements from another collection with a more specialized item type 
+    /// to this collection. 
+    /// </summary>
+    /// <typeparam name="U">The type of items to add</typeparam>
+    /// <param name="items">The items to add</param>
+    public virtual void AddAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      updatecheck();
+#warning We could easily raise bag events
+      bool mustRaiseAdded = (ActiveEvents & EventTypeEnum.Added) != 0;
+      CircularQueue<T> wasAdded = mustRaiseAdded ? new CircularQueue<T>() : null;
+      bool wasChanged = false;
+      foreach (T item in items)
+      {
+        T jtem = item;
+        add(ref jtem);
+        wasChanged = true;
+        if (mustRaiseAdded)
+          wasAdded.Enqueue(jtem);
+      }
+      if (!wasChanged)
+        return;
+      if (mustRaiseAdded)
+        foreach (T item in wasAdded)
+          raiseItemsAdded(item, 1);
+      if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+        raiseCollectionChanged();
+    }
+
+    #endregion
+
+    #region IEnumerable<T> Members
+
+
+    /// <summary>
+    /// Choose some item of this collection. 
+    /// </summary>
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>
+    /// <returns></returns>
+    public override T Choose()
+    {
+      return dict.Choose().Key;
+    }
+
+    /// <summary>
+    /// Create an enumerator for this bag.
+    /// </summary>
+    /// <returns>The enumerator</returns>
+    [Tested]
+    public override SCG.IEnumerator<T> GetEnumerator()
+    {
+      int left;
+      int mystamp = stamp;
+
+      foreach (KeyValuePair<T, int> p in dict)
+      {
+        left = p.Value;
+        while (left > 0)
+        {
+          if (mystamp != stamp)
+            throw new CollectionModifiedException();
+
+          left--;
+          yield return p.Key;
+        }
+      }
+    }
+    #endregion
+
+    #region ICloneable Members
+
+    /// <summary>
+    /// Make a shallow copy of this HashBag.
+    /// </summary>
+    /// <returns></returns>
+    public virtual object Clone()
+    {
+      //TODO: make sure this 
+      HashBag<T> clone = new HashBag<T>(dict.Count > 0 ? dict.Count : 1, itemequalityComparer);
+      //TODO: make sure this really adds in the counting bag way!
+      clone.AddAll(this);
+      return clone;
+    }
+
+    #endregion
+
+
+    #region Diagnostics
+    /// <summary>
+    /// Test internal structure of data (invariants)
+    /// </summary>
+    /// <returns>True if pass</returns>
+    [Tested]
+    public virtual bool Check()
+    {
+      bool retval = dict.Check();
+      int count = 0;
+
+      foreach (KeyValuePair<T, int> p in dict)
+        count += p.Value;
+
+      if (count != size)
+      {
+        Console.WriteLine("count({0}) != size({1})", count, size);
+        retval = false;
+      }
+
+      return retval;
+    }
+    #endregion
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/hashing/HashDictionary.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/hashing/HashDictionary.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/hashing/HashDictionary.cs	(revision 3)
@@ -0,0 +1,77 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+
+namespace C5
+{
+  /// <summary>
+  /// A generic dictionary class based on a hash set class <see cref="T:C5.HashSet`1"/>. 
+  /// </summary>
+  [Serializable]
+  public class HashDictionary<K, V> : DictionaryBase<K, V>, IDictionary<K, V>
+  {
+    /// <summary>
+    /// Create a hash dictionary using a default equalityComparer for the keys.
+    /// Initial capacity of internal table will be 16 entries and threshold for 
+    /// expansion is 66% fill.
+    /// </summary>
+    public HashDictionary() : this(EqualityComparer<K>.Default) { }
+
+    /// <summary>
+    /// Create a hash dictionary using a custom equalityComparer for the keys.
+    /// Initial capacity of internal table will be 16 entries and threshold for 
+    /// expansion is 66% fill.
+    /// </summary>
+    /// <param name="keyequalityComparer">The external key equalityComparer</param>
+    public HashDictionary(SCG.IEqualityComparer<K> keyequalityComparer) : base(keyequalityComparer)
+    {
+      pairs = new HashSet<KeyValuePair<K, V>>(new KeyValuePairEqualityComparer<K, V>(keyequalityComparer));
+    }
+
+    /// <summary>
+    /// Create a hash dictionary using a custom equalityComparer and prescribing the 
+    /// initial size of the dictionary and a non-default threshold for internal table expansion.
+    /// </summary>
+    /// <param name="capacity">The initial capacity. Will be rounded upwards to nearest
+    /// power of 2, at least 16.</param>
+    /// <param name="fill">The expansion threshold. Must be between 10% and 90%.</param>
+    /// <param name="keyequalityComparer">The external key equalityComparer</param>
+    public HashDictionary(int capacity, double fill, SCG.IEqualityComparer<K> keyequalityComparer): base(keyequalityComparer)
+    {
+      pairs = new HashSet<KeyValuePair<K, V>>(capacity, fill, new KeyValuePairEqualityComparer<K, V>(keyequalityComparer));
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override object Clone()
+    {
+      HashDictionary<K, V> clone = new HashDictionary<K, V>(EqualityComparer);
+      clone.pairs.AddAll(pairs);
+      return clone;
+    }
+
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/hashing/HashTable.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/hashing/HashTable.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/hashing/HashTable.cs	(revision 3)
@@ -0,0 +1,1640 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+#define LINEARPROBINGnot
+#define REFBUCKET
+#define SHRINKnot
+#define INTERHASHINGnot
+#define RANDOMINTERHASHING
+
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+
+namespace C5
+{
+  /// <summary>
+  /// A set collection class based on linear hashing
+  /// </summary>
+  [Serializable]
+  public class HashSet<T> : CollectionBase<T>, ICollection<T>
+  {
+    #region Feature
+    /// <summary>
+    /// Enum class to assist printing of compilation alternatives.
+    /// </summary>
+    [Flags]
+    public enum Feature : short
+    {
+      /// <summary>
+      /// Nothing
+      /// </summary>
+      Dummy = 0,
+      /// <summary>
+      /// Buckets are of reference type
+      /// </summary>
+      RefTypeBucket = 1,
+      /// <summary>
+      /// Primary buckets are of value type
+      /// </summary>
+      ValueTypeBucket = 2,
+      /// <summary>
+      /// Using linear probing to resolve index clashes
+      /// </summary>
+      LinearProbing = 4,
+      /// <summary>
+      /// Shrink table when very sparsely filled
+      /// </summary>
+      ShrinkTable = 8,
+      /// <summary>
+      /// Use chaining to resolve index clashes
+      /// </summary>
+      Chaining = 16,
+      /// <summary>
+      /// Use hash function on item hash code
+      /// </summary>
+      InterHashing = 32,
+      /// <summary>
+      /// Use a universal family of hash functions on item hash code
+      /// </summary>
+      RandomInterHashing = 64
+    }
+
+
+
+    static Feature features = Feature.Dummy
+#if REFBUCKET
+ | Feature.RefTypeBucket
+#else
+ | Feature.ValueTypeBucket
+#endif
+#if SHRINK
+		| Feature.ShrinkTable
+#endif
+#if LINEARPROBING
+ | Feature.LinearProbing
+#else
+ | Feature.Chaining
+#endif
+#if INTERHASHING
+		| Feature.InterHashing
+#elif RANDOMINTERHASHING
+ | Feature.RandomInterHashing
+#endif
+;
+
+
+    /// <summary>
+    /// Show which implementation features was chosen at compilation time
+    /// </summary>
+    public static Feature Features { get { return features; } }
+
+    #endregion
+
+    #region Fields
+
+    int indexmask, bits, bitsc, origbits, lastchosen; //bitsc==32-bits; indexmask==(1<<bits)-1;
+
+    Bucket[] table;
+
+#if !REFBUCKET
+    bool defaultvalid = false;
+
+    T defaultitem;
+#endif
+    double fillfactor = 0.66;
+
+    int resizethreshhold;
+
+#if RANDOMINTERHASHING
+#if DEBUG
+    const uint randomhashfactor = 1529784659;
+#else
+    uint randomhashfactor = (2 * (uint)(new Random()).Next() + 1) * 1529784659;
+#endif
+#endif
+
+    #endregion
+
+    #region Events
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public override EventTypeEnum ListenableEvents { get { return EventTypeEnum.Basic; } }
+
+    #endregion
+
+    #region Bucket nested class(es)
+#if REFBUCKET
+    [Serializable]
+    class Bucket
+    {
+      internal T item;
+
+      internal int hashval; //Cache!
+
+#if LINEARPROBING
+      internal Bucket(T item, int hashval)
+      {
+        this.item = item;
+        this.hashval = hashval;
+      }
+#else
+      internal Bucket overflow;
+
+      internal Bucket(T item, int hashval, Bucket overflow)
+      {
+        this.item = item;
+        this.hashval = hashval;
+        this.overflow = overflow;
+      }
+#endif
+    }
+#else
+    struct Bucket
+    {
+      internal T item;
+
+      internal int hashval; //Cache!
+
+#if LINEARPROBING
+      internal Bucket(T item, int hashval)
+      {
+        this.item = item;
+        this.hashval = hashval;
+      }
+#else
+			internal OverflowBucket overflow;
+
+
+			internal Bucket(T item, int hashval)
+			{
+				this.item = item;
+				this.hashval = hashval;
+				this.overflow = default(OverflowBucket);
+			}
+#endif
+    }
+
+
+#if !LINEARPROBING
+		class OverflowBucket
+		{
+			internal T item;
+
+			internal int hashval; //Cache!
+
+			internal OverflowBucket overflow;
+
+
+			internal OverflowBucket(T item, int hashval, OverflowBucket overflow)
+			{
+				this.item = item;
+				this.hashval = hashval;
+				this.overflow = overflow;
+			}
+		}
+#endif
+#endif
+
+    #endregion
+
+    #region Basic Util
+
+    bool equals(T i1, T i2) { return itemequalityComparer.Equals(i1, i2); }
+
+#if !REFBUCKET
+    bool isnull(T item) { return itemequalityComparer.Equals(item, default(T)); }
+#endif
+
+    int gethashcode(T item) { return itemequalityComparer.GetHashCode(item); }
+
+
+    int hv2i(int hashval)
+    {
+#if INTERHASHING
+			//Note: *inverse  mod 2^32 is -1503427877
+			return (int)(((uint)hashval * 1529784659) >>bitsc); 
+#elif RANDOMINTERHASHING
+      return (int)(((uint)hashval * randomhashfactor) >> bitsc);
+#else
+			return indexmask & hashval;
+#endif
+    }
+
+
+    void expand()
+    {
+      //Console.WriteLine(String.Format("Expand to {0} bits", bits+1));
+      resize(bits + 1);
+    }
+
+
+    void shrink()
+    {
+      if (bits > 3)
+      {
+        //Console.WriteLine(String.Format("Shrink to {0} bits", bits - 1));
+        resize(bits - 1);
+      }
+    }
+
+
+    void resize(int bits)
+    {
+      //Console.WriteLine(String.Format("Resize to {0} bits", bits));
+      this.bits = bits;
+      bitsc = 32 - bits;
+      indexmask = (1 << bits) - 1;
+
+      Bucket[] newtable = new Bucket[indexmask + 1];
+
+      for (int i = 0, s = table.Length; i < s; i++)
+      {
+        Bucket b = table[i];
+
+#if LINEARPROBING
+#if REFBUCKET
+        if (b != null)
+        {
+          int j = hv2i(b.hashval);
+
+          while (newtable[j] != null) { j = indexmask & (j + 1); }
+
+          newtable[j] = b;
+        }
+#else
+        if (!isnull(b.item))
+        {
+          int j = hv2i(b.hashval);
+
+          while (!isnull(newtable[j].item)) { j = indexmask & (j + 1); }
+
+          newtable[j] = b;
+        }
+#endif
+#else
+#if REFBUCKET
+        while (b != null)
+        {
+          int j = hv2i(b.hashval);
+
+          newtable[j] = new Bucket(b.item, b.hashval, newtable[j]);
+          b = b.overflow;
+        }
+#else
+				if (!isnull(b.item))
+				{
+					insert(b.item, b.hashval, newtable);
+
+					OverflowBucket ob = b.overflow;
+
+					while (ob != null)
+					{
+						insert(ob.item, ob.hashval, newtable);
+						ob = ob.overflow;
+					}
+				}
+#endif
+#endif
+      }
+
+      table = newtable;
+      resizethreshhold = (int)(table.Length * fillfactor);
+      //Console.WriteLine(String.Format("Resize to {0} bits done", bits));
+    }
+
+#if REFBUCKET
+#else
+#if LINEARPROBING
+#else
+		//Only for resize!!!
+		private void insert(T item, int hashval, Bucket[] t)
+		{
+			int i = hv2i(hashval);
+			Bucket b = t[i];
+
+			if (!isnull(b.item))
+			{
+				t[i].overflow = new OverflowBucket(item, hashval, b.overflow);
+			}
+			else
+				t[i] = new Bucket(item, hashval);
+		}
+#endif
+#endif
+
+    /// <summary>
+    /// Search for an item equal (according to itemequalityComparer) to the supplied item.  
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="add">If true, add item to table if not found.</param>
+    /// <param name="update">If true, update table entry if item found.</param>
+    /// <param name="raise">If true raise events</param>
+    /// <returns>True if found</returns>
+    private bool searchoradd(ref T item, bool add, bool update, bool raise)
+    {
+
+#if LINEARPROBING
+#if REFBUCKET
+      int hashval = gethashcode(item);
+      int i = hv2i(hashval);
+      Bucket b = table[i];
+
+      while (b != null)
+      {
+        T olditem = b.item;
+        if (equals(olditem, item))
+        {
+          if (update)
+            b.item = item;
+          else
+            item = olditem;
+
+          if (raise && update)
+            raiseForUpdate(item, olditem);
+          return true;
+        }
+
+        b = table[i = indexmask & (i + 1)];
+      }
+
+      if (!add) goto notfound;
+
+      table[i] = new Bucket(item, hashval);
+
+#else
+      if (isnull(item))
+      {
+        if (defaultvalid)
+        {
+          T olditem = defaultitem;
+          if (update)
+            defaultitem = item;
+          else
+            item = defaultitem;
+
+          if (raise && update)
+            raiseForUpdate(item, olditem);
+          return true;
+        }
+
+        if (!add) goto notfound;
+
+        defaultvalid = true;
+        defaultitem = item;
+      }
+      else
+      {
+        int hashval = gethashcode(item);
+        int i = hv2i(hashval);
+        T t = table[i].item;
+
+        while (!isnull(t))
+        {
+          if (equals(t, item))
+          {
+            if (update)
+              table[i].item = item;
+            else
+              item = t;
+
+            if (raise && update)
+              raiseForUpdate(item, t);
+            return true;
+          }
+
+          t = table[i = indexmask & (i + 1)].item;
+        }
+
+        if (!add) goto notfound;
+
+        table[i] = new Bucket(item, hashval);
+      }
+#endif
+#else
+#if REFBUCKET
+      int hashval = gethashcode(item);
+      int i = hv2i(hashval);
+      Bucket b = table[i], bold = null;
+
+      if (b != null)
+      {
+        while (b != null)
+        {
+          T olditem = b.item;
+          if (equals(olditem, item))
+          {
+            if (update)
+            {
+              b.item = item;
+            }
+            if (raise && update)
+              raiseForUpdate(item, olditem);
+            // bug20071112:
+            item = olditem;
+            return true;
+          }
+
+          bold = b;
+          b = b.overflow;
+        }
+
+        if (!add) goto notfound;
+
+        bold.overflow = new Bucket(item, hashval, null);
+      }
+      else
+      {
+        if (!add) goto notfound;
+
+        table[i] = new Bucket(item, hashval, null);
+      }
+#else
+			if (isnull(item))
+			{
+        if (defaultvalid)
+        {
+          T olditem = defaultitem;
+          if (update)
+            defaultitem = item;
+          else
+            item = defaultitem;
+
+          if (raise && update)
+            raiseForUpdate(item, olditem);
+          return true;
+        }
+
+				if (!add) goto notfound;
+
+				defaultvalid = true;
+				defaultitem = item;
+			}
+			else
+			{
+				int hashval = gethashcode(item);
+				int i = hv2i(hashval);
+				Bucket b = table[i];
+
+				if (!isnull(b.item))
+				{
+					if (equals(b.item, item))
+					{
+						if (update)
+							table[i].item = item;
+						else
+							item = b.item;
+
+            if (raise && update)
+              raiseForUpdate(item, b.item);
+            return true;
+					}
+
+					OverflowBucket ob = table[i].overflow;
+
+					if (ob == null)
+					{
+						if (!add) goto notfound;
+
+						table[i].overflow = new OverflowBucket(item, hashval, null);
+					}
+					else
+					{
+            T olditem = ob.item;
+						while (ob.overflow != null)
+						{
+              if (equals(item, olditem))
+              {
+                if (update)
+                  ob.item = item;
+                else
+                  item = olditem;
+
+                if (raise && update)
+                  raiseForUpdate(item, olditem);
+                return true;
+              }
+
+							ob = ob.overflow;
+              olditem = ob.item;
+						}
+
+            if (equals(item, olditem))
+            {
+              if (update)
+                ob.item = item;
+              else
+                item = olditem;
+
+              if (raise && update)
+                raiseForUpdate(item, olditem);
+              return true;
+            }
+
+						if (!add) goto notfound;
+
+						ob.overflow = new OverflowBucket(item, hashval, null);
+					}
+				}
+				else
+				{
+					if (!add) goto notfound;
+
+					table[i] = new Bucket(item, hashval);
+				}
+			}
+#endif
+#endif
+      size++;
+      if (size > resizethreshhold)
+        expand();
+    notfound:
+      if (raise && add)
+        raiseForAdd(item);
+      if (update)
+        item = default(T);
+      return false;
+    }
+
+
+    private bool remove(ref T item)
+    {
+
+      if (size == 0)
+        return false;
+#if LINEARPROBING
+#if REFBUCKET
+      int hashval = gethashcode(item);
+      int index = hv2i(hashval);
+      Bucket b = table[index];
+
+      while (b != null)
+      {
+        if (equals(item, b.item))
+        {
+          //ref
+          item = table[index].item;
+          table[index] = null;
+
+          //Algorithm R
+          int j = (index + 1) & indexmask;
+
+          b = table[j];
+          while (b != null)
+          {
+            int k = hv2i(b.hashval);
+
+            if ((k <= index && index < j) || (index < j && j < k) || (j < k && k <= index))
+            //if (index > j ? (j < k && k <= index): (k <= index || j < k) )
+            {
+              table[index] = b;
+              table[j] = null;
+              index = j;
+            }
+
+            j = (j + 1) & indexmask;
+            b = table[j];
+          }
+
+          goto found;
+        }
+
+        b = table[index = indexmask & (index + 1)];
+      }
+      return false;
+#else
+      if (isnull(item))
+      {
+        if (!defaultvalid)
+          return false;
+
+        //ref
+        item = defaultitem;
+        defaultvalid = false;
+        defaultitem = default(T); //No spaceleaks!
+      }
+      else
+      {
+        int hashval = gethashcode(item);
+        int index = hv2i(hashval);
+        T t = table[index].item;
+
+        while (!isnull(t))
+        {
+          if (equals(item, t))
+          {
+            //ref
+            item = table[index].item;
+            table[index].item = default(T);
+
+            //algorithm R
+            int j = (index + 1) & indexmask;
+            Bucket b = table[j];
+
+            while (!isnull(b.item))
+            {
+              int k = hv2i(b.hashval);
+
+              if ((k <= index && index < j) || (index < j && j < k) || (j < k && k <= index))
+              {
+                table[index] = b;
+                table[j].item = default(T);
+                index = j;
+              }
+
+              j = (j + 1) & indexmask;
+              b = table[j];
+            }
+
+            goto found;
+          }
+
+          t = table[index = indexmask & (index + 1)].item;
+        }
+
+        return false;
+      }
+#endif
+    found:
+#else
+#if REFBUCKET
+      int hashval = gethashcode(item);
+      int index = hv2i(hashval);
+      Bucket b = table[index], bold;
+
+      if (b == null)
+        return false;
+
+      if (equals(item, b.item))
+      {
+        //ref
+        item = b.item;
+        table[index] = b.overflow;
+      }
+      else
+      {
+        bold = b;
+        b = b.overflow;
+        while (b != null && !equals(item, b.item))
+        {
+          bold = b;
+          b = b.overflow;
+        }
+
+        if (b == null)
+          return false;
+
+        //ref
+        item = b.item;
+        bold.overflow = b.overflow;
+      }
+
+#else
+			if (isnull(item))
+			{
+				if (!defaultvalid)
+					return false;
+
+				//ref
+				item = defaultitem;
+				defaultvalid = false;
+				defaultitem = default(T); //No spaceleaks!
+			}
+			else
+			{
+				int hashval = gethashcode(item);
+				int index = hv2i(hashval);
+				Bucket b = table[index];
+				OverflowBucket ob = b.overflow;
+
+				if (equals(item, b.item))
+				{
+					//ref
+					item = b.item;
+					if (ob == null)
+					{
+						table[index] = new Bucket();
+					}
+					else
+					{
+						b = new Bucket(ob.item, ob.hashval);
+						b.overflow = ob.overflow;
+						table[index] = b;
+					}
+				}
+				else
+				{
+					if (ob == null)
+						return false;
+
+					if (equals(item, ob.item)) 
+					{
+						//ref
+						item=ob.item;
+						table[index].overflow = ob.overflow;
+					}
+					else
+					{
+						while (ob.overflow != null)
+							if (equals(item, ob.overflow.item))
+							{
+								//ref
+								item = ob.overflow.item;
+								break;
+							}
+							else
+								ob = ob.overflow;
+
+						if (ob.overflow == null)
+							return false;
+
+						ob.overflow = ob.overflow.overflow;
+					}
+				}
+			}
+#endif
+#endif
+      size--;
+
+      return true;
+    }
+
+
+    private void clear()
+    {
+      bits = origbits;
+      bitsc = 32 - bits;
+      indexmask = (1 << bits) - 1;
+      size = 0;
+      table = new Bucket[indexmask + 1];
+      resizethreshhold = (int)(table.Length * fillfactor);
+#if !REFBUCKET
+      defaultitem = default(T);
+      defaultvalid = false;
+#endif
+    }
+
+    #endregion
+
+    #region Constructors
+    /// <summary>
+    /// Create a hash set with natural item equalityComparer and default fill threshold (66%)
+    /// and initial table size (16).
+    /// </summary>
+    public HashSet()
+      : this(EqualityComparer<T>.Default) { }
+
+
+    /// <summary>
+    /// Create a hash set with external item equalityComparer and default fill threshold (66%)
+    /// and initial table size (16).
+    /// </summary>
+    /// <param name="itemequalityComparer">The external item equalityComparer</param>
+    public HashSet(SCG.IEqualityComparer<T> itemequalityComparer)
+      : this(16, itemequalityComparer) { }
+
+
+    /// <summary>
+    /// Create a hash set with external item equalityComparer and default fill threshold (66%)
+    /// </summary>
+    /// <param name="capacity">Initial table size (rounded to power of 2, at least 16)</param>
+    /// <param name="itemequalityComparer">The external item equalityComparer</param>
+    public HashSet(int capacity, SCG.IEqualityComparer<T> itemequalityComparer)
+      : this(capacity, 0.66, itemequalityComparer) { }
+
+
+    /// <summary>
+    /// Create a hash set with external item equalityComparer.
+    /// </summary>
+    /// <param name="capacity">Initial table size (rounded to power of 2, at least 16)</param>
+    /// <param name="fill">Fill threshold (in range 10% to 90%)</param>
+    /// <param name="itemequalityComparer">The external item equalityComparer</param>
+    public HashSet(int capacity, double fill, SCG.IEqualityComparer<T> itemequalityComparer)
+      : base(itemequalityComparer)
+    {
+      if (fill < 0.1 || fill > 0.9)
+        throw new ArgumentException("Fill outside valid range [0.1, 0.9]");
+      if (capacity <= 0)
+        throw new ArgumentException("Capacity must be non-negative");
+      //this.itemequalityComparer = itemequalityComparer;
+      origbits = 4;
+      while (capacity - 1 >> origbits > 0) origbits++;
+      clear();
+    }
+
+
+
+    #endregion
+
+    #region IEditableCollection<T> Members
+
+    /// <summary>
+    /// The complexity of the Contains operation
+    /// </summary>
+    /// <value>Always returns Speed.Constant</value>
+    [Tested]
+    public virtual Speed ContainsSpeed { [Tested]get { return Speed.Constant; } }
+
+    /// <summary>
+    /// Check if an item is in the set 
+    /// </summary>
+    /// <param name="item">The item to look for</param>
+    /// <returns>True if set contains item</returns>
+    [Tested]
+    public virtual bool Contains(T item) { return searchoradd(ref item, false, false, false); }
+
+
+    /// <summary>
+    /// Check if an item (collection equal to a given one) is in the set and
+    /// if so report the actual item object found.
+    /// </summary>
+    /// <param name="item">On entry, the item to look for.
+    /// On exit the item found, if any</param>
+    /// <returns>True if set contains item</returns>
+    [Tested]
+    public virtual bool Find(ref T item) { return searchoradd(ref item, false, false, false); }
+
+
+    /// <summary>
+    /// Check if an item (collection equal to a given one) is in the set and
+    /// if so replace the item object in the set with the supplied one.
+    /// </summary>
+    /// <param name="item">The item object to update with</param>
+    /// <returns>True if item was found (and updated)</returns>
+    [Tested]
+    public virtual bool Update(T item)
+    { updatecheck(); return searchoradd(ref item, false, true, true); }
+
+    /// <summary>
+    /// Check if an item (collection equal to a given one) is in the set and
+    /// if so replace the item object in the set with the supplied one.
+    /// </summary>
+    /// <param name="item">The item object to update with</param>
+    /// <param name="olditem"></param>
+    /// <returns>True if item was found (and updated)</returns>
+    public virtual bool Update(T item, out T olditem)
+    { updatecheck(); olditem = item; return searchoradd(ref olditem, false, true, true); }
+
+
+    /// <summary>
+    /// Check if an item (collection equal to a given one) is in the set.
+    /// If found, report the actual item object in the set,
+    /// else add the supplied one.
+    /// </summary>
+    /// <param name="item">On entry, the item to look for or add.
+    /// On exit the actual object found, if any.</param>
+    /// <returns>True if item was found</returns>
+    [Tested]
+    public virtual bool FindOrAdd(ref T item)
+    { updatecheck(); return searchoradd(ref item, true, false, true); }
+
+
+    /// <summary>
+    /// Check if an item (collection equal to a supplied one) is in the set and
+    /// if so replace the item object in the set with the supplied one; else
+    /// add the supplied one.
+    /// </summary>
+    /// <param name="item">The item to look for and update or add</param>
+    /// <returns>True if item was updated</returns>
+    [Tested]
+    public virtual bool UpdateOrAdd(T item)
+    { updatecheck(); return searchoradd(ref item, true, true, true); }
+
+
+    /// <summary>
+    /// Check if an item (collection equal to a supplied one) is in the set and
+    /// if so replace the item object in the set with the supplied one; else
+    /// add the supplied one.
+    /// </summary>
+    /// <param name="item">The item to look for and update or add</param>
+    /// <param name="olditem"></param>
+    /// <returns>True if item was updated</returns>
+    public virtual bool UpdateOrAdd(T item, out T olditem)
+    { updatecheck(); olditem = item; return searchoradd(ref olditem, true, true, true); }
+
+
+    /// <summary>
+    /// Remove an item from the set
+    /// </summary>
+    /// <param name="item">The item to remove</param>
+    /// <returns>True if item was (found and) removed </returns>
+    [Tested]
+    public virtual bool Remove(T item)
+    {
+      updatecheck();
+      if (remove(ref item))
+      {
+#if SHRINK
+				if (size<resizethreshhold/2 && resizethreshhold>8)
+					shrink();
+#endif
+        raiseForRemove(item);
+        return true;
+      }
+      else
+        return false;
+    }
+
+
+    /// <summary>
+    /// Remove an item from the set, reporting the actual matching item object.
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    /// <param name="removeditem">The removed value.</param>
+    /// <returns>True if item was found.</returns>
+    [Tested]
+    public virtual bool Remove(T item, out T removeditem)
+    {
+      updatecheck();
+      removeditem = item;
+      if (remove(ref removeditem))
+      {
+#if SHRINK
+				if (size<resizethreshhold/2 && resizethreshhold>8)
+					shrink();
+#endif
+        raiseForRemove(removeditem);
+        return true;
+      }
+      else
+        return false;
+    }
+
+
+    /// <summary>
+    /// Remove all items in a supplied collection from this set.
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to remove.</param>
+    [Tested]
+    public virtual void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      updatecheck();
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(this);
+      bool raise = raiseHandler.MustFire;
+      T jtem;
+      foreach (U item in items)
+      { jtem = item; if (remove(ref jtem) && raise) raiseHandler.Remove(jtem); }
+#if SHRINK
+			if (size < resizethreshhold / 2 && resizethreshhold > 16)
+			{
+				int newlength = table.Length;
+
+				while (newlength >= 32 && newlength * fillfactor / 2 > size)
+					newlength /= 2;
+
+				resize(newlength - 1);
+			}
+#endif
+      if (raise) raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// Remove all items from the set, resetting internal table to initial size.
+    /// </summary>
+    [Tested]
+    public virtual void Clear()
+    {
+      updatecheck();
+      int oldsize = size;
+      clear();
+      if (ActiveEvents != 0 && oldsize > 0)
+      {
+        raiseCollectionCleared(true, oldsize);
+        raiseCollectionChanged();
+      }
+    }
+
+
+    /// <summary>
+    /// Remove all items *not* in a supplied collection from this set.
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to retain</param>
+    [Tested]
+    public virtual void RetainAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      updatecheck();
+
+      HashSet<T> aux = new HashSet<T>(EqualityComparer);
+
+      //This only works for sets:
+      foreach (U item in items)
+        if (Contains(item))
+        {
+          T jtem = item;
+
+          aux.searchoradd(ref jtem, true, false, false);
+        }
+
+      if (size == aux.size)
+        return;
+
+      CircularQueue<T> wasRemoved = null;
+      if ((ActiveEvents & EventTypeEnum.Removed) != 0)
+      {
+        wasRemoved = new CircularQueue<T>();
+        foreach (T item in this)
+          if (!aux.Contains(item))
+            wasRemoved.Enqueue(item);
+      }
+
+      table = aux.table;
+      size = aux.size;
+#if !REFBUCKET
+      defaultvalid = aux.defaultvalid;
+      defaultitem = aux.defaultitem;
+#endif
+      indexmask = aux.indexmask;
+      resizethreshhold = aux.resizethreshhold;
+      bits = aux.bits;
+      bitsc = aux.bitsc;
+#if DEBUG
+#else
+      randomhashfactor = aux.randomhashfactor;
+#endif
+
+      if ((ActiveEvents & EventTypeEnum.Removed) != 0)
+        raiseForRemoveAll(wasRemoved);
+      else if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+        raiseCollectionChanged();
+    }
+
+    /// <summary>
+    /// Check if all items in a supplied collection is in this set
+    /// (ignoring multiplicities). 
+    /// </summary>
+    /// <param name="items">The items to look for.</param>
+    /// <typeparam name="U"></typeparam>
+    /// <returns>True if all items are found.</returns>
+    [Tested]
+    public virtual bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      foreach (U item in items)
+        if (!Contains(item))
+          return false;
+      return true;
+    }
+
+
+    /// <summary>
+    /// Create an array containing all items in this set (in enumeration order).
+    /// </summary>
+    /// <returns>The array</returns>
+    [Tested]
+    public override T[] ToArray()
+    {
+      T[] res = new T[size];
+      int index = 0;
+
+#if !REFBUCKET
+      if (defaultvalid)
+        res[index++] = defaultitem;
+#endif
+      for (int i = 0; i < table.Length; i++)
+      {
+        Bucket b = table[i];
+#if LINEARPROBING
+#if REFBUCKET
+        if (b != null)
+          res[index++] = b.item;
+#else
+        if (!isnull(b.item))
+          res[index++] = b.item;
+#endif
+#else
+#if REFBUCKET
+        while (b != null)
+        {
+          res[index++] = b.item;
+          b = b.overflow;
+        }
+#else
+				if (!isnull(b.item))
+				{
+					res[index++] = b.item;
+
+					OverflowBucket ob = b.overflow;
+
+					while (ob != null)
+					{
+						res[index++] = ob.item;
+						ob = ob.overflow;
+					}
+				}
+#endif
+#endif
+      }
+
+      Debug.Assert(size == index);
+      return res;
+    }
+
+
+    /// <summary>
+    /// Count the number of times an item is in this set (either 0 or 1).
+    /// </summary>
+    /// <param name="item">The item to look for.</param>
+    /// <returns>1 if item is in set, 0 else</returns>
+    [Tested]
+    public virtual int ContainsCount(T item) { return Contains(item) ? 1 : 0; }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<T> UniqueItems() { return this; }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities()
+    {
+      return new MultiplicityOne<T>(this);
+    }
+
+    /// <summary>
+    /// Remove all (at most 1) copies of item from this set.
+    /// </summary>
+    /// <param name="item">The item to remove</param>
+    [Tested]
+    public virtual void RemoveAllCopies(T item) { Remove(item); }
+
+    #endregion
+
+    #region IEnumerable<T> Members
+
+
+    /// <summary>
+    /// Choose some item of this collection. 
+    /// </summary>
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>
+    /// <returns></returns>
+    [Tested]
+    public override T Choose()
+    {
+      int len = table.Length;
+      if (size == 0)
+        throw new NoSuchItemException();
+#if REFBUCKET
+      do { if (++lastchosen >= len) lastchosen = 0; } while (table[lastchosen] == null);
+#else
+      if (defaultvalid) return defaultitem;
+      do { if (++lastchosen >= len) lastchosen = 0; } while (isnull(table[lastchosen].item));
+#endif
+      return table[lastchosen].item;
+    }
+
+    /// <summary>
+    /// Create an enumerator for this set.
+    /// </summary>
+    /// <returns>The enumerator</returns>
+    [Tested]
+    public override SCG.IEnumerator<T> GetEnumerator()
+    {
+      int index = -1;
+      int mystamp = stamp;
+      int len = table.Length;
+
+#if LINEARPROBING
+#if REFBUCKET
+      while (++index < len)
+      {
+        if (mystamp != stamp) throw new CollectionModifiedException();
+
+        if (table[index] != null) yield return table[index].item;
+      }
+#else
+      if (defaultvalid)
+        yield return defaultitem;
+
+      while (++index < len)
+      {
+        if (mystamp != stamp) throw new CollectionModifiedException();
+
+        T item = table[index].item;
+
+        if (!isnull(item)) yield return item;
+      }
+#endif
+#else
+#if REFBUCKET
+      Bucket b = null;
+#else
+			OverflowBucket ob = null;
+
+			if (defaultvalid)
+				yield return defaultitem;
+#endif
+      while (true)
+      {
+        if (mystamp != stamp)
+          throw new CollectionModifiedException();
+
+#if REFBUCKET
+        if (b == null || b.overflow == null)
+        {
+          do
+          {
+            if (++index >= len) yield break;
+          } while (table[index] == null);
+
+          b = table[index];
+          yield return b.item;
+        }
+        else
+        {
+          b = b.overflow;
+          yield return b.item;
+        }
+#else
+				if (ob != null && ob.overflow != null)
+				{
+					ob = ob.overflow;
+					yield return ob.item;
+				}
+				else if (index >= 0 && ob == null && (ob = table[index].overflow) != null)
+				{
+					yield return  ob.item;
+				}
+				else
+				{
+					do
+					{
+						if (++index >= len) yield break;
+					} while (isnull(table[index].item));
+
+          yield return table[index].item;
+          ob = null;
+				}
+#endif
+      }
+#endif
+    }
+
+    #endregion
+
+    #region ISink<T> Members
+    /// <summary>
+    /// Report if this is a set collection.
+    /// </summary>
+    /// <value>Always false</value>
+    [Tested]
+    public virtual bool AllowsDuplicates { [Tested]get { return false; } }
+
+    /// <summary>
+    /// By convention this is true for any collection with set semantics.
+    /// </summary>
+    /// <value>True if only one representative of a group of equal items 
+    /// is kept in the collection together with the total count.</value>
+    public virtual bool DuplicatesByCounting { get { return true; } }
+
+    /// <summary>
+    /// Add an item to this set.
+    /// </summary>
+    /// <param name="item">The item to add.</param>
+    /// <returns>True if item was added (i.e. not found)</returns>
+    [Tested]
+    public virtual bool Add(T item)
+    {
+      updatecheck();
+      return !searchoradd(ref item, true, false, true);
+    }
+
+    /// <summary>
+    /// Add an item to this set.
+    /// </summary>
+    /// <param name="item">The item to add.</param>
+    [Tested]
+    void SCG.ICollection<T>.Add(T item)
+    {
+        Add(item);
+    }
+
+    /// <summary>
+    /// Add the elements from another collection with a more specialized item type 
+    /// to this collection. Since this
+    /// collection has set semantics, only items not already in the collection
+    /// will be added.
+    /// </summary>
+    /// <typeparam name="U">The type of items to add</typeparam>
+    /// <param name="items">The items to add</param>
+    [Tested]
+    public virtual void AddAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      updatecheck();
+      bool wasChanged = false;
+      bool raiseAdded = (ActiveEvents & EventTypeEnum.Added) != 0;
+      CircularQueue<T> wasAdded = raiseAdded ? new CircularQueue<T>() : null;
+      foreach (T item in items)
+      {
+        T jtem = item;
+
+        if (!searchoradd(ref jtem, true, false, false))
+        {
+          wasChanged = true;
+          if (raiseAdded)
+            wasAdded.Enqueue(item);
+        }
+      }
+      //TODO: implement a RaiseForAddAll() method
+      if (raiseAdded & wasChanged)
+        foreach (T item in wasAdded)
+          raiseItemsAdded(item, 1);
+      if (((ActiveEvents & EventTypeEnum.Changed) != 0 && wasChanged))
+        raiseCollectionChanged();
+    }
+
+
+    #endregion
+
+    #region Diagnostics
+
+    /// <summary>
+    /// Test internal structure of data (invariants)
+    /// </summary>
+    /// <returns>True if pass</returns>
+    [Tested]
+    public virtual bool Check()
+    {
+      int count = 0;
+#if LINEARPROBING
+      int lasthole = table.Length - 1;
+
+#if REFBUCKET
+      while (lasthole >= 0 && table[lasthole] != null)
+#else
+      while (lasthole >= 0 && !isnull(table[lasthole].item))
+#endif
+      {
+        lasthole--;
+        count++;
+      }
+
+      if (lasthole < 0)
+      {
+        Console.WriteLine("Table is completely filled!");
+        return false;
+      }
+
+      for (int cellindex = lasthole + 1, s = table.Length; cellindex < s; cellindex++)
+      {
+        Bucket b = table[cellindex];
+        int hashindex = hv2i(b.hashval);
+
+        if (hashindex <= lasthole || hashindex > cellindex)
+        {
+          Console.WriteLine("Bad cell item={0}, hashval={1}, hashindex={2}, cellindex={3}, lasthole={4}", b.item, b.hashval, hashindex, cellindex, lasthole);
+          return false;
+        }
+      }
+
+      int latesthole = -1;
+
+      for (int cellindex = 0; cellindex < lasthole; cellindex++)
+      {
+        Bucket b = table[cellindex];
+
+#if REFBUCKET
+        if (b != null)
+#else
+        if (!isnull(b.item))
+#endif
+        {
+          count++;
+
+          int hashindex = hv2i(b.hashval);
+
+          if (cellindex < hashindex && hashindex <= lasthole)
+          {
+            Console.WriteLine("Bad cell item={0}, hashval={1}, hashindex={2}, cellindex={3}, latesthole={4}", b.item, b.hashval, hashindex, cellindex, latesthole);
+            return false;
+          }
+        }
+        else
+        {
+          latesthole = cellindex;
+          break;
+        }
+      }
+
+      for (int cellindex = latesthole + 1; cellindex < lasthole; cellindex++)
+      {
+        Bucket b = table[cellindex];
+
+#if REFBUCKET
+        if (b != null)
+#else
+        if (!isnull(b.item))
+#endif
+        {
+          count++;
+
+          int hashindex = hv2i(b.hashval);
+
+          if (hashindex <= latesthole || cellindex < hashindex)
+          {
+            Console.WriteLine("Bad cell item={0}, hashval={1}, hashindex={2}, cellindex={3}, latesthole={4}", b.item, b.hashval, hashindex, cellindex, latesthole);
+            return false;
+          }
+        }
+        else
+        {
+          latesthole = cellindex;
+        }
+      }
+
+      return true;
+#else
+      bool retval = true;
+
+      if (bitsc != 32 - bits)
+      {
+        Console.WriteLine("bitsc != 32 - bits ({0}, {1})", bitsc, bits);
+        retval = false;
+      }
+      if (indexmask != (1 << bits) - 1)
+      {
+        Console.WriteLine("indexmask != (1 << bits) - 1 ({0}, {1})", indexmask, bits);
+        retval = false;
+      }
+      if (table.Length != indexmask + 1)
+      {
+        Console.WriteLine("table.Length != indexmask + 1 ({0}, {1})", table.Length, indexmask);
+        retval = false;
+      }
+      if (bitsc != 32 - bits)
+      {
+        Console.WriteLine("resizethreshhold != (int)(table.Length * fillfactor) ({0}, {1}, {2})", resizethreshhold, table.Length, fillfactor);
+        retval = false;
+      }
+
+      for (int i = 0, s = table.Length; i < s; i++)
+      {
+        int level = 0;
+        Bucket b = table[i];
+#if REFBUCKET
+        while (b != null)
+        {
+          if (i != hv2i(b.hashval))
+          {
+            Console.WriteLine("Bad cell item={0}, hashval={1}, index={2}, level={3}", b.item, b.hashval, i, level);
+            retval = false;
+          }
+
+          count++;
+          level++;
+          b = b.overflow;
+        }
+#else
+				if (!isnull(b.item))
+				{
+					count++;
+					if (i != hv2i(b.hashval))
+					{
+						Console.WriteLine("Bad cell item={0}, hashval={1}, index={2}, level={3}", b.item, b.hashval, i, level);
+						retval = false;
+					}
+
+					OverflowBucket ob = b.overflow;
+
+					while (ob != null)
+					{
+						level++;
+						count++;
+						if (i != hv2i(ob.hashval))
+						{
+							Console.WriteLine("Bad cell item={0}, hashval={1}, index={2}, level={3}", b.item, b.hashval, i, level);
+							retval = false;
+						}
+
+						ob = ob.overflow;
+					}
+				}
+#endif
+      }
+
+      if (count != size)
+      {
+        Console.WriteLine("size({0}) != count({1})", size, count);
+        retval = false;
+      }
+
+      return retval;
+#endif
+    }
+
+
+    /// <summary>
+    /// Produce statistics on distribution of bucket sizes. Current implementation is incomplete.
+    /// </summary>
+    /// <returns>Histogram data.</returns>
+    [Tested(via = "Manually")]
+    public ISortedDictionary<int, int> BucketCostDistribution()
+    {
+      TreeDictionary<int, int> res = new TreeDictionary<int, int>();
+#if LINEARPROBING
+      int count = 0;
+#if REFBUCKET
+      while (table[count] != null)
+#else
+      while (!isnull(table[count].item))
+#endif
+        count++;
+      for (int i = table.Length - 1; i >= 0; i--)
+      {
+#if REFBUCKET
+        if (table[i] != null)
+#else
+        if (!isnull(table[i].item))
+#endif
+          count++;
+        else
+          count = 0;
+        if (res.Contains(count))
+          res[count]++;
+        else
+          res[count] = 1;
+      }
+
+      return res;
+#else
+      for (int i = 0, s = table.Length; i < s; i++)
+      {
+        int count = 0;
+#if REFBUCKET
+        Bucket b = table[i];
+
+        while (b != null)
+        {
+          count++;
+          b = b.overflow;
+        }
+#else
+				Bucket b = table[i];
+
+				if (!isnull(b.item))
+				{
+					count = 1;
+
+					OverflowBucket ob = b.overflow;
+
+					while (ob != null)
+					{
+						count++;
+						ob = ob.overflow;
+					}
+				}
+#endif
+        if (res.Contains(count))
+          res[count]++;
+        else
+          res[count] = 1;
+      }
+
+      return res;
+#endif
+    }
+
+    #endregion
+
+    #region ICloneable Members
+
+    /// <summary>
+    /// Make a shallow copy of this HashSet.
+    /// </summary>
+    /// <returns></returns>
+    public virtual object Clone()
+    {
+      HashSet<T> clone = new HashSet<T>(size > 0 ? size : 1, itemequalityComparer);
+      //TODO: make sure this really adds in the counting bag way!
+      clone.AddAll(this);
+      return clone;
+    }
+
+    #endregion
+
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/heaps/IntervalHeap.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/heaps/IntervalHeap.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/heaps/IntervalHeap.cs	(revision 3)
@@ -0,0 +1,1091 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+
+namespace C5
+{
+  /// <summary>
+  /// A priority queue class based on an interval heap data structure.
+  /// </summary>
+  /// <typeparam name="T">The item type</typeparam>
+  [Serializable]
+  public class IntervalHeap<T> : CollectionValueBase<T>, IPriorityQueue<T>
+  {
+    #region Events
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public override EventTypeEnum ListenableEvents { get { return EventTypeEnum.Basic; } }
+
+    #endregion
+
+    #region Fields
+    [Serializable]
+    struct Interval
+    {
+      internal T first, last; internal Handle firsthandle, lasthandle;
+
+
+      public override string ToString() { return String.Format("[{0}; {1}]", first, last); }
+    }
+
+    int stamp;
+
+    SCG.IComparer<T> comparer;
+    SCG.IEqualityComparer<T> itemequalityComparer;
+
+    Interval[] heap;
+
+    int size;
+    #endregion
+
+    #region Util
+    bool heapifyMin(int i)
+    {
+      bool swappedroot = false;
+      int cell = i, currentmin = cell;
+      T currentitem = heap[cell].first;
+      Handle currenthandle = heap[cell].firsthandle;
+
+      if (i > 0)
+      {
+        T other = heap[cell].last;
+        if (2 * cell + 1 < size && comparer.Compare(currentitem, other) > 0)
+        {
+          swappedroot = true;
+          Handle otherhandle = heap[cell].lasthandle;
+          updateLast(cell, currentitem, currenthandle);
+          currentitem = other;
+          currenthandle = otherhandle;
+        }
+      }
+
+      T minitem = currentitem;
+      Handle minhandle = currenthandle;
+
+      while (true)
+      {
+        int l = 2 * cell + 1, r = l + 1;
+        T lv, rv;
+
+        if (2 * l < size && comparer.Compare(lv = heap[l].first, minitem) < 0)
+        { currentmin = l; minitem = lv; }
+
+        if (2 * r < size && comparer.Compare(rv = heap[r].first, minitem) < 0)
+        { currentmin = r; minitem = rv; }
+
+        if (currentmin == cell)
+          break;
+
+        minhandle = heap[currentmin].firsthandle;
+        updateFirst(cell, minitem, minhandle);
+        cell = currentmin;
+
+        //Maybe swap first and last
+        T other = heap[cell].last;
+        if (2 * currentmin + 1 < size && comparer.Compare(currentitem, other) > 0)
+        {
+          Handle otherhandle = heap[cell].lasthandle;
+          updateLast(cell, currentitem, currenthandle);
+          currentitem = other;
+          currenthandle = otherhandle;
+        }
+
+
+        minitem = currentitem;
+        minhandle = currenthandle;
+      }
+
+      if (cell != i || swappedroot)
+        updateFirst(cell, minitem, minhandle);
+      return swappedroot;
+    }
+
+
+    bool heapifyMax(int i)
+    {
+      bool swappedroot = false;
+      int cell = i, currentmax = cell;
+      T currentitem = heap[cell].last;
+      Handle currenthandle = heap[cell].lasthandle;
+
+      if (i > 0)
+      {
+        T other = heap[cell].first;
+        if (comparer.Compare(currentitem, other) < 0)
+        {
+          swappedroot = true;
+          Handle otherhandle = heap[cell].firsthandle;
+          updateFirst(cell, currentitem, currenthandle);
+          currentitem = other;
+          currenthandle = otherhandle;
+        }
+      }
+
+      T maxitem = currentitem;
+      Handle maxhandle = currenthandle;
+
+      while (true)
+      {
+        int l = 2 * cell + 1, r = l + 1;
+        T lv, rv;
+
+        if (2 * l + 1 < size && comparer.Compare(lv = heap[l].last, maxitem) > 0)
+        { currentmax = l; maxitem = lv; }
+
+        if (2 * r + 1 < size && comparer.Compare(rv = heap[r].last, maxitem) > 0)
+        { currentmax = r; maxitem = rv; }
+
+        if (currentmax == cell)
+          break;
+
+        maxhandle = heap[currentmax].lasthandle;
+        updateLast(cell, maxitem, maxhandle);
+        cell = currentmax;
+
+        //Maybe swap first and last
+        T other = heap[cell].first;
+        if (comparer.Compare(currentitem, other) < 0)
+        {
+          Handle otherhandle = heap[cell].firsthandle;
+          updateFirst(cell, currentitem, currenthandle);
+          currentitem = other;
+          currenthandle = otherhandle;
+        }
+
+        maxitem = currentitem;
+        maxhandle = currenthandle;
+      }
+
+      if (cell != i || swappedroot) //Check could be better?
+        updateLast(cell, maxitem, maxhandle);
+      return swappedroot;
+    }
+
+
+    void bubbleUpMin(int i)
+    {
+      if (i > 0)
+      {
+        T min = heap[i].first, iv = min;
+        Handle minhandle = heap[i].firsthandle;
+        int p = (i + 1) / 2 - 1;
+
+        while (i > 0)
+        {
+          if (comparer.Compare(iv, min = heap[p = (i + 1) / 2 - 1].first) < 0)
+          {
+            updateFirst(i, min, heap[p].firsthandle);
+            min = iv;
+            i = p;
+          }
+          else
+            break;
+        }
+
+        updateFirst(i, iv, minhandle);
+      }
+    }
+
+
+    void bubbleUpMax(int i)
+    {
+      if (i > 0)
+      {
+        T max = heap[i].last, iv = max;
+        Handle maxhandle = heap[i].lasthandle;
+        int p = (i + 1) / 2 - 1;
+
+        while (i > 0)
+        {
+          if (comparer.Compare(iv, max = heap[p = (i + 1) / 2 - 1].last) > 0)
+          {
+            updateLast(i, max, heap[p].lasthandle);
+            max = iv;
+            i = p;
+          }
+          else
+            break;
+        }
+
+        updateLast(i, iv, maxhandle);
+
+      }
+    }
+
+    #endregion
+
+    #region Constructors
+    /// <summary>
+    /// Create an interval heap with natural item comparer and default initial capacity (16)
+    /// </summary>
+    public IntervalHeap() : this(16) { }
+
+
+    /// <summary>
+    /// Create an interval heap with external item comparer and default initial capacity (16)
+    /// </summary>
+    /// <param name="comparer">The external comparer</param>
+    public IntervalHeap(SCG.IComparer<T> comparer) : this(16, comparer) { }
+
+
+    //TODO: maybe remove
+    /// <summary>
+    /// Create an interval heap with natural item comparer and prescribed initial capacity
+    /// </summary>
+    /// <param name="capacity">The initial capacity</param>
+    public IntervalHeap(int capacity) : this(capacity, Comparer<T>.Default, EqualityComparer<T>.Default) { }
+
+
+    /// <summary>
+    /// Create an interval heap with external item comparer and prescribed initial capacity
+    /// </summary>
+    /// <param name="comparer">The external comparer</param>
+    /// <param name="capacity">The initial capacity</param>
+    public IntervalHeap(int capacity, SCG.IComparer<T> comparer) : this(capacity, comparer, new ComparerZeroHashCodeEqualityComparer<T>(comparer)) { }
+
+    IntervalHeap(int capacity, SCG.IComparer<T> comparer, SCG.IEqualityComparer<T> itemequalityComparer)
+    {
+      if (comparer == null)
+        throw new NullReferenceException("Item comparer cannot be null");
+      if (itemequalityComparer == null)
+        throw new NullReferenceException("Item equality comparer cannot be null");
+      this.comparer = comparer;
+      this.itemequalityComparer = itemequalityComparer;
+      int length = 1;
+      while (length < capacity) length <<= 1;
+      heap = new Interval[length];
+    }
+
+    #endregion
+
+    #region IPriorityQueue<T> Members
+
+    /// <summary>
+    /// Find the current least item of this priority queue.
+    /// <exception cref="NoSuchItemException"/> if queue is empty
+    /// </summary>
+    /// <returns>The least item.</returns>
+    [Tested]
+    public T FindMin()
+    {
+      if (size == 0)
+        throw new NoSuchItemException();
+
+      return heap[0].first;
+    }
+
+
+    /// <summary>
+    /// Remove the least item from this  priority queue.
+    /// <exception cref="NoSuchItemException"/> if queue is empty
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public T DeleteMin()
+    {
+      IPriorityQueueHandle<T> handle = null;
+      return DeleteMin(out handle);
+    }
+
+
+    /// <summary>
+    /// Find the current largest item of this priority queue.
+    /// <exception cref="NoSuchItemException"/> if queue is empty
+    /// </summary>
+    /// <returns>The largest item.</returns>
+    [Tested]
+    public T FindMax()
+    {
+      if (size == 0)
+        throw new NoSuchItemException("Heap is empty");
+      else if (size == 1)
+        return heap[0].first;
+      else
+        return heap[0].last;
+    }
+
+
+    /// <summary>
+    /// Remove the largest item from this  priority queue.
+    /// <exception cref="NoSuchItemException"/> if queue is empty
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public T DeleteMax()
+    {
+      IPriorityQueueHandle<T> handle = null;
+      return DeleteMax(out handle);
+    }
+
+
+    /// <summary>
+    /// The comparer object supplied at creation time for this collection
+    /// </summary>
+    /// <value>The comparer</value>
+    public SCG.IComparer<T> Comparer { get { return comparer; } }
+
+    #endregion
+
+    #region IExtensible<T> Members
+
+    /// <summary>
+    /// If true any call of an updating operation will throw an
+    /// <code>ReadOnlyCollectionException</code>
+    /// </summary>
+    /// <value>True if this collection is read-only.</value>
+    public bool IsReadOnly { get { return false; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>True since this collection has bag semantics</value>
+    [Tested]
+    public bool AllowsDuplicates { [Tested]get { return true; } }
+
+    /// <summary>
+    /// Value is null since this collection has no equality concept for its items. 
+    /// </summary>
+    /// <value></value>
+    public virtual SCG.IEqualityComparer<T> EqualityComparer { get { return itemequalityComparer; } }
+
+    /// <summary>
+    /// By convention this is true for any collection with set semantics.
+    /// </summary>
+    /// <value>True if only one representative of a group of equal items 
+    /// is kept in the collection together with the total count.</value>
+    public virtual bool DuplicatesByCounting { get { return false; } }
+
+
+
+    /// <summary>
+    /// Add an item to this priority queue.
+    /// </summary>
+    /// <param name="item">The item to add.</param>
+    /// <returns>True</returns>
+    [Tested]
+    public bool Add(T item)
+    {
+      stamp++;
+      if (add(null, item))
+      {
+        raiseItemsAdded(item, 1);
+        raiseCollectionChanged();
+        return true;
+      }
+      return false;
+    }
+
+    private bool add(Handle itemhandle, T item)
+    {
+      if (size == 0)
+      {
+        size = 1;
+        updateFirst(0, item, itemhandle);
+        return true;
+      }
+
+      if (size == 2 * heap.Length)
+      {
+        Interval[] newheap = new Interval[2 * heap.Length];
+
+        Array.Copy(heap, newheap, heap.Length);
+        heap = newheap;
+      }
+
+      if (size % 2 == 0)
+      {
+        int i = size / 2, p = (i + 1) / 2 - 1;
+        T tmp = heap[p].last;
+
+        if (comparer.Compare(item, tmp) > 0)
+        {
+          updateFirst(i, tmp, heap[p].lasthandle);
+          updateLast(p, item, itemhandle);
+          bubbleUpMax(p);
+        }
+        else
+        {
+          updateFirst(i, item, itemhandle);
+
+          if (comparer.Compare(item, heap[p].first) < 0)
+            bubbleUpMin(i);
+        }
+      }
+      else
+      {
+        int i = size / 2;
+        T other = heap[i].first;
+
+        if (comparer.Compare(item, other) < 0)
+        {
+          updateLast(i, other, heap[i].firsthandle);
+          updateFirst(i, item, itemhandle);
+          bubbleUpMin(i);
+        }
+        else
+        {
+          updateLast(i, item, itemhandle);
+          bubbleUpMax(i);
+        }
+      }
+      size++;
+
+      return true;
+    }
+
+    private void updateLast(int cell, T item, Handle handle)
+    {
+      heap[cell].last = item;
+      if (handle != null)
+        handle.index = 2 * cell + 1;
+      heap[cell].lasthandle = handle;
+    }
+
+    private void updateFirst(int cell, T item, Handle handle)
+    {
+      heap[cell].first = item;
+      if (handle != null)
+        handle.index = 2 * cell;
+      heap[cell].firsthandle = handle;
+    }
+
+
+    /// <summary>
+    /// Add the elements from another collection with a more specialized item type 
+    /// to this collection. 
+    /// </summary>
+    /// <typeparam name="U">The type of items to add</typeparam>
+    /// <param name="items">The items to add</param>
+    [Tested]
+    public void AddAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      stamp++;
+      int oldsize = size;
+      foreach (T item in items)
+        add(null, item);
+      if (size != oldsize)
+      {
+        if ((ActiveEvents & EventTypeEnum.Added) != 0)
+          foreach (T item in items)
+            raiseItemsAdded(item, 1);
+        raiseCollectionChanged();
+      }
+    }
+
+    #endregion
+
+    #region ICollection<T> members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>True if this collection is empty.</value>
+    [Tested]
+    public override bool IsEmpty { [Tested]get { return size == 0; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>The size of this collection</value>
+    [Tested]
+    public override int Count { [Tested]get { return size; } }
+
+
+    /// <summary>
+    /// The value is symbolic indicating the type of asymptotic complexity
+    /// in terms of the size of this collection (worst-case or amortized as
+    /// relevant).
+    /// </summary>
+    /// <value>A characterization of the speed of the 
+    /// <code>Count</code> property in this collection.</value>
+    public override Speed CountSpeed { get { return Speed.Constant; } }
+
+    /// <summary>
+    /// Choose some item of this collection. 
+    /// </summary>
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>
+    /// <returns></returns>
+    public override T Choose()
+    {
+      if (size == 0)
+        throw new NoSuchItemException("Collection is empty");
+      return heap[0].first;
+    }
+
+
+    /// <summary>
+    /// Create an enumerator for the collection
+    /// <para>Note: the enumerator does *not* enumerate the items in sorted order, 
+    /// but in the internal table order.</para>
+    /// </summary>
+    /// <returns>The enumerator(SIC)</returns>
+    [Tested]
+    public override SCG.IEnumerator<T> GetEnumerator()
+    {
+      int mystamp = stamp;
+      for (int i = 0; i < size; i++)
+      {
+        if (mystamp != stamp) throw new CollectionModifiedException();
+        yield return i % 2 == 0 ? heap[i >> 1].first : heap[i >> 1].last;
+      }
+      yield break;
+    }
+
+
+    #endregion
+
+    #region Diagnostics
+    private bool check(int i, T min, T max)
+    {
+      bool retval = true;
+      Interval interval = heap[i];
+      T first = interval.first, last = interval.last;
+
+      if (2 * i + 1 == size)
+      {
+        if (comparer.Compare(min, first) > 0)
+        {
+          Console.WriteLine("Cell {0}: parent.first({1}) > first({2})  [size={3}]", i, min, first, size);
+          retval = false;
+        }
+
+        if (comparer.Compare(first, max) > 0)
+        {
+          Console.WriteLine("Cell {0}: first({1}) > parent.last({2})  [size={3}]", i, first, max, size);
+          retval = false;
+        }
+        if (interval.firsthandle != null && interval.firsthandle.index != 2 * i)
+        {
+          Console.WriteLine("Cell {0}: firsthandle.index({1}) != 2*cell({2})  [size={3}]", i, interval.firsthandle.index, 2 * i, size);
+          retval = false;
+        }
+
+        return retval;
+      }
+      else
+      {
+        if (comparer.Compare(min, first) > 0)
+        {
+          Console.WriteLine("Cell {0}: parent.first({1}) > first({2})  [size={3}]", i, min, first, size);
+          retval = false;
+        }
+
+        if (comparer.Compare(first, last) > 0)
+        {
+          Console.WriteLine("Cell {0}: first({1}) > last({2})  [size={3}]", i, first, last, size);
+          retval = false;
+        }
+
+        if (comparer.Compare(last, max) > 0)
+        {
+          Console.WriteLine("Cell {0}: last({1}) > parent.last({2})  [size={3}]", i, last, max, size);
+          retval = false;
+        }
+        if (interval.firsthandle != null && interval.firsthandle.index != 2 * i)
+        {
+          Console.WriteLine("Cell {0}: firsthandle.index({1}) != 2*cell({2})  [size={3}]", i, interval.firsthandle.index, 2 * i, size);
+          retval = false;
+        }
+        if (interval.lasthandle != null && interval.lasthandle.index != 2 * i + 1)
+        {
+          Console.WriteLine("Cell {0}: lasthandle.index({1}) != 2*cell+1({2})  [size={3}]", i, interval.lasthandle.index, 2 * i + 1, size);
+          retval = false;
+        }
+
+        int l = 2 * i + 1, r = l + 1;
+
+        if (2 * l < size)
+          retval = retval && check(l, first, last);
+
+        if (2 * r < size)
+          retval = retval && check(r, first, last);
+      }
+
+      return retval;
+    }
+
+
+    /// <summary>
+    /// Check the integrity of the internal data structures of this collection.
+    /// Only avaliable in DEBUG builds???
+    /// </summary>
+    /// <returns>True if check does not fail.</returns>
+    [Tested]
+    public bool Check()
+    {
+      if (size == 0)
+        return true;
+
+      if (size == 1)
+        return (object)(heap[0].first) != null;
+
+      return check(0, heap[0].first, heap[0].last);
+    }
+
+    #endregion
+
+    #region IPriorityQueue<T> Members
+
+    [Serializable]
+    class Handle : IPriorityQueueHandle<T>
+    {
+      /// <summary>
+      /// To save space, the index is 2*cell for heap[cell].first, and 2*cell+1 for heap[cell].last
+      /// </summary>
+      internal int index = -1;
+
+      public override string ToString()
+      {
+        return String.Format("[{0}]", index);
+      }
+
+    }
+
+    /// <summary>
+    /// Get or set the item corresponding to a handle. 
+    /// </summary>
+    /// <exception cref="InvalidPriorityQueueHandleException">if the handle is invalid for this queue</exception>
+    /// <param name="handle">The reference into the heap</param>
+    /// <returns></returns>
+    [Tested]
+    public T this[IPriorityQueueHandle<T> handle]
+    {
+      get
+      {
+        int cell;
+        bool isfirst;
+        checkHandle(handle, out cell, out isfirst);
+
+        return isfirst ? heap[cell].first : heap[cell].last;
+      }
+      set
+      {
+        Replace(handle, value);
+      }
+    }
+
+
+    /// <summary>
+    /// Check safely if a handle is valid for this queue and if so, report the corresponding queue item.
+    /// </summary>
+    /// <param name="handle">The handle to check</param>
+    /// <param name="item">If the handle is valid this will contain the corresponding item on output.</param>
+    /// <returns>True if the handle is valid.</returns>
+    public bool Find(IPriorityQueueHandle<T> handle, out T item)
+    {
+      Handle myhandle = handle as Handle;
+      if (myhandle == null)
+      {
+        item = default(T);
+        return false;
+      }
+      int toremove = myhandle.index;
+      int cell = toremove / 2;
+      bool isfirst = toremove % 2 == 0;
+      {
+        if (toremove == -1 || toremove >= size)
+        {
+          item = default(T);
+          return false;
+        }
+        Handle actualhandle = isfirst ? heap[cell].firsthandle : heap[cell].lasthandle;
+        if (actualhandle != myhandle)
+        {
+          item = default(T);
+          return false;
+        }
+      }
+      item = isfirst ? heap[cell].first : heap[cell].last;
+      return true;
+    }
+
+
+    /// <summary>
+    /// Add an item to the priority queue, receiving a 
+    /// handle for the item in the queue, 
+    /// or reusing an already existing handle.
+    /// </summary>
+    /// <param name="handle">On output: a handle for the added item. 
+    /// On input: null for allocating a new handle, an invalid handle for reuse. 
+    /// A handle for reuse must be compatible with this priority queue, 
+    /// by being created by a priority queue of the same runtime type, but not 
+    /// necessarily the same priority queue object.</param>
+    /// <param name="item">The item to add.</param>
+    /// <returns>True since item will always be added unless the call throws an exception.</returns>
+    [Tested]
+    public bool Add(ref IPriorityQueueHandle<T> handle, T item)
+    {
+      stamp++;
+      Handle myhandle = (Handle)handle;
+      if (myhandle == null)
+        handle = myhandle = new Handle();
+      else
+        if (myhandle.index != -1)
+          throw new InvalidPriorityQueueHandleException("Handle not valid for reuse");
+      if (add(myhandle, item))
+      {
+        raiseItemsAdded(item, 1);
+        raiseCollectionChanged();
+        return true;
+      }
+      return false;
+    }
+
+    /// <summary>
+    /// Delete an item with a handle from a priority queue.
+    /// </summary>
+    /// <exception cref="InvalidPriorityQueueHandleException">if the handle is invalid</exception>
+    /// <param name="handle">The handle for the item. The handle will be invalidated, but reusable.</param>
+    /// <returns>The deleted item</returns>
+    [Tested]
+    public T Delete(IPriorityQueueHandle<T> handle)
+    {
+      stamp++;
+      int cell;
+      bool isfirst;
+      Handle myhandle = checkHandle(handle, out cell, out isfirst);
+
+      T retval;
+      myhandle.index = -1;
+      int lastcell = (size - 1) / 2;
+
+      if (cell == lastcell)
+      {
+        if (isfirst)
+        {
+          retval = heap[cell].first;
+          if (size % 2 == 0)
+          {
+            updateFirst(cell, heap[cell].last, heap[cell].lasthandle);
+            heap[cell].last = default(T);
+            heap[cell].lasthandle = null;
+          }
+          else
+          {
+            heap[cell].first = default(T);
+            heap[cell].firsthandle = null;
+          }
+        }
+        else
+        {
+          retval = heap[cell].last;
+          heap[cell].last = default(T);
+          heap[cell].lasthandle = null;
+        }
+        size--;
+      }
+      else if (isfirst)
+      {
+        retval = heap[cell].first;
+
+        if (size % 2 == 0)
+        {
+          updateFirst(cell, heap[lastcell].last, heap[lastcell].lasthandle);
+          heap[lastcell].last = default(T);
+          heap[lastcell].lasthandle = null;
+        }
+        else
+        {
+          updateFirst(cell, heap[lastcell].first, heap[lastcell].firsthandle);
+          heap[lastcell].first = default(T);
+          heap[lastcell].firsthandle = null;
+        }
+
+        size--;
+        if (heapifyMin(cell))
+          bubbleUpMax(cell);
+        else
+          bubbleUpMin(cell);
+      }
+      else
+      {
+        retval = heap[cell].last;
+
+        if (size % 2 == 0)
+        {
+          updateLast(cell, heap[lastcell].last, heap[lastcell].lasthandle);
+          heap[lastcell].last = default(T);
+          heap[lastcell].lasthandle = null;
+        }
+        else
+        {
+          updateLast(cell, heap[lastcell].first, heap[lastcell].firsthandle);
+          heap[lastcell].first = default(T);
+          heap[lastcell].firsthandle = null;
+        }
+
+        size--;
+        if (heapifyMax(cell))
+          bubbleUpMin(cell);
+        else
+          bubbleUpMax(cell);
+      }
+
+      raiseItemsRemoved(retval, 1);
+      raiseCollectionChanged();
+
+      return retval;
+    }
+
+    private Handle checkHandle(IPriorityQueueHandle<T> handle, out int cell, out bool isfirst)
+    {
+      Handle myhandle = (Handle)handle;
+      int toremove = myhandle.index;
+      cell = toremove / 2;
+      isfirst = toremove % 2 == 0;
+      {
+        if (toremove == -1 || toremove >= size)
+          throw new InvalidPriorityQueueHandleException("Invalid handle, index out of range");
+        Handle actualhandle = isfirst ? heap[cell].firsthandle : heap[cell].lasthandle;
+        if (actualhandle != myhandle)
+          throw new InvalidPriorityQueueHandleException("Invalid handle, doesn't match queue");
+      }
+      return myhandle;
+    }
+
+
+    /// <summary>
+    /// Replace an item with a handle in a priority queue with a new item. 
+    /// Typically used for changing the priority of some queued object.
+    /// </summary>
+    /// <param name="handle">The handle for the old item</param>
+    /// <param name="item">The new item</param>
+    /// <returns>The old item</returns>
+    [Tested]
+    public T Replace(IPriorityQueueHandle<T> handle, T item)
+    {
+      stamp++;
+      int cell;
+      bool isfirst;
+      checkHandle(handle, out cell, out isfirst);
+      if (size == 0)
+        throw new NoSuchItemException();
+
+      T retval;
+
+      if (isfirst)
+      {
+        retval = heap[cell].first;
+        heap[cell].first = item;
+        if (size == 1)
+        {
+        }
+        else if (size == 2 * cell + 1) // cell == lastcell
+        {
+          int p = (cell + 1) / 2 - 1;
+          if (comparer.Compare(item, heap[p].last) > 0)
+          {
+            Handle thehandle = heap[cell].firsthandle;
+            updateFirst(cell, heap[p].last, heap[p].lasthandle);
+            updateLast(p, item, thehandle);
+            bubbleUpMax(p);
+          }
+          else
+            bubbleUpMin(cell);
+        }
+        else if (heapifyMin(cell))
+          bubbleUpMax(cell);
+        else
+          bubbleUpMin(cell);
+      }
+      else
+      {
+        retval = heap[cell].last;
+        heap[cell].last = item;
+        if (heapifyMax(cell))
+          bubbleUpMin(cell);
+        else
+          bubbleUpMax(cell);
+      }
+
+      raiseItemsRemoved(retval, 1);
+      raiseItemsAdded(item, 1);
+      raiseCollectionChanged();
+
+      return retval;
+    }
+
+    /// <summary>
+    /// Find the current least item of this priority queue.
+    /// </summary>
+    /// <param name="handle">On return: the handle of the item.</param>
+    /// <returns>The least item.</returns>
+    public T FindMin(out IPriorityQueueHandle<T> handle)
+    {
+      if (size == 0)
+        throw new NoSuchItemException();
+      handle = heap[0].firsthandle;
+
+      return heap[0].first;
+    }
+
+    /// <summary>
+    /// Find the current largest item of this priority queue.
+    /// </summary>
+    /// <param name="handle">On return: the handle of the item.</param>
+    /// <returns>The largest item.</returns>
+    public T FindMax(out IPriorityQueueHandle<T> handle)
+    {
+      if (size == 0)
+        throw new NoSuchItemException();
+      else if (size == 1)
+      {
+        handle = heap[0].firsthandle;
+        return heap[0].first;
+      }
+      else
+      {
+        handle = heap[0].lasthandle;
+        return heap[0].last;
+      }
+    }
+
+    /// <summary>
+    /// Remove the least item from this priority queue.
+    /// </summary>
+    /// <param name="handle">On return: the handle of the removed item.</param>
+    /// <returns>The removed item.</returns>
+    public T DeleteMin(out IPriorityQueueHandle<T> handle)
+    {
+      stamp++;
+      if (size == 0)
+        throw new NoSuchItemException();
+
+      T retval = heap[0].first;
+      Handle myhandle = heap[0].firsthandle;
+      handle = myhandle;
+      if (myhandle != null)
+        myhandle.index = -1;
+
+      if (size == 1)
+      {
+        size = 0;
+        heap[0].first = default(T);
+        heap[0].firsthandle = null;
+      }
+      else
+      {
+        int lastcell = (size - 1) / 2;
+
+        if (size % 2 == 0)
+        {
+          updateFirst(0, heap[lastcell].last, heap[lastcell].lasthandle);
+          heap[lastcell].last = default(T);
+          heap[lastcell].lasthandle = null;
+        }
+        else
+        {
+          updateFirst(0, heap[lastcell].first, heap[lastcell].firsthandle);
+          heap[lastcell].first = default(T);
+          heap[lastcell].firsthandle = null;
+        }
+
+        size--;
+        heapifyMin(0);
+      }
+
+      raiseItemsRemoved(retval, 1);
+      raiseCollectionChanged();
+      return retval;
+
+    }
+
+    /// <summary>
+    /// Remove the largest item from this priority queue.
+    /// </summary>
+    /// <param name="handle">On return: the handle of the removed item.</param>
+    /// <returns>The removed item.</returns>
+    public T DeleteMax(out IPriorityQueueHandle<T> handle)
+    {
+      stamp++;
+      if (size == 0)
+        throw new NoSuchItemException();
+
+      T retval;
+      Handle myhandle;
+
+      if (size == 1)
+      {
+        size = 0;
+        retval = heap[0].first;
+        myhandle = heap[0].firsthandle;
+        if (myhandle != null)
+          myhandle.index = -1;
+        heap[0].first = default(T);
+        heap[0].firsthandle = null;
+      }
+      else
+      {
+        retval = heap[0].last;
+        myhandle = heap[0].lasthandle;
+        if (myhandle != null)
+          myhandle.index = -1;
+
+        int lastcell = (size - 1) / 2;
+
+        if (size % 2 == 0)
+        {
+          updateLast(0, heap[lastcell].last, heap[lastcell].lasthandle);
+          heap[lastcell].last = default(T);
+          heap[lastcell].lasthandle = null;
+        }
+        else
+        {
+          updateLast(0, heap[lastcell].first, heap[lastcell].firsthandle);
+          heap[lastcell].first = default(T);
+          heap[lastcell].firsthandle = null;
+        }
+
+        size--;
+        heapifyMax(0);
+      }
+      raiseItemsRemoved(retval, 1);
+      raiseCollectionChanged();
+      handle = myhandle;
+      return retval;
+    }
+
+    #endregion
+
+    #region ICloneable Members
+
+    /// <summary>
+    /// Make a shallow copy of this IntervalHeap.
+    /// </summary>
+    /// <returns></returns>
+    public virtual object Clone()
+    {
+      IntervalHeap<T> clone = new IntervalHeap<T>(size, comparer, itemequalityComparer);
+      clone.AddAll(this);
+      return clone;
+    }
+
+    #endregion
+
+  }
+
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/linkedlists/HashedLinkedList.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/linkedlists/HashedLinkedList.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/linkedlists/HashedLinkedList.cs	(revision 3)
@@ -0,0 +1,3919 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+#define HASHINDEX
+
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+
+namespace C5
+{
+  /// <summary>
+  /// A list collection class based on a doubly linked list data structure.
+  /// </summary>
+  [Serializable]
+  public class HashedLinkedList<T> : SequencedBase<T>, IList<T>, SCG.IList<T>
+#if HASHINDEX
+#else
+, IStack<T>, IQueue<T>
+#endif
+  {
+    #region Fields
+    /// <summary>
+    /// IExtensible.Add(T) always does AddLast(T), fIFO determines 
+    /// if T Remove() does RemoveFirst() or RemoveLast()
+    /// </summary>
+    bool fIFO = true;
+
+    #region Events
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public override EventTypeEnum ListenableEvents { get { return underlying == null ? EventTypeEnum.All : EventTypeEnum.None; } }
+
+    #endregion
+
+    //Invariant:  startsentinel != null && endsentinel != null
+    //If size==0: startsentinel.next == endsentinel && endsentinel.prev == startsentinel
+    //Else:      startsentinel.next == First && endsentinel.prev == Last)
+    /// <summary>
+    /// Node to the left of first node 
+    /// </summary>
+    Node startsentinel;
+    /// <summary>
+    /// Node to the right of last node
+    /// </summary>
+    Node endsentinel;
+    /// <summary>
+    /// Offset of this view in underlying list
+    /// </summary>
+#if HASHINDEX
+    int? offset;
+#else
+    int offset;
+#endif
+
+    /// <summary>
+    /// underlying list of this view (or null for the underlying list)
+    /// </summary>
+    HashedLinkedList<T> underlying;
+
+    //Note: all views will have the same views list since all view objects are created by MemberwiseClone()
+    WeakViewList<HashedLinkedList<T>> views;
+    WeakViewList<HashedLinkedList<T>>.Node myWeakReference;
+
+    /// <summary>
+    /// Has this list or view not been invalidated by some operation (by someone calling Dispose())
+    /// </summary>
+    bool isValid = true;
+
+
+#if HASHINDEX
+    HashDictionary<T, Node> dict;
+    /// <summary>
+    /// Number of taggroups
+    /// </summary>
+    int taggroups;
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    int Taggroups
+    {
+      get { return underlying == null ? taggroups : underlying.taggroups; }
+      set { if (underlying == null) taggroups = value; else underlying.taggroups = value; }
+    }
+#endif
+
+    #endregion
+
+    #region Util
+
+    bool equals(T i1, T i2) { return itemequalityComparer.Equals(i1, i2); }
+
+    #region Check utilities
+    /// <summary>
+    /// Check if it is valid to perform updates and increment stamp of 
+    /// underlying if this is a view.
+    /// <para>This method should be called in every public modifying 
+    /// methods before any modifications are performed.
+    /// </para>
+    /// </summary>
+    /// <exception cref="InvalidOperationException"> if check fails.</exception>
+    protected override void updatecheck()
+    {
+      validitycheck();
+      base.updatecheck();
+      if (underlying != null)
+        underlying.stamp++;
+    }
+
+    /// <summary>
+    /// Check if we are a view that the underlyinglist has only been updated through us.
+    /// <br/>
+    /// This method should be called from enumerators etc to guard against 
+    /// modification of the base collection.
+    /// </summary>
+    /// <exception cref="InvalidOperationException"> if check fails.</exception>
+    void validitycheck()
+    {
+      if (!isValid)
+        throw new ViewDisposedException();
+    }
+
+    /// <summary>
+    /// Check that the list has not been updated since a particular time.
+    /// </summary>
+    /// <param name="stamp">The stamp indicating the time.</param>
+    /// <exception cref="CollectionModifiedException"> if check fails.</exception>
+    protected override void modifycheck(int stamp)
+    {
+      validitycheck();
+      if ((underlying != null ? underlying.stamp : this.stamp) != stamp)
+        throw new CollectionModifiedException();
+    }
+    #endregion
+
+    #region Searching
+    bool contains(T item, out Node node)
+    {
+#if HASHINDEX
+      if (dict.Find(item, out node))
+        return insideview(node);
+#else
+      //TODO: search from both ends? Or search from the end selected by FIFO?
+      node = startsentinel.next;
+      while (node != endsentinel)
+      {
+        if (equals(item, node.item))
+          return true;
+        node = node.next;
+      }
+#endif
+      return false;
+    }
+
+    /// <summary>
+    /// Search forwards from a node for a node with a particular item.
+    /// </summary>
+    /// <param name="item">The item to look for</param>
+    /// <param name="node">On input, the node to start at. If item was found, the node found on output.</param>
+    /// <param name="index">If node was found, the value will be the number of links followed higher than 
+    /// the value on input. If item was not found, the value on output is undefined.</param>
+    /// <returns>True if node was found.</returns>
+    bool find(T item, ref Node node, ref int index)
+    {
+      while (node != endsentinel)
+      {
+        //if (item.Equals(node.item))
+        if (itemequalityComparer.Equals(item, node.item))
+          return true;
+
+        index++;
+        node = node.next;
+      }
+
+      return false;
+    }
+
+    bool dnif(T item, ref Node node, ref int index)
+    {
+      while (node != startsentinel)
+      {
+        //if (item.Equals(node.item))
+        if (itemequalityComparer.Equals(item, node.item))
+          return true;
+
+        index--;
+        node = node.prev;
+      }
+
+      return false;
+    }
+
+#if HASHINDEX
+    bool insideview(Node node)
+    {
+      if (underlying == null)
+        return true;
+      return (startsentinel.precedes(node) && node.precedes(endsentinel));
+    }
+#endif
+
+    #endregion
+
+    #region Indexing
+    /// <summary>
+    /// Return the node at position pos
+    /// </summary>
+    /// <param name="pos"></param>
+    /// <returns></returns>
+    Node get(int pos)
+    {
+      if (pos < 0 || pos >= size)
+        throw new IndexOutOfRangeException();
+      else if (pos < size / 2)
+      {              // Closer to front
+        Node node = startsentinel;
+
+        for (int i = 0; i <= pos; i++)
+          node = node.next;
+
+        return node;
+      }
+      else
+      {                            // Closer to end
+        Node node = endsentinel;
+
+        for (int i = size; i > pos; i--)
+          node = node.prev;
+
+        return node;
+      }
+    }
+
+    /// <summary>
+    /// Find the distance from pos to the set given by positions. Return the
+    /// signed distance as return value and as an out parameter, the
+    /// array index of the nearest position. This is used for up to length 5 of
+    /// positions, and we do not assume it is sorted. 
+    /// </summary>
+    /// <param name="pos"></param>
+    /// <param name="positions"></param>
+    /// <param name="nearest"></param>
+    /// <returns></returns>
+    int dist(int pos, out int nearest, int[] positions)
+    {
+      nearest = -1;
+      int bestdist = int.MaxValue;
+      int signeddist = bestdist;
+      for (int i = 0; i < positions.Length; i++)
+      {
+        int thisdist = positions[i] - pos;
+        if (thisdist >= 0 && thisdist < bestdist) { nearest = i; bestdist = thisdist; signeddist = thisdist; }
+        if (thisdist < 0 && -thisdist < bestdist) { nearest = i; bestdist = -thisdist; signeddist = thisdist; }
+      }
+      return signeddist;
+    }
+
+    /// <summary>
+    /// Find the node at position pos, given known positions of several nodes.
+    /// </summary>
+    /// <param name="pos"></param>
+    /// <param name="positions"></param>
+    /// <param name="nodes"></param>
+    /// <returns></returns>
+    Node get(int pos, int[] positions, Node[] nodes)
+    {
+      int nearest;
+      int delta = dist(pos, out nearest, positions);
+      Node node = nodes[nearest];
+      if (delta > 0)
+        for (int i = 0; i < delta; i++)
+          node = node.prev;
+      else
+        for (int i = 0; i > delta; i--)
+          node = node.next;
+      return node;
+    }
+
+    /// <summary>
+    /// Get nodes at positions p1 and p2, given nodes at several positions.
+    /// </summary>
+    /// <param name="p1"></param>
+    /// <param name="p2"></param>
+    /// <param name="n1"></param>
+    /// <param name="n2"></param>
+    /// <param name="positions"></param>
+    /// <param name="nodes"></param>
+    void getPair(int p1, int p2, out Node n1, out Node n2, int[] positions, Node[] nodes)
+    {
+      int nearest1, nearest2;
+      int delta1 = dist(p1, out nearest1, positions), d1 = delta1 < 0 ? -delta1 : delta1;
+      int delta2 = dist(p2, out nearest2, positions), d2 = delta2 < 0 ? -delta2 : delta2;
+
+      if (d1 < d2)
+      {
+        n1 = get(p1, positions, nodes);
+        n2 = get(p2, new int[] { positions[nearest2], p1 }, new Node[] { nodes[nearest2], n1 });
+      }
+      else
+      {
+        n2 = get(p2, positions, nodes);
+        n1 = get(p1, new int[] { positions[nearest1], p2 }, new Node[] { nodes[nearest1], n2 });
+      }
+    }
+    #endregion
+
+    #region Insertion
+#if HASHINDEX
+    void insert(int index, Node succ, T item)
+    {
+      Node newnode = new Node(item);
+      if (dict.FindOrAdd(item, ref newnode))
+        throw new DuplicateNotAllowedException("Item already in indexed list");
+      insertNode(true, succ, newnode);
+    }
+
+    /// <summary>
+    /// Insert a Node before another one. Unchecked version. 
+    /// </summary>
+    /// <param name="succ">The successor to be</param>
+    /// <param name="newnode">Node to insert</param>
+    /// <param name="updateViews">update overlapping view in this call</param>
+    void insertNode(bool updateViews, Node succ, Node newnode)
+    {
+      newnode.next = succ;
+      Node pred = newnode.prev = succ.prev;
+      succ.prev.next = newnode;
+      succ.prev = newnode;
+      size++;
+      if (underlying != null)
+        underlying.size++;
+      settag(newnode);
+      if (updateViews)
+        fixViewsAfterInsert(succ, pred, 1, 0);
+    }
+#else
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="index">The index in this view</param>
+    /// <param name="succ"></param>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    Node insert(int index, Node succ, T item)
+    {
+      Node newnode = new Node(item, succ.prev, succ);
+      succ.prev.next = newnode;
+      succ.prev = newnode;
+      size++;
+      if (underlying != null)
+        underlying.size++;
+      fixViewsAfterInsert(succ, newnode.prev, 1, Offset + index);
+      return newnode;
+    }
+#endif
+    #endregion
+
+    #region Removal
+    T remove(Node node, int index)
+    {
+      fixViewsBeforeSingleRemove(node, Offset + index);
+      node.prev.next = node.next;
+      node.next.prev = node.prev;
+      size--;
+      if (underlying != null)
+        underlying.size--;
+#if HASHINDEX
+      removefromtaggroup(node);
+#endif
+      return node.item;
+    }
+
+#if HASHINDEX
+    private bool dictremove(T item, out Node node)
+    {
+      if (underlying == null)
+      {
+        if (!dict.Remove(item, out node))
+          return false;
+      }
+      else
+      {
+        //We cannot avoid calling dict twice - have to intersperse the listorder test!
+        if (!contains(item, out node))
+          return false;
+        dict.Remove(item);
+      }
+      return true;
+    }
+#endif
+    #endregion
+
+    #region fixView utilities
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="added">The actual number of inserted nodes</param>
+    /// <param name="pred">The predecessor of the inserted nodes</param>
+    /// <param name="succ">The successor of the added nodes</param>
+    /// <param name="realInsertionIndex"></param>
+    void fixViewsAfterInsert(Node succ, Node pred, int added, int realInsertionIndex)
+    {
+      if (views != null)
+        foreach (HashedLinkedList<T> view in views)
+        {
+          if (view != this)
+          {
+#if HASHINDEX
+            if (pred.precedes(view.startsentinel) || (view.startsentinel == pred && view.size > 0))
+              view.offset += added;
+            if (view.startsentinel.precedes(pred) && succ.precedes(view.endsentinel))
+              view.size += added;
+            if (view.startsentinel == pred && view.size > 0)
+              view.startsentinel = succ.prev;
+            if (view.endsentinel == succ)
+              view.endsentinel = pred.next;
+#else
+            if (view.Offset == realInsertionIndex && view.size > 0)
+              view.startsentinel = succ.prev;
+            if (view.Offset + view.size == realInsertionIndex)
+              view.endsentinel = pred.next;
+            if (view.Offset < realInsertionIndex && view.Offset + view.size > realInsertionIndex)
+              view.size += added;
+            if (view.Offset > realInsertionIndex || (view.Offset == realInsertionIndex && view.size > 0))
+              view.offset += added;
+#endif
+          }
+        }
+    }
+
+    void fixViewsBeforeSingleRemove(Node node, int realRemovalIndex)
+    {
+      if (views != null)
+        foreach (HashedLinkedList<T> view in views)
+        {
+          if (view != this)
+          {
+#if HASHINDEX
+            if (view.startsentinel.precedes(node) && node.precedes(view.endsentinel))
+              view.size--;
+            if (!view.startsentinel.precedes(node))
+              view.offset--;
+            if (view.startsentinel == node)
+              view.startsentinel = node.prev;
+            if (view.endsentinel == node)
+              view.endsentinel = node.next;
+#else
+            if (view.offset - 1 == realRemovalIndex)
+              view.startsentinel = node.prev;
+            if (view.offset + view.size == realRemovalIndex)
+              view.endsentinel = node.next;
+            if (view.offset <= realRemovalIndex && view.offset + view.size > realRemovalIndex)
+              view.size--;
+            if (view.offset > realRemovalIndex)
+              view.offset--;
+#endif
+          }
+        }
+    }
+
+#if HASHINDEX
+#else
+    void fixViewsBeforeRemove(int start, int count, Node first, Node last)
+    {
+      int clearend = start + count - 1;
+      if (views != null)
+        foreach (HashedLinkedList<T> view in views)
+        {
+          if (view == this)
+            continue;
+          int viewoffset = view.Offset, viewend = viewoffset + view.size - 1;
+          //sentinels
+          if (start < viewoffset && viewoffset - 1 <= clearend)
+            view.startsentinel = first.prev;
+          if (start <= viewend + 1 && viewend < clearend)
+            view.endsentinel = last.next;
+          //offsets and sizes
+          if (start < viewoffset)
+          {
+            if (clearend < viewoffset)
+              view.offset = viewoffset - count;
+            else
+            {
+              view.offset = start;
+              view.size = clearend < viewend ? viewend - clearend : 0;
+            }
+          }
+          else if (start <= viewend)
+            view.size = clearend <= viewend ? view.size - count : start - viewoffset;
+        }
+    }
+#endif
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="otherView"></param>
+    /// <returns>The position of View(otherOffset, otherSize) wrt. this view</returns>
+    MutualViewPosition viewPosition(HashedLinkedList<T> otherView)
+    {
+#if HASHINDEX
+      Node otherstartsentinel = otherView.startsentinel, otherendsentinel = otherView.endsentinel,
+        first = startsentinel.next, last = endsentinel.prev,
+        otherfirst = otherstartsentinel.next, otherlast = otherendsentinel.prev;
+      if (last.precedes(otherfirst) || otherlast.precedes(first))
+        return MutualViewPosition.NonOverlapping;
+      if (size == 0 || (otherstartsentinel.precedes(first) && last.precedes(otherendsentinel)))
+        return MutualViewPosition.Contains;
+      if (otherView.size == 0 || (startsentinel.precedes(otherfirst) && otherlast.precedes(endsentinel)))
+        return MutualViewPosition.ContainedIn;
+      return MutualViewPosition.Overlapping;
+#else
+      int end = offset + size, otherOffset = otherView.offset, otherSize = otherView.size, otherEnd = otherOffset + otherSize;
+      if (otherOffset >= end || otherEnd <= offset)
+        return MutualViewPosition.NonOverlapping;
+      if (size == 0 || (otherOffset <= offset && end <= otherEnd))
+        return MutualViewPosition.Contains;
+      if (otherSize == 0 || (offset <= otherOffset && otherEnd <= end))
+        return MutualViewPosition.ContainedIn;
+      return MutualViewPosition.Overlapping;
+#endif
+    }
+
+    void disposeOverlappingViews(bool reverse)
+    {
+      if (views != null)
+      {
+        foreach (HashedLinkedList<T> view in views)
+        {
+          if (view != this)
+          {
+            switch (viewPosition(view))
+            {
+              case MutualViewPosition.ContainedIn:
+                if (reverse)
+                { }
+                else
+                  view.Dispose();
+                break;
+              case MutualViewPosition.Overlapping:
+                view.Dispose();
+                break;
+              case MutualViewPosition.Contains:
+              case MutualViewPosition.NonOverlapping:
+                break;
+            }
+          }
+        }
+      }
+    }
+
+    #endregion
+
+    #endregion
+
+    #region Constructors
+
+    /// <summary>
+    /// Create a linked list with en external item equalityComparer
+    /// </summary>
+    /// <param name="itemequalityComparer">The external equalityComparer</param>
+    public HashedLinkedList(SCG.IEqualityComparer<T> itemequalityComparer)
+      : base(itemequalityComparer)
+    {
+      offset = 0;
+      size = stamp = 0;
+      startsentinel = new Node(default(T));
+      endsentinel = new Node(default(T));
+      startsentinel.next = endsentinel;
+      endsentinel.prev = startsentinel;
+#if HASHINDEX
+      //It is important that the sentinels are different:
+      startsentinel.taggroup = new TagGroup();
+      startsentinel.taggroup.tag = int.MinValue;
+      startsentinel.taggroup.count = 0;
+      endsentinel.taggroup = new TagGroup();
+      endsentinel.taggroup.tag = int.MaxValue;
+      endsentinel.taggroup.count = 0;
+      dict = new HashDictionary<T, Node>(itemequalityComparer);
+#endif
+    }
+
+    /// <summary>
+    /// Create a linked list with the natural item equalityComparer
+    /// </summary>
+    public HashedLinkedList() : this(EqualityComparer<T>.Default) { }
+
+    #endregion
+
+    #region Node nested class
+
+    /// <summary>
+    /// An individual cell in the linked list
+    /// </summary>
+    [Serializable]
+    class Node
+    {
+      public Node prev;
+
+      public Node next;
+
+      public T item;
+
+      #region Tag support
+#if HASHINDEX
+      internal int tag;
+
+      internal TagGroup taggroup;
+
+      internal bool precedes(Node that)
+      {
+        //Debug.Assert(taggroup != null, "taggroup field null");
+        //Debug.Assert(that.taggroup != null, "that.taggroup field null");
+        int t1 = taggroup.tag;
+        int t2 = that.taggroup.tag;
+
+        return t1 < t2 ? true : t1 > t2 ? false : tag < that.tag;
+      }
+#endif
+      #endregion
+
+      [Tested]
+      internal Node(T item) { this.item = item; }
+
+      [Tested]
+      internal Node(T item, Node prev, Node next)
+      {
+        this.item = item; this.prev = prev; this.next = next;
+      }
+
+      public override string ToString()
+      {
+#if HASHINDEX
+        return String.Format("Node: (item={0}, tag={1})", item, tag);
+#else
+        return String.Format("Node(item={0})", item);
+#endif
+      }
+    }
+
+    #endregion
+
+    #region Taggroup nested class and tag maintenance utilities
+#if HASHINDEX
+    /// <summary>
+    /// A group of nodes with the same high tag. Purpose is to be
+    /// able to tell the sequence order of two nodes without having to scan through
+    /// the list.
+    /// </summary>
+    [Serializable]
+    class TagGroup
+    {
+      internal int tag, count;
+
+      internal Node first, last;
+
+      /// <summary>
+      /// Pretty print a tag group
+      /// </summary>
+      /// <returns>Formatted tag group</returns>
+      public override string ToString()
+      { return String.Format("TagGroup(tag={0}, cnt={1}, fst={2}, lst={3})", tag, count, first, last); }
+    }
+
+    //Constants for tag maintenance
+    const int wordsize = 32;
+
+    const int lobits = 3;
+
+    const int hibits = lobits + 1;
+
+    const int losize = 1 << lobits;
+
+    const int hisize = 1 << hibits;
+
+    const int logwordsize = 5;
+
+    TagGroup gettaggroup(Node pred, Node succ, out int lowbound, out int highbound)
+    {
+      TagGroup predgroup = pred.taggroup, succgroup = succ.taggroup;
+
+      if (predgroup == succgroup)
+      {
+        lowbound = pred.tag + 1;
+        highbound = succ.tag - 1;
+        return predgroup;
+      }
+      else if (predgroup.first != null)
+      {
+        lowbound = pred.tag + 1;
+        highbound = int.MaxValue;
+        return predgroup;
+      }
+      else if (succgroup.first != null)
+      {
+        lowbound = int.MinValue;
+        highbound = succ.tag - 1;
+        return succgroup;
+      }
+      else
+      {
+        lowbound = int.MinValue;
+        highbound = int.MaxValue;
+        return new TagGroup();
+      }
+    }
+
+
+    /// <summary>
+    /// Put a tag on a node (already inserted in the list). Split taggroups and renumber as 
+    /// necessary.
+    /// </summary>
+    /// <param name="node">The node to tag</param>
+    void settag(Node node)
+    {
+      Node pred = node.prev, succ = node.next;
+      TagGroup predgroup = pred.taggroup, succgroup = succ.taggroup;
+
+      if (predgroup == succgroup)
+      {
+        node.taggroup = predgroup;
+        predgroup.count++;
+        if (pred.tag + 1 == succ.tag)
+          splittaggroup(predgroup);
+        else
+          node.tag = (pred.tag + 1) / 2 + (succ.tag - 1) / 2;
+      }
+      else if (predgroup.first != null)
+      {
+        node.taggroup = predgroup;
+        predgroup.last = node;
+        predgroup.count++;
+        if (pred.tag == int.MaxValue)
+          splittaggroup(predgroup);
+        else
+          node.tag = pred.tag / 2 + int.MaxValue / 2 + 1;
+      }
+      else if (succgroup.first != null)
+      {
+        node.taggroup = succgroup;
+        succgroup.first = node;
+        succgroup.count++;
+        if (succ.tag == int.MinValue)
+          splittaggroup(node.taggroup);
+        else
+          node.tag = int.MinValue / 2 + (succ.tag - 1) / 2;
+      }
+      else
+      {
+        Debug.Assert(Taggroups == 0);
+
+        TagGroup newgroup = new TagGroup();
+
+        Taggroups = 1;
+        node.taggroup = newgroup;
+        newgroup.first = newgroup.last = node;
+        newgroup.count = 1;
+        return;
+      }
+    }
+
+
+    /// <summary>
+    /// Remove a node from its taggroup.
+    /// <br/> When this is called, node must already have been removed from the underlying list
+    /// </summary>
+    /// <param name="node">The node to remove</param>
+    void removefromtaggroup(Node node)
+    {
+     
+      TagGroup taggroup = node.taggroup;
+
+      if (--taggroup.count == 0)
+      {
+        Taggroups--;
+        return;
+      }
+
+      if (node == taggroup.first)
+        taggroup.first = node.next;
+
+      if (node == taggroup.last)
+        taggroup.last = node.prev;
+
+      //node.taggroup = null;
+      if (taggroup.count != losize || Taggroups == 1)
+        return;
+
+      TagGroup otg;
+      // bug20070911:
+      Node neighbor;
+      if ((neighbor = taggroup.first.prev) != startsentinel
+          && (otg = neighbor.taggroup).count <= losize)
+        taggroup.first = otg.first;
+      else if ((neighbor = taggroup.last.next) != endsentinel 
+               && (otg = neighbor.taggroup).count <= losize)
+        taggroup.last = otg.last;
+      else
+        return;
+
+      Node n = otg.first;
+
+      for (int i = 0, length = otg.count; i < length; i++)
+      {
+        n.taggroup = taggroup;
+        n = n.next;
+      }
+
+      taggroup.count += otg.count;
+      Taggroups--;
+      n = taggroup.first;
+
+      const int ofs = wordsize - hibits;
+
+      for (int i = 0, count = taggroup.count; i < count; i++)
+      {
+        n.tag = (i - losize) << ofs; //(i-8)<<28 
+        n = n.next;
+      }
+    }
+
+
+    /// <summary>
+    /// Split a tag group to make rom for more tags.
+    /// </summary>
+    /// <param name="taggroup">The tag group</param>
+    void splittaggroup(TagGroup taggroup)
+    {
+      Node n = taggroup.first;
+      int ptgt = taggroup.first.prev.taggroup.tag;
+      int ntgt = taggroup.last.next.taggroup.tag;
+
+      Debug.Assert(ptgt + 1 <= ntgt - 1);
+
+      int ofs = wordsize - hibits;
+      int newtgs = (taggroup.count - 1) / hisize;
+      int tgtdelta = (int)((ntgt + 0.0 - ptgt) / (newtgs + 2)), tgtag = ptgt;
+
+      tgtdelta = tgtdelta == 0 ? 1 : tgtdelta;
+      for (int j = 0; j < newtgs; j++)
+      {
+        TagGroup newtaggroup = new TagGroup();
+
+        newtaggroup.tag = (tgtag = tgtag >= ntgt - tgtdelta ? ntgt : tgtag + tgtdelta);
+        newtaggroup.first = n;
+        newtaggroup.count = hisize;
+        for (int i = 0; i < hisize; i++)
+        {
+          n.taggroup = newtaggroup;
+          n.tag = (i - losize) << ofs; //(i-8)<<28 
+          n = n.next;
+        }
+
+        newtaggroup.last = n.prev;
+      }
+
+      int rest = taggroup.count - hisize * newtgs;
+
+      taggroup.first = n;
+      taggroup.count = rest;
+      taggroup.tag = (tgtag = tgtag >= ntgt - tgtdelta ? ntgt : tgtag + tgtdelta); ofs--;
+      for (int i = 0; i < rest; i++)
+      {
+        n.tag = (i - hisize) << ofs; //(i-16)<<27 
+        n = n.next;
+      }
+
+      taggroup.last = n.prev;
+      Taggroups += newtgs;
+      if (tgtag == ntgt)
+        redistributetaggroups(taggroup);
+    }
+
+
+    private void redistributetaggroups(TagGroup taggroup)
+    {
+      TagGroup pred = taggroup, succ = taggroup, tmp;
+      double limit = 1, bigt = Math.Pow(Taggroups, 1.0 / 30);//?????
+      int bits = 1, count = 1, lowmask = 0, himask = 0, target = 0;
+
+      do
+      {
+        bits++;
+        lowmask = (1 << bits) - 1;
+        himask = ~lowmask;
+        target = taggroup.tag & himask;
+        while ((tmp = pred.first.prev.taggroup).first != null && (tmp.tag & himask) == target)
+        { count++; pred = tmp; }
+
+        while ((tmp = succ.last.next.taggroup).last != null && (tmp.tag & himask) == target)
+        { count++; succ = tmp; }
+
+        limit *= bigt;
+      } while (count > limit);
+
+      //redistibute tags
+      int lob = pred.first.prev.taggroup.tag, upb = succ.last.next.taggroup.tag;
+      int delta = upb / (count + 1) - lob / (count + 1);
+
+      Debug.Assert(delta > 0);
+      for (int i = 0; i < count; i++)
+      {
+        pred.tag = lob + (i + 1) * delta;
+        pred = pred.last.next.taggroup;
+      }
+    }
+#endif
+
+    #endregion
+
+    #region Position, PositionComparer and ViewHandler nested types
+    class PositionComparer : SCG.IComparer<Position>
+    {
+      static PositionComparer _default;
+      PositionComparer() { }
+      public static PositionComparer Default { get { return _default ?? (_default = new PositionComparer()); } }
+      public int Compare(Position a, Position b)
+      {
+#if HASHINDEX
+        return a.Endpoint == b.Endpoint ? 0 : a.Endpoint.precedes(b.Endpoint) ? -1 : 1;
+#else
+        return a.Index.CompareTo(b.Index);
+#endif
+      }
+    }
+    /// <summary>
+    /// During RemoveAll, we need to cache the original endpoint indices of views
+    /// </summary>
+    struct Position
+    {
+      public readonly HashedLinkedList<T> View;
+      public bool Left;
+#if HASHINDEX
+      public readonly Node Endpoint;
+#else
+      public readonly int Index;
+#endif
+      public Position(HashedLinkedList<T> view, bool left)
+      {
+        View = view;
+        Left = left;
+#if HASHINDEX
+        Endpoint = left ? view.startsentinel.next : view.endsentinel.prev;
+#else
+        Index = left ? view.Offset : view.Offset + view.size - 1;
+#endif
+      }
+#if HASHINDEX
+      public Position(Node node, int foo) { this.Endpoint = node; View = null; Left = false; }
+#else
+      public Position(int index) { this.Index = index; View = null; Left = false; }
+#endif
+    }
+
+    //TODO: merge the two implementations using Position values as arguments
+    /// <summary>
+    /// Handle the update of (other) views during a multi-remove operation.
+    /// </summary>
+    struct ViewHandler
+    {
+      ArrayList<Position> leftEnds;
+      ArrayList<Position> rightEnds;
+      int leftEndIndex, rightEndIndex, leftEndIndex2, rightEndIndex2;
+      internal readonly int viewCount;
+      internal ViewHandler(HashedLinkedList<T> list)
+      {
+        leftEndIndex = rightEndIndex = leftEndIndex2 = rightEndIndex2 = viewCount = 0;
+        leftEnds = rightEnds = null;
+        if (list.views != null)
+          foreach (HashedLinkedList<T> v in list.views)
+            if (v != list)
+            {
+              if (leftEnds == null)
+              {
+                leftEnds = new ArrayList<Position>();
+                rightEnds = new ArrayList<Position>();
+              }
+              leftEnds.Add(new Position(v, true));
+              rightEnds.Add(new Position(v, false));
+            }
+        if (leftEnds == null)
+          return;
+        viewCount = leftEnds.Count;
+        leftEnds.Sort(PositionComparer.Default);
+        rightEnds.Sort(PositionComparer.Default);
+      }
+#if HASHINDEX
+      internal void skipEndpoints(int removed, Node n)
+      {
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex < viewCount && ((endpoint = leftEnds[leftEndIndex]).Endpoint.prev.precedes(n)))
+          {
+            HashedLinkedList<T> view = endpoint.View;
+            view.offset = view.offset - removed;//TODO: extract offset.Value?
+            view.size += removed;
+            leftEndIndex++;
+          }
+          while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).Endpoint.precedes(n))
+          {
+            HashedLinkedList<T> view = endpoint.View;
+            view.size -= removed;
+            rightEndIndex++;
+          }
+        }
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex2 < viewCount && (endpoint = leftEnds[leftEndIndex2]).Endpoint.prev.precedes(n))
+            leftEndIndex2++;
+          while (rightEndIndex2 < viewCount && (endpoint = rightEnds[rightEndIndex2]).Endpoint.next.precedes(n))
+            rightEndIndex2++;
+        }
+      }
+      /// <summary>
+      /// To be called with n pointing to the right of each node to be removed in a stretch. 
+      /// And at the endsentinel. 
+      /// 
+      /// Update offset of a view whose left endpoint (has not already been handled and) is n or precedes n.
+      /// I.e. startsentinel precedes n.
+      /// Also update the size as a prelude to handling the right endpoint.
+      /// 
+      /// Update size of a view not already handled and whose right endpoint precedes n.
+      /// </summary>
+      /// <param name="removed">The number of nodes left of n to be removed</param>
+      /// <param name="n"></param>
+      internal void updateViewSizesAndCounts(int removed, Node n)
+      {
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex < viewCount && ((endpoint = leftEnds[leftEndIndex]).Endpoint.prev.precedes(n)))
+          {
+            HashedLinkedList<T> view = endpoint.View;
+            view.offset = view.offset - removed; //TODO: fix use of offset
+            view.size += removed;
+            leftEndIndex++;
+          }
+          while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).Endpoint.precedes(n))
+          {
+            HashedLinkedList<T> view = endpoint.View;
+            view.size -= removed;
+            rightEndIndex++;
+          }
+        }
+      }
+      /// <summary>
+      /// To be called with n being the first not-to-be-removed node after a (stretch of) node(s) to be removed.
+      /// 
+      /// It will update the startsentinel of views (that have not been handled before and) 
+      /// whose startsentinel precedes n, i.e. is to be deleted.
+      /// 
+      /// It will update the endsentinel of views (...) whose endsentinel precedes n, i.e. is to be deleted.
+      /// 
+      /// PROBLEM: DOESNT WORK AS ORIGINALLY ADVERTISED. WE MUST DO THIS BEFORE WE ACTUALLY REMOVE THE NODES. WHEN THE 
+      /// NODES HAVE BEEN REMOVED, THE precedes METHOD WILL NOT WORK!
+      /// </summary>
+      /// <param name="n"></param>
+      /// <param name="newstart"></param>
+      /// <param name="newend"></param>
+      internal void updateSentinels(Node n, Node newstart, Node newend)
+      {
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex2 < viewCount && (endpoint = leftEnds[leftEndIndex2]).Endpoint.prev.precedes(n))
+          {
+            HashedLinkedList<T> view = endpoint.View;
+            view.startsentinel = newstart;
+            leftEndIndex2++;
+          }
+          while (rightEndIndex2 < viewCount && (endpoint = rightEnds[rightEndIndex2]).Endpoint.next.precedes(n))
+          {
+            HashedLinkedList<T> view = endpoint.View;
+            view.endsentinel = newend;
+            rightEndIndex2++;
+          }
+        }
+      }
+#else
+      /// <summary>
+      /// This is to be called with realindex pointing to the first node to be removed after a (stretch of) node that was not removed
+      /// </summary>
+      /// <param name="removed"></param>
+      /// <param name="realindex"></param>
+      internal void skipEndpoints(int removed, int realindex)
+      {
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex < viewCount && (endpoint = leftEnds[leftEndIndex]).Index <= realindex)
+          {
+            HashedLinkedList<T> view = endpoint.View;
+            view.offset = view.offset - removed;
+            view.size += removed;
+            leftEndIndex++;
+          }
+          while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).Index < realindex)
+          {
+            HashedLinkedList<T> view = endpoint.View;
+            view.size -= removed;
+            rightEndIndex++;
+          }
+        }
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex2 < viewCount && (endpoint = leftEnds[leftEndIndex2]).Index <= realindex)
+            leftEndIndex2++;
+          while (rightEndIndex2 < viewCount && (endpoint = rightEnds[rightEndIndex2]).Index < realindex - 1)
+            rightEndIndex2++;
+        }
+      }
+      internal void updateViewSizesAndCounts(int removed, int realindex)
+      {
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex < viewCount && (endpoint = leftEnds[leftEndIndex]).Index <= realindex)
+          {
+            HashedLinkedList<T> view = endpoint.View;
+            view.offset = view.Offset - removed;
+            view.size += removed;
+            leftEndIndex++;
+          }
+          while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).Index < realindex)
+          {
+            HashedLinkedList<T> view = endpoint.View;
+            view.size -= removed;
+            rightEndIndex++;
+          }
+        }
+      }
+      internal void updateSentinels(int realindex, Node newstart, Node newend)
+      {
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex2 < viewCount && (endpoint = leftEnds[leftEndIndex2]).Index <= realindex)
+          {
+            HashedLinkedList<T> view = endpoint.View;
+            view.startsentinel = newstart;
+            leftEndIndex2++;
+          }
+          while (rightEndIndex2 < viewCount && (endpoint = rightEnds[rightEndIndex2]).Index < realindex - 1)
+          {
+            HashedLinkedList<T> view = endpoint.View;
+            view.endsentinel = newend;
+            rightEndIndex2++;
+          }
+        }
+      }
+#endif
+    }
+    #endregion
+
+    #region Range nested class
+
+    class Range : DirectedCollectionValueBase<T>, IDirectedCollectionValue<T>
+    {
+      int start, count, rangestamp;
+      Node startnode, endnode;
+
+      HashedLinkedList<T> list;
+
+      bool forwards;
+
+
+      internal Range(HashedLinkedList<T> list, int start, int count, bool forwards)
+      {
+        this.list = list; this.rangestamp = list.underlying != null ? list.underlying.stamp : list.stamp;
+        this.start = start; this.count = count; this.forwards = forwards;
+        if (count > 0)
+        {
+          startnode = list.get(start);
+          endnode = list.get(start + count - 1);
+        }
+      }
+
+      public override bool IsEmpty { get { list.modifycheck(rangestamp); return count == 0; } }
+
+      [Tested]
+      public override int Count { [Tested]get { list.modifycheck(rangestamp); return count; } }
+
+
+      public override Speed CountSpeed { get { list.modifycheck(rangestamp); return Speed.Constant; } }
+
+
+      public override T Choose()
+      {
+        list.modifycheck(rangestamp);
+        if (count > 0) return startnode.item;
+        throw new NoSuchItemException();
+      }
+
+
+      [Tested]
+      public override SCG.IEnumerator<T> GetEnumerator()
+      {
+        int togo = count;
+
+        list.modifycheck(rangestamp);
+        if (togo == 0)
+          yield break;
+
+        Node cursor = forwards ? startnode : endnode;
+
+        yield return cursor.item;
+        while (--togo > 0)
+        {
+          cursor = forwards ? cursor.next : cursor.prev;
+          list.modifycheck(rangestamp);
+          yield return cursor.item;
+        }
+      }
+
+
+      [Tested]
+      public override IDirectedCollectionValue<T> Backwards()
+      {
+        list.modifycheck(rangestamp);
+
+        Range b = (Range)MemberwiseClone();
+
+        b.forwards = !forwards;
+        return b;
+      }
+
+
+      [Tested]
+      IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
+
+
+      [Tested]
+      public override EnumerationDirection Direction
+      {
+        [Tested]
+        get
+        { return forwards ? EnumerationDirection.Forwards : EnumerationDirection.Backwards; }
+      }
+    }
+
+
+    #endregion
+
+    #region IDisposable Members
+
+    /// <summary>
+    /// Invalidate this list. If a view, just invalidate the view. 
+    /// If not a view, invalidate the list and all views on it.
+    /// </summary>
+    public virtual void Dispose()
+    {
+      Dispose(false);
+    }
+
+    void Dispose(bool disposingUnderlying)
+    {
+      if (isValid)
+      {
+        if (underlying != null)
+        {
+          isValid = false;
+          if (!disposingUnderlying && views != null)
+            views.Remove(myWeakReference);
+          endsentinel = null;
+          startsentinel = null;
+          underlying = null;
+          views = null;
+          myWeakReference = null;
+        }
+        else
+        {
+          //isValid = false;
+          //endsentinel = null;
+          //startsentinel = null;
+          if (views != null)
+            foreach (HashedLinkedList<T> view in views)
+              view.Dispose(true);
+          //views = null;
+          Clear();
+        }
+      }
+    }
+
+    #endregion IDisposable stuff
+
+    #region IList<T> Members
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+    /// <value>The first item in this list.</value>
+    [Tested]
+    public virtual T First
+    {
+      [Tested]
+      get
+      {
+        validitycheck();
+        if (size == 0)
+          throw new NoSuchItemException();
+        return startsentinel.next.item;
+      }
+    }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+    /// <value>The last item in this list.</value>
+    [Tested]
+    public virtual T Last
+    {
+      [Tested]
+      get
+      {
+        validitycheck();
+        if (size == 0)
+          throw new NoSuchItemException();
+        return endsentinel.prev.item;
+      }
+    }
+
+    /// <summary>
+    /// Since <code>Add(T item)</code> always add at the end of the list,
+    /// this describes if list has FIFO or LIFO semantics.
+    /// </summary>
+    /// <value>True if the <code>Remove()</code> operation removes from the
+    /// start of the list, false if it removes from the end. THe default for a new linked list is true.</value>
+    [Tested]
+    public virtual bool FIFO
+    {
+      [Tested]
+      get { validitycheck(); return fIFO; }
+      [Tested]
+      set { updatecheck(); fIFO = value; }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public virtual bool IsFixedSize
+    {
+      get { validitycheck(); return false; }
+    }
+
+    /// <summary>
+    /// On this list, this indexer is read/write.
+    /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+    /// &gt;= the size of the collection.
+    /// </summary>
+    /// <value>The i'th item of this list.</value>
+    /// <param name="index">The index of the item to fetch or store.</param>
+    [Tested]
+    public virtual T this[int index]
+    {
+      [Tested]
+      get { validitycheck(); return get(index).item; }
+      [Tested]
+      set
+      {
+        updatecheck();
+        Node n = get(index);
+        //
+        T item = n.item;
+#if HASHINDEX
+
+        if (itemequalityComparer.Equals(value, item))
+        {
+          n.item = value;
+          dict.Update(value, n);
+        }
+        else if (!dict.FindOrAdd(value, ref n))
+        {
+          dict.Remove(item);
+          n.item = value;
+        }
+        else
+          throw new ArgumentException("Item already in indexed list");
+#else
+        n.item = value;
+#endif
+        (underlying ?? this).raiseForSetThis(index, value, item);
+      }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual Speed IndexingSpeed { get { return Speed.Linear; } }
+
+    /// <summary>
+    /// Insert an item at a specific index location in this list. 
+    /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+    /// &gt; the size of the collection.</summary>
+    /// <param name="i">The index at which to insert.</param>
+    /// <param name="item">The item to insert.</param>
+    [Tested]
+    public virtual void Insert(int i, T item)
+    {
+      updatecheck();
+      insert(i, i == size ? endsentinel : get(i), item);
+      if (ActiveEvents != EventTypeEnum.None)
+        (underlying ?? this).raiseForInsert(i + Offset, item);
+    }
+
+    /// <summary>
+    /// Insert an item at the end of a compatible view, used as a pointer.
+    /// <para>The <code>pointer</code> must be a view on the same list as
+    /// <code>this</code> and the endpoitn of <code>pointer</code> must be
+    /// a valid insertion point of <code>this</code></para>
+    /// </summary>
+    /// <exception cref="IncompatibleViewException">If <code>pointer</code> 
+    /// is not a view on the same list as <code>this</code></exception>
+    /// <exception cref="IndexOutOfRangeException"><b>??????</b> if the endpoint of 
+    ///  <code>pointer</code> is not inside <code>this</code></exception>
+    /// <exception cref="DuplicateNotAllowedException"> if the list has
+    /// <code>AllowsDuplicates==false</code> and the item is 
+    /// already in the list.</exception>
+    /// <param name="pointer"></param>
+    /// <param name="item"></param>
+    public void Insert(IList<T> pointer, T item)
+    {
+      updatecheck();
+      if ((pointer == null) || ((pointer.Underlying ?? pointer) != (underlying ?? this)))
+        throw new IncompatibleViewException();
+#warning INEFFICIENT
+      //TODO: make this efficient (the whole point of the method:
+      //Do NOT use Insert, but insert the node at pointer.endsentinel, checking
+      //via the ordering that this is a valid insertion point
+      Insert(pointer.Offset + pointer.Count - Offset, item);
+    }
+
+    /// <summary>
+    /// Insert into this list all items from an enumerable collection starting 
+    /// at a particular index.
+    /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+    /// &gt; the size of the collection.
+    /// </summary>
+    /// <param name="i">Index to start inserting at</param>
+    /// <param name="items">Items to insert</param>
+    /// <typeparam name="U"></typeparam>
+    [Tested]
+    public virtual void InsertAll<U>(int i, SCG.IEnumerable<U> items) where U : T
+    {
+      insertAll(i, items, true);
+    }
+
+    void insertAll<U>(int i, SCG.IEnumerable<U> items, bool insertion) where U : T
+    {
+      updatecheck();
+      Node succ, node, pred;
+      int count = 0;
+      succ = i == size ? endsentinel : get(i);
+      pred = node = succ.prev;
+#if HASHINDEX
+      TagGroup taggroup = null;
+      int taglimit = 0, thetag = 0;
+      taggroup = gettaggroup(node, succ, out thetag, out taglimit);
+      try
+      {
+        foreach (T item in items)
+        {
+          Node tmp = new Node(item, node, null);
+          if (!dict.FindOrAdd(item, ref tmp))
+          {
+            tmp.tag = thetag < taglimit ? ++thetag : thetag;
+            tmp.taggroup = taggroup;
+            node.next = tmp;
+            count++;
+            node = tmp;
+          }
+          else
+            throw new DuplicateNotAllowedException("Item already in indexed list");
+        }
+      }
+      finally
+      {
+        if (count != 0)
+        { 
+          taggroup.count += count;
+          if (taggroup != pred.taggroup)
+            taggroup.first = pred.next;
+          if (taggroup != succ.taggroup)
+            taggroup.last = node;
+          succ.prev = node;
+          node.next = succ;
+          if (node.tag == node.prev.tag)
+            splittaggroup(taggroup);
+          size += count;
+          if (underlying != null)
+            underlying.size += count;
+          fixViewsAfterInsert(succ, pred, count, 0);
+          raiseForInsertAll(pred, i, count, insertion);
+        }
+      }
+#else
+      foreach (T item in items)
+      {
+        Node tmp = new Node(item, node, null);
+        node.next = tmp;
+        count++;
+        node = tmp;
+      }
+      if (count == 0)
+        return;
+      succ.prev = node;
+      node.next = succ;
+      size += count;
+      if (underlying != null)
+        underlying.size += count;
+      if (count > 0)
+      {
+        fixViewsAfterInsert(succ, pred, count, offset + i);
+        raiseForInsertAll(pred, i, count, insertion);
+      }
+#endif
+    }
+
+    private void raiseForInsertAll(Node node, int i, int added, bool insertion)
+    {
+      if (ActiveEvents != 0)
+      {
+        int index = Offset + i;
+        if ((ActiveEvents & (EventTypeEnum.Added | EventTypeEnum.Inserted)) != 0)
+          for (int j = index; j < index + added; j++)
+          {
+#warning must we check stamps here?
+            node = node.next;
+            T item = node.item;
+            if (insertion) raiseItemInserted(item, j);
+            raiseItemsAdded(item, 1);
+          }
+        raiseCollectionChanged();
+      }
+    }
+
+    /// <summary>
+    /// Insert an item at the front of this list.
+    /// </summary>
+    /// <param name="item">The item to insert.</param>
+    [Tested]
+    public virtual void InsertFirst(T item)
+    {
+      updatecheck();
+      insert(0, startsentinel.next, item);
+      if (ActiveEvents != EventTypeEnum.None)
+        (underlying ?? this).raiseForInsert(0 + Offset, item);
+    }
+
+    /// <summary>
+    /// Insert an item at the back of this list.
+    /// </summary>
+    /// <param name="item">The item to insert.</param>
+    [Tested]
+    public virtual void InsertLast(T item)
+    {
+      updatecheck();
+      insert(size, endsentinel, item);
+      if (ActiveEvents != EventTypeEnum.None)
+        (underlying ?? this).raiseForInsert(size - 1 + Offset, item);
+    }
+
+    /// <summary>
+    /// Create a new list consisting of the results of mapping all items of this
+    /// list.
+    /// </summary>
+    /// <param name="mapper">The delegate defining the map.</param>
+    /// <returns>The new list.</returns>
+    [Tested]
+    public IList<V> Map<V>(Fun<T, V> mapper)
+    {
+      validitycheck();
+
+      HashedLinkedList<V> retval = new HashedLinkedList<V>();
+      return map<V>(mapper, retval);
+    }
+
+    /// <summary>
+    /// Create a new list consisting of the results of mapping all items of this
+    /// list. The new list will use a specified equalityComparer for the item type.
+    /// </summary>
+    /// <typeparam name="V">The type of items of the new list</typeparam>
+    /// <param name="mapper">The delegate defining the map.</param>
+    /// <param name="equalityComparer">The equalityComparer to use for the new list</param>
+    /// <returns>The new list.</returns>
+    public IList<V> Map<V>(Fun<T, V> mapper, SCG.IEqualityComparer<V> equalityComparer)
+    {
+      validitycheck();
+
+      HashedLinkedList<V> retval = new HashedLinkedList<V>(equalityComparer);
+      return map<V>(mapper, retval);
+    }
+
+    private IList<V> map<V>(Fun<T, V> mapper, HashedLinkedList<V> retval)
+    {
+      if (size == 0)
+        return retval;
+      int stamp = this.stamp;
+      Node cursor = startsentinel.next;
+      HashedLinkedList<V>.Node mcursor = retval.startsentinel;
+
+#if HASHINDEX
+      double tagdelta = int.MaxValue / (size + 1.0);
+      int count = 1;
+      HashedLinkedList<V>.TagGroup taggroup = null;
+      taggroup = new HashedLinkedList<V>.TagGroup();
+      retval.taggroups = 1;
+      taggroup.count = size;
+#endif
+      while (cursor != endsentinel)
+      {
+        V v = mapper(cursor.item);
+        modifycheck(stamp);
+        mcursor.next = new HashedLinkedList<V>.Node(v, mcursor, null);
+        cursor = cursor.next;
+        mcursor = mcursor.next;
+#if HASHINDEX
+        retval.dict.Add(v, mcursor);
+        mcursor.taggroup = taggroup;
+        mcursor.tag = (int)(tagdelta * count++);
+#endif
+      }
+
+#if HASHINDEX
+      taggroup.first = retval.startsentinel.next;
+      taggroup.last = mcursor;
+#endif
+      retval.endsentinel.prev = mcursor;
+      mcursor.next = retval.endsentinel;
+      retval.size = size;
+      return retval;
+    }
+
+    /// <summary>
+    /// Remove one item from the list: from the front if <code>FIFO</code>
+    /// is true, else from the back.
+    /// <exception cref="NoSuchItemException"/> if this list is empty.
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public virtual T Remove()
+    {
+      updatecheck();
+      if (size == 0)
+        throw new NoSuchItemException("List is empty");
+      T item = fIFO ? remove(startsentinel.next, 0) : remove(endsentinel.prev, size - 1);
+#if HASHINDEX
+      dict.Remove(item);
+#endif
+      (underlying ?? this).raiseForRemove(item);
+      return item;
+    }
+
+    /// <summary>
+    /// Remove one item from the front of the list.
+    /// <exception cref="NoSuchItemException"/> if this list is empty.
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public virtual T RemoveFirst()
+    {
+      updatecheck();
+      if (size == 0)
+        throw new NoSuchItemException("List is empty");
+
+      T item = remove(startsentinel.next, 0);
+#if HASHINDEX
+      dict.Remove(item);
+#endif
+      if (ActiveEvents != EventTypeEnum.None)
+        (underlying ?? this).raiseForRemoveAt(Offset, item);
+      return item;
+    }
+
+    /// <summary>
+    /// Remove one item from the back of the list.
+    /// <exception cref="NoSuchItemException"/> if this list is empty.
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public virtual T RemoveLast()
+    {
+      updatecheck();
+      if (size == 0)
+        throw new NoSuchItemException("List is empty");
+
+      T item = remove(endsentinel.prev, size - 1);
+#if HASHINDEX
+      dict.Remove(item);
+#endif
+      if (ActiveEvents != EventTypeEnum.None)
+        (underlying ?? this).raiseForRemoveAt(size + Offset, item);
+      return item;
+    }
+
+    /// <summary>
+    /// Create a list view on this list. 
+    /// </summary>
+    /// <exception cref="ArgumentOutOfRangeException"> if the start or count is negative</exception>
+    /// <exception cref="ArgumentException"> if the range does not fit within list.</exception>
+    /// <param name="start">The index in this list of the start of the view.</param>
+    /// <param name="count">The size of the view.</param>
+    /// <returns>The new list view.</returns>
+    [Tested]
+    public virtual IList<T> View(int start, int count)
+    {
+      checkRange(start, count);
+      validitycheck();
+      if (views == null)
+        views = new WeakViewList<HashedLinkedList<T>>();
+      HashedLinkedList<T> retval = (HashedLinkedList<T>)MemberwiseClone();
+      retval.underlying = underlying != null ? underlying : this;
+      retval.offset = offset + start;
+      retval.size = count;
+      getPair(start - 1, start + count, out retval.startsentinel, out retval.endsentinel,
+          new int[] { -1, size }, new Node[] { startsentinel, endsentinel });
+      //retval.startsentinel = start == 0 ? startsentinel : get(start - 1);
+      //retval.endsentinel = start + count == size ? endsentinel : get(start + count);
+
+      //TODO: for the purpose of Dispose, we need to retain a ref to the node
+      retval.myWeakReference = views.Add(retval);
+      return retval;
+    }
+
+    /// <summary>
+    /// Create a list view on this list containing the (first) occurrence of a particular item. 
+    /// </summary>
+    /// <exception cref="ArgumentException"> if the item is not in this list.</exception>
+    /// <param name="item">The item to find.</param>
+    /// <returns>The new list view.</returns>
+    public virtual IList<T> ViewOf(T item)
+    {
+#if HASHINDEX
+      Node n;
+      validitycheck();
+      if (!contains(item, out n))
+        return null;
+      HashedLinkedList<T> retval = (HashedLinkedList<T>)MemberwiseClone();
+      retval.underlying = underlying != null ? underlying : this;
+      retval.offset = null;
+      retval.startsentinel = n.prev;
+      retval.endsentinel = n.next;
+      retval.size = 1;
+      return retval;
+#else
+      int index = 0;
+      Node n = startsentinel.next;
+      if (!find(item, ref n, ref index))
+        return null;
+      //TODO: optimize with getpair!
+      return View(index, 1);
+#endif
+    }
+
+    /// <summary>
+    /// Create a list view on this list containing the last occurrence of a particular item. 
+    /// <exception cref="ArgumentException"/> if the item is not in this list.
+    /// </summary>
+    /// <param name="item">The item to find.</param>
+    /// <returns>The new list view.</returns>
+    public virtual IList<T> LastViewOf(T item)
+    {
+#if HASHINDEX
+      return ViewOf(item);
+#else
+      int index = size - 1;
+      Node n = endsentinel.prev;
+      if (!dnif(item, ref n, ref index))
+        return null;
+      return View(index, 1);
+#endif
+    }
+
+    /// <summary>
+    /// Null if this list is not a view.
+    /// </summary>
+    /// <value>Underlying list for view.</value>
+    [Tested]
+    public virtual IList<T> Underlying { [Tested]get { validitycheck(); return underlying; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual bool IsValid { get { return isValid; } }
+
+    /// <summary>
+    /// </summary>
+    /// <value>Offset for this list view or 0 for a underlying list.</value>
+    [Tested]
+    public virtual int Offset
+    {
+      [Tested]
+      get
+      {
+        validitycheck();
+#if HASHINDEX
+        if (offset == null && underlying != null)
+        {
+          //TODO: search from both ends simultaneously!
+          Node n = underlying.startsentinel;
+          int i = 0;
+          while (n != startsentinel) { n = n.next; i++; }
+          offset = i;
+        }
+#endif
+        return (int)offset;
+      }
+    }
+
+    /// <summary>
+    /// Slide this list view along the underlying list.
+    /// </summary>
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>
+    /// <exception cref="ArgumentOutOfRangeException"> if the operation
+    /// would bring either end of the view outside the underlying list.</exception>
+    /// <param name="offset">The signed amount to slide: positive to slide
+    /// towards the end.</param>
+    [Tested]
+    public IList<T> Slide(int offset)
+    {
+      if (!TrySlide(offset, size))
+        throw new ArgumentOutOfRangeException();
+      return this;
+    }
+
+    //TODO: more test cases
+    /// <summary>
+    /// Slide this list view along the underlying list, perhaps changing its size.
+    /// </summary>
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>
+    /// <exception cref="ArgumentOutOfRangeException"> if the operation
+    /// would bring either end of the view outside the underlying list.</exception>
+    /// <param name="offset">The signed amount to slide: positive to slide
+    /// towards the end.</param>
+    /// <param name="size">The new size of the view.</param>
+    public IList<T> Slide(int offset, int size)
+    {
+      if (!TrySlide(offset, size))
+        throw new ArgumentOutOfRangeException();
+      return this;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="offset"></param>
+    /// <returns></returns>
+    public virtual bool TrySlide(int offset) { return TrySlide(offset, size); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="offset"></param>
+    /// <param name="size"></param>
+    /// <returns></returns>
+    public virtual bool TrySlide(int offset, int size)
+    {
+      updatecheck();
+      if (underlying == null)
+        throw new NotAViewException("List not a view");
+
+#pragma warning disable 472
+      if (this.offset == null) //Note: only possible with HASHINDEX
+#pragma warning restore 472
+      {
+#pragma warning disable 162
+        try
+        {
+          getPair(offset - 1, offset + size, out startsentinel, out endsentinel,
+              new int[] { -1, this.size }, new Node[] { startsentinel, endsentinel });
+          //TODO: maybe-update offset field
+        }
+        catch (NullReferenceException)
+        {
+          return false;
+        }
+#pragma warning restore 162
+      }
+      else
+      {
+        if (offset + this.offset < 0 || offset + this.offset + size > underlying.size)
+          return false;
+        int oldoffset = (int)(this.offset);
+        getPair(offset - 1, offset + size, out startsentinel, out endsentinel,
+            new int[] { -oldoffset - 1, -1, this.size, underlying.size - oldoffset },
+            new Node[] { underlying.startsentinel, startsentinel, endsentinel, underlying.endsentinel });
+      }
+      this.size = size;
+      this.offset += offset;
+      return true;
+    }
+
+
+    //TODO: improve the complexity of the implementation
+    /// <summary>
+    /// 
+    /// <para>Returns null if <code>otherView</code> is strictly to the left of this view</para>
+    /// </summary>
+    /// <param name="otherView"></param>
+    /// <exception cref="IncompatibleViewException">If otherView does not have the same underlying list as this</exception>
+    /// <returns></returns>
+    public virtual IList<T> Span(IList<T> otherView)
+    {
+      if ((otherView == null) || ((otherView.Underlying ?? otherView) != (underlying ?? this)))
+        throw new IncompatibleViewException();
+      if (otherView.Offset + otherView.Count - Offset < 0)
+        return null;
+      return (underlying ?? this).View(Offset, otherView.Offset + otherView.Count - Offset);
+    }
+
+
+    //Question: should we swap items or move nodes around?
+    //The first seems much more efficient unless the items are value types 
+    //with a large memory footprint.
+    //(Swapping will do count*3/2 T assignments, linking around will do 
+    // 4*count ref assignments; note that ref assignments are more expensive 
+    //than copying non-ref bits)
+    /// <summary>
+    /// Reverse the list so the items are in the opposite sequence order.
+    /// </summary>
+    [Tested]
+    public virtual void Reverse()
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+
+      Position[] positions = null;
+      int poslow = 0, poshigh = 0;
+      if (views != null)
+      {
+        CircularQueue<Position> _positions = null;
+        foreach (HashedLinkedList<T> view in views)
+        {
+          if (view != this)
+          {
+            switch (viewPosition(view))
+            {
+              case MutualViewPosition.ContainedIn:
+                (_positions ?? (_positions = new CircularQueue<Position>())).Enqueue(new Position(view, true));
+                _positions.Enqueue(new Position(view, false));
+                break;
+              case MutualViewPosition.Overlapping:
+                view.Dispose();
+                break;
+              case MutualViewPosition.Contains:
+              case MutualViewPosition.NonOverlapping:
+                break;
+            }
+          }
+        }
+        if (_positions != null)
+        {
+          positions = _positions.ToArray();
+          Sorting.IntroSort<Position>(positions, 0, positions.Length, PositionComparer.Default);
+          poshigh = positions.Length - 1;
+        }
+      }
+
+      Node a = get(0), b = get(size - 1);
+      for (int i = 0; i < size / 2; i++)
+      {
+        T swap;
+        swap = a.item; a.item = b.item; b.item = swap;
+#if HASHINDEX
+        dict[a.item] = a; dict[b.item] = b;
+#endif
+        if (positions != null)
+          mirrorViewSentinelsForReverse(positions, ref poslow, ref poshigh, a, b, i);
+        a = a.next; b = b.prev;
+      }
+      if (positions != null && size % 2 != 0)
+        mirrorViewSentinelsForReverse(positions, ref poslow, ref poshigh, a, b, size / 2);
+      (underlying ?? this).raiseCollectionChanged();
+    }
+
+    private void mirrorViewSentinelsForReverse(Position[] positions, ref int poslow, ref int poshigh, Node a, Node b, int i)
+    {
+#if HASHINDEX
+      int? aindex = offset + i, bindex = offset + size - 1 - i;
+#else
+      int aindex = offset + i, bindex = offset + size - 1 - i;
+#endif
+      Position pos;
+#if HASHINDEX
+      while (poslow <= poshigh && (pos = positions[poslow]).Endpoint == a)
+#else
+      while (poslow <= poshigh && (pos = positions[poslow]).Index == aindex)
+#endif
+      {
+        //TODO: Note: in the case og hashed linked list, if this.offset == null, but pos.View.offset!=null
+        //we may at this point compute this.offset and non-null values of aindex and bindex
+        if (pos.Left)
+          pos.View.endsentinel = b.next;
+        else
+        {
+          pos.View.startsentinel = b.prev;
+          pos.View.offset = bindex;
+        }
+        poslow++;
+      }
+#if HASHINDEX
+      while (poslow < poshigh && (pos = positions[poshigh]).Endpoint == b)
+#else
+      while (poslow < poshigh && (pos = positions[poshigh]).Index == bindex)
+#endif
+      {
+        if (pos.Left)
+          pos.View.endsentinel = a.next;
+        else
+        {
+          pos.View.startsentinel = a.prev;
+          pos.View.offset = aindex;
+        }
+        poshigh--;
+      }
+    }
+
+    /// <summary>
+    /// Check if this list is sorted according to the default sorting order
+    /// for the item type T, as defined by the <see cref="T:C5.Comparer`1"/> class 
+    /// </summary>
+    /// <exception cref="NotComparableException">if T is not comparable</exception>
+    /// <returns>True if the list is sorted, else false.</returns>
+    public bool IsSorted() { return IsSorted(Comparer<T>.Default); }
+
+    /// <summary>
+    /// Check if this list is sorted according to a specific sorting order.
+    /// </summary>
+    /// <param name="c">The comparer defining the sorting order.</param>
+    /// <returns>True if the list is sorted, else false.</returns>
+    [Tested]
+    public virtual bool IsSorted(SCG.IComparer<T> c)
+    {
+      validitycheck();
+      if (size <= 1)
+        return true;
+
+      Node node = startsentinel.next;
+      T prevItem = node.item;
+
+      node = node.next;
+      while (node != endsentinel)
+      {
+        if (c.Compare(prevItem, node.item) > 0)
+          return false;
+        else
+        {
+          prevItem = node.item;
+          node = node.next;
+        }
+      }
+
+      return true;
+    }
+
+    /// <summary>
+    /// Sort the items of the list according to the default sorting order
+    /// for the item type T, as defined by the Comparer[T] class. 
+    /// (<see cref="T:C5.Comparer`1"/>).
+    /// The sorting is stable.
+    /// </summary>
+    /// <exception cref="InvalidOperationException">if T is not comparable</exception>
+    public virtual void Sort() { Sort(Comparer<T>.Default); }
+
+    // Sort the linked list using mergesort
+    /// <summary>
+    /// Sort the items of the list according to a specific sorting order.
+    /// The sorting is stable.
+    /// </summary>
+    /// <param name="c">The comparer defining the sorting order.</param>
+    [Tested]
+    public virtual void Sort(SCG.IComparer<T> c)
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      disposeOverlappingViews(false);
+#if HASHINDEX
+      if (underlying != null)
+      {
+        Node cursor = startsentinel.next;
+        while (cursor != endsentinel)
+        {
+          cursor.taggroup.count--;
+          cursor = cursor.next;
+        }
+      }
+#endif
+      // Build a linked list of non-empty runs.
+      // The prev field in first node of a run points to next run's first node
+      Node runTail = startsentinel.next;
+      Node prevNode = startsentinel.next;
+
+      endsentinel.prev.next = null;
+      while (prevNode != null)
+      {
+        Node node = prevNode.next;
+
+        while (node != null && c.Compare(prevNode.item, node.item) <= 0)
+        {
+          prevNode = node;
+          node = prevNode.next;
+        }
+
+        // Completed a run; prevNode is the last node of that run
+        prevNode.next = null;	// Finish the run
+        runTail.prev = node;	// Link it into the chain of runs
+        runTail = node;
+        if (c.Compare(endsentinel.prev.item, prevNode.item) <= 0)
+          endsentinel.prev = prevNode;	// Update last pointer to point to largest
+
+        prevNode = node;		// Start a new run
+      }
+
+      // Repeatedly merge runs two and two, until only one run remains
+      while (startsentinel.next.prev != null)
+      {
+        Node run = startsentinel.next;
+        Node newRunTail = null;
+
+        while (run != null && run.prev != null)
+        { // At least two runs, merge
+          Node nextRun = run.prev.prev;
+          Node newrun = mergeRuns(run, run.prev, c);
+
+          if (newRunTail != null)
+            newRunTail.prev = newrun;
+          else
+            startsentinel.next = newrun;
+
+          newRunTail = newrun;
+          run = nextRun;
+        }
+
+        if (run != null) // Add the last run, if any
+          newRunTail.prev = run;
+      }
+
+      endsentinel.prev.next = endsentinel;
+      startsentinel.next.prev = startsentinel;
+
+      //assert invariant();
+      //assert isSorted();
+#if HASHINDEX
+      {
+        Node cursor = startsentinel.next, end = endsentinel;
+        int tag, taglimit;
+        TagGroup t = gettaggroup(startsentinel, endsentinel, out tag, out taglimit);
+        int tagdelta = taglimit / (size + 1) - tag / (size + 1);
+        tagdelta = tagdelta == 0 ? 1 : tagdelta;
+        if (underlying == null)
+          taggroups = 1;
+        while (cursor != end)
+        {
+          tag = tag + tagdelta > taglimit ? taglimit : tag + tagdelta;
+          cursor.tag = tag;
+          t.count++;
+          cursor.taggroup = t;
+          cursor = cursor.next;
+        }
+        if (t != startsentinel.taggroup)
+          t.first = startsentinel.next;
+        if (t != endsentinel.taggroup)
+          t.last = endsentinel.prev;
+        if (tag == taglimit)
+          splittaggroup(t);
+      }
+#endif
+      (underlying ?? this).raiseCollectionChanged();
+    }
+
+    private static Node mergeRuns(Node run1, Node run2, SCG.IComparer<T> c)
+    {
+      //assert run1 != null && run2 != null;
+      Node prev;
+      bool prev1;	// is prev from run1?
+
+      if (c.Compare(run1.item, run2.item) <= 0)
+      {
+        prev = run1;
+        prev1 = true;
+        run1 = run1.next;
+      }
+      else
+      {
+        prev = run2;
+        prev1 = false;
+        run2 = run2.next;
+      }
+
+      Node start = prev;
+
+      //assert start != null;
+      start.prev = null;
+      while (run1 != null && run2 != null)
+      {
+        if (prev1)
+        {
+          //assert prev.next == run1;
+          //Comparable run2item = (Comparable)run2.item;
+          while (run1 != null && c.Compare(run2.item, run1.item) >= 0)
+          {
+            prev = run1;
+            run1 = prev.next;
+          }
+
+          if (run1 != null)
+          { // prev.item <= run2.item < run1.item; insert run2
+            prev.next = run2;
+            run2.prev = prev;
+            prev = run2;
+            run2 = prev.next;
+            prev1 = false;
+          }
+        }
+        else
+        {
+          //assert prev.next == run2;
+          //Comparable run1item = (Comparable)run1.item;
+          while (run2 != null && c.Compare(run1.item, run2.item) > 0)
+          {
+            prev = run2;
+            run2 = prev.next;
+          }
+
+          if (run2 != null)
+          { // prev.item < run1.item <= run2.item; insert run1
+            prev.next = run1;
+            run1.prev = prev;
+            prev = run1;
+            run1 = prev.next;
+            prev1 = true;
+          }
+        }
+      }
+
+      //assert !(run1 != null && prev1) && !(run2 != null && !prev1);
+      if (run1 != null)
+      { // last run2 < all of run1; attach run1 at end
+        prev.next = run1;
+        run1.prev = prev;
+      }
+      else if (run2 != null)
+      { // last run1 
+        prev.next = run2;
+        run2.prev = prev;
+      }
+
+      return start;
+    }
+
+    /// <summary>
+    /// Randomly shuffle the items of this list. 
+    /// <para>Will invalidate overlapping views???</para>
+    /// </summary>
+    public virtual void Shuffle() { Shuffle(new C5Random()); }
+
+
+    /// <summary>
+    /// Shuffle the items of this list according to a specific random source.
+    /// <para>Will invalidate overlapping views???</para>
+    /// </summary>
+    /// <param name="rnd">The random source.</param>
+    public virtual void Shuffle(Random rnd)
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      disposeOverlappingViews(false);
+      ArrayList<T> a = new ArrayList<T>();
+      a.AddAll(this);
+      a.Shuffle(rnd);
+      Node cursor = startsentinel.next;
+      int j = 0;
+      while (cursor != endsentinel)
+      {
+        cursor.item = a[j++];
+#if HASHINDEX
+        dict[cursor.item] = cursor;
+#endif
+        cursor = cursor.next;
+      }
+      (underlying ?? this).raiseCollectionChanged();
+    }
+
+    #endregion
+
+    #region IIndexed<T> Members
+
+    /// <summary>
+    /// <exception cref="IndexOutOfRangeException"/>.
+    /// </summary>
+    /// <value>The directed collection of items in a specific index interval.</value>
+    /// <param name="start">The low index of the interval (inclusive).</param>
+    /// <param name="count">The size of the range.</param>
+    [Tested]
+    public IDirectedCollectionValue<T> this[int start, int count]
+    {
+      [Tested]
+      get
+      {
+        validitycheck();
+        checkRange(start, count);
+        return new Range(this, start, count, true);
+      }
+    }
+
+    /// <summary>
+    /// Searches for an item in the list going forwrds from the start.
+    /// </summary>
+    /// <param name="item">Item to search for.</param>
+    /// <returns>Index of item from start.</returns>
+    [Tested]
+    public virtual int IndexOf(T item)
+    {
+      validitycheck();
+      Node node;
+#if HASHINDEX
+      if (!dict.Find(item, out node) || !insideview(node))
+        return ~size;
+#endif
+      node = startsentinel.next;
+      int index = 0;
+      if (find(item, ref node, ref index))
+        return index;
+      else
+        return ~size;
+    }
+
+    /// <summary>
+    /// Searches for an item in the list going backwords from the end.
+    /// </summary>
+    /// <param name="item">Item to search for.</param>
+    /// <returns>Index of of item from the end.</returns>
+    [Tested]
+    public virtual int LastIndexOf(T item)
+    {
+#if HASHINDEX
+      return IndexOf(item);
+#else
+      validitycheck();
+
+      Node node = endsentinel.prev;
+      int index = size - 1;
+
+      if (dnif(item, ref node, ref index))
+        return index;
+      else
+        return ~size;
+#endif
+    }
+
+    /// <summary>
+    /// Remove the item at a specific position of the list.
+    /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+    /// &gt;= the size of the collection.
+    /// </summary>
+    /// <param name="i">The index of the item to remove.</param>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public virtual T RemoveAt(int i)
+    {
+      updatecheck();
+      T retval = remove(get(i), i);
+#if HASHINDEX
+      dict.Remove(retval);
+#endif
+      if (ActiveEvents != EventTypeEnum.None)
+        (underlying ?? this).raiseForRemoveAt(Offset + i, retval);
+      return retval;
+    }
+
+    /// <summary>
+    /// Remove all items in an index interval.
+    /// <exception cref="IndexOutOfRangeException"/>???. 
+    /// </summary>
+    /// <param name="start">The index of the first item to remove.</param>
+    /// <param name="count">The number of items to remove.</param>
+    [Tested]
+    public virtual void RemoveInterval(int start, int count)
+    {
+#if HASHINDEX
+      updatecheck();
+      checkRange(start, count);
+      if (count == 0)
+        return;
+
+      View(start, count).Clear();
+#else
+      //Note: this is really almost equaivalent to Clear on a view
+      updatecheck();
+      checkRange(start, count);
+      if (count == 0)
+        return;
+
+      //for small count: optimize
+      //use an optimal get(int i, int j, ref Node ni, ref Node nj)?
+      Node a = get(start), b = get(start + count - 1);
+      fixViewsBeforeRemove(start, count, a, b);
+      a.prev.next = b.next;
+      b.next.prev = a.prev;
+      if (underlying != null)
+        underlying.size -= count;
+
+      size -= count;
+      if (ActiveEvents != EventTypeEnum.None)
+        (underlying ?? this).raiseForRemoveInterval(start + Offset, count);
+#endif
+    }
+
+    void raiseForRemoveInterval(int start, int count)
+    {
+      if (ActiveEvents != 0)
+      {
+        raiseCollectionCleared(size == 0, count, start);
+        raiseCollectionChanged();
+      }
+    }
+    #endregion
+
+    #region ISequenced<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    [Tested]
+    public override int GetSequencedHashCode() { validitycheck(); return base.GetSequencedHashCode(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="that"></param>
+    /// <returns></returns>
+    [Tested]
+    public override bool SequencedEquals(ISequenced<T> that) { validitycheck(); return base.SequencedEquals(that); }
+
+    #endregion
+
+    #region IDirectedCollection<T> Members
+
+    /// <summary>
+    /// Create a collection containing the same items as this collection, but
+    /// whose enumerator will enumerate the items backwards. The new collection
+    /// will become invalid if the original is modified. Method typicaly used as in
+    /// <code>foreach (T x in coll.Backwards()) {...}</code>
+    /// </summary>
+    /// <returns>The backwards collection.</returns>
+    [Tested]
+    public override IDirectedCollectionValue<T> Backwards()
+    { return this[0, size].Backwards(); }
+
+    #endregion
+
+    #region IDirectedEnumerable<T> Members
+
+    [Tested]
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
+
+    #endregion
+
+    #region IEditableCollection<T> Members
+
+    /// <summary>
+    /// The value is symbolic indicating the type of asymptotic complexity
+    /// in terms of the size of this collection (worst-case or amortized as
+    /// relevant).
+    /// </summary>
+    /// <value>Speed.Linear</value>
+    [Tested]
+    public virtual Speed ContainsSpeed
+    {
+      [Tested]
+      get
+      {
+#if HASHINDEX
+        return Speed.Constant;
+#else
+        return Speed.Linear;
+#endif
+      }
+    }
+
+    /// <summary>
+    /// Performs a check for view validity before calling base.GetUnsequencedHashCode()
+    /// </summary>
+    /// <returns></returns>
+    [Tested]
+    public override int GetUnsequencedHashCode()
+    { validitycheck(); return base.GetUnsequencedHashCode(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="that"></param>
+    /// <returns></returns>
+    [Tested]
+    public override bool UnsequencedEquals(ICollection<T> that)
+    { validitycheck(); return base.UnsequencedEquals(that); }
+
+    /// <summary>
+    /// Check if this collection contains (an item equivalent to according to the
+    /// itemequalityComparer) a particular value.
+    /// </summary>
+    /// <param name="item">The value to check for.</param>
+    /// <returns>True if the items is in this collection.</returns>
+    [Tested]
+    public virtual bool Contains(T item)
+    {
+      validitycheck();
+      Node node;
+      return contains(item, out node);
+    }
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, return in the ref argument (a
+    /// binary copy of) the actual value found.
+    /// </summary>
+    /// <param name="item">The value to look for.</param>
+    /// <returns>True if the items is in this collection.</returns>
+    [Tested]
+    public virtual bool Find(ref T item)
+    {
+      validitycheck();
+      Node node;
+      if (contains(item, out node)) { item = node.item; return true; }
+      return false;
+    }
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// to with a binary copy of the supplied value. Will update a single item.
+    /// </summary>
+    /// <param name="item">Value to update.</param>
+    /// <returns>True if the item was found and hence updated.</returns>
+    [Tested]
+    public virtual bool Update(T item) { T olditem; return Update(item, out olditem); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public virtual bool Update(T item, out T olditem)
+    {
+      updatecheck();
+      Node node;
+
+      if (contains(item, out node))
+      {
+        olditem = node.item;
+        node.item = item;
+#if HASHINDEX
+        //Avoid clinging onto a reference to olditem via dict!
+        dict.Update(item, node);
+#endif
+        (underlying ?? this).raiseForUpdate(item, olditem);
+        return true;
+      }
+
+      olditem = default(T);
+      return false;
+    }
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, return in the ref argument (a
+    /// binary copy of) the actual value found. Else, add the item to the collection.
+    /// </summary>
+    /// <param name="item">The value to look for.</param>
+    /// <returns>True if the item was found (hence not added).</returns>
+    [Tested]
+    public virtual bool FindOrAdd(ref T item)
+    {
+      updatecheck();
+#if HASHINDEX
+      //This is an extended myinsert:
+      Node node = new Node(item);
+      if (!dict.FindOrAdd(item, ref node))
+      {
+        insertNode(true, endsentinel, node);
+        (underlying ?? this).raiseForAdd(item);
+        return false;
+      }
+      if (!insideview(node))
+        throw new ArgumentException("Item alredy in indexed list but outside view");
+      item = node.item;
+      return true;
+#else
+      if (Find(ref item))
+        return true;
+
+      Add(item);
+      return false;
+#endif
+    }
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// to with a binary copy of the supplied value; else add the value to the collection. 
+    /// </summary>
+    /// <param name="item">Value to add or update.</param>
+    /// <returns>True if the item was found and updated (hence not added).</returns>
+    [Tested]
+    public virtual bool UpdateOrAdd(T item) { T olditem; return UpdateOrAdd(item, out olditem); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public virtual bool UpdateOrAdd(T item, out T olditem)
+    {
+      updatecheck();
+#if HASHINDEX
+      Node node = new Node(item);
+      //NOTE: it is hard to do this without double access to the dictionary
+      //in the update case
+      if (dict.FindOrAdd(item, ref node))
+      {
+        if (!insideview(node))
+          throw new ArgumentException("Item in indexed list but outside view");
+        olditem = node.item;
+        //Avoid clinging onto a reference to olditem via dict!
+        dict.Update(item, node);
+        node.item = item;
+        (underlying ?? this).raiseForUpdate(item, olditem);
+        return true;
+      }
+      insertNode(true, endsentinel, node);
+      (underlying ?? this).raiseForAdd(item);
+#else
+      if (Update(item, out olditem))
+        return true;
+      Add(item);
+#endif
+      olditem = default(T);
+      return false;
+    }
+
+    /// <summary>
+    /// Remove a particular item from this collection. Since the collection has bag
+    /// semantics only one copy equivalent to the supplied item is removed. 
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    /// <returns>True if the item was found (and removed).</returns>
+    [Tested]
+    public virtual bool Remove(T item)
+    {
+      updatecheck();
+      int i = 0;
+      Node node;
+#if HASHINDEX
+      if (!dictremove(item, out node))
+#else
+      node = fIFO ? startsentinel.next : endsentinel.prev;
+      if (!(fIFO ? find(item, ref node, ref i) : dnif(item, ref node, ref i)))
+#endif
+        return false;
+      T removeditem = remove(node, i);
+      (underlying ?? this).raiseForRemove(removeditem);
+      return true;
+    }
+
+    /// <summary>
+    /// Remove a particular item from this collection if found (only one copy). 
+    /// If an item was removed, report a binary copy of the actual item removed in 
+    /// the argument.
+    /// </summary>
+    /// <param name="item">The value to remove on input.</param>
+    /// <param name="removeditem">The value removed.</param>
+    /// <returns>True if the item was found (and removed).</returns>
+    [Tested]
+    public virtual bool Remove(T item, out T removeditem)
+    {
+      updatecheck();
+      int i = 0;
+      Node node;
+#if HASHINDEX
+      if (!dictremove(item, out node))
+#else
+      node = fIFO ? startsentinel.next : endsentinel.prev;
+      if (!(fIFO ? find(item, ref node, ref i) : dnif(item, ref node, ref i)))
+#endif
+      {
+        removeditem = default(T);
+        return false;
+      }
+      removeditem = node.item;
+      remove(node, i);
+      (underlying ?? this).raiseForRemove(removeditem);
+      return true;
+    }
+
+    /// <summary>
+    /// Remove all items in another collection from this one, taking multiplicities into account.
+    /// <para>Always removes from the front of the list.
+    /// </para>
+    /// <para>The asymptotic running time complexity of this method is <code>O(n+m+v*log(v))</code>, 
+    /// where <code>n</code> is the size of this list, <code>m</code> is the size of the
+    /// <code>items</code> collection and <code>v</code> is the number of views. 
+    /// The method will temporarily allocate memory of size <code>O(m+v)</code>.
+    /// </para>
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to remove.</param>
+    [Tested]
+    public virtual void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+#if HASHINDEX
+      Node node;
+      foreach (T item in items)
+        if (dictremove(item, out node))
+        {
+          if (mustFire)
+            raiseHandler.Remove(node.item);
+          remove(node, 118);
+        }
+#else
+      HashBag<T> toremove = new HashBag<T>(itemequalityComparer);
+      toremove.AddAll(items);
+      ViewHandler viewHandler = new ViewHandler(this);
+      int index = 0, removed = 0, myoffset = Offset;
+      Node node = startsentinel.next;
+      while (node != endsentinel)
+      {
+        //pass by a stretch of nodes
+        while (node != endsentinel && !toremove.Contains(node.item))
+        {
+          node = node.next;
+          index++;
+        }
+        viewHandler.skipEndpoints(removed, myoffset + index);
+        //Remove a stretch of nodes
+        Node localend = node.prev; //Latest node not to be removed
+        while (node != endsentinel && toremove.Remove(node.item))
+        {
+          if (mustFire)
+            raiseHandler.Remove(node.item);
+          removed++;
+          node = node.next;
+          index++;
+          viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+        }
+        viewHandler.updateSentinels(myoffset + index, localend, node);
+        localend.next = node;
+        node.prev = localend;
+      }
+      index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset;
+      viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+      size -= removed;
+      if (underlying != null)
+        underlying.size -= removed;
+#endif
+      raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="predicate"></param>
+    void RemoveAll(Fun<T, bool> predicate)
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+#if HASHINDEX
+      {
+        Node n = startsentinel.next;
+
+        while (n != endsentinel)
+        {
+          bool removeIt = predicate(n.item);
+          updatecheck();
+          if (removeIt)
+          {
+            dict.Remove(n.item);
+            remove(n, 119);
+            if (mustFire)
+              raiseHandler.Remove(n.item);
+          }
+
+          n = n.next;
+        }
+      }
+#else
+      ViewHandler viewHandler = new ViewHandler(this);
+      int index = 0, removed = 0, myoffset = Offset;
+      Node node = startsentinel.next;
+      while (node != endsentinel)
+      {
+        //pass by a stretch of nodes
+        while (node != endsentinel && !predicate(node.item))
+        {
+          updatecheck();
+          node = node.next;
+          index++;
+        }
+        updatecheck();
+        viewHandler.skipEndpoints(removed, myoffset + index);
+        //Remove a stretch of nodes
+        Node localend = node.prev; //Latest node not to be removed
+        while (node != endsentinel && predicate(node.item))
+        {
+          updatecheck();
+          if (mustFire)
+            raiseHandler.Remove(node.item);
+          removed++;
+          node = node.next;
+          index++;
+          viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+        }
+        updatecheck();
+        viewHandler.updateSentinels(myoffset + index, localend, node);
+        localend.next = node;
+        node.prev = localend;
+      }
+      index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset;
+      viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+      size -= removed;
+      if (underlying != null)
+        underlying.size -= removed;
+#endif
+      raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// Remove all items from this collection.
+    /// </summary>
+    [Tested]
+    public virtual void Clear()
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      int oldsize = size;
+#if HASHINDEX
+      if (underlying == null)
+        dict.Clear();
+      else
+        foreach (T item in this)
+          dict.Remove(item);
+#endif
+      clear();
+      (underlying ?? this).raiseForRemoveInterval(Offset, oldsize);
+    }
+
+    void clear()
+    {
+      if (size == 0)
+        return;
+#if HASHINDEX
+      //TODO: mix with tag maintenance to only run through list once?
+      ViewHandler viewHandler = new ViewHandler(this);
+      if (viewHandler.viewCount > 0)
+      {
+        int removed = 0;
+        Node n = startsentinel.next;
+        viewHandler.skipEndpoints(0, n);
+        while (n != endsentinel)
+        {
+          removed++;
+          n = n.next;
+          viewHandler.updateViewSizesAndCounts(removed, n);
+        }
+        viewHandler.updateSentinels(endsentinel, startsentinel, endsentinel);
+        if (underlying != null)
+          viewHandler.updateViewSizesAndCounts(removed, underlying.endsentinel);
+      }
+#else
+      fixViewsBeforeRemove(Offset, size, startsentinel.next, endsentinel.prev);
+#endif
+#if HASHINDEX
+      if (underlying != null)
+      {
+        Node n = startsentinel.next;
+
+        while (n != endsentinel)
+        {
+          n.next.prev = startsentinel;
+          startsentinel.next = n.next;
+          removefromtaggroup(n);
+          n = n.next;
+        }
+      }
+      else
+        taggroups = 0;
+#endif
+      endsentinel.prev = startsentinel;
+      startsentinel.next = endsentinel;
+      if (underlying != null)
+        underlying.size -= size;
+      size = 0;
+    }
+
+    /// <summary>
+    /// Remove all items not in some other collection from this one, taking multiplicities into account.
+    /// <para>The asymptotic running time complexity of this method is <code>O(n+m+v*log(v))</code>, 
+    /// where <code>n</code> is the size of this collection, <code>m</code> is the size of the
+    /// <code>items</code> collection and <code>v</code> is the number of views. 
+    /// The method will temporarily allocate memory of size <code>O(m+v)</code>. The stated complexitiy 
+    /// holds under the assumption that the itemequalityComparer of this list is well-behaved.
+    /// </para>
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to retain.</param>
+    [Tested]
+    public virtual void RetainAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+#if HASHINDEX
+      /*if (underlying == null)
+      {
+        HashDictionary<T, Node> newdict = new HashDictionary<T, Node>(itemequalityComparer);
+        foreach (T item in items)
+        {
+          Node node;
+
+          if (dict.Remove(item, out node))
+            newdict.Add(item, node);
+        }
+        foreach (KeyValuePair<T, Node> pair in dict)
+        {
+          Node n = pair.Value;
+          fixViewsBeforeSingleRemove(n, 117);
+          Node p = n.prev, s = n.next; s.prev = p; p.next = s;
+          removefromtaggroup(n);
+        }
+        dict = newdict;
+        size = dict.Count;
+        //For a small number of items to retain it might be faster to 
+        //iterate through the list and splice out the chunks not needed
+      }
+      else*/
+      {
+        HashSet<T> toremove = new HashSet<T>(itemequalityComparer);
+
+        foreach (T item in this)
+          toremove.Add(item);
+
+        foreach (T item in items)
+          toremove.Remove(item);
+
+        Node n = startsentinel.next;
+
+        while (n != endsentinel && toremove.Count > 0)
+        {
+          if (toremove.Contains(n.item))
+          {
+            dict.Remove(n.item);
+            remove(n, 119);
+            if (mustFire)
+              raiseHandler.Remove(n.item);
+          }
+
+          n = n.next;
+        }
+      }
+#else
+      HashBag<T> toretain = new HashBag<T>(itemequalityComparer);
+      toretain.AddAll(items);
+      ViewHandler viewHandler = new ViewHandler(this);
+      int index = 0, removed = 0, myoffset = Offset;
+      Node node = startsentinel.next;
+      while (node != endsentinel)
+      {
+        //Skip a stretch of nodes
+        while (node != endsentinel && toretain.Remove(node.item))
+        {
+          node = node.next;
+          index++;
+        }
+        viewHandler.skipEndpoints(removed, myoffset + index);
+        //Remove a stretch of nodes
+        Node localend = node.prev; //Latest node not to be removed
+        while (node != endsentinel && !toretain.Contains(node.item))
+        {
+          if (mustFire)
+            raiseHandler.Remove(node.item);
+          removed++;
+          node = node.next;
+          index++;
+          viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+        }
+        viewHandler.updateSentinels(myoffset + index, localend, node);
+        localend.next = node;
+        node.prev = localend;
+      }
+      index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset;
+      viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+      size -= removed;
+      if (underlying != null)
+        underlying.size -= removed;
+#endif
+      raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="predicate"></param>
+    void RetainAll(Fun<T, bool> predicate)
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+#if HASHINDEX
+      {
+        Node n = startsentinel.next;
+
+        while (n != endsentinel)
+        {
+          bool removeIt = !predicate(n.item);
+          updatecheck();
+          if (removeIt)
+          {
+            dict.Remove(n.item);
+            remove(n, 119);
+            if (mustFire)
+              raiseHandler.Remove(n.item);
+          }
+
+          n = n.next;
+        }
+      }
+#else
+      ViewHandler viewHandler = new ViewHandler(this);
+      int index = 0, removed = 0, myoffset = Offset;
+      Node node = startsentinel.next;
+      while (node != endsentinel)
+      {
+        //Skip a stretch of nodes
+        while (node != endsentinel && predicate(node.item))
+        {
+          updatecheck();
+          node = node.next;
+          index++;
+        }
+        updatecheck();
+        viewHandler.skipEndpoints(removed, myoffset + index);
+        //Remove a stretch of nodes
+        Node localend = node.prev; //Latest node not to be removed
+        while (node != endsentinel && !predicate(node.item))
+        {
+          updatecheck();
+          if (mustFire)
+            raiseHandler.Remove(node.item);
+          removed++;
+          node = node.next;
+          index++;
+          viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+        }
+        updatecheck();
+        viewHandler.updateSentinels(myoffset + index, localend, node);
+        localend.next = node;
+        node.prev = localend;
+      }
+      index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset;
+      viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+      size -= removed;
+      if (underlying != null)
+        underlying.size -= removed;
+#endif
+      raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// Check if this collection contains all the values in another collection
+    /// with respect to multiplicities.
+    /// </summary>
+    /// <param name="items">The </param>
+    /// <typeparam name="U"></typeparam>
+    /// <returns>True if all values in <code>items</code>is in this collection.</returns>
+    [Tested]
+    public virtual bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      validitycheck();
+#if HASHINDEX
+      Node node;
+      foreach (T item in items)
+        if (!contains(item, out node))
+          return false;
+      return true;
+#else
+      HashBag<T> tocheck = new HashBag<T>(itemequalityComparer);
+      tocheck.AddAll(items);
+      if (tocheck.Count > size)
+        return false;
+      Node node = startsentinel.next;
+      while (node != endsentinel)
+      {
+        tocheck.Remove(node.item);
+        node = node.next;
+      }
+      return tocheck.IsEmpty;
+#endif
+    }
+
+
+    /// <summary>
+    /// Create a new list consisting of the items of this list satisfying a 
+    /// certain predicate.
+    /// </summary>
+    /// <param name="filter">The filter delegate defining the predicate.</param>
+    /// <returns>The new list.</returns>
+    [Tested]
+    public IList<T> FindAll(Fun<T, bool> filter)
+    {
+      validitycheck();
+      int stamp = this.stamp;
+      HashedLinkedList<T> retval = new HashedLinkedList<T>();
+      Node cursor = startsentinel.next;
+      Node mcursor = retval.startsentinel;
+#if HASHINDEX
+      double tagdelta = int.MaxValue / (size + 1.0);
+      int count = 1;
+      TagGroup taggroup = new TagGroup();
+      retval.taggroups = 1;
+#endif
+      while (cursor != endsentinel)
+      {
+        bool found = filter(cursor.item);
+        modifycheck(stamp);
+        if (found)
+        {
+          mcursor.next = new Node(cursor.item, mcursor, null);
+          mcursor = mcursor.next;
+          retval.size++;
+#if HASHINDEX
+          retval.dict.Add(cursor.item, mcursor);
+          mcursor.taggroup = taggroup;
+          mcursor.tag = (int)(tagdelta * count++);
+#endif
+        }
+        cursor = cursor.next;
+      }
+#if HASHINDEX
+      if (retval.size > 0)
+      {
+        taggroup.count = retval.size;
+        taggroup.first = retval.startsentinel.next;
+        taggroup.last = mcursor;
+      }
+#endif
+      retval.endsentinel.prev = mcursor;
+      mcursor.next = retval.endsentinel;
+      return retval;
+    }
+
+
+    /// <summary>
+    /// Count the number of items of the collection equal to a particular value.
+    /// Returns 0 if and only if the value is not in the collection.
+    /// </summary>
+    /// <param name="item">The value to count.</param>
+    /// <returns>The number of copies found.</returns>
+    [Tested]
+    public virtual int ContainsCount(T item)
+    {
+#if HASHINDEX
+      return Contains(item) ? 1 : 0;
+#else
+      validitycheck();
+      int retval = 0;
+      Node node = startsentinel.next;
+      while (node != endsentinel)
+      {
+        if (itemequalityComparer.Equals(node.item, item))
+          retval++;
+        node = node.next;
+      }
+      return retval;
+#endif
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<T> UniqueItems()
+    {
+#if HASHINDEX
+      return this;
+#else
+      HashBag<T> hashbag = new HashBag<T>(itemequalityComparer);
+      hashbag.AddAll(this);
+      return hashbag.UniqueItems();
+#endif
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities()
+    {
+#if HASHINDEX
+      return new MultiplicityOne<T>(this);
+#else
+      HashBag<T> hashbag = new HashBag<T>(itemequalityComparer);
+      hashbag.AddAll(this);
+      return hashbag.ItemMultiplicities();
+#endif
+    }
+
+    /// <summary>
+    /// Remove all items equivalent to a given value.
+    /// <para>The asymptotic complexity of this method is <code>O(n+v*log(v))</code>, 
+    /// where <code>n</code> is the size of the collection and <code>v</code> 
+    /// is the number of views.
+    /// </para>
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    [Tested]
+    public virtual void RemoveAllCopies(T item)
+    {
+#if HASHINDEX
+      Remove(item);
+#else
+      updatecheck();
+      if (size == 0)
+        return;
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+      ViewHandler viewHandler = new ViewHandler(this);
+      int index = 0, removed = 0, myoffset = Offset;
+      //
+      Node node = startsentinel.next;
+      while (node != endsentinel)
+      {
+        //pass by a stretch of nodes
+        while (node != endsentinel && !itemequalityComparer.Equals(node.item, item))
+        {
+          node = node.next;
+          index++;
+        }
+        viewHandler.skipEndpoints(removed, myoffset + index);
+        //Remove a stretch of nodes
+        Node localend = node.prev; //Latest node not to be removed
+        while (node != endsentinel && itemequalityComparer.Equals(node.item, item))
+        {
+          if (mustFire)
+            raiseHandler.Remove(node.item);
+          removed++;
+          node = node.next;
+          index++;
+          viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+        }
+        viewHandler.updateSentinels(myoffset + index, localend, node);
+        localend.next = node;
+        node.prev = localend;
+      }
+      index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset;
+      viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+      size -= removed;
+      if (underlying != null)
+        underlying.size -= removed;
+      raiseHandler.Raise();
+#endif
+    }
+
+    #endregion
+
+    #region ICollectionValue<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>The number of items in this collection</value>
+    [Tested]
+    public override int Count { [Tested]get { validitycheck(); return size; } }
+
+    /// <summary>
+    /// Choose some item of this collection. 
+    /// </summary>
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>
+    /// <returns></returns>
+    [Tested]
+    public override T Choose() { return First; }
+
+    /// <summary>
+    /// Create an enumerable, enumerating the items of this collection that satisfies 
+    /// a certain condition.
+    /// </summary>
+    /// <param name="filter">The T->bool filter delegate defining the condition</param>
+    /// <returns>The filtered enumerable</returns>
+    public override SCG.IEnumerable<T> Filter(Fun<T, bool> filter) { validitycheck(); return base.Filter(filter); }
+
+    #endregion
+
+    #region IEnumerable<T> Members
+    /// <summary>
+    /// Create an enumerator for the collection
+    /// </summary>
+    /// <returns>The enumerator</returns>
+    [Tested]
+    public override SCG.IEnumerator<T> GetEnumerator()
+    {
+      validitycheck();
+      Node cursor = startsentinel.next;
+      int enumeratorstamp = underlying != null ? underlying.stamp : this.stamp;
+
+      while (cursor != endsentinel)
+      {
+        modifycheck(enumeratorstamp);
+        yield return cursor.item;
+        cursor = cursor.next;
+      }
+    }
+
+    #endregion
+
+    #region IExtensible<T> Members
+    /// <summary>
+    /// Add an item to this collection if possible. 
+    /// </summary>
+    /// <param name="item">The item to add.</param>
+    /// <returns>True.</returns>
+    [Tested]
+    public virtual bool Add(T item)
+    {
+      updatecheck();
+#if HASHINDEX
+      Node node = new Node(item);
+      if (!dict.FindOrAdd(item, ref node))
+      {
+        insertNode(true, endsentinel, node);
+        (underlying ?? this).raiseForAdd(item);
+        return true;
+      }
+      return false;
+#else
+      insert(size, endsentinel, item);
+      (underlying ?? this).raiseForAdd(item);
+      return true;
+#endif
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>True since this collection has bag semantics.</value>
+    [Tested]
+    public virtual bool AllowsDuplicates
+    {
+      [Tested]
+      get
+      {
+#if HASHINDEX
+        return false;
+#else
+        return true;
+#endif
+      }
+    }
+
+    /// <summary>
+    /// By convention this is true for any collection with set semantics.
+    /// </summary>
+    /// <value>True if only one representative of a group of equal items 
+    /// is kept in the collection together with the total count.</value>
+    public virtual bool DuplicatesByCounting
+    {
+      get
+      {
+#if HASHINDEX
+        return true;
+#else
+        return false;
+#endif
+      }
+    }
+
+    /// <summary>
+    /// Add the elements from another collection with a more specialized item type 
+    /// to this collection. 
+    /// </summary>
+    /// <typeparam name="U">The type of items to add</typeparam>
+    /// <param name="items">The items to add</param>
+    [Tested]
+    public virtual void AddAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+#if HASHINDEX
+      updatecheck();
+      int added = 0;
+      Node pred = endsentinel.prev;
+      foreach (U item in items)
+      {
+        Node node = new Node(item);
+        if (!dict.FindOrAdd(item, ref node))
+        {
+          insertNode(false, endsentinel, node);
+          added++;
+        }
+      }
+      if (added > 0)
+      {
+        fixViewsAfterInsert(endsentinel, pred, added, 0);
+        raiseForInsertAll(pred, size - added, added, false);
+      }
+#else
+      insertAll(size, items, false);
+#endif
+    }
+
+    #endregion
+
+#if HASHINDEX
+#else
+    #region IStack<T> Members
+
+    /// <summary>
+    /// Push an item to the top of the stack.
+    /// </summary>
+    /// <param name="item">The item</param>
+    [Tested]
+    public void Push(T item)
+    {
+      InsertLast(item);
+    }
+
+    /// <summary>
+    /// Pop the item at the top of the stack from the stack.
+    /// </summary>
+    /// <returns>The popped item.</returns>
+    [Tested]
+    public T Pop()
+    {
+      return RemoveLast();
+    }
+
+    #endregion
+
+    #region IQueue<T> Members
+
+    /// <summary>
+    /// Enqueue an item at the back of the queue. 
+    /// </summary>
+    /// <param name="item">The item</param>
+    [Tested]
+    public virtual void Enqueue(T item)
+    {
+      InsertLast(item);
+    }
+
+    /// <summary>
+    /// Dequeue an item from the front of the queue.
+    /// </summary>
+    /// <returns>The item</returns>
+    [Tested]
+    public virtual T Dequeue()
+    {
+      return RemoveFirst();
+    }
+    #endregion
+#endif
+
+    #region Diagnostic
+
+    private bool checkViews()
+    {
+      if (underlying != null)
+        throw new InternalException(System.Reflection.MethodInfo.GetCurrentMethod() + " called on a view");
+      if (views == null)
+        return true;
+      bool retval = true;
+
+      Node[] nodes = new Node[size + 2];
+      int i = 0;
+      Node n = startsentinel;
+      while (n != null)
+      {
+        nodes[i++] = n;
+        n = n.next;
+      }
+      //Console.WriteLine("###");
+      foreach (HashedLinkedList<T> view in views)
+      {
+        if (!view.isValid)
+        {
+          Console.WriteLine("Invalid view(hash {0}, offset {1}, size {2})",
+            view.GetHashCode(), view.offset, view.size);
+          retval = false;
+          continue;
+        }
+        if (view.Offset > size || view.Offset < 0)
+        {
+          Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), Offset > underlying.size ({2})",
+            view.GetHashCode(), view.offset, view.size, size);
+          retval = false;
+        }
+        else if (view.startsentinel != nodes[view.Offset])
+        {
+          Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), startsentinel {3} should be {4}",
+            view.GetHashCode(), view.offset, view.size,
+            view.startsentinel + " " + view.startsentinel.GetHashCode(),
+            nodes[view.Offset] + " " + nodes[view.Offset].GetHashCode());
+          retval = false;
+        }
+        if (view.Offset + view.size > size || view.Offset + view.size < 0)
+        {
+          Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), end index > underlying.size ({3})",
+            view.GetHashCode(), view.offset, view.size, size);
+          retval = false;
+        }
+        else if (view.endsentinel != nodes[view.Offset + view.size + 1])
+        {
+          Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), endsentinel {3} should be {4}",
+            view.GetHashCode(), view.offset, view.size,
+            view.endsentinel + " " + view.endsentinel.GetHashCode(),
+            nodes[view.Offset + view.size + 1] + " " + nodes[view.Offset + view.size + 1].GetHashCode());
+          retval = false;
+        }
+        if (view.views != views)
+        {
+          Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), wrong views list {3} <> {4}",
+            view.GetHashCode(), view.offset, view.size, view.views.GetHashCode(), views.GetHashCode());
+          retval = false;
+        }
+        if (view.underlying != this)
+        {
+          Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), wrong underlying {3} <> this {4}",
+            view.GetHashCode(), view.offset, view.size, view.underlying.GetHashCode(), GetHashCode());
+          retval = false;
+        }
+        if (view.stamp != stamp)
+        {
+          //Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), wrong stamp view:{2} underlying: {3}", view.GetHashCode(),view.offset, view.size, view.stamp, stamp);
+          //retval = false;
+        }
+      }
+      return retval;
+    }
+
+    string zeitem(Node node)
+    {
+      return node == null ? "(null node)" : node.item.ToString();
+    }
+
+    /// <summary>
+    /// Check the sanity of this list
+    /// </summary>
+    /// <returns>true if sane</returns>
+    [Tested]
+    public virtual bool Check()
+    {
+      bool retval = true;
+
+      /*if (underlying != null && underlying.stamp != stamp)
+      {
+        Console.WriteLine("underlying != null && underlying.stamp({0}) != stamp({1})", underlying.stamp, stamp);
+        retval = false;
+      }*/
+
+      if (underlying != null)
+      {
+        //TODO: check that this view is included in viewsEndpoints tree
+        return underlying.Check();
+      }
+
+      if (startsentinel == null)
+      {
+        Console.WriteLine("startsentinel == null");
+        retval = false;
+      }
+
+      if (endsentinel == null)
+      {
+        Console.WriteLine("endsentinel == null");
+        retval = false;
+      }
+
+      if (size == 0)
+      {
+        if (startsentinel != null && startsentinel.next != endsentinel)
+        {
+          Console.WriteLine("size == 0 but startsentinel.next != endsentinel");
+          retval = false;
+        }
+
+        if (endsentinel != null && endsentinel.prev != startsentinel)
+        {
+          Console.WriteLine("size == 0 but endsentinel.prev != startsentinel");
+          retval = false;
+        }
+      }
+
+      if (startsentinel == null)
+      {
+        Console.WriteLine("NULL startsentinel");
+        return retval;
+      }
+
+      int count = 0;
+      Node node = startsentinel.next, prev = startsentinel;
+#if HASHINDEX
+      int taggroupsize = 0, oldtaggroupsize = losize + 1, seentaggroups = 0;
+      TagGroup oldtg = null;
+
+      if (underlying == null)
+      {
+        TagGroup tg = startsentinel.taggroup;
+
+        if (tg.count != 0 || tg.first != null || tg.last != null || tg.tag != int.MinValue)
+        {
+          Console.WriteLine("Bad startsentinel tag group: {0}", tg);
+          retval = false;
+        }
+
+        tg = endsentinel.taggroup;
+        if (tg.count != 0 || tg.first != null || tg.last != null || tg.tag != int.MaxValue)
+        {
+          Console.WriteLine("Bad endsentinel tag group: {0}", tg);
+          retval = false;
+        }
+      }
+#endif
+      while (node != endsentinel)
+      {
+        count++;
+        if (node.prev != prev)
+        {
+          Console.WriteLine("Bad backpointer at node {0}", count);
+          retval = false;
+        }
+#if HASHINDEX
+        if (underlying == null)
+        {
+          if (!node.prev.precedes(node))
+          {
+            Console.WriteLine("node.prev.tag ({0}, {1}) >= node.tag ({2}, {3}) at index={4} item={5} ", node.prev.taggroup.tag, node.prev.tag, node.taggroup.tag, node.tag, count, node.item);
+            retval = false;
+          }
+
+          if (node.taggroup != oldtg)
+          {
+
+            if (node.taggroup.first != node)
+            {
+              string ntfi = zeitem(node.taggroup.first);
+              Console.WriteLine("Bad first pointer in taggroup: node.taggroup.first.item ({0}), node.item ({1}) at index={2} item={3}", ntfi, node.item, count, node.item);
+              retval = false;
+            }
+
+            if (oldtg != null)
+            {
+              if (oldtg.count != taggroupsize)
+              {
+                Console.WriteLine("Bad taggroupsize: oldtg.count ({0}) != taggroupsize ({1}) at index={2} item={3}", oldtg.count, taggroupsize, count, node.item);
+                retval = false;
+              }
+
+              if (oldtaggroupsize <= losize && taggroupsize <= losize)
+              {
+                Console.WriteLine("Two small taggroups in a row: oldtaggroupsize ({0}), taggroupsize ({1}) at index={2} item={3}", oldtaggroupsize, taggroupsize, count, node.item);
+                retval = false;
+              }
+
+              if (node.taggroup.tag <= oldtg.tag)
+              {
+                Console.WriteLine("Taggroup tags not strictly increasing: oldtaggrouptag ({0}), taggrouptag ({1}) at index={2} item={3}", oldtg.tag, node.taggroup.tag, count, node.item);
+                retval = false;
+              }
+
+              if (oldtg.last != node.prev)
+              {
+                Console.WriteLine("Bad last pointer in taggroup: oldtg.last.item ({0}), node.prev.item ({1}) at index={2} item={3}", oldtg.last.item, node.prev.item, count, node.item);
+                retval = false;
+              }
+
+              oldtaggroupsize = taggroupsize;
+            }
+
+            seentaggroups++;
+            oldtg = node.taggroup;
+            taggroupsize = 1;
+          }
+          else
+          {
+            taggroupsize++;
+          }
+        }
+
+#endif
+        prev = node;
+        node = node.next;
+        if (node == null)
+        {
+          Console.WriteLine("Null next pointer at node {0}", count);
+          return false;
+        }
+      }
+
+#if HASHINDEX
+      if (underlying == null && size == 0 && taggroups != 0)
+      {
+        Console.WriteLine("Bad taggroups for empty list: size={0}   taggroups={1}", size, taggroups);
+        retval = false;
+      }
+      if (underlying == null && size > 0)
+      {
+        oldtg = node.prev.taggroup;
+        if (oldtg != null)
+        {
+          if (oldtg.count != taggroupsize)
+          {
+            Console.WriteLine("Bad taggroupsize: oldtg.count ({0}) != taggroupsize ({1}) at index={2} item={3}", oldtg.count, taggroupsize, count, node.item);
+            retval = false;
+          }
+
+          if (oldtaggroupsize <= losize && taggroupsize <= losize)
+          {
+            Console.WriteLine("Two small taggroups in a row: oldtaggroupsize ({0}), taggroupsize ({1}) at index={2} item={3}", oldtaggroupsize, taggroupsize, count, node.item);
+            retval = false;
+          }
+
+              if (node.taggroup.tag <= oldtg.tag)
+              {
+                Console.WriteLine("Taggroup tags not strictly increasing: oldtaggrouptag ({0}), taggrouptag ({1}) at index={2} item={3}", oldtg.tag, node.taggroup.tag, count, node.item);
+                retval = false;
+              }
+
+              if (oldtg.last != node.prev)
+              {
+                Console.WriteLine("Bad last pointer in taggroup: oldtg.last.item ({0}), node.prev.item ({1}) at index={2} item={3}", zeitem(oldtg.last), zeitem(node.prev), count, node.item);
+                retval = false;
+              }
+        }
+
+        if (seentaggroups != taggroups)
+        {
+          Console.WriteLine("seentaggroups ({0}) != taggroups ({1}) (at size {2})", seentaggroups, taggroups, size);
+          retval = false;
+        }
+      }
+#endif
+      if (count != size)
+      {
+        Console.WriteLine("size={0} but enumeration gives {1} nodes ", size, count);
+        retval = false;
+      }
+
+      retval = checkViews() && retval;
+
+#if HASHINDEX
+      if (!retval)
+        return false;
+      if (underlying == null)
+      {
+        if (size != dict.Count)
+        {
+          Console.WriteLine("list.size ({0}) != dict.Count ({1})", size, dict.Count);
+          retval = false;
+        }
+        Node n = startsentinel.next, n2;
+        while (n != endsentinel)
+        {
+          if (!dict.Find(n.item, out n2))
+          {
+            Console.WriteLine("Item in list but not dict: {0}", n.item);
+            retval = false;
+          }
+          else if (n != n2)
+          {
+            Console.WriteLine("Wrong node in dict for item: {0}", n.item);
+            retval = false;
+          }
+          n = n.next;
+        }
+      }
+#endif
+      return retval;
+    }
+    #endregion
+
+    #region ICloneable Members
+
+    /// <summary>
+    /// Make a shallow copy of this HashedLinkedList.
+    /// </summary>
+    /// <returns></returns>
+    public virtual object Clone()
+    {
+      HashedLinkedList<T> clone = new HashedLinkedList<T>(itemequalityComparer);
+      clone.AddAll(this);
+      return clone;
+    }
+
+    #endregion
+
+    #region System.Collections.Generic.IList<T> Members
+
+    void System.Collections.Generic.IList<T>.RemoveAt(int index)
+    {
+      RemoveAt(index);
+    }
+
+    void System.Collections.Generic.ICollection<T>.Add(T item)
+    {
+      Add(item);
+    }
+
+    #endregion
+
+    #region System.Collections.ICollection Members
+
+    bool System.Collections.ICollection.IsSynchronized
+    {
+      get { return false; }
+    }
+
+    [Obsolete]
+    Object System.Collections.ICollection.SyncRoot
+    {
+      // Presumably safe to use the startsentinel (of type Node, always != null) as SyncRoot
+      // since the class Node is private.
+      get { return underlying != null ? ((System.Collections.ICollection)underlying).SyncRoot : startsentinel; }
+    }
+
+    void System.Collections.ICollection.CopyTo(Array arr, int index)
+    {
+      if (index < 0 || index + Count > arr.Length)
+        throw new ArgumentOutOfRangeException();
+
+      foreach (T item in this)
+        arr.SetValue(item, index++);
+    }
+
+    #endregion
+  
+    #region System.Collections.IList Members
+
+    Object System.Collections.IList.this[int index] 
+    {
+      get { return this[index]; }
+      set { this[index] = (T)value; }
+    }
+
+    int System.Collections.IList.Add(Object o)
+    {
+      bool added = Add((T)o);
+      // What position to report if item not added? SC.IList.Add doesn't say
+      return added ? Count-1 : -1; 
+    }
+
+    bool System.Collections.IList.Contains(Object o)
+    {
+      return Contains((T)o);
+    }
+
+    int System.Collections.IList.IndexOf(Object o)
+    {
+      return Math.Max(-1, IndexOf((T)o));
+    }
+
+    void System.Collections.IList.Insert(int index, Object o)
+    {
+      Insert(index, (T)o);
+    }
+
+    void System.Collections.IList.Remove(Object o)
+    {
+      Remove((T)o);
+    }
+
+    void System.Collections.IList.RemoveAt(int index)
+    {
+      RemoveAt(index);
+    }
+
+    #endregion
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/linkedlists/LinkedList.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/linkedlists/LinkedList.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/linkedlists/LinkedList.cs	(revision 3)
@@ -0,0 +1,3919 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+#define HASHINDEXnot
+
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+
+namespace C5
+{
+  /// <summary>
+  /// A list collection class based on a doubly linked list data structure.
+  /// </summary>
+  [Serializable]
+  public class LinkedList<T> : SequencedBase<T>, IList<T>, SCG.IList<T>
+#if HASHINDEX
+#else
+, IStack<T>, IQueue<T>
+#endif
+  {
+    #region Fields
+    /// <summary>
+    /// IExtensible.Add(T) always does AddLast(T), fIFO determines 
+    /// if T Remove() does RemoveFirst() or RemoveLast()
+    /// </summary>
+    bool fIFO = true;
+
+    #region Events
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public override EventTypeEnum ListenableEvents { get { return underlying == null ? EventTypeEnum.All : EventTypeEnum.None; } }
+
+    #endregion
+
+    //Invariant:  startsentinel != null && endsentinel != null
+    //If size==0: startsentinel.next == endsentinel && endsentinel.prev == startsentinel
+    //Else:      startsentinel.next == First && endsentinel.prev == Last)
+    /// <summary>
+    /// Node to the left of first node 
+    /// </summary>
+    Node startsentinel;
+    /// <summary>
+    /// Node to the right of last node
+    /// </summary>
+    Node endsentinel;
+    /// <summary>
+    /// Offset of this view in underlying list
+    /// </summary>
+#if HASHINDEX
+    int? offset;
+#else
+    int offset;
+#endif
+
+    /// <summary>
+    /// underlying list of this view (or null for the underlying list)
+    /// </summary>
+    LinkedList<T> underlying;
+
+    //Note: all views will have the same views list since all view objects are created by MemberwiseClone()
+    WeakViewList<LinkedList<T>> views;
+    WeakViewList<LinkedList<T>>.Node myWeakReference;
+
+    /// <summary>
+    /// Has this list or view not been invalidated by some operation (by someone calling Dispose())
+    /// </summary>
+    bool isValid = true;
+
+
+#if HASHINDEX
+    HashDictionary<T, Node> dict;
+    /// <summary>
+    /// Number of taggroups
+    /// </summary>
+    int taggroups;
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    int Taggroups
+    {
+      get { return underlying == null ? taggroups : underlying.taggroups; }
+      set { if (underlying == null) taggroups = value; else underlying.taggroups = value; }
+    }
+#endif
+
+    #endregion
+
+    #region Util
+
+    bool equals(T i1, T i2) { return itemequalityComparer.Equals(i1, i2); }
+
+    #region Check utilities
+    /// <summary>
+    /// Check if it is valid to perform updates and increment stamp of 
+    /// underlying if this is a view.
+    /// <para>This method should be called in every public modifying 
+    /// methods before any modifications are performed.
+    /// </para>
+    /// </summary>
+    /// <exception cref="InvalidOperationException"> if check fails.</exception>
+    protected override void updatecheck()
+    {
+      validitycheck();
+      base.updatecheck();
+      if (underlying != null)
+        underlying.stamp++;
+    }
+
+    /// <summary>
+    /// Check if we are a view that the underlyinglist has only been updated through us.
+    /// <br/>
+    /// This method should be called from enumerators etc to guard against 
+    /// modification of the base collection.
+    /// </summary>
+    /// <exception cref="InvalidOperationException"> if check fails.</exception>
+    void validitycheck()
+    {
+      if (!isValid)
+        throw new ViewDisposedException();
+    }
+
+    /// <summary>
+    /// Check that the list has not been updated since a particular time.
+    /// </summary>
+    /// <param name="stamp">The stamp indicating the time.</param>
+    /// <exception cref="CollectionModifiedException"> if check fails.</exception>
+    protected override void modifycheck(int stamp)
+    {
+      validitycheck();
+      if ((underlying != null ? underlying.stamp : this.stamp) != stamp)
+        throw new CollectionModifiedException();
+    }
+    #endregion
+
+    #region Searching
+    bool contains(T item, out Node node)
+    {
+#if HASHINDEX
+      if (dict.Find(item, out node))
+        return insideview(node);
+#else
+      //TODO: search from both ends? Or search from the end selected by FIFO?
+      node = startsentinel.next;
+      while (node != endsentinel)
+      {
+        if (equals(item, node.item))
+          return true;
+        node = node.next;
+      }
+#endif
+      return false;
+    }
+
+    /// <summary>
+    /// Search forwards from a node for a node with a particular item.
+    /// </summary>
+    /// <param name="item">The item to look for</param>
+    /// <param name="node">On input, the node to start at. If item was found, the node found on output.</param>
+    /// <param name="index">If node was found, the value will be the number of links followed higher than 
+    /// the value on input. If item was not found, the value on output is undefined.</param>
+    /// <returns>True if node was found.</returns>
+    bool find(T item, ref Node node, ref int index)
+    {
+      while (node != endsentinel)
+      {
+        //if (item.Equals(node.item))
+        if (itemequalityComparer.Equals(item, node.item))
+          return true;
+
+        index++;
+        node = node.next;
+      }
+
+      return false;
+    }
+
+    bool dnif(T item, ref Node node, ref int index)
+    {
+      while (node != startsentinel)
+      {
+        //if (item.Equals(node.item))
+        if (itemequalityComparer.Equals(item, node.item))
+          return true;
+
+        index--;
+        node = node.prev;
+      }
+
+      return false;
+    }
+
+#if HASHINDEX
+    bool insideview(Node node)
+    {
+      if (underlying == null)
+        return true;
+      return (startsentinel.precedes(node) && node.precedes(endsentinel));
+    }
+#endif
+
+    #endregion
+
+    #region Indexing
+    /// <summary>
+    /// Return the node at position pos
+    /// </summary>
+    /// <param name="pos"></param>
+    /// <returns></returns>
+    Node get(int pos)
+    {
+      if (pos < 0 || pos >= size)
+        throw new IndexOutOfRangeException();
+      else if (pos < size / 2)
+      {              // Closer to front
+        Node node = startsentinel;
+
+        for (int i = 0; i <= pos; i++)
+          node = node.next;
+
+        return node;
+      }
+      else
+      {                            // Closer to end
+        Node node = endsentinel;
+
+        for (int i = size; i > pos; i--)
+          node = node.prev;
+
+        return node;
+      }
+    }
+
+    /// <summary>
+    /// Find the distance from pos to the set given by positions. Return the
+    /// signed distance as return value and as an out parameter, the
+    /// array index of the nearest position. This is used for up to length 5 of
+    /// positions, and we do not assume it is sorted. 
+    /// </summary>
+    /// <param name="pos"></param>
+    /// <param name="positions"></param>
+    /// <param name="nearest"></param>
+    /// <returns></returns>
+    int dist(int pos, out int nearest, int[] positions)
+    {
+      nearest = -1;
+      int bestdist = int.MaxValue;
+      int signeddist = bestdist;
+      for (int i = 0; i < positions.Length; i++)
+      {
+        int thisdist = positions[i] - pos;
+        if (thisdist >= 0 && thisdist < bestdist) { nearest = i; bestdist = thisdist; signeddist = thisdist; }
+        if (thisdist < 0 && -thisdist < bestdist) { nearest = i; bestdist = -thisdist; signeddist = thisdist; }
+      }
+      return signeddist;
+    }
+
+    /// <summary>
+    /// Find the node at position pos, given known positions of several nodes.
+    /// </summary>
+    /// <param name="pos"></param>
+    /// <param name="positions"></param>
+    /// <param name="nodes"></param>
+    /// <returns></returns>
+    Node get(int pos, int[] positions, Node[] nodes)
+    {
+      int nearest;
+      int delta = dist(pos, out nearest, positions);
+      Node node = nodes[nearest];
+      if (delta > 0)
+        for (int i = 0; i < delta; i++)
+          node = node.prev;
+      else
+        for (int i = 0; i > delta; i--)
+          node = node.next;
+      return node;
+    }
+
+    /// <summary>
+    /// Get nodes at positions p1 and p2, given nodes at several positions.
+    /// </summary>
+    /// <param name="p1"></param>
+    /// <param name="p2"></param>
+    /// <param name="n1"></param>
+    /// <param name="n2"></param>
+    /// <param name="positions"></param>
+    /// <param name="nodes"></param>
+    void getPair(int p1, int p2, out Node n1, out Node n2, int[] positions, Node[] nodes)
+    {
+      int nearest1, nearest2;
+      int delta1 = dist(p1, out nearest1, positions), d1 = delta1 < 0 ? -delta1 : delta1;
+      int delta2 = dist(p2, out nearest2, positions), d2 = delta2 < 0 ? -delta2 : delta2;
+
+      if (d1 < d2)
+      {
+        n1 = get(p1, positions, nodes);
+        n2 = get(p2, new int[] { positions[nearest2], p1 }, new Node[] { nodes[nearest2], n1 });
+      }
+      else
+      {
+        n2 = get(p2, positions, nodes);
+        n1 = get(p1, new int[] { positions[nearest1], p2 }, new Node[] { nodes[nearest1], n2 });
+      }
+    }
+    #endregion
+
+    #region Insertion
+#if HASHINDEX
+    void insert(int index, Node succ, T item)
+    {
+      Node newnode = new Node(item);
+      if (dict.FindOrAdd(item, ref newnode))
+        throw new DuplicateNotAllowedException("Item already in indexed list");
+      insertNode(true, succ, newnode);
+    }
+
+    /// <summary>
+    /// Insert a Node before another one. Unchecked version. 
+    /// </summary>
+    /// <param name="succ">The successor to be</param>
+    /// <param name="newnode">Node to insert</param>
+    /// <param name="updateViews">update overlapping view in this call</param>
+    void insertNode(bool updateViews, Node succ, Node newnode)
+    {
+      newnode.next = succ;
+      Node pred = newnode.prev = succ.prev;
+      succ.prev.next = newnode;
+      succ.prev = newnode;
+      size++;
+      if (underlying != null)
+        underlying.size++;
+      settag(newnode);
+      if (updateViews)
+        fixViewsAfterInsert(succ, pred, 1, 0);
+    }
+#else
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="index">The index in this view</param>
+    /// <param name="succ"></param>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    Node insert(int index, Node succ, T item)
+    {
+      Node newnode = new Node(item, succ.prev, succ);
+      succ.prev.next = newnode;
+      succ.prev = newnode;
+      size++;
+      if (underlying != null)
+        underlying.size++;
+      fixViewsAfterInsert(succ, newnode.prev, 1, Offset + index);
+      return newnode;
+    }
+#endif
+    #endregion
+
+    #region Removal
+    T remove(Node node, int index)
+    {
+      fixViewsBeforeSingleRemove(node, Offset + index);
+      node.prev.next = node.next;
+      node.next.prev = node.prev;
+      size--;
+      if (underlying != null)
+        underlying.size--;
+#if HASHINDEX
+      removefromtaggroup(node);
+#endif
+      return node.item;
+    }
+
+#if HASHINDEX
+    private bool dictremove(T item, out Node node)
+    {
+      if (underlying == null)
+      {
+        if (!dict.Remove(item, out node))
+          return false;
+      }
+      else
+      {
+        //We cannot avoid calling dict twice - have to intersperse the listorder test!
+        if (!contains(item, out node))
+          return false;
+        dict.Remove(item);
+      }
+      return true;
+    }
+#endif
+    #endregion
+
+    #region fixView utilities
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="added">The actual number of inserted nodes</param>
+    /// <param name="pred">The predecessor of the inserted nodes</param>
+    /// <param name="succ">The successor of the added nodes</param>
+    /// <param name="realInsertionIndex"></param>
+    void fixViewsAfterInsert(Node succ, Node pred, int added, int realInsertionIndex)
+    {
+      if (views != null)
+        foreach (LinkedList<T> view in views)
+        {
+          if (view != this)
+          {
+#if HASHINDEX
+            if (pred.precedes(view.startsentinel) || (view.startsentinel == pred && view.size > 0))
+              view.offset += added;
+            if (view.startsentinel.precedes(pred) && succ.precedes(view.endsentinel))
+              view.size += added;
+            if (view.startsentinel == pred && view.size > 0)
+              view.startsentinel = succ.prev;
+            if (view.endsentinel == succ)
+              view.endsentinel = pred.next;
+#else
+            if (view.Offset == realInsertionIndex && view.size > 0)
+              view.startsentinel = succ.prev;
+            if (view.Offset + view.size == realInsertionIndex)
+              view.endsentinel = pred.next;
+            if (view.Offset < realInsertionIndex && view.Offset + view.size > realInsertionIndex)
+              view.size += added;
+            if (view.Offset > realInsertionIndex || (view.Offset == realInsertionIndex && view.size > 0))
+              view.offset += added;
+#endif
+          }
+        }
+    }
+
+    void fixViewsBeforeSingleRemove(Node node, int realRemovalIndex)
+    {
+      if (views != null)
+        foreach (LinkedList<T> view in views)
+        {
+          if (view != this)
+          {
+#if HASHINDEX
+            if (view.startsentinel.precedes(node) && node.precedes(view.endsentinel))
+              view.size--;
+            if (!view.startsentinel.precedes(node))
+              view.offset--;
+            if (view.startsentinel == node)
+              view.startsentinel = node.prev;
+            if (view.endsentinel == node)
+              view.endsentinel = node.next;
+#else
+            if (view.offset - 1 == realRemovalIndex)
+              view.startsentinel = node.prev;
+            if (view.offset + view.size == realRemovalIndex)
+              view.endsentinel = node.next;
+            if (view.offset <= realRemovalIndex && view.offset + view.size > realRemovalIndex)
+              view.size--;
+            if (view.offset > realRemovalIndex)
+              view.offset--;
+#endif
+          }
+        }
+    }
+
+#if HASHINDEX
+#else
+    void fixViewsBeforeRemove(int start, int count, Node first, Node last)
+    {
+      int clearend = start + count - 1;
+      if (views != null)
+        foreach (LinkedList<T> view in views)
+        {
+          if (view == this)
+            continue;
+          int viewoffset = view.Offset, viewend = viewoffset + view.size - 1;
+          //sentinels
+          if (start < viewoffset && viewoffset - 1 <= clearend)
+            view.startsentinel = first.prev;
+          if (start <= viewend + 1 && viewend < clearend)
+            view.endsentinel = last.next;
+          //offsets and sizes
+          if (start < viewoffset)
+          {
+            if (clearend < viewoffset)
+              view.offset = viewoffset - count;
+            else
+            {
+              view.offset = start;
+              view.size = clearend < viewend ? viewend - clearend : 0;
+            }
+          }
+          else if (start <= viewend)
+            view.size = clearend <= viewend ? view.size - count : start - viewoffset;
+        }
+    }
+#endif
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="otherView"></param>
+    /// <returns>The position of View(otherOffset, otherSize) wrt. this view</returns>
+    MutualViewPosition viewPosition(LinkedList<T> otherView)
+    {
+#if HASHINDEX
+      Node otherstartsentinel = otherView.startsentinel, otherendsentinel = otherView.endsentinel,
+        first = startsentinel.next, last = endsentinel.prev,
+        otherfirst = otherstartsentinel.next, otherlast = otherendsentinel.prev;
+      if (last.precedes(otherfirst) || otherlast.precedes(first))
+        return MutualViewPosition.NonOverlapping;
+      if (size == 0 || (otherstartsentinel.precedes(first) && last.precedes(otherendsentinel)))
+        return MutualViewPosition.Contains;
+      if (otherView.size == 0 || (startsentinel.precedes(otherfirst) && otherlast.precedes(endsentinel)))
+        return MutualViewPosition.ContainedIn;
+      return MutualViewPosition.Overlapping;
+#else
+      int end = offset + size, otherOffset = otherView.offset, otherSize = otherView.size, otherEnd = otherOffset + otherSize;
+      if (otherOffset >= end || otherEnd <= offset)
+        return MutualViewPosition.NonOverlapping;
+      if (size == 0 || (otherOffset <= offset && end <= otherEnd))
+        return MutualViewPosition.Contains;
+      if (otherSize == 0 || (offset <= otherOffset && otherEnd <= end))
+        return MutualViewPosition.ContainedIn;
+      return MutualViewPosition.Overlapping;
+#endif
+    }
+
+    void disposeOverlappingViews(bool reverse)
+    {
+      if (views != null)
+      {
+        foreach (LinkedList<T> view in views)
+        {
+          if (view != this)
+          {
+            switch (viewPosition(view))
+            {
+              case MutualViewPosition.ContainedIn:
+                if (reverse)
+                { }
+                else
+                  view.Dispose();
+                break;
+              case MutualViewPosition.Overlapping:
+                view.Dispose();
+                break;
+              case MutualViewPosition.Contains:
+              case MutualViewPosition.NonOverlapping:
+                break;
+            }
+          }
+        }
+      }
+    }
+
+    #endregion
+
+    #endregion
+
+    #region Constructors
+
+    /// <summary>
+    /// Create a linked list with en external item equalityComparer
+    /// </summary>
+    /// <param name="itemequalityComparer">The external equalityComparer</param>
+    public LinkedList(SCG.IEqualityComparer<T> itemequalityComparer)
+      : base(itemequalityComparer)
+    {
+      offset = 0;
+      size = stamp = 0;
+      startsentinel = new Node(default(T));
+      endsentinel = new Node(default(T));
+      startsentinel.next = endsentinel;
+      endsentinel.prev = startsentinel;
+#if HASHINDEX
+      //It is important that the sentinels are different:
+      startsentinel.taggroup = new TagGroup();
+      startsentinel.taggroup.tag = int.MinValue;
+      startsentinel.taggroup.count = 0;
+      endsentinel.taggroup = new TagGroup();
+      endsentinel.taggroup.tag = int.MaxValue;
+      endsentinel.taggroup.count = 0;
+      dict = new HashDictionary<T, Node>(itemequalityComparer);
+#endif
+    }
+
+    /// <summary>
+    /// Create a linked list with the natural item equalityComparer
+    /// </summary>
+    public LinkedList() : this(EqualityComparer<T>.Default) { }
+
+    #endregion
+
+    #region Node nested class
+
+    /// <summary>
+    /// An individual cell in the linked list
+    /// </summary>
+    [Serializable]
+    class Node
+    {
+      public Node prev;
+
+      public Node next;
+
+      public T item;
+
+      #region Tag support
+#if HASHINDEX
+      internal int tag;
+
+      internal TagGroup taggroup;
+
+      internal bool precedes(Node that)
+      {
+        //Debug.Assert(taggroup != null, "taggroup field null");
+        //Debug.Assert(that.taggroup != null, "that.taggroup field null");
+        int t1 = taggroup.tag;
+        int t2 = that.taggroup.tag;
+
+        return t1 < t2 ? true : t1 > t2 ? false : tag < that.tag;
+      }
+#endif
+      #endregion
+
+      [Tested]
+      internal Node(T item) { this.item = item; }
+
+      [Tested]
+      internal Node(T item, Node prev, Node next)
+      {
+        this.item = item; this.prev = prev; this.next = next;
+      }
+
+      public override string ToString()
+      {
+#if HASHINDEX
+        return String.Format("Node: (item={0}, tag={1})", item, tag);
+#else
+        return String.Format("Node(item={0})", item);
+#endif
+      }
+    }
+
+    #endregion
+
+    #region Taggroup nested class and tag maintenance utilities
+#if HASHINDEX
+    /// <summary>
+    /// A group of nodes with the same high tag. Purpose is to be
+    /// able to tell the sequence order of two nodes without having to scan through
+    /// the list.
+    /// </summary>
+    [Serializable]
+    class TagGroup
+    {
+      internal int tag, count;
+
+      internal Node first, last;
+
+      /// <summary>
+      /// Pretty print a tag group
+      /// </summary>
+      /// <returns>Formatted tag group</returns>
+      public override string ToString()
+      { return String.Format("TagGroup(tag={0}, cnt={1}, fst={2}, lst={3})", tag, count, first, last); }
+    }
+
+    //Constants for tag maintenance
+    const int wordsize = 32;
+
+    const int lobits = 3;
+
+    const int hibits = lobits + 1;
+
+    const int losize = 1 << lobits;
+
+    const int hisize = 1 << hibits;
+
+    const int logwordsize = 5;
+
+    TagGroup gettaggroup(Node pred, Node succ, out int lowbound, out int highbound)
+    {
+      TagGroup predgroup = pred.taggroup, succgroup = succ.taggroup;
+
+      if (predgroup == succgroup)
+      {
+        lowbound = pred.tag + 1;
+        highbound = succ.tag - 1;
+        return predgroup;
+      }
+      else if (predgroup.first != null)
+      {
+        lowbound = pred.tag + 1;
+        highbound = int.MaxValue;
+        return predgroup;
+      }
+      else if (succgroup.first != null)
+      {
+        lowbound = int.MinValue;
+        highbound = succ.tag - 1;
+        return succgroup;
+      }
+      else
+      {
+        lowbound = int.MinValue;
+        highbound = int.MaxValue;
+        return new TagGroup();
+      }
+    }
+
+
+    /// <summary>
+    /// Put a tag on a node (already inserted in the list). Split taggroups and renumber as 
+    /// necessary.
+    /// </summary>
+    /// <param name="node">The node to tag</param>
+    void settag(Node node)
+    {
+      Node pred = node.prev, succ = node.next;
+      TagGroup predgroup = pred.taggroup, succgroup = succ.taggroup;
+
+      if (predgroup == succgroup)
+      {
+        node.taggroup = predgroup;
+        predgroup.count++;
+        if (pred.tag + 1 == succ.tag)
+          splittaggroup(predgroup);
+        else
+          node.tag = (pred.tag + 1) / 2 + (succ.tag - 1) / 2;
+      }
+      else if (predgroup.first != null)
+      {
+        node.taggroup = predgroup;
+        predgroup.last = node;
+        predgroup.count++;
+        if (pred.tag == int.MaxValue)
+          splittaggroup(predgroup);
+        else
+          node.tag = pred.tag / 2 + int.MaxValue / 2 + 1;
+      }
+      else if (succgroup.first != null)
+      {
+        node.taggroup = succgroup;
+        succgroup.first = node;
+        succgroup.count++;
+        if (succ.tag == int.MinValue)
+          splittaggroup(node.taggroup);
+        else
+          node.tag = int.MinValue / 2 + (succ.tag - 1) / 2;
+      }
+      else
+      {
+        Debug.Assert(Taggroups == 0);
+
+        TagGroup newgroup = new TagGroup();
+
+        Taggroups = 1;
+        node.taggroup = newgroup;
+        newgroup.first = newgroup.last = node;
+        newgroup.count = 1;
+        return;
+      }
+    }
+
+
+    /// <summary>
+    /// Remove a node from its taggroup.
+    /// <br/> When this is called, node must already have been removed from the underlying list
+    /// </summary>
+    /// <param name="node">The node to remove</param>
+    void removefromtaggroup(Node node)
+    {
+     
+      TagGroup taggroup = node.taggroup;
+
+      if (--taggroup.count == 0)
+      {
+        Taggroups--;
+        return;
+      }
+
+      if (node == taggroup.first)
+        taggroup.first = node.next;
+
+      if (node == taggroup.last)
+        taggroup.last = node.prev;
+
+      //node.taggroup = null;
+      if (taggroup.count != losize || Taggroups == 1)
+        return;
+
+      TagGroup otg;
+      // bug20070911:
+      Node neighbor;
+      if ((neighbor = taggroup.first.prev) != startsentinel
+          && (otg = neighbor.taggroup).count <= losize)
+        taggroup.first = otg.first;
+      else if ((neighbor = taggroup.last.next) != endsentinel 
+               && (otg = neighbor.taggroup).count <= losize)
+        taggroup.last = otg.last;
+      else
+        return;
+
+      Node n = otg.first;
+
+      for (int i = 0, length = otg.count; i < length; i++)
+      {
+        n.taggroup = taggroup;
+        n = n.next;
+      }
+
+      taggroup.count += otg.count;
+      Taggroups--;
+      n = taggroup.first;
+
+      const int ofs = wordsize - hibits;
+
+      for (int i = 0, count = taggroup.count; i < count; i++)
+      {
+        n.tag = (i - losize) << ofs; //(i-8)<<28 
+        n = n.next;
+      }
+    }
+
+
+    /// <summary>
+    /// Split a tag group to make rom for more tags.
+    /// </summary>
+    /// <param name="taggroup">The tag group</param>
+    void splittaggroup(TagGroup taggroup)
+    {
+      Node n = taggroup.first;
+      int ptgt = taggroup.first.prev.taggroup.tag;
+      int ntgt = taggroup.last.next.taggroup.tag;
+
+      Debug.Assert(ptgt + 1 <= ntgt - 1);
+
+      int ofs = wordsize - hibits;
+      int newtgs = (taggroup.count - 1) / hisize;
+      int tgtdelta = (int)((ntgt + 0.0 - ptgt) / (newtgs + 2)), tgtag = ptgt;
+
+      tgtdelta = tgtdelta == 0 ? 1 : tgtdelta;
+      for (int j = 0; j < newtgs; j++)
+      {
+        TagGroup newtaggroup = new TagGroup();
+
+        newtaggroup.tag = (tgtag = tgtag >= ntgt - tgtdelta ? ntgt : tgtag + tgtdelta);
+        newtaggroup.first = n;
+        newtaggroup.count = hisize;
+        for (int i = 0; i < hisize; i++)
+        {
+          n.taggroup = newtaggroup;
+          n.tag = (i - losize) << ofs; //(i-8)<<28 
+          n = n.next;
+        }
+
+        newtaggroup.last = n.prev;
+      }
+
+      int rest = taggroup.count - hisize * newtgs;
+
+      taggroup.first = n;
+      taggroup.count = rest;
+      taggroup.tag = (tgtag = tgtag >= ntgt - tgtdelta ? ntgt : tgtag + tgtdelta); ofs--;
+      for (int i = 0; i < rest; i++)
+      {
+        n.tag = (i - hisize) << ofs; //(i-16)<<27 
+        n = n.next;
+      }
+
+      taggroup.last = n.prev;
+      Taggroups += newtgs;
+      if (tgtag == ntgt)
+        redistributetaggroups(taggroup);
+    }
+
+
+    private void redistributetaggroups(TagGroup taggroup)
+    {
+      TagGroup pred = taggroup, succ = taggroup, tmp;
+      double limit = 1, bigt = Math.Pow(Taggroups, 1.0 / 30);//?????
+      int bits = 1, count = 1, lowmask = 0, himask = 0, target = 0;
+
+      do
+      {
+        bits++;
+        lowmask = (1 << bits) - 1;
+        himask = ~lowmask;
+        target = taggroup.tag & himask;
+        while ((tmp = pred.first.prev.taggroup).first != null && (tmp.tag & himask) == target)
+        { count++; pred = tmp; }
+
+        while ((tmp = succ.last.next.taggroup).last != null && (tmp.tag & himask) == target)
+        { count++; succ = tmp; }
+
+        limit *= bigt;
+      } while (count > limit);
+
+      //redistibute tags
+      int lob = pred.first.prev.taggroup.tag, upb = succ.last.next.taggroup.tag;
+      int delta = upb / (count + 1) - lob / (count + 1);
+
+      Debug.Assert(delta > 0);
+      for (int i = 0; i < count; i++)
+      {
+        pred.tag = lob + (i + 1) * delta;
+        pred = pred.last.next.taggroup;
+      }
+    }
+#endif
+
+    #endregion
+
+    #region Position, PositionComparer and ViewHandler nested types
+    class PositionComparer : SCG.IComparer<Position>
+    {
+      static PositionComparer _default;
+      PositionComparer() { }
+      public static PositionComparer Default { get { return _default ?? (_default = new PositionComparer()); } }
+      public int Compare(Position a, Position b)
+      {
+#if HASHINDEX
+        return a.Endpoint == b.Endpoint ? 0 : a.Endpoint.precedes(b.Endpoint) ? -1 : 1;
+#else
+        return a.Index.CompareTo(b.Index);
+#endif
+      }
+    }
+    /// <summary>
+    /// During RemoveAll, we need to cache the original endpoint indices of views
+    /// </summary>
+    struct Position
+    {
+      public readonly LinkedList<T> View;
+      public bool Left;
+#if HASHINDEX
+      public readonly Node Endpoint;
+#else
+      public readonly int Index;
+#endif
+      public Position(LinkedList<T> view, bool left)
+      {
+        View = view;
+        Left = left;
+#if HASHINDEX
+        Endpoint = left ? view.startsentinel.next : view.endsentinel.prev;
+#else
+        Index = left ? view.Offset : view.Offset + view.size - 1;
+#endif
+      }
+#if HASHINDEX
+      public Position(Node node, int foo) { this.Endpoint = node; View = null; Left = false; }
+#else
+      public Position(int index) { this.Index = index; View = null; Left = false; }
+#endif
+    }
+
+    //TODO: merge the two implementations using Position values as arguments
+    /// <summary>
+    /// Handle the update of (other) views during a multi-remove operation.
+    /// </summary>
+    struct ViewHandler
+    {
+      ArrayList<Position> leftEnds;
+      ArrayList<Position> rightEnds;
+      int leftEndIndex, rightEndIndex, leftEndIndex2, rightEndIndex2;
+      internal readonly int viewCount;
+      internal ViewHandler(LinkedList<T> list)
+      {
+        leftEndIndex = rightEndIndex = leftEndIndex2 = rightEndIndex2 = viewCount = 0;
+        leftEnds = rightEnds = null;
+        if (list.views != null)
+          foreach (LinkedList<T> v in list.views)
+            if (v != list)
+            {
+              if (leftEnds == null)
+              {
+                leftEnds = new ArrayList<Position>();
+                rightEnds = new ArrayList<Position>();
+              }
+              leftEnds.Add(new Position(v, true));
+              rightEnds.Add(new Position(v, false));
+            }
+        if (leftEnds == null)
+          return;
+        viewCount = leftEnds.Count;
+        leftEnds.Sort(PositionComparer.Default);
+        rightEnds.Sort(PositionComparer.Default);
+      }
+#if HASHINDEX
+      internal void skipEndpoints(int removed, Node n)
+      {
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex < viewCount && ((endpoint = leftEnds[leftEndIndex]).Endpoint.prev.precedes(n)))
+          {
+            LinkedList<T> view = endpoint.View;
+            view.offset = view.offset - removed;//TODO: extract offset.Value?
+            view.size += removed;
+            leftEndIndex++;
+          }
+          while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).Endpoint.precedes(n))
+          {
+            LinkedList<T> view = endpoint.View;
+            view.size -= removed;
+            rightEndIndex++;
+          }
+        }
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex2 < viewCount && (endpoint = leftEnds[leftEndIndex2]).Endpoint.prev.precedes(n))
+            leftEndIndex2++;
+          while (rightEndIndex2 < viewCount && (endpoint = rightEnds[rightEndIndex2]).Endpoint.next.precedes(n))
+            rightEndIndex2++;
+        }
+      }
+      /// <summary>
+      /// To be called with n pointing to the right of each node to be removed in a stretch. 
+      /// And at the endsentinel. 
+      /// 
+      /// Update offset of a view whose left endpoint (has not already been handled and) is n or precedes n.
+      /// I.e. startsentinel precedes n.
+      /// Also update the size as a prelude to handling the right endpoint.
+      /// 
+      /// Update size of a view not already handled and whose right endpoint precedes n.
+      /// </summary>
+      /// <param name="removed">The number of nodes left of n to be removed</param>
+      /// <param name="n"></param>
+      internal void updateViewSizesAndCounts(int removed, Node n)
+      {
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex < viewCount && ((endpoint = leftEnds[leftEndIndex]).Endpoint.prev.precedes(n)))
+          {
+            LinkedList<T> view = endpoint.View;
+            view.offset = view.offset - removed; //TODO: fix use of offset
+            view.size += removed;
+            leftEndIndex++;
+          }
+          while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).Endpoint.precedes(n))
+          {
+            LinkedList<T> view = endpoint.View;
+            view.size -= removed;
+            rightEndIndex++;
+          }
+        }
+      }
+      /// <summary>
+      /// To be called with n being the first not-to-be-removed node after a (stretch of) node(s) to be removed.
+      /// 
+      /// It will update the startsentinel of views (that have not been handled before and) 
+      /// whose startsentinel precedes n, i.e. is to be deleted.
+      /// 
+      /// It will update the endsentinel of views (...) whose endsentinel precedes n, i.e. is to be deleted.
+      /// 
+      /// PROBLEM: DOESNT WORK AS ORIGINALLY ADVERTISED. WE MUST DO THIS BEFORE WE ACTUALLY REMOVE THE NODES. WHEN THE 
+      /// NODES HAVE BEEN REMOVED, THE precedes METHOD WILL NOT WORK!
+      /// </summary>
+      /// <param name="n"></param>
+      /// <param name="newstart"></param>
+      /// <param name="newend"></param>
+      internal void updateSentinels(Node n, Node newstart, Node newend)
+      {
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex2 < viewCount && (endpoint = leftEnds[leftEndIndex2]).Endpoint.prev.precedes(n))
+          {
+            LinkedList<T> view = endpoint.View;
+            view.startsentinel = newstart;
+            leftEndIndex2++;
+          }
+          while (rightEndIndex2 < viewCount && (endpoint = rightEnds[rightEndIndex2]).Endpoint.next.precedes(n))
+          {
+            LinkedList<T> view = endpoint.View;
+            view.endsentinel = newend;
+            rightEndIndex2++;
+          }
+        }
+      }
+#else
+      /// <summary>
+      /// This is to be called with realindex pointing to the first node to be removed after a (stretch of) node that was not removed
+      /// </summary>
+      /// <param name="removed"></param>
+      /// <param name="realindex"></param>
+      internal void skipEndpoints(int removed, int realindex)
+      {
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex < viewCount && (endpoint = leftEnds[leftEndIndex]).Index <= realindex)
+          {
+            LinkedList<T> view = endpoint.View;
+            view.offset = view.offset - removed;
+            view.size += removed;
+            leftEndIndex++;
+          }
+          while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).Index < realindex)
+          {
+            LinkedList<T> view = endpoint.View;
+            view.size -= removed;
+            rightEndIndex++;
+          }
+        }
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex2 < viewCount && (endpoint = leftEnds[leftEndIndex2]).Index <= realindex)
+            leftEndIndex2++;
+          while (rightEndIndex2 < viewCount && (endpoint = rightEnds[rightEndIndex2]).Index < realindex - 1)
+            rightEndIndex2++;
+        }
+      }
+      internal void updateViewSizesAndCounts(int removed, int realindex)
+      {
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex < viewCount && (endpoint = leftEnds[leftEndIndex]).Index <= realindex)
+          {
+            LinkedList<T> view = endpoint.View;
+            view.offset = view.Offset - removed;
+            view.size += removed;
+            leftEndIndex++;
+          }
+          while (rightEndIndex < viewCount && (endpoint = rightEnds[rightEndIndex]).Index < realindex)
+          {
+            LinkedList<T> view = endpoint.View;
+            view.size -= removed;
+            rightEndIndex++;
+          }
+        }
+      }
+      internal void updateSentinels(int realindex, Node newstart, Node newend)
+      {
+        if (viewCount > 0)
+        {
+          Position endpoint;
+          while (leftEndIndex2 < viewCount && (endpoint = leftEnds[leftEndIndex2]).Index <= realindex)
+          {
+            LinkedList<T> view = endpoint.View;
+            view.startsentinel = newstart;
+            leftEndIndex2++;
+          }
+          while (rightEndIndex2 < viewCount && (endpoint = rightEnds[rightEndIndex2]).Index < realindex - 1)
+          {
+            LinkedList<T> view = endpoint.View;
+            view.endsentinel = newend;
+            rightEndIndex2++;
+          }
+        }
+      }
+#endif
+    }
+    #endregion
+
+    #region Range nested class
+
+    class Range : DirectedCollectionValueBase<T>, IDirectedCollectionValue<T>
+    {
+      int start, count, rangestamp;
+      Node startnode, endnode;
+
+      LinkedList<T> list;
+
+      bool forwards;
+
+
+      internal Range(LinkedList<T> list, int start, int count, bool forwards)
+      {
+        this.list = list; this.rangestamp = list.underlying != null ? list.underlying.stamp : list.stamp;
+        this.start = start; this.count = count; this.forwards = forwards;
+        if (count > 0)
+        {
+          startnode = list.get(start);
+          endnode = list.get(start + count - 1);
+        }
+      }
+
+      public override bool IsEmpty { get { list.modifycheck(rangestamp); return count == 0; } }
+
+      [Tested]
+      public override int Count { [Tested]get { list.modifycheck(rangestamp); return count; } }
+
+
+      public override Speed CountSpeed { get { list.modifycheck(rangestamp); return Speed.Constant; } }
+
+
+      public override T Choose()
+      {
+        list.modifycheck(rangestamp);
+        if (count > 0) return startnode.item;
+        throw new NoSuchItemException();
+      }
+
+
+      [Tested]
+      public override SCG.IEnumerator<T> GetEnumerator()
+      {
+        int togo = count;
+
+        list.modifycheck(rangestamp);
+        if (togo == 0)
+          yield break;
+
+        Node cursor = forwards ? startnode : endnode;
+
+        yield return cursor.item;
+        while (--togo > 0)
+        {
+          cursor = forwards ? cursor.next : cursor.prev;
+          list.modifycheck(rangestamp);
+          yield return cursor.item;
+        }
+      }
+
+
+      [Tested]
+      public override IDirectedCollectionValue<T> Backwards()
+      {
+        list.modifycheck(rangestamp);
+
+        Range b = (Range)MemberwiseClone();
+
+        b.forwards = !forwards;
+        return b;
+      }
+
+
+      [Tested]
+      IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
+
+
+      [Tested]
+      public override EnumerationDirection Direction
+      {
+        [Tested]
+        get
+        { return forwards ? EnumerationDirection.Forwards : EnumerationDirection.Backwards; }
+      }
+    }
+
+
+    #endregion
+
+    #region IDisposable Members
+
+    /// <summary>
+    /// Invalidate this list. If a view, just invalidate the view. 
+    /// If not a view, invalidate the list and all views on it.
+    /// </summary>
+    public virtual void Dispose()
+    {
+      Dispose(false);
+    }
+
+    void Dispose(bool disposingUnderlying)
+    {
+      if (isValid)
+      {
+        if (underlying != null)
+        {
+          isValid = false;
+          if (!disposingUnderlying && views != null)
+            views.Remove(myWeakReference);
+          endsentinel = null;
+          startsentinel = null;
+          underlying = null;
+          views = null;
+          myWeakReference = null;
+        }
+        else
+        {
+          //isValid = false;
+          //endsentinel = null;
+          //startsentinel = null;
+          if (views != null)
+            foreach (LinkedList<T> view in views)
+              view.Dispose(true);
+          //views = null;
+          Clear();
+        }
+      }
+    }
+
+    #endregion IDisposable stuff
+
+    #region IList<T> Members
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+    /// <value>The first item in this list.</value>
+    [Tested]
+    public virtual T First
+    {
+      [Tested]
+      get
+      {
+        validitycheck();
+        if (size == 0)
+          throw new NoSuchItemException();
+        return startsentinel.next.item;
+      }
+    }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+    /// <value>The last item in this list.</value>
+    [Tested]
+    public virtual T Last
+    {
+      [Tested]
+      get
+      {
+        validitycheck();
+        if (size == 0)
+          throw new NoSuchItemException();
+        return endsentinel.prev.item;
+      }
+    }
+
+    /// <summary>
+    /// Since <code>Add(T item)</code> always add at the end of the list,
+    /// this describes if list has FIFO or LIFO semantics.
+    /// </summary>
+    /// <value>True if the <code>Remove()</code> operation removes from the
+    /// start of the list, false if it removes from the end. THe default for a new linked list is true.</value>
+    [Tested]
+    public virtual bool FIFO
+    {
+      [Tested]
+      get { validitycheck(); return fIFO; }
+      [Tested]
+      set { updatecheck(); fIFO = value; }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public virtual bool IsFixedSize
+    {
+      get { validitycheck(); return false; }
+    }
+
+    /// <summary>
+    /// On this list, this indexer is read/write.
+    /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+    /// &gt;= the size of the collection.
+    /// </summary>
+    /// <value>The i'th item of this list.</value>
+    /// <param name="index">The index of the item to fetch or store.</param>
+    [Tested]
+    public virtual T this[int index]
+    {
+      [Tested]
+      get { validitycheck(); return get(index).item; }
+      [Tested]
+      set
+      {
+        updatecheck();
+        Node n = get(index);
+        //
+        T item = n.item;
+#if HASHINDEX
+
+        if (itemequalityComparer.Equals(value, item))
+        {
+          n.item = value;
+          dict.Update(value, n);
+        }
+        else if (!dict.FindOrAdd(value, ref n))
+        {
+          dict.Remove(item);
+          n.item = value;
+        }
+        else
+          throw new ArgumentException("Item already in indexed list");
+#else
+        n.item = value;
+#endif
+        (underlying ?? this).raiseForSetThis(index, value, item);
+      }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual Speed IndexingSpeed { get { return Speed.Linear; } }
+
+    /// <summary>
+    /// Insert an item at a specific index location in this list. 
+    /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+    /// &gt; the size of the collection.</summary>
+    /// <param name="i">The index at which to insert.</param>
+    /// <param name="item">The item to insert.</param>
+    [Tested]
+    public virtual void Insert(int i, T item)
+    {
+      updatecheck();
+      insert(i, i == size ? endsentinel : get(i), item);
+      if (ActiveEvents != EventTypeEnum.None)
+        (underlying ?? this).raiseForInsert(i + Offset, item);
+    }
+
+    /// <summary>
+    /// Insert an item at the end of a compatible view, used as a pointer.
+    /// <para>The <code>pointer</code> must be a view on the same list as
+    /// <code>this</code> and the endpoitn of <code>pointer</code> must be
+    /// a valid insertion point of <code>this</code></para>
+    /// </summary>
+    /// <exception cref="IncompatibleViewException">If <code>pointer</code> 
+    /// is not a view on the same list as <code>this</code></exception>
+    /// <exception cref="IndexOutOfRangeException"><b>??????</b> if the endpoint of 
+    ///  <code>pointer</code> is not inside <code>this</code></exception>
+    /// <exception cref="DuplicateNotAllowedException"> if the list has
+    /// <code>AllowsDuplicates==false</code> and the item is 
+    /// already in the list.</exception>
+    /// <param name="pointer"></param>
+    /// <param name="item"></param>
+    public void Insert(IList<T> pointer, T item)
+    {
+      updatecheck();
+      if ((pointer == null) || ((pointer.Underlying ?? pointer) != (underlying ?? this)))
+        throw new IncompatibleViewException();
+#warning INEFFICIENT
+      //TODO: make this efficient (the whole point of the method:
+      //Do NOT use Insert, but insert the node at pointer.endsentinel, checking
+      //via the ordering that this is a valid insertion point
+      Insert(pointer.Offset + pointer.Count - Offset, item);
+    }
+
+    /// <summary>
+    /// Insert into this list all items from an enumerable collection starting 
+    /// at a particular index.
+    /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+    /// &gt; the size of the collection.
+    /// </summary>
+    /// <param name="i">Index to start inserting at</param>
+    /// <param name="items">Items to insert</param>
+    /// <typeparam name="U"></typeparam>
+    [Tested]
+    public virtual void InsertAll<U>(int i, SCG.IEnumerable<U> items) where U : T
+    {
+      insertAll(i, items, true);
+    }
+
+    void insertAll<U>(int i, SCG.IEnumerable<U> items, bool insertion) where U : T
+    {
+      updatecheck();
+      Node succ, node, pred;
+      int count = 0;
+      succ = i == size ? endsentinel : get(i);
+      pred = node = succ.prev;
+#if HASHINDEX
+      TagGroup taggroup = null;
+      int taglimit = 0, thetag = 0;
+      taggroup = gettaggroup(node, succ, out thetag, out taglimit);
+      try
+      {
+        foreach (T item in items)
+        {
+          Node tmp = new Node(item, node, null);
+          if (!dict.FindOrAdd(item, ref tmp))
+          {
+            tmp.tag = thetag < taglimit ? ++thetag : thetag;
+            tmp.taggroup = taggroup;
+            node.next = tmp;
+            count++;
+            node = tmp;
+          }
+          else
+            throw new DuplicateNotAllowedException("Item already in indexed list");
+        }
+      }
+      finally
+      {
+        if (count != 0)
+        { 
+          taggroup.count += count;
+          if (taggroup != pred.taggroup)
+            taggroup.first = pred.next;
+          if (taggroup != succ.taggroup)
+            taggroup.last = node;
+          succ.prev = node;
+          node.next = succ;
+          if (node.tag == node.prev.tag)
+            splittaggroup(taggroup);
+          size += count;
+          if (underlying != null)
+            underlying.size += count;
+          fixViewsAfterInsert(succ, pred, count, 0);
+          raiseForInsertAll(pred, i, count, insertion);
+        }
+      }
+#else
+      foreach (T item in items)
+      {
+        Node tmp = new Node(item, node, null);
+        node.next = tmp;
+        count++;
+        node = tmp;
+      }
+      if (count == 0)
+        return;
+      succ.prev = node;
+      node.next = succ;
+      size += count;
+      if (underlying != null)
+        underlying.size += count;
+      if (count > 0)
+      {
+        fixViewsAfterInsert(succ, pred, count, offset + i);
+        raiseForInsertAll(pred, i, count, insertion);
+      }
+#endif
+    }
+
+    private void raiseForInsertAll(Node node, int i, int added, bool insertion)
+    {
+      if (ActiveEvents != 0)
+      {
+        int index = Offset + i;
+        if ((ActiveEvents & (EventTypeEnum.Added | EventTypeEnum.Inserted)) != 0)
+          for (int j = index; j < index + added; j++)
+          {
+#warning must we check stamps here?
+            node = node.next;
+            T item = node.item;
+            if (insertion) raiseItemInserted(item, j);
+            raiseItemsAdded(item, 1);
+          }
+        raiseCollectionChanged();
+      }
+    }
+
+    /// <summary>
+    /// Insert an item at the front of this list.
+    /// </summary>
+    /// <param name="item">The item to insert.</param>
+    [Tested]
+    public virtual void InsertFirst(T item)
+    {
+      updatecheck();
+      insert(0, startsentinel.next, item);
+      if (ActiveEvents != EventTypeEnum.None)
+        (underlying ?? this).raiseForInsert(0 + Offset, item);
+    }
+
+    /// <summary>
+    /// Insert an item at the back of this list.
+    /// </summary>
+    /// <param name="item">The item to insert.</param>
+    [Tested]
+    public virtual void InsertLast(T item)
+    {
+      updatecheck();
+      insert(size, endsentinel, item);
+      if (ActiveEvents != EventTypeEnum.None)
+        (underlying ?? this).raiseForInsert(size - 1 + Offset, item);
+    }
+
+    /// <summary>
+    /// Create a new list consisting of the results of mapping all items of this
+    /// list.
+    /// </summary>
+    /// <param name="mapper">The delegate defining the map.</param>
+    /// <returns>The new list.</returns>
+    [Tested]
+    public IList<V> Map<V>(Fun<T, V> mapper)
+    {
+      validitycheck();
+
+      LinkedList<V> retval = new LinkedList<V>();
+      return map<V>(mapper, retval);
+    }
+
+    /// <summary>
+    /// Create a new list consisting of the results of mapping all items of this
+    /// list. The new list will use a specified equalityComparer for the item type.
+    /// </summary>
+    /// <typeparam name="V">The type of items of the new list</typeparam>
+    /// <param name="mapper">The delegate defining the map.</param>
+    /// <param name="equalityComparer">The equalityComparer to use for the new list</param>
+    /// <returns>The new list.</returns>
+    public IList<V> Map<V>(Fun<T, V> mapper, SCG.IEqualityComparer<V> equalityComparer)
+    {
+      validitycheck();
+
+      LinkedList<V> retval = new LinkedList<V>(equalityComparer);
+      return map<V>(mapper, retval);
+    }
+
+    private IList<V> map<V>(Fun<T, V> mapper, LinkedList<V> retval)
+    {
+      if (size == 0)
+        return retval;
+      int stamp = this.stamp;
+      Node cursor = startsentinel.next;
+      LinkedList<V>.Node mcursor = retval.startsentinel;
+
+#if HASHINDEX
+      double tagdelta = int.MaxValue / (size + 1.0);
+      int count = 1;
+      LinkedList<V>.TagGroup taggroup = null;
+      taggroup = new LinkedList<V>.TagGroup();
+      retval.taggroups = 1;
+      taggroup.count = size;
+#endif
+      while (cursor != endsentinel)
+      {
+        V v = mapper(cursor.item);
+        modifycheck(stamp);
+        mcursor.next = new LinkedList<V>.Node(v, mcursor, null);
+        cursor = cursor.next;
+        mcursor = mcursor.next;
+#if HASHINDEX
+        retval.dict.Add(v, mcursor);
+        mcursor.taggroup = taggroup;
+        mcursor.tag = (int)(tagdelta * count++);
+#endif
+      }
+
+#if HASHINDEX
+      taggroup.first = retval.startsentinel.next;
+      taggroup.last = mcursor;
+#endif
+      retval.endsentinel.prev = mcursor;
+      mcursor.next = retval.endsentinel;
+      retval.size = size;
+      return retval;
+    }
+
+    /// <summary>
+    /// Remove one item from the list: from the front if <code>FIFO</code>
+    /// is true, else from the back.
+    /// <exception cref="NoSuchItemException"/> if this list is empty.
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public virtual T Remove()
+    {
+      updatecheck();
+      if (size == 0)
+        throw new NoSuchItemException("List is empty");
+      T item = fIFO ? remove(startsentinel.next, 0) : remove(endsentinel.prev, size - 1);
+#if HASHINDEX
+      dict.Remove(item);
+#endif
+      (underlying ?? this).raiseForRemove(item);
+      return item;
+    }
+
+    /// <summary>
+    /// Remove one item from the front of the list.
+    /// <exception cref="NoSuchItemException"/> if this list is empty.
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public virtual T RemoveFirst()
+    {
+      updatecheck();
+      if (size == 0)
+        throw new NoSuchItemException("List is empty");
+
+      T item = remove(startsentinel.next, 0);
+#if HASHINDEX
+      dict.Remove(item);
+#endif
+      if (ActiveEvents != EventTypeEnum.None)
+        (underlying ?? this).raiseForRemoveAt(Offset, item);
+      return item;
+    }
+
+    /// <summary>
+    /// Remove one item from the back of the list.
+    /// <exception cref="NoSuchItemException"/> if this list is empty.
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public virtual T RemoveLast()
+    {
+      updatecheck();
+      if (size == 0)
+        throw new NoSuchItemException("List is empty");
+
+      T item = remove(endsentinel.prev, size - 1);
+#if HASHINDEX
+      dict.Remove(item);
+#endif
+      if (ActiveEvents != EventTypeEnum.None)
+        (underlying ?? this).raiseForRemoveAt(size + Offset, item);
+      return item;
+    }
+
+    /// <summary>
+    /// Create a list view on this list. 
+    /// </summary>
+    /// <exception cref="ArgumentOutOfRangeException"> if the start or count is negative</exception>
+    /// <exception cref="ArgumentException"> if the range does not fit within list.</exception>
+    /// <param name="start">The index in this list of the start of the view.</param>
+    /// <param name="count">The size of the view.</param>
+    /// <returns>The new list view.</returns>
+    [Tested]
+    public virtual IList<T> View(int start, int count)
+    {
+      checkRange(start, count);
+      validitycheck();
+      if (views == null)
+        views = new WeakViewList<LinkedList<T>>();
+      LinkedList<T> retval = (LinkedList<T>)MemberwiseClone();
+      retval.underlying = underlying != null ? underlying : this;
+      retval.offset = offset + start;
+      retval.size = count;
+      getPair(start - 1, start + count, out retval.startsentinel, out retval.endsentinel,
+          new int[] { -1, size }, new Node[] { startsentinel, endsentinel });
+      //retval.startsentinel = start == 0 ? startsentinel : get(start - 1);
+      //retval.endsentinel = start + count == size ? endsentinel : get(start + count);
+
+      //TODO: for the purpose of Dispose, we need to retain a ref to the node
+      retval.myWeakReference = views.Add(retval);
+      return retval;
+    }
+
+    /// <summary>
+    /// Create a list view on this list containing the (first) occurrence of a particular item. 
+    /// </summary>
+    /// <exception cref="ArgumentException"> if the item is not in this list.</exception>
+    /// <param name="item">The item to find.</param>
+    /// <returns>The new list view.</returns>
+    public virtual IList<T> ViewOf(T item)
+    {
+#if HASHINDEX
+      Node n;
+      validitycheck();
+      if (!contains(item, out n))
+        return null;
+      LinkedList<T> retval = (LinkedList<T>)MemberwiseClone();
+      retval.underlying = underlying != null ? underlying : this;
+      retval.offset = null;
+      retval.startsentinel = n.prev;
+      retval.endsentinel = n.next;
+      retval.size = 1;
+      return retval;
+#else
+      int index = 0;
+      Node n = startsentinel.next;
+      if (!find(item, ref n, ref index))
+        return null;
+      //TODO: optimize with getpair!
+      return View(index, 1);
+#endif
+    }
+
+    /// <summary>
+    /// Create a list view on this list containing the last occurrence of a particular item. 
+    /// <exception cref="ArgumentException"/> if the item is not in this list.
+    /// </summary>
+    /// <param name="item">The item to find.</param>
+    /// <returns>The new list view.</returns>
+    public virtual IList<T> LastViewOf(T item)
+    {
+#if HASHINDEX
+      return ViewOf(item);
+#else
+      int index = size - 1;
+      Node n = endsentinel.prev;
+      if (!dnif(item, ref n, ref index))
+        return null;
+      return View(index, 1);
+#endif
+    }
+
+    /// <summary>
+    /// Null if this list is not a view.
+    /// </summary>
+    /// <value>Underlying list for view.</value>
+    [Tested]
+    public virtual IList<T> Underlying { [Tested]get { validitycheck(); return underlying; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual bool IsValid { get { return isValid; } }
+
+    /// <summary>
+    /// </summary>
+    /// <value>Offset for this list view or 0 for a underlying list.</value>
+    [Tested]
+    public virtual int Offset
+    {
+      [Tested]
+      get
+      {
+        validitycheck();
+#if HASHINDEX
+        if (offset == null && underlying != null)
+        {
+          //TODO: search from both ends simultaneously!
+          Node n = underlying.startsentinel;
+          int i = 0;
+          while (n != startsentinel) { n = n.next; i++; }
+          offset = i;
+        }
+#endif
+        return (int)offset;
+      }
+    }
+
+    /// <summary>
+    /// Slide this list view along the underlying list.
+    /// </summary>
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>
+    /// <exception cref="ArgumentOutOfRangeException"> if the operation
+    /// would bring either end of the view outside the underlying list.</exception>
+    /// <param name="offset">The signed amount to slide: positive to slide
+    /// towards the end.</param>
+    [Tested]
+    public IList<T> Slide(int offset)
+    {
+      if (!TrySlide(offset, size))
+        throw new ArgumentOutOfRangeException();
+      return this;
+    }
+
+    //TODO: more test cases
+    /// <summary>
+    /// Slide this list view along the underlying list, perhaps changing its size.
+    /// </summary>
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>
+    /// <exception cref="ArgumentOutOfRangeException"> if the operation
+    /// would bring either end of the view outside the underlying list.</exception>
+    /// <param name="offset">The signed amount to slide: positive to slide
+    /// towards the end.</param>
+    /// <param name="size">The new size of the view.</param>
+    public IList<T> Slide(int offset, int size)
+    {
+      if (!TrySlide(offset, size))
+        throw new ArgumentOutOfRangeException();
+      return this;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="offset"></param>
+    /// <returns></returns>
+    public virtual bool TrySlide(int offset) { return TrySlide(offset, size); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="offset"></param>
+    /// <param name="size"></param>
+    /// <returns></returns>
+    public virtual bool TrySlide(int offset, int size)
+    {
+      updatecheck();
+      if (underlying == null)
+        throw new NotAViewException("List not a view");
+
+#pragma warning disable 472
+      if (this.offset == null) //Note: only possible with HASHINDEX
+#pragma warning restore 472
+      {
+#pragma warning disable 162
+        try
+        {
+          getPair(offset - 1, offset + size, out startsentinel, out endsentinel,
+              new int[] { -1, this.size }, new Node[] { startsentinel, endsentinel });
+          //TODO: maybe-update offset field
+        }
+        catch (NullReferenceException)
+        {
+          return false;
+        }
+#pragma warning restore 162
+      }
+      else
+      {
+        if (offset + this.offset < 0 || offset + this.offset + size > underlying.size)
+          return false;
+        int oldoffset = (int)(this.offset);
+        getPair(offset - 1, offset + size, out startsentinel, out endsentinel,
+            new int[] { -oldoffset - 1, -1, this.size, underlying.size - oldoffset },
+            new Node[] { underlying.startsentinel, startsentinel, endsentinel, underlying.endsentinel });
+      }
+      this.size = size;
+      this.offset += offset;
+      return true;
+    }
+
+
+    //TODO: improve the complexity of the implementation
+    /// <summary>
+    /// 
+    /// <para>Returns null if <code>otherView</code> is strictly to the left of this view</para>
+    /// </summary>
+    /// <param name="otherView"></param>
+    /// <exception cref="IncompatibleViewException">If otherView does not have the same underlying list as this</exception>
+    /// <returns></returns>
+    public virtual IList<T> Span(IList<T> otherView)
+    {
+      if ((otherView == null) || ((otherView.Underlying ?? otherView) != (underlying ?? this)))
+        throw new IncompatibleViewException();
+      if (otherView.Offset + otherView.Count - Offset < 0)
+        return null;
+      return (underlying ?? this).View(Offset, otherView.Offset + otherView.Count - Offset);
+    }
+
+
+    //Question: should we swap items or move nodes around?
+    //The first seems much more efficient unless the items are value types 
+    //with a large memory footprint.
+    //(Swapping will do count*3/2 T assignments, linking around will do 
+    // 4*count ref assignments; note that ref assignments are more expensive 
+    //than copying non-ref bits)
+    /// <summary>
+    /// Reverse the list so the items are in the opposite sequence order.
+    /// </summary>
+    [Tested]
+    public virtual void Reverse()
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+
+      Position[] positions = null;
+      int poslow = 0, poshigh = 0;
+      if (views != null)
+      {
+        CircularQueue<Position> _positions = null;
+        foreach (LinkedList<T> view in views)
+        {
+          if (view != this)
+          {
+            switch (viewPosition(view))
+            {
+              case MutualViewPosition.ContainedIn:
+                (_positions ?? (_positions = new CircularQueue<Position>())).Enqueue(new Position(view, true));
+                _positions.Enqueue(new Position(view, false));
+                break;
+              case MutualViewPosition.Overlapping:
+                view.Dispose();
+                break;
+              case MutualViewPosition.Contains:
+              case MutualViewPosition.NonOverlapping:
+                break;
+            }
+          }
+        }
+        if (_positions != null)
+        {
+          positions = _positions.ToArray();
+          Sorting.IntroSort<Position>(positions, 0, positions.Length, PositionComparer.Default);
+          poshigh = positions.Length - 1;
+        }
+      }
+
+      Node a = get(0), b = get(size - 1);
+      for (int i = 0; i < size / 2; i++)
+      {
+        T swap;
+        swap = a.item; a.item = b.item; b.item = swap;
+#if HASHINDEX
+        dict[a.item] = a; dict[b.item] = b;
+#endif
+        if (positions != null)
+          mirrorViewSentinelsForReverse(positions, ref poslow, ref poshigh, a, b, i);
+        a = a.next; b = b.prev;
+      }
+      if (positions != null && size % 2 != 0)
+        mirrorViewSentinelsForReverse(positions, ref poslow, ref poshigh, a, b, size / 2);
+      (underlying ?? this).raiseCollectionChanged();
+    }
+
+    private void mirrorViewSentinelsForReverse(Position[] positions, ref int poslow, ref int poshigh, Node a, Node b, int i)
+    {
+#if HASHINDEX
+      int? aindex = offset + i, bindex = offset + size - 1 - i;
+#else
+      int aindex = offset + i, bindex = offset + size - 1 - i;
+#endif
+      Position pos;
+#if HASHINDEX
+      while (poslow <= poshigh && (pos = positions[poslow]).Endpoint == a)
+#else
+      while (poslow <= poshigh && (pos = positions[poslow]).Index == aindex)
+#endif
+      {
+        //TODO: Note: in the case og hashed linked list, if this.offset == null, but pos.View.offset!=null
+        //we may at this point compute this.offset and non-null values of aindex and bindex
+        if (pos.Left)
+          pos.View.endsentinel = b.next;
+        else
+        {
+          pos.View.startsentinel = b.prev;
+          pos.View.offset = bindex;
+        }
+        poslow++;
+      }
+#if HASHINDEX
+      while (poslow < poshigh && (pos = positions[poshigh]).Endpoint == b)
+#else
+      while (poslow < poshigh && (pos = positions[poshigh]).Index == bindex)
+#endif
+      {
+        if (pos.Left)
+          pos.View.endsentinel = a.next;
+        else
+        {
+          pos.View.startsentinel = a.prev;
+          pos.View.offset = aindex;
+        }
+        poshigh--;
+      }
+    }
+
+    /// <summary>
+    /// Check if this list is sorted according to the default sorting order
+    /// for the item type T, as defined by the <see cref="T:C5.Comparer`1"/> class 
+    /// </summary>
+    /// <exception cref="NotComparableException">if T is not comparable</exception>
+    /// <returns>True if the list is sorted, else false.</returns>
+    public bool IsSorted() { return IsSorted(Comparer<T>.Default); }
+
+    /// <summary>
+    /// Check if this list is sorted according to a specific sorting order.
+    /// </summary>
+    /// <param name="c">The comparer defining the sorting order.</param>
+    /// <returns>True if the list is sorted, else false.</returns>
+    [Tested]
+    public virtual bool IsSorted(SCG.IComparer<T> c)
+    {
+      validitycheck();
+      if (size <= 1)
+        return true;
+
+      Node node = startsentinel.next;
+      T prevItem = node.item;
+
+      node = node.next;
+      while (node != endsentinel)
+      {
+        if (c.Compare(prevItem, node.item) > 0)
+          return false;
+        else
+        {
+          prevItem = node.item;
+          node = node.next;
+        }
+      }
+
+      return true;
+    }
+
+    /// <summary>
+    /// Sort the items of the list according to the default sorting order
+    /// for the item type T, as defined by the Comparer[T] class. 
+    /// (<see cref="T:C5.Comparer`1"/>).
+    /// The sorting is stable.
+    /// </summary>
+    /// <exception cref="InvalidOperationException">if T is not comparable</exception>
+    public virtual void Sort() { Sort(Comparer<T>.Default); }
+
+    // Sort the linked list using mergesort
+    /// <summary>
+    /// Sort the items of the list according to a specific sorting order.
+    /// The sorting is stable.
+    /// </summary>
+    /// <param name="c">The comparer defining the sorting order.</param>
+    [Tested]
+    public virtual void Sort(SCG.IComparer<T> c)
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      disposeOverlappingViews(false);
+#if HASHINDEX
+      if (underlying != null)
+      {
+        Node cursor = startsentinel.next;
+        while (cursor != endsentinel)
+        {
+          cursor.taggroup.count--;
+          cursor = cursor.next;
+        }
+      }
+#endif
+      // Build a linked list of non-empty runs.
+      // The prev field in first node of a run points to next run's first node
+      Node runTail = startsentinel.next;
+      Node prevNode = startsentinel.next;
+
+      endsentinel.prev.next = null;
+      while (prevNode != null)
+      {
+        Node node = prevNode.next;
+
+        while (node != null && c.Compare(prevNode.item, node.item) <= 0)
+        {
+          prevNode = node;
+          node = prevNode.next;
+        }
+
+        // Completed a run; prevNode is the last node of that run
+        prevNode.next = null;	// Finish the run
+        runTail.prev = node;	// Link it into the chain of runs
+        runTail = node;
+        if (c.Compare(endsentinel.prev.item, prevNode.item) <= 0)
+          endsentinel.prev = prevNode;	// Update last pointer to point to largest
+
+        prevNode = node;		// Start a new run
+      }
+
+      // Repeatedly merge runs two and two, until only one run remains
+      while (startsentinel.next.prev != null)
+      {
+        Node run = startsentinel.next;
+        Node newRunTail = null;
+
+        while (run != null && run.prev != null)
+        { // At least two runs, merge
+          Node nextRun = run.prev.prev;
+          Node newrun = mergeRuns(run, run.prev, c);
+
+          if (newRunTail != null)
+            newRunTail.prev = newrun;
+          else
+            startsentinel.next = newrun;
+
+          newRunTail = newrun;
+          run = nextRun;
+        }
+
+        if (run != null) // Add the last run, if any
+          newRunTail.prev = run;
+      }
+
+      endsentinel.prev.next = endsentinel;
+      startsentinel.next.prev = startsentinel;
+
+      //assert invariant();
+      //assert isSorted();
+#if HASHINDEX
+      {
+        Node cursor = startsentinel.next, end = endsentinel;
+        int tag, taglimit;
+        TagGroup t = gettaggroup(startsentinel, endsentinel, out tag, out taglimit);
+        int tagdelta = taglimit / (size + 1) - tag / (size + 1);
+        tagdelta = tagdelta == 0 ? 1 : tagdelta;
+        if (underlying == null)
+          taggroups = 1;
+        while (cursor != end)
+        {
+          tag = tag + tagdelta > taglimit ? taglimit : tag + tagdelta;
+          cursor.tag = tag;
+          t.count++;
+          cursor.taggroup = t;
+          cursor = cursor.next;
+        }
+        if (t != startsentinel.taggroup)
+          t.first = startsentinel.next;
+        if (t != endsentinel.taggroup)
+          t.last = endsentinel.prev;
+        if (tag == taglimit)
+          splittaggroup(t);
+      }
+#endif
+      (underlying ?? this).raiseCollectionChanged();
+    }
+
+    private static Node mergeRuns(Node run1, Node run2, SCG.IComparer<T> c)
+    {
+      //assert run1 != null && run2 != null;
+      Node prev;
+      bool prev1;	// is prev from run1?
+
+      if (c.Compare(run1.item, run2.item) <= 0)
+      {
+        prev = run1;
+        prev1 = true;
+        run1 = run1.next;
+      }
+      else
+      {
+        prev = run2;
+        prev1 = false;
+        run2 = run2.next;
+      }
+
+      Node start = prev;
+
+      //assert start != null;
+      start.prev = null;
+      while (run1 != null && run2 != null)
+      {
+        if (prev1)
+        {
+          //assert prev.next == run1;
+          //Comparable run2item = (Comparable)run2.item;
+          while (run1 != null && c.Compare(run2.item, run1.item) >= 0)
+          {
+            prev = run1;
+            run1 = prev.next;
+          }
+
+          if (run1 != null)
+          { // prev.item <= run2.item < run1.item; insert run2
+            prev.next = run2;
+            run2.prev = prev;
+            prev = run2;
+            run2 = prev.next;
+            prev1 = false;
+          }
+        }
+        else
+        {
+          //assert prev.next == run2;
+          //Comparable run1item = (Comparable)run1.item;
+          while (run2 != null && c.Compare(run1.item, run2.item) > 0)
+          {
+            prev = run2;
+            run2 = prev.next;
+          }
+
+          if (run2 != null)
+          { // prev.item < run1.item <= run2.item; insert run1
+            prev.next = run1;
+            run1.prev = prev;
+            prev = run1;
+            run1 = prev.next;
+            prev1 = true;
+          }
+        }
+      }
+
+      //assert !(run1 != null && prev1) && !(run2 != null && !prev1);
+      if (run1 != null)
+      { // last run2 < all of run1; attach run1 at end
+        prev.next = run1;
+        run1.prev = prev;
+      }
+      else if (run2 != null)
+      { // last run1 
+        prev.next = run2;
+        run2.prev = prev;
+      }
+
+      return start;
+    }
+
+    /// <summary>
+    /// Randomly shuffle the items of this list. 
+    /// <para>Will invalidate overlapping views???</para>
+    /// </summary>
+    public virtual void Shuffle() { Shuffle(new C5Random()); }
+
+
+    /// <summary>
+    /// Shuffle the items of this list according to a specific random source.
+    /// <para>Will invalidate overlapping views???</para>
+    /// </summary>
+    /// <param name="rnd">The random source.</param>
+    public virtual void Shuffle(Random rnd)
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      disposeOverlappingViews(false);
+      ArrayList<T> a = new ArrayList<T>();
+      a.AddAll(this);
+      a.Shuffle(rnd);
+      Node cursor = startsentinel.next;
+      int j = 0;
+      while (cursor != endsentinel)
+      {
+        cursor.item = a[j++];
+#if HASHINDEX
+        dict[cursor.item] = cursor;
+#endif
+        cursor = cursor.next;
+      }
+      (underlying ?? this).raiseCollectionChanged();
+    }
+
+    #endregion
+
+    #region IIndexed<T> Members
+
+    /// <summary>
+    /// <exception cref="IndexOutOfRangeException"/>.
+    /// </summary>
+    /// <value>The directed collection of items in a specific index interval.</value>
+    /// <param name="start">The low index of the interval (inclusive).</param>
+    /// <param name="count">The size of the range.</param>
+    [Tested]
+    public IDirectedCollectionValue<T> this[int start, int count]
+    {
+      [Tested]
+      get
+      {
+        validitycheck();
+        checkRange(start, count);
+        return new Range(this, start, count, true);
+      }
+    }
+
+    /// <summary>
+    /// Searches for an item in the list going forwrds from the start.
+    /// </summary>
+    /// <param name="item">Item to search for.</param>
+    /// <returns>Index of item from start.</returns>
+    [Tested]
+    public virtual int IndexOf(T item)
+    {
+      validitycheck();
+      Node node;
+#if HASHINDEX
+      if (!dict.Find(item, out node) || !insideview(node))
+        return ~size;
+#endif
+      node = startsentinel.next;
+      int index = 0;
+      if (find(item, ref node, ref index))
+        return index;
+      else
+        return ~size;
+    }
+
+    /// <summary>
+    /// Searches for an item in the list going backwords from the end.
+    /// </summary>
+    /// <param name="item">Item to search for.</param>
+    /// <returns>Index of of item from the end.</returns>
+    [Tested]
+    public virtual int LastIndexOf(T item)
+    {
+#if HASHINDEX
+      return IndexOf(item);
+#else
+      validitycheck();
+
+      Node node = endsentinel.prev;
+      int index = size - 1;
+
+      if (dnif(item, ref node, ref index))
+        return index;
+      else
+        return ~size;
+#endif
+    }
+
+    /// <summary>
+    /// Remove the item at a specific position of the list.
+    /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+    /// &gt;= the size of the collection.
+    /// </summary>
+    /// <param name="i">The index of the item to remove.</param>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public virtual T RemoveAt(int i)
+    {
+      updatecheck();
+      T retval = remove(get(i), i);
+#if HASHINDEX
+      dict.Remove(retval);
+#endif
+      if (ActiveEvents != EventTypeEnum.None)
+        (underlying ?? this).raiseForRemoveAt(Offset + i, retval);
+      return retval;
+    }
+
+    /// <summary>
+    /// Remove all items in an index interval.
+    /// <exception cref="IndexOutOfRangeException"/>???. 
+    /// </summary>
+    /// <param name="start">The index of the first item to remove.</param>
+    /// <param name="count">The number of items to remove.</param>
+    [Tested]
+    public virtual void RemoveInterval(int start, int count)
+    {
+#if HASHINDEX
+      updatecheck();
+      checkRange(start, count);
+      if (count == 0)
+        return;
+
+      View(start, count).Clear();
+#else
+      //Note: this is really almost equaivalent to Clear on a view
+      updatecheck();
+      checkRange(start, count);
+      if (count == 0)
+        return;
+
+      //for small count: optimize
+      //use an optimal get(int i, int j, ref Node ni, ref Node nj)?
+      Node a = get(start), b = get(start + count - 1);
+      fixViewsBeforeRemove(start, count, a, b);
+      a.prev.next = b.next;
+      b.next.prev = a.prev;
+      if (underlying != null)
+        underlying.size -= count;
+
+      size -= count;
+      if (ActiveEvents != EventTypeEnum.None)
+        (underlying ?? this).raiseForRemoveInterval(start + Offset, count);
+#endif
+    }
+
+    void raiseForRemoveInterval(int start, int count)
+    {
+      if (ActiveEvents != 0)
+      {
+        raiseCollectionCleared(size == 0, count, start);
+        raiseCollectionChanged();
+      }
+    }
+    #endregion
+
+    #region ISequenced<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    [Tested]
+    public override int GetSequencedHashCode() { validitycheck(); return base.GetSequencedHashCode(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="that"></param>
+    /// <returns></returns>
+    [Tested]
+    public override bool SequencedEquals(ISequenced<T> that) { validitycheck(); return base.SequencedEquals(that); }
+
+    #endregion
+
+    #region IDirectedCollection<T> Members
+
+    /// <summary>
+    /// Create a collection containing the same items as this collection, but
+    /// whose enumerator will enumerate the items backwards. The new collection
+    /// will become invalid if the original is modified. Method typicaly used as in
+    /// <code>foreach (T x in coll.Backwards()) {...}</code>
+    /// </summary>
+    /// <returns>The backwards collection.</returns>
+    [Tested]
+    public override IDirectedCollectionValue<T> Backwards()
+    { return this[0, size].Backwards(); }
+
+    #endregion
+
+    #region IDirectedEnumerable<T> Members
+
+    [Tested]
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
+
+    #endregion
+
+    #region IEditableCollection<T> Members
+
+    /// <summary>
+    /// The value is symbolic indicating the type of asymptotic complexity
+    /// in terms of the size of this collection (worst-case or amortized as
+    /// relevant).
+    /// </summary>
+    /// <value>Speed.Linear</value>
+    [Tested]
+    public virtual Speed ContainsSpeed
+    {
+      [Tested]
+      get
+      {
+#if HASHINDEX
+        return Speed.Constant;
+#else
+        return Speed.Linear;
+#endif
+      }
+    }
+
+    /// <summary>
+    /// Performs a check for view validity before calling base.GetUnsequencedHashCode()
+    /// </summary>
+    /// <returns></returns>
+    [Tested]
+    public override int GetUnsequencedHashCode()
+    { validitycheck(); return base.GetUnsequencedHashCode(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="that"></param>
+    /// <returns></returns>
+    [Tested]
+    public override bool UnsequencedEquals(ICollection<T> that)
+    { validitycheck(); return base.UnsequencedEquals(that); }
+
+    /// <summary>
+    /// Check if this collection contains (an item equivalent to according to the
+    /// itemequalityComparer) a particular value.
+    /// </summary>
+    /// <param name="item">The value to check for.</param>
+    /// <returns>True if the items is in this collection.</returns>
+    [Tested]
+    public virtual bool Contains(T item)
+    {
+      validitycheck();
+      Node node;
+      return contains(item, out node);
+    }
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, return in the ref argument (a
+    /// binary copy of) the actual value found.
+    /// </summary>
+    /// <param name="item">The value to look for.</param>
+    /// <returns>True if the items is in this collection.</returns>
+    [Tested]
+    public virtual bool Find(ref T item)
+    {
+      validitycheck();
+      Node node;
+      if (contains(item, out node)) { item = node.item; return true; }
+      return false;
+    }
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// to with a binary copy of the supplied value. Will update a single item.
+    /// </summary>
+    /// <param name="item">Value to update.</param>
+    /// <returns>True if the item was found and hence updated.</returns>
+    [Tested]
+    public virtual bool Update(T item) { T olditem; return Update(item, out olditem); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public virtual bool Update(T item, out T olditem)
+    {
+      updatecheck();
+      Node node;
+
+      if (contains(item, out node))
+      {
+        olditem = node.item;
+        node.item = item;
+#if HASHINDEX
+        //Avoid clinging onto a reference to olditem via dict!
+        dict.Update(item, node);
+#endif
+        (underlying ?? this).raiseForUpdate(item, olditem);
+        return true;
+      }
+
+      olditem = default(T);
+      return false;
+    }
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, return in the ref argument (a
+    /// binary copy of) the actual value found. Else, add the item to the collection.
+    /// </summary>
+    /// <param name="item">The value to look for.</param>
+    /// <returns>True if the item was found (hence not added).</returns>
+    [Tested]
+    public virtual bool FindOrAdd(ref T item)
+    {
+      updatecheck();
+#if HASHINDEX
+      //This is an extended myinsert:
+      Node node = new Node(item);
+      if (!dict.FindOrAdd(item, ref node))
+      {
+        insertNode(true, endsentinel, node);
+        (underlying ?? this).raiseForAdd(item);
+        return false;
+      }
+      if (!insideview(node))
+        throw new ArgumentException("Item alredy in indexed list but outside view");
+      item = node.item;
+      return true;
+#else
+      if (Find(ref item))
+        return true;
+
+      Add(item);
+      return false;
+#endif
+    }
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// to with a binary copy of the supplied value; else add the value to the collection. 
+    /// </summary>
+    /// <param name="item">Value to add or update.</param>
+    /// <returns>True if the item was found and updated (hence not added).</returns>
+    [Tested]
+    public virtual bool UpdateOrAdd(T item) { T olditem; return UpdateOrAdd(item, out olditem); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public virtual bool UpdateOrAdd(T item, out T olditem)
+    {
+      updatecheck();
+#if HASHINDEX
+      Node node = new Node(item);
+      //NOTE: it is hard to do this without double access to the dictionary
+      //in the update case
+      if (dict.FindOrAdd(item, ref node))
+      {
+        if (!insideview(node))
+          throw new ArgumentException("Item in indexed list but outside view");
+        olditem = node.item;
+        //Avoid clinging onto a reference to olditem via dict!
+        dict.Update(item, node);
+        node.item = item;
+        (underlying ?? this).raiseForUpdate(item, olditem);
+        return true;
+      }
+      insertNode(true, endsentinel, node);
+      (underlying ?? this).raiseForAdd(item);
+#else
+      if (Update(item, out olditem))
+        return true;
+      Add(item);
+#endif
+      olditem = default(T);
+      return false;
+    }
+
+    /// <summary>
+    /// Remove a particular item from this collection. Since the collection has bag
+    /// semantics only one copy equivalent to the supplied item is removed. 
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    /// <returns>True if the item was found (and removed).</returns>
+    [Tested]
+    public virtual bool Remove(T item)
+    {
+      updatecheck();
+      int i = 0;
+      Node node;
+#if HASHINDEX
+      if (!dictremove(item, out node))
+#else
+      node = fIFO ? startsentinel.next : endsentinel.prev;
+      if (!(fIFO ? find(item, ref node, ref i) : dnif(item, ref node, ref i)))
+#endif
+        return false;
+      T removeditem = remove(node, i);
+      (underlying ?? this).raiseForRemove(removeditem);
+      return true;
+    }
+
+    /// <summary>
+    /// Remove a particular item from this collection if found (only one copy). 
+    /// If an item was removed, report a binary copy of the actual item removed in 
+    /// the argument.
+    /// </summary>
+    /// <param name="item">The value to remove on input.</param>
+    /// <param name="removeditem">The value removed.</param>
+    /// <returns>True if the item was found (and removed).</returns>
+    [Tested]
+    public virtual bool Remove(T item, out T removeditem)
+    {
+      updatecheck();
+      int i = 0;
+      Node node;
+#if HASHINDEX
+      if (!dictremove(item, out node))
+#else
+      node = fIFO ? startsentinel.next : endsentinel.prev;
+      if (!(fIFO ? find(item, ref node, ref i) : dnif(item, ref node, ref i)))
+#endif
+      {
+        removeditem = default(T);
+        return false;
+      }
+      removeditem = node.item;
+      remove(node, i);
+      (underlying ?? this).raiseForRemove(removeditem);
+      return true;
+    }
+
+    /// <summary>
+    /// Remove all items in another collection from this one, taking multiplicities into account.
+    /// <para>Always removes from the front of the list.
+    /// </para>
+    /// <para>The asymptotic running time complexity of this method is <code>O(n+m+v*log(v))</code>, 
+    /// where <code>n</code> is the size of this list, <code>m</code> is the size of the
+    /// <code>items</code> collection and <code>v</code> is the number of views. 
+    /// The method will temporarily allocate memory of size <code>O(m+v)</code>.
+    /// </para>
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to remove.</param>
+    [Tested]
+    public virtual void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+#if HASHINDEX
+      Node node;
+      foreach (T item in items)
+        if (dictremove(item, out node))
+        {
+          if (mustFire)
+            raiseHandler.Remove(node.item);
+          remove(node, 118);
+        }
+#else
+      HashBag<T> toremove = new HashBag<T>(itemequalityComparer);
+      toremove.AddAll(items);
+      ViewHandler viewHandler = new ViewHandler(this);
+      int index = 0, removed = 0, myoffset = Offset;
+      Node node = startsentinel.next;
+      while (node != endsentinel)
+      {
+        //pass by a stretch of nodes
+        while (node != endsentinel && !toremove.Contains(node.item))
+        {
+          node = node.next;
+          index++;
+        }
+        viewHandler.skipEndpoints(removed, myoffset + index);
+        //Remove a stretch of nodes
+        Node localend = node.prev; //Latest node not to be removed
+        while (node != endsentinel && toremove.Remove(node.item))
+        {
+          if (mustFire)
+            raiseHandler.Remove(node.item);
+          removed++;
+          node = node.next;
+          index++;
+          viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+        }
+        viewHandler.updateSentinels(myoffset + index, localend, node);
+        localend.next = node;
+        node.prev = localend;
+      }
+      index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset;
+      viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+      size -= removed;
+      if (underlying != null)
+        underlying.size -= removed;
+#endif
+      raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="predicate"></param>
+    void RemoveAll(Fun<T, bool> predicate)
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+#if HASHINDEX
+      {
+        Node n = startsentinel.next;
+
+        while (n != endsentinel)
+        {
+          bool removeIt = predicate(n.item);
+          updatecheck();
+          if (removeIt)
+          {
+            dict.Remove(n.item);
+            remove(n, 119);
+            if (mustFire)
+              raiseHandler.Remove(n.item);
+          }
+
+          n = n.next;
+        }
+      }
+#else
+      ViewHandler viewHandler = new ViewHandler(this);
+      int index = 0, removed = 0, myoffset = Offset;
+      Node node = startsentinel.next;
+      while (node != endsentinel)
+      {
+        //pass by a stretch of nodes
+        while (node != endsentinel && !predicate(node.item))
+        {
+          updatecheck();
+          node = node.next;
+          index++;
+        }
+        updatecheck();
+        viewHandler.skipEndpoints(removed, myoffset + index);
+        //Remove a stretch of nodes
+        Node localend = node.prev; //Latest node not to be removed
+        while (node != endsentinel && predicate(node.item))
+        {
+          updatecheck();
+          if (mustFire)
+            raiseHandler.Remove(node.item);
+          removed++;
+          node = node.next;
+          index++;
+          viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+        }
+        updatecheck();
+        viewHandler.updateSentinels(myoffset + index, localend, node);
+        localend.next = node;
+        node.prev = localend;
+      }
+      index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset;
+      viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+      size -= removed;
+      if (underlying != null)
+        underlying.size -= removed;
+#endif
+      raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// Remove all items from this collection.
+    /// </summary>
+    [Tested]
+    public virtual void Clear()
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      int oldsize = size;
+#if HASHINDEX
+      if (underlying == null)
+        dict.Clear();
+      else
+        foreach (T item in this)
+          dict.Remove(item);
+#endif
+      clear();
+      (underlying ?? this).raiseForRemoveInterval(Offset, oldsize);
+    }
+
+    void clear()
+    {
+      if (size == 0)
+        return;
+#if HASHINDEX
+      //TODO: mix with tag maintenance to only run through list once?
+      ViewHandler viewHandler = new ViewHandler(this);
+      if (viewHandler.viewCount > 0)
+      {
+        int removed = 0;
+        Node n = startsentinel.next;
+        viewHandler.skipEndpoints(0, n);
+        while (n != endsentinel)
+        {
+          removed++;
+          n = n.next;
+          viewHandler.updateViewSizesAndCounts(removed, n);
+        }
+        viewHandler.updateSentinels(endsentinel, startsentinel, endsentinel);
+        if (underlying != null)
+          viewHandler.updateViewSizesAndCounts(removed, underlying.endsentinel);
+      }
+#else
+      fixViewsBeforeRemove(Offset, size, startsentinel.next, endsentinel.prev);
+#endif
+#if HASHINDEX
+      if (underlying != null)
+      {
+        Node n = startsentinel.next;
+
+        while (n != endsentinel)
+        {
+          n.next.prev = startsentinel;
+          startsentinel.next = n.next;
+          removefromtaggroup(n);
+          n = n.next;
+        }
+      }
+      else
+        taggroups = 0;
+#endif
+      endsentinel.prev = startsentinel;
+      startsentinel.next = endsentinel;
+      if (underlying != null)
+        underlying.size -= size;
+      size = 0;
+    }
+
+    /// <summary>
+    /// Remove all items not in some other collection from this one, taking multiplicities into account.
+    /// <para>The asymptotic running time complexity of this method is <code>O(n+m+v*log(v))</code>, 
+    /// where <code>n</code> is the size of this collection, <code>m</code> is the size of the
+    /// <code>items</code> collection and <code>v</code> is the number of views. 
+    /// The method will temporarily allocate memory of size <code>O(m+v)</code>. The stated complexitiy 
+    /// holds under the assumption that the itemequalityComparer of this list is well-behaved.
+    /// </para>
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to retain.</param>
+    [Tested]
+    public virtual void RetainAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+#if HASHINDEX
+      /*if (underlying == null)
+      {
+        HashDictionary<T, Node> newdict = new HashDictionary<T, Node>(itemequalityComparer);
+        foreach (T item in items)
+        {
+          Node node;
+
+          if (dict.Remove(item, out node))
+            newdict.Add(item, node);
+        }
+        foreach (KeyValuePair<T, Node> pair in dict)
+        {
+          Node n = pair.Value;
+          fixViewsBeforeSingleRemove(n, 117);
+          Node p = n.prev, s = n.next; s.prev = p; p.next = s;
+          removefromtaggroup(n);
+        }
+        dict = newdict;
+        size = dict.Count;
+        //For a small number of items to retain it might be faster to 
+        //iterate through the list and splice out the chunks not needed
+      }
+      else*/
+      {
+        HashSet<T> toremove = new HashSet<T>(itemequalityComparer);
+
+        foreach (T item in this)
+          toremove.Add(item);
+
+        foreach (T item in items)
+          toremove.Remove(item);
+
+        Node n = startsentinel.next;
+
+        while (n != endsentinel && toremove.Count > 0)
+        {
+          if (toremove.Contains(n.item))
+          {
+            dict.Remove(n.item);
+            remove(n, 119);
+            if (mustFire)
+              raiseHandler.Remove(n.item);
+          }
+
+          n = n.next;
+        }
+      }
+#else
+      HashBag<T> toretain = new HashBag<T>(itemequalityComparer);
+      toretain.AddAll(items);
+      ViewHandler viewHandler = new ViewHandler(this);
+      int index = 0, removed = 0, myoffset = Offset;
+      Node node = startsentinel.next;
+      while (node != endsentinel)
+      {
+        //Skip a stretch of nodes
+        while (node != endsentinel && toretain.Remove(node.item))
+        {
+          node = node.next;
+          index++;
+        }
+        viewHandler.skipEndpoints(removed, myoffset + index);
+        //Remove a stretch of nodes
+        Node localend = node.prev; //Latest node not to be removed
+        while (node != endsentinel && !toretain.Contains(node.item))
+        {
+          if (mustFire)
+            raiseHandler.Remove(node.item);
+          removed++;
+          node = node.next;
+          index++;
+          viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+        }
+        viewHandler.updateSentinels(myoffset + index, localend, node);
+        localend.next = node;
+        node.prev = localend;
+      }
+      index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset;
+      viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+      size -= removed;
+      if (underlying != null)
+        underlying.size -= removed;
+#endif
+      raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="predicate"></param>
+    void RetainAll(Fun<T, bool> predicate)
+    {
+      updatecheck();
+      if (size == 0)
+        return;
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+#if HASHINDEX
+      {
+        Node n = startsentinel.next;
+
+        while (n != endsentinel)
+        {
+          bool removeIt = !predicate(n.item);
+          updatecheck();
+          if (removeIt)
+          {
+            dict.Remove(n.item);
+            remove(n, 119);
+            if (mustFire)
+              raiseHandler.Remove(n.item);
+          }
+
+          n = n.next;
+        }
+      }
+#else
+      ViewHandler viewHandler = new ViewHandler(this);
+      int index = 0, removed = 0, myoffset = Offset;
+      Node node = startsentinel.next;
+      while (node != endsentinel)
+      {
+        //Skip a stretch of nodes
+        while (node != endsentinel && predicate(node.item))
+        {
+          updatecheck();
+          node = node.next;
+          index++;
+        }
+        updatecheck();
+        viewHandler.skipEndpoints(removed, myoffset + index);
+        //Remove a stretch of nodes
+        Node localend = node.prev; //Latest node not to be removed
+        while (node != endsentinel && !predicate(node.item))
+        {
+          updatecheck();
+          if (mustFire)
+            raiseHandler.Remove(node.item);
+          removed++;
+          node = node.next;
+          index++;
+          viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+        }
+        updatecheck();
+        viewHandler.updateSentinels(myoffset + index, localend, node);
+        localend.next = node;
+        node.prev = localend;
+      }
+      index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset;
+      viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+      size -= removed;
+      if (underlying != null)
+        underlying.size -= removed;
+#endif
+      raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// Check if this collection contains all the values in another collection
+    /// with respect to multiplicities.
+    /// </summary>
+    /// <param name="items">The </param>
+    /// <typeparam name="U"></typeparam>
+    /// <returns>True if all values in <code>items</code>is in this collection.</returns>
+    [Tested]
+    public virtual bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      validitycheck();
+#if HASHINDEX
+      Node node;
+      foreach (T item in items)
+        if (!contains(item, out node))
+          return false;
+      return true;
+#else
+      HashBag<T> tocheck = new HashBag<T>(itemequalityComparer);
+      tocheck.AddAll(items);
+      if (tocheck.Count > size)
+        return false;
+      Node node = startsentinel.next;
+      while (node != endsentinel)
+      {
+        tocheck.Remove(node.item);
+        node = node.next;
+      }
+      return tocheck.IsEmpty;
+#endif
+    }
+
+
+    /// <summary>
+    /// Create a new list consisting of the items of this list satisfying a 
+    /// certain predicate.
+    /// </summary>
+    /// <param name="filter">The filter delegate defining the predicate.</param>
+    /// <returns>The new list.</returns>
+    [Tested]
+    public IList<T> FindAll(Fun<T, bool> filter)
+    {
+      validitycheck();
+      int stamp = this.stamp;
+      LinkedList<T> retval = new LinkedList<T>();
+      Node cursor = startsentinel.next;
+      Node mcursor = retval.startsentinel;
+#if HASHINDEX
+      double tagdelta = int.MaxValue / (size + 1.0);
+      int count = 1;
+      TagGroup taggroup = new TagGroup();
+      retval.taggroups = 1;
+#endif
+      while (cursor != endsentinel)
+      {
+        bool found = filter(cursor.item);
+        modifycheck(stamp);
+        if (found)
+        {
+          mcursor.next = new Node(cursor.item, mcursor, null);
+          mcursor = mcursor.next;
+          retval.size++;
+#if HASHINDEX
+          retval.dict.Add(cursor.item, mcursor);
+          mcursor.taggroup = taggroup;
+          mcursor.tag = (int)(tagdelta * count++);
+#endif
+        }
+        cursor = cursor.next;
+      }
+#if HASHINDEX
+      if (retval.size > 0)
+      {
+        taggroup.count = retval.size;
+        taggroup.first = retval.startsentinel.next;
+        taggroup.last = mcursor;
+      }
+#endif
+      retval.endsentinel.prev = mcursor;
+      mcursor.next = retval.endsentinel;
+      return retval;
+    }
+
+
+    /// <summary>
+    /// Count the number of items of the collection equal to a particular value.
+    /// Returns 0 if and only if the value is not in the collection.
+    /// </summary>
+    /// <param name="item">The value to count.</param>
+    /// <returns>The number of copies found.</returns>
+    [Tested]
+    public virtual int ContainsCount(T item)
+    {
+#if HASHINDEX
+      return Contains(item) ? 1 : 0;
+#else
+      validitycheck();
+      int retval = 0;
+      Node node = startsentinel.next;
+      while (node != endsentinel)
+      {
+        if (itemequalityComparer.Equals(node.item, item))
+          retval++;
+        node = node.next;
+      }
+      return retval;
+#endif
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<T> UniqueItems()
+    {
+#if HASHINDEX
+      return this;
+#else
+      HashBag<T> hashbag = new HashBag<T>(itemequalityComparer);
+      hashbag.AddAll(this);
+      return hashbag.UniqueItems();
+#endif
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities()
+    {
+#if HASHINDEX
+      return new MultiplicityOne<T>(this);
+#else
+      HashBag<T> hashbag = new HashBag<T>(itemequalityComparer);
+      hashbag.AddAll(this);
+      return hashbag.ItemMultiplicities();
+#endif
+    }
+
+    /// <summary>
+    /// Remove all items equivalent to a given value.
+    /// <para>The asymptotic complexity of this method is <code>O(n+v*log(v))</code>, 
+    /// where <code>n</code> is the size of the collection and <code>v</code> 
+    /// is the number of views.
+    /// </para>
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    [Tested]
+    public virtual void RemoveAllCopies(T item)
+    {
+#if HASHINDEX
+      Remove(item);
+#else
+      updatecheck();
+      if (size == 0)
+        return;
+      RaiseForRemoveAllHandler raiseHandler = new RaiseForRemoveAllHandler(underlying ?? this);
+      bool mustFire = raiseHandler.MustFire;
+      ViewHandler viewHandler = new ViewHandler(this);
+      int index = 0, removed = 0, myoffset = Offset;
+      //
+      Node node = startsentinel.next;
+      while (node != endsentinel)
+      {
+        //pass by a stretch of nodes
+        while (node != endsentinel && !itemequalityComparer.Equals(node.item, item))
+        {
+          node = node.next;
+          index++;
+        }
+        viewHandler.skipEndpoints(removed, myoffset + index);
+        //Remove a stretch of nodes
+        Node localend = node.prev; //Latest node not to be removed
+        while (node != endsentinel && itemequalityComparer.Equals(node.item, item))
+        {
+          if (mustFire)
+            raiseHandler.Remove(node.item);
+          removed++;
+          node = node.next;
+          index++;
+          viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+        }
+        viewHandler.updateSentinels(myoffset + index, localend, node);
+        localend.next = node;
+        node.prev = localend;
+      }
+      index = underlying != null ? underlying.size + 1 - myoffset : size + 1 - myoffset;
+      viewHandler.updateViewSizesAndCounts(removed, myoffset + index);
+      size -= removed;
+      if (underlying != null)
+        underlying.size -= removed;
+      raiseHandler.Raise();
+#endif
+    }
+
+    #endregion
+
+    #region ICollectionValue<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>The number of items in this collection</value>
+    [Tested]
+    public override int Count { [Tested]get { validitycheck(); return size; } }
+
+    /// <summary>
+    /// Choose some item of this collection. 
+    /// </summary>
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>
+    /// <returns></returns>
+    [Tested]
+    public override T Choose() { return First; }
+
+    /// <summary>
+    /// Create an enumerable, enumerating the items of this collection that satisfies 
+    /// a certain condition.
+    /// </summary>
+    /// <param name="filter">The T->bool filter delegate defining the condition</param>
+    /// <returns>The filtered enumerable</returns>
+    public override SCG.IEnumerable<T> Filter(Fun<T, bool> filter) { validitycheck(); return base.Filter(filter); }
+
+    #endregion
+
+    #region IEnumerable<T> Members
+    /// <summary>
+    /// Create an enumerator for the collection
+    /// </summary>
+    /// <returns>The enumerator</returns>
+    [Tested]
+    public override SCG.IEnumerator<T> GetEnumerator()
+    {
+      validitycheck();
+      Node cursor = startsentinel.next;
+      int enumeratorstamp = underlying != null ? underlying.stamp : this.stamp;
+
+      while (cursor != endsentinel)
+      {
+        modifycheck(enumeratorstamp);
+        yield return cursor.item;
+        cursor = cursor.next;
+      }
+    }
+
+    #endregion
+
+    #region IExtensible<T> Members
+    /// <summary>
+    /// Add an item to this collection if possible. 
+    /// </summary>
+    /// <param name="item">The item to add.</param>
+    /// <returns>True.</returns>
+    [Tested]
+    public virtual bool Add(T item)
+    {
+      updatecheck();
+#if HASHINDEX
+      Node node = new Node(item);
+      if (!dict.FindOrAdd(item, ref node))
+      {
+        insertNode(true, endsentinel, node);
+        (underlying ?? this).raiseForAdd(item);
+        return true;
+      }
+      return false;
+#else
+      insert(size, endsentinel, item);
+      (underlying ?? this).raiseForAdd(item);
+      return true;
+#endif
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>True since this collection has bag semantics.</value>
+    [Tested]
+    public virtual bool AllowsDuplicates
+    {
+      [Tested]
+      get
+      {
+#if HASHINDEX
+        return false;
+#else
+        return true;
+#endif
+      }
+    }
+
+    /// <summary>
+    /// By convention this is true for any collection with set semantics.
+    /// </summary>
+    /// <value>True if only one representative of a group of equal items 
+    /// is kept in the collection together with the total count.</value>
+    public virtual bool DuplicatesByCounting
+    {
+      get
+      {
+#if HASHINDEX
+        return true;
+#else
+        return false;
+#endif
+      }
+    }
+
+    /// <summary>
+    /// Add the elements from another collection with a more specialized item type 
+    /// to this collection. 
+    /// </summary>
+    /// <typeparam name="U">The type of items to add</typeparam>
+    /// <param name="items">The items to add</param>
+    [Tested]
+    public virtual void AddAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+#if HASHINDEX
+      updatecheck();
+      int added = 0;
+      Node pred = endsentinel.prev;
+      foreach (U item in items)
+      {
+        Node node = new Node(item);
+        if (!dict.FindOrAdd(item, ref node))
+        {
+          insertNode(false, endsentinel, node);
+          added++;
+        }
+      }
+      if (added > 0)
+      {
+        fixViewsAfterInsert(endsentinel, pred, added, 0);
+        raiseForInsertAll(pred, size - added, added, false);
+      }
+#else
+      insertAll(size, items, false);
+#endif
+    }
+
+    #endregion
+
+#if HASHINDEX
+#else
+    #region IStack<T> Members
+
+    /// <summary>
+    /// Push an item to the top of the stack.
+    /// </summary>
+    /// <param name="item">The item</param>
+    [Tested]
+    public void Push(T item)
+    {
+      InsertLast(item);
+    }
+
+    /// <summary>
+    /// Pop the item at the top of the stack from the stack.
+    /// </summary>
+    /// <returns>The popped item.</returns>
+    [Tested]
+    public T Pop()
+    {
+      return RemoveLast();
+    }
+
+    #endregion
+
+    #region IQueue<T> Members
+
+    /// <summary>
+    /// Enqueue an item at the back of the queue. 
+    /// </summary>
+    /// <param name="item">The item</param>
+    [Tested]
+    public virtual void Enqueue(T item)
+    {
+      InsertLast(item);
+    }
+
+    /// <summary>
+    /// Dequeue an item from the front of the queue.
+    /// </summary>
+    /// <returns>The item</returns>
+    [Tested]
+    public virtual T Dequeue()
+    {
+      return RemoveFirst();
+    }
+    #endregion
+#endif
+
+    #region Diagnostic
+
+    private bool checkViews()
+    {
+      if (underlying != null)
+        throw new InternalException(System.Reflection.MethodInfo.GetCurrentMethod() + " called on a view");
+      if (views == null)
+        return true;
+      bool retval = true;
+
+      Node[] nodes = new Node[size + 2];
+      int i = 0;
+      Node n = startsentinel;
+      while (n != null)
+      {
+        nodes[i++] = n;
+        n = n.next;
+      }
+      //Console.WriteLine("###");
+      foreach (LinkedList<T> view in views)
+      {
+        if (!view.isValid)
+        {
+          Console.WriteLine("Invalid view(hash {0}, offset {1}, size {2})",
+            view.GetHashCode(), view.offset, view.size);
+          retval = false;
+          continue;
+        }
+        if (view.Offset > size || view.Offset < 0)
+        {
+          Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), Offset > underlying.size ({2})",
+            view.GetHashCode(), view.offset, view.size, size);
+          retval = false;
+        }
+        else if (view.startsentinel != nodes[view.Offset])
+        {
+          Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), startsentinel {3} should be {4}",
+            view.GetHashCode(), view.offset, view.size,
+            view.startsentinel + " " + view.startsentinel.GetHashCode(),
+            nodes[view.Offset] + " " + nodes[view.Offset].GetHashCode());
+          retval = false;
+        }
+        if (view.Offset + view.size > size || view.Offset + view.size < 0)
+        {
+          Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), end index > underlying.size ({3})",
+            view.GetHashCode(), view.offset, view.size, size);
+          retval = false;
+        }
+        else if (view.endsentinel != nodes[view.Offset + view.size + 1])
+        {
+          Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), endsentinel {3} should be {4}",
+            view.GetHashCode(), view.offset, view.size,
+            view.endsentinel + " " + view.endsentinel.GetHashCode(),
+            nodes[view.Offset + view.size + 1] + " " + nodes[view.Offset + view.size + 1].GetHashCode());
+          retval = false;
+        }
+        if (view.views != views)
+        {
+          Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), wrong views list {3} <> {4}",
+            view.GetHashCode(), view.offset, view.size, view.views.GetHashCode(), views.GetHashCode());
+          retval = false;
+        }
+        if (view.underlying != this)
+        {
+          Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), wrong underlying {3} <> this {4}",
+            view.GetHashCode(), view.offset, view.size, view.underlying.GetHashCode(), GetHashCode());
+          retval = false;
+        }
+        if (view.stamp != stamp)
+        {
+          //Console.WriteLine("Bad view(hash {0}, offset {1}, size {2}), wrong stamp view:{2} underlying: {3}", view.GetHashCode(),view.offset, view.size, view.stamp, stamp);
+          //retval = false;
+        }
+      }
+      return retval;
+    }
+
+    string zeitem(Node node)
+    {
+      return node == null ? "(null node)" : node.item.ToString();
+    }
+
+    /// <summary>
+    /// Check the sanity of this list
+    /// </summary>
+    /// <returns>true if sane</returns>
+    [Tested]
+    public virtual bool Check()
+    {
+      bool retval = true;
+
+      /*if (underlying != null && underlying.stamp != stamp)
+      {
+        Console.WriteLine("underlying != null && underlying.stamp({0}) != stamp({1})", underlying.stamp, stamp);
+        retval = false;
+      }*/
+
+      if (underlying != null)
+      {
+        //TODO: check that this view is included in viewsEndpoints tree
+        return underlying.Check();
+      }
+
+      if (startsentinel == null)
+      {
+        Console.WriteLine("startsentinel == null");
+        retval = false;
+      }
+
+      if (endsentinel == null)
+      {
+        Console.WriteLine("endsentinel == null");
+        retval = false;
+      }
+
+      if (size == 0)
+      {
+        if (startsentinel != null && startsentinel.next != endsentinel)
+        {
+          Console.WriteLine("size == 0 but startsentinel.next != endsentinel");
+          retval = false;
+        }
+
+        if (endsentinel != null && endsentinel.prev != startsentinel)
+        {
+          Console.WriteLine("size == 0 but endsentinel.prev != startsentinel");
+          retval = false;
+        }
+      }
+
+      if (startsentinel == null)
+      {
+        Console.WriteLine("NULL startsentinel");
+        return retval;
+      }
+
+      int count = 0;
+      Node node = startsentinel.next, prev = startsentinel;
+#if HASHINDEX
+      int taggroupsize = 0, oldtaggroupsize = losize + 1, seentaggroups = 0;
+      TagGroup oldtg = null;
+
+      if (underlying == null)
+      {
+        TagGroup tg = startsentinel.taggroup;
+
+        if (tg.count != 0 || tg.first != null || tg.last != null || tg.tag != int.MinValue)
+        {
+          Console.WriteLine("Bad startsentinel tag group: {0}", tg);
+          retval = false;
+        }
+
+        tg = endsentinel.taggroup;
+        if (tg.count != 0 || tg.first != null || tg.last != null || tg.tag != int.MaxValue)
+        {
+          Console.WriteLine("Bad endsentinel tag group: {0}", tg);
+          retval = false;
+        }
+      }
+#endif
+      while (node != endsentinel)
+      {
+        count++;
+        if (node.prev != prev)
+        {
+          Console.WriteLine("Bad backpointer at node {0}", count);
+          retval = false;
+        }
+#if HASHINDEX
+        if (underlying == null)
+        {
+          if (!node.prev.precedes(node))
+          {
+            Console.WriteLine("node.prev.tag ({0}, {1}) >= node.tag ({2}, {3}) at index={4} item={5} ", node.prev.taggroup.tag, node.prev.tag, node.taggroup.tag, node.tag, count, node.item);
+            retval = false;
+          }
+
+          if (node.taggroup != oldtg)
+          {
+
+            if (node.taggroup.first != node)
+            {
+              string ntfi = zeitem(node.taggroup.first);
+              Console.WriteLine("Bad first pointer in taggroup: node.taggroup.first.item ({0}), node.item ({1}) at index={2} item={3}", ntfi, node.item, count, node.item);
+              retval = false;
+            }
+
+            if (oldtg != null)
+            {
+              if (oldtg.count != taggroupsize)
+              {
+                Console.WriteLine("Bad taggroupsize: oldtg.count ({0}) != taggroupsize ({1}) at index={2} item={3}", oldtg.count, taggroupsize, count, node.item);
+                retval = false;
+              }
+
+              if (oldtaggroupsize <= losize && taggroupsize <= losize)
+              {
+                Console.WriteLine("Two small taggroups in a row: oldtaggroupsize ({0}), taggroupsize ({1}) at index={2} item={3}", oldtaggroupsize, taggroupsize, count, node.item);
+                retval = false;
+              }
+
+              if (node.taggroup.tag <= oldtg.tag)
+              {
+                Console.WriteLine("Taggroup tags not strictly increasing: oldtaggrouptag ({0}), taggrouptag ({1}) at index={2} item={3}", oldtg.tag, node.taggroup.tag, count, node.item);
+                retval = false;
+              }
+
+              if (oldtg.last != node.prev)
+              {
+                Console.WriteLine("Bad last pointer in taggroup: oldtg.last.item ({0}), node.prev.item ({1}) at index={2} item={3}", oldtg.last.item, node.prev.item, count, node.item);
+                retval = false;
+              }
+
+              oldtaggroupsize = taggroupsize;
+            }
+
+            seentaggroups++;
+            oldtg = node.taggroup;
+            taggroupsize = 1;
+          }
+          else
+          {
+            taggroupsize++;
+          }
+        }
+
+#endif
+        prev = node;
+        node = node.next;
+        if (node == null)
+        {
+          Console.WriteLine("Null next pointer at node {0}", count);
+          return false;
+        }
+      }
+
+#if HASHINDEX
+      if (underlying == null && size == 0 && taggroups != 0)
+      {
+        Console.WriteLine("Bad taggroups for empty list: size={0}   taggroups={1}", size, taggroups);
+        retval = false;
+      }
+      if (underlying == null && size > 0)
+      {
+        oldtg = node.prev.taggroup;
+        if (oldtg != null)
+        {
+          if (oldtg.count != taggroupsize)
+          {
+            Console.WriteLine("Bad taggroupsize: oldtg.count ({0}) != taggroupsize ({1}) at index={2} item={3}", oldtg.count, taggroupsize, count, node.item);
+            retval = false;
+          }
+
+          if (oldtaggroupsize <= losize && taggroupsize <= losize)
+          {
+            Console.WriteLine("Two small taggroups in a row: oldtaggroupsize ({0}), taggroupsize ({1}) at index={2} item={3}", oldtaggroupsize, taggroupsize, count, node.item);
+            retval = false;
+          }
+
+              if (node.taggroup.tag <= oldtg.tag)
+              {
+                Console.WriteLine("Taggroup tags not strictly increasing: oldtaggrouptag ({0}), taggrouptag ({1}) at index={2} item={3}", oldtg.tag, node.taggroup.tag, count, node.item);
+                retval = false;
+              }
+
+              if (oldtg.last != node.prev)
+              {
+                Console.WriteLine("Bad last pointer in taggroup: oldtg.last.item ({0}), node.prev.item ({1}) at index={2} item={3}", zeitem(oldtg.last), zeitem(node.prev), count, node.item);
+                retval = false;
+              }
+        }
+
+        if (seentaggroups != taggroups)
+        {
+          Console.WriteLine("seentaggroups ({0}) != taggroups ({1}) (at size {2})", seentaggroups, taggroups, size);
+          retval = false;
+        }
+      }
+#endif
+      if (count != size)
+      {
+        Console.WriteLine("size={0} but enumeration gives {1} nodes ", size, count);
+        retval = false;
+      }
+
+      retval = checkViews() && retval;
+
+#if HASHINDEX
+      if (!retval)
+        return false;
+      if (underlying == null)
+      {
+        if (size != dict.Count)
+        {
+          Console.WriteLine("list.size ({0}) != dict.Count ({1})", size, dict.Count);
+          retval = false;
+        }
+        Node n = startsentinel.next, n2;
+        while (n != endsentinel)
+        {
+          if (!dict.Find(n.item, out n2))
+          {
+            Console.WriteLine("Item in list but not dict: {0}", n.item);
+            retval = false;
+          }
+          else if (n != n2)
+          {
+            Console.WriteLine("Wrong node in dict for item: {0}", n.item);
+            retval = false;
+          }
+          n = n.next;
+        }
+      }
+#endif
+      return retval;
+    }
+    #endregion
+
+    #region ICloneable Members
+
+    /// <summary>
+    /// Make a shallow copy of this LinkedList.
+    /// </summary>
+    /// <returns></returns>
+    public virtual object Clone()
+    {
+      LinkedList<T> clone = new LinkedList<T>(itemequalityComparer);
+      clone.AddAll(this);
+      return clone;
+    }
+
+    #endregion
+
+    #region System.Collections.Generic.IList<T> Members
+
+    void System.Collections.Generic.IList<T>.RemoveAt(int index)
+    {
+      RemoveAt(index);
+    }
+
+    void System.Collections.Generic.ICollection<T>.Add(T item)
+    {
+      Add(item);
+    }
+
+    #endregion
+
+    #region System.Collections.ICollection Members
+
+    bool System.Collections.ICollection.IsSynchronized
+    {
+      get { return false; }
+    }
+
+    [Obsolete]
+    Object System.Collections.ICollection.SyncRoot
+    {
+      // Presumably safe to use the startsentinel (of type Node, always != null) as SyncRoot
+      // since the class Node is private.
+      get { return underlying != null ? ((System.Collections.ICollection)underlying).SyncRoot : startsentinel; }
+    }
+
+    void System.Collections.ICollection.CopyTo(Array arr, int index)
+    {
+      if (index < 0 || index + Count > arr.Length)
+        throw new ArgumentOutOfRangeException();
+
+      foreach (T item in this)
+        arr.SetValue(item, index++);
+    }
+
+    #endregion
+  
+    #region System.Collections.IList Members
+
+    Object System.Collections.IList.this[int index] 
+    {
+      get { return this[index]; }
+      set { this[index] = (T)value; }
+    }
+
+    int System.Collections.IList.Add(Object o)
+    {
+      bool added = Add((T)o);
+      // What position to report if item not added? SC.IList.Add doesn't say
+      return added ? Count-1 : -1; 
+    }
+
+    bool System.Collections.IList.Contains(Object o)
+    {
+      return Contains((T)o);
+    }
+
+    int System.Collections.IList.IndexOf(Object o)
+    {
+      return Math.Max(-1, IndexOf((T)o));
+    }
+
+    void System.Collections.IList.Insert(int index, Object o)
+    {
+      Insert(index, (T)o);
+    }
+
+    void System.Collections.IList.Remove(Object o)
+    {
+      Remove((T)o);
+    }
+
+    void System.Collections.IList.RemoveAt(int index)
+    {
+      RemoveAt(index);
+    }
+
+    #endregion
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/trees/RedBlackTreeBag.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/trees/RedBlackTreeBag.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/trees/RedBlackTreeBag.cs	(revision 3)
@@ -0,0 +1,4595 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+#define MAINTAIN_SIZE
+#define BAG
+#define NCP
+
+#if BAG
+#if !MAINTAIN_SIZE
+#error  BAG defined without MAINTAIN_SIZE!
+#endif
+#endif
+
+
+using System;
+using SCG = System.Collections.Generic;
+
+// NOTE NOTE NOTE NOTE
+// This source file is used to produce both TreeBag<T> and TreeBag<T>
+// It should be copied to a file called TreeBag.cs in which all code mentions of 
+// TreeBag is changed to TreeBag and the preprocessor symbol BAG is defined.
+// NOTE: there may be problems with documentation comments.
+
+namespace C5
+{
+#if BAG
+  /// <summary>
+  /// An implementation of Red-Black trees as an indexed, sorted collection with bag semantics,
+  /// cf. <a href="litterature.htm#CLRS">CLRS</a>. (<see cref="T:C5.TreeBag`1"/> for an 
+  /// implementation with set semantics).
+  /// <br/>
+  /// The comparer (sorting order) may be either natural, because the item type is comparable 
+  /// (generic: <see cref="T:C5.IComparable`1"/> or non-generic: System.IComparable) or it can
+  /// be external and supplied by the user in the constructor.
+  /// <br/>
+  /// Each distinct item is only kept in one place in the tree - together with the number
+  /// of times it is a member of the bag. Thus, if two items that are equal according
+  /// </summary>
+#else
+  /// <summary>
+  /// An implementation of Red-Black trees as an indexed, sorted collection with set semantics,
+  /// cf. <a href="litterature.htm#CLRS">CLRS</a>. <see cref="T:C5.TreeBag`1"/> for a version 
+  /// with bag semantics. <see cref="T:C5.TreeDictionary`2"/> for a sorted dictionary 
+  /// based on this tree implementation.
+  /// <i>
+  /// The comparer (sorting order) may be either natural, because the item type is comparable 
+  /// (generic: <see cref="T:C5.IComparable`1"/> or non-generic: System.IComparable) or it can
+  /// be external and supplied by the user in the constructor.</i>
+  ///
+  /// <i>TODO: describe performance here</i>
+  /// <i>TODO: discuss persistence and its useful usage modes. Warn about the space
+  /// leak possible with other usage modes.</i>
+  /// </summary>
+#endif
+  [Serializable]
+  public class TreeBag<T> : SequencedBase<T>, IIndexedSorted<T>, IPersistentSorted<T>
+  {
+    #region Fields
+
+    SCG.IComparer<T> comparer;
+
+    Node root;
+
+    //TODO: wonder if we should remove that
+    int blackdepth = 0;
+
+    //We double these stacks for the iterative add and remove on demand
+    //TODO: refactor dirs[] into bool fields on Node (?)
+    private int[] dirs = new int[2];
+
+    private Node[] path = new Node[2];
+#if NCP
+    //TODO: refactor into separate class
+    bool isSnapShot = false;
+
+    int generation;
+
+    bool isValid = true;
+
+    SnapRef snapList;
+#endif
+    #endregion
+
+    #region Events
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public override EventTypeEnum ListenableEvents { get { return EventTypeEnum.Basic; } }
+
+    #endregion
+    #region Util
+
+    /// <summary>
+    /// Fetch the left child of n taking node-copying persistence into
+    /// account if relevant. 
+    /// </summary>
+    /// <param name="n"></param>
+    /// <returns></returns>
+    private Node left(Node n)
+    {
+#if NCP
+      if (isSnapShot)
+      {
+#if SEPARATE_EXTRA
+				Node.Extra e = n.extra;
+
+				if (e != null && e.lastgeneration >= treegen && e.leftnode)
+					return e.oldref;
+#else
+        if (n.lastgeneration >= generation && n.leftnode)
+          return n.oldref;
+#endif
+      }
+#endif
+      return n.left;
+    }
+
+
+    private Node right(Node n)
+    {
+#if NCP
+      if (isSnapShot)
+      {
+#if SEPARATE_EXTRA
+				Node.Extra e = n.extra;
+
+				if (e != null && e.lastgeneration >= treegen && !e.leftnode)
+					return e.oldref;
+#else
+        if (n.lastgeneration >= generation && !n.leftnode)
+          return n.oldref;
+#endif
+      }
+#endif
+      return n.right;
+    }
+
+
+    //This method should be called by methods that use the internal 
+    //traversal stack, unless certain that there is room enough
+    private void stackcheck()
+    {
+      while (dirs.Length < 2 * blackdepth)
+      {
+        dirs = new int[2 * dirs.Length];
+        path = new Node[2 * dirs.Length];
+      }
+    }
+
+    #endregion
+
+    #region Node nested class
+
+
+    /// <summary>
+    /// The type of node in a Red-Black binary tree
+    /// </summary>
+    [Serializable]
+    class Node
+    {
+      public bool red = true;
+
+      public T item;
+
+      public Node left;
+
+      public Node right;
+
+#if MAINTAIN_SIZE
+      public int size = 1;
+#endif
+
+#if BAG
+      public int items = 1;
+#endif
+
+#if NCP
+      //TODO: move everything into (separate) Extra
+      public int generation;
+#if SEPARATE_EXTRA
+			internal class Extra
+			{
+				public int lastgeneration;
+
+				public Node oldref;
+
+				public bool leftnode;
+
+				//public Node next;
+			}
+
+			public Extra extra;
+
+#else
+      public int lastgeneration = -1;
+
+      public Node oldref;
+
+      public bool leftnode;
+#endif
+
+      /// <summary>
+      /// Update a child pointer
+      /// </summary>
+      /// <param name="cursor"></param>
+      /// <param name="leftnode"></param>
+      /// <param name="child"></param>
+      /// <param name="maxsnapid"></param>
+      /// <param name="generation"></param>
+      /// <returns>True if node was *copied*</returns>
+      internal static bool update(ref Node cursor, bool leftnode, Node child, int maxsnapid, int generation)
+      {
+        Node oldref = leftnode ? cursor.left : cursor.right;
+
+        if (child == oldref)
+          return false;
+
+        bool retval = false;
+
+        if (cursor.generation <= maxsnapid)
+        {
+#if SEPARATE_EXTRA
+					if (cursor.extra == null)
+					{
+						Extra extra = cursor.extra = new Extra();	
+
+						extra.leftnode = leftnode;
+						extra.lastgeneration = maxsnapid;
+						extra.oldref = oldref;
+					}
+					else if (cursor.extra.leftnode != leftnode || cursor.extra.lastgeneration < maxsnapid)
+#else
+          if (cursor.lastgeneration == -1)
+          {
+            cursor.leftnode = leftnode;
+            cursor.lastgeneration = maxsnapid;
+            cursor.oldref = oldref;
+          }
+          else if (cursor.leftnode != leftnode || cursor.lastgeneration < maxsnapid)
+#endif
+          {
+            CopyNode(ref cursor, maxsnapid, generation);
+            retval = true;
+          }
+        }
+
+        if (leftnode)
+          cursor.left = child;
+        else
+          cursor.right = child;
+
+        return retval;
+      }
+
+
+      //If cursor.extra.lastgeneration==maxsnapid, the extra pointer will 
+      //always be used in the old copy of cursor. Therefore, after 
+      //making the clone, we should update the old copy by restoring
+      //the child pointer and setting extra to null.
+      //OTOH then we cannot clean up unused Extra objects unless we link
+      //them together in a doubly linked list.
+      public static bool CopyNode(ref Node cursor, int maxsnapid, int generation)
+      {
+        if (cursor.generation <= maxsnapid)
+        {
+          cursor = (Node)(cursor.MemberwiseClone());
+          cursor.generation = generation;
+#if SEPARATE_EXTRA
+					cursor.extra = null;
+#else
+          cursor.lastgeneration = -1;
+#endif
+          return true;
+        }
+        else
+          return false;
+      }
+
+#endif
+    }
+
+    #endregion
+
+    #region Constructors
+
+    /// <summary>
+    /// Create a red-black tree collection with natural comparer and item equalityComparer.
+    /// We assume that if <code>T</code> is comparable, its default equalityComparer 
+    /// will be compatible with the comparer.
+    /// </summary>
+    /// <exception cref="NotComparableException">If <code>T</code> is not comparable.
+    /// </exception>
+    public TreeBag() : this(Comparer<T>.Default, EqualityComparer<T>.Default) { }
+
+
+    /// <summary>
+    /// Create a red-black tree collection with an external comparer. 
+    /// <para>The itemequalityComparer will be a compatible 
+    /// <see cref="T:C5.ComparerZeroHashCodeEqualityComparer`1"/> since the 
+    /// default equalityComparer for T (<see cref="P:C5.EqualityComparer`1.Default"/>)
+    /// is unlikely to be compatible with the external comparer. This makes the
+    /// tree inadequate for use as item in a collection of unsequenced or sequenced sets or bags
+    /// (<see cref="T:C5.ICollection`1"/> and <see cref="T:C5.ISequenced`1"/>)
+    /// </para>
+    /// </summary>
+    /// <param name="comparer">The external comparer</param>
+    public TreeBag(SCG.IComparer<T> comparer) : this(comparer, new ComparerZeroHashCodeEqualityComparer<T>(comparer)) { }
+
+    /// <summary>
+    /// Create a red-black tree collection with an external comparer and an external
+    /// item equalityComparer, assumed consistent.
+    /// </summary>
+    /// <param name="comparer">The external comparer</param>
+    /// <param name="equalityComparer">The external item equalityComparer</param>
+    public TreeBag(SCG.IComparer<T> comparer, SCG.IEqualityComparer<T> equalityComparer)
+      : base(equalityComparer)
+    {
+      if (comparer == null)
+        throw new NullReferenceException("Item comparer cannot be null");
+      this.comparer = comparer;
+    }
+
+    #endregion
+
+    #region TreeBag.Enumerator nested class
+
+    /// <summary>
+    /// An enumerator for a red-black tree collection. Based on an explicit stack
+    /// of subtrees waiting to be enumerated. Currently only used for the tree set 
+    /// enumerators (tree bag enumerators use an iterator block based enumerator).
+    /// </summary>
+    internal class Enumerator : SCG.IEnumerator<T>
+    {
+      #region Private Fields
+      TreeBag<T> tree;
+
+      bool valid = false;
+
+      int stamp;
+
+      T current;
+
+      Node cursor;
+
+      Node[] path; // stack of nodes
+
+      int level = 0;
+      #endregion
+      /// <summary>
+      /// Create a tree enumerator
+      /// </summary>
+      /// <param name="tree">The red-black tree to enumerate</param>
+      public Enumerator(TreeBag<T> tree)
+      {
+        this.tree = tree;
+        stamp = tree.stamp;
+        path = new Node[2 * tree.blackdepth];
+        cursor = new Node();
+        cursor.right = tree.root;
+      }
+
+
+      /// <summary>
+      /// Undefined if enumerator is not valid (MoveNext hash been called returning true)
+      /// </summary>
+      /// <value>The current item of the enumerator.</value>
+      [Tested]
+      public T Current
+      {
+        [Tested]
+        get
+        {
+          if (valid)
+            return current;
+          else
+            throw new InvalidOperationException();
+        }
+      }
+
+
+      //Maintain a stack of nodes that are roots of
+      //subtrees not completely exported yet. Invariant:
+      //The stack nodes together with their right subtrees
+      //consists of exactly the items we have not passed
+      //yet (the top of the stack holds current item).
+      /// <summary>
+      /// Move enumerator to next item in tree, or the first item if
+      /// this is the first call to MoveNext. 
+      /// <exception cref="CollectionModifiedException"/> if underlying tree was modified.
+      /// </summary>
+      /// <returns>True if enumerator is valid now</returns>
+      [Tested]
+      public bool MoveNext()
+      {
+        tree.modifycheck(stamp);
+        if (cursor.right != null)
+        {
+          path[level] = cursor = cursor.right;
+          while (cursor.left != null)
+            path[++level] = cursor = cursor.left;
+        }
+        else if (level == 0)
+          return valid = false;
+        else
+          cursor = path[--level];
+
+        current = cursor.item;
+        return valid = true;
+      }
+
+
+      #region IDisposable Members for Enumerator
+
+      bool disposed;
+
+
+      /// <summary>
+      /// Call Dispose(true) and then suppress finalization of this enumerator.
+      /// </summary>
+      [Tested]
+      public void Dispose()
+      {
+        Dispose(true);
+        GC.SuppressFinalize(this);
+      }
+
+
+      /// <summary>
+      /// Remove the internal data (notably the stack array).
+      /// </summary>
+      /// <param name="disposing">True if called from Dispose(),
+      /// false if called from the finalizer</param>
+      protected virtual void Dispose(bool disposing)
+      {
+        if (!disposed)
+        {
+          if (disposing)
+          {
+          }
+
+          current = default(T);
+          cursor = null;
+          path = null;
+          disposed = true;
+        }
+      }
+
+
+      /// <summary>
+      /// Finalizer for enumerator
+      /// </summary>
+      ~Enumerator()
+      {
+        Dispose(false);
+      }
+      #endregion
+
+
+      #region IEnumerator Members
+
+      object System.Collections.IEnumerator.Current
+      {
+        get { return Current; }
+      }
+
+      bool System.Collections.IEnumerator.MoveNext()
+      {
+        return MoveNext();
+      }
+
+      void System.Collections.IEnumerator.Reset()
+      {
+        throw new Exception("The method or operation is not implemented.");
+      }
+
+      #endregion
+    }
+#if NCP
+    /// <summary>
+    /// An enumerator for a snapshot of a node copy persistent red-black tree
+    /// collection.
+    /// </summary>
+    internal class SnapEnumerator : SCG.IEnumerator<T>
+    {
+      #region Private Fields
+      TreeBag<T> tree;
+
+      bool valid = false;
+
+      int stamp;
+#if BAG
+      int togo;
+#endif
+
+      T current;
+
+      Node cursor;
+
+      Node[] path; // stack of nodes
+
+      int level;
+      #endregion
+
+      /// <summary>
+      /// Creta an enumerator for a snapshot of a node copy persistent red-black tree
+      /// collection
+      /// </summary>
+      /// <param name="tree">The snapshot</param>
+      public SnapEnumerator(TreeBag<T> tree)
+      {
+        this.tree = tree;
+        stamp = tree.stamp;
+        path = new Node[2 * tree.blackdepth];
+        cursor = new Node();
+        cursor.right = tree.root;
+      }
+
+
+      #region SCG.IEnumerator<T> Members
+
+      /// <summary>
+      /// Move enumerator to next item in tree, or the first item if
+      /// this is the first call to MoveNext. 
+      /// <exception cref="CollectionModifiedException"/> if underlying tree was modified.
+      /// </summary>
+      /// <returns>True if enumerator is valid now</returns>
+      [Tested]
+      public bool MoveNext()
+      {
+        tree.modifycheck(stamp);//???
+
+#if BAG
+        if (--togo > 0)
+          return true;
+#endif
+        Node next = tree.right(cursor);
+
+        if (next != null)
+        {
+          path[level] = cursor = next;
+          next = tree.left(cursor);
+          while (next != null)
+          {
+            path[++level] = cursor = next;
+            next = tree.left(cursor);
+          }
+        }
+        else if (level == 0)
+          return valid = false;
+        else
+          cursor = path[--level];
+
+#if BAG
+        togo = cursor.items;
+#endif
+        current = cursor.item;
+        return valid = true;
+      }
+
+
+      /// <summary>
+      /// Undefined if enumerator is not valid (MoveNext hash been called returning true)
+      /// </summary>
+      /// <value>The current value of the enumerator.</value>
+      [Tested]
+      public T Current
+      {
+        [Tested]
+        get
+        {
+          if (valid)
+            return current;
+          else
+            throw new InvalidOperationException();
+        }
+      }
+
+      #endregion
+
+      #region IDisposable Members
+
+      [Tested]
+      void System.IDisposable.Dispose()
+      {
+        tree = null;
+        valid = false;
+        current = default(T);
+        cursor = null;
+        path = null;
+      }
+
+      #endregion
+
+      #region IEnumerator Members
+
+      object System.Collections.IEnumerator.Current
+      {
+        get { return Current; }
+      }
+
+      bool System.Collections.IEnumerator.MoveNext()
+      {
+        return MoveNext();
+      }
+
+      void System.Collections.IEnumerator.Reset()
+      {
+        throw new Exception("The method or operation is not implemented.");
+      }
+
+      #endregion
+    }
+#endif
+    #endregion
+
+    #region IEnumerable<T> Members
+
+    private SCG.IEnumerator<T> getEnumerator(Node node, int origstamp)
+    {
+      if (node == null)
+        yield break;
+
+      if (node.left != null)
+      {
+        SCG.IEnumerator<T> child = getEnumerator(node.left, origstamp);
+
+        while (child.MoveNext())
+        {
+          modifycheck(origstamp);
+          yield return child.Current;
+        }
+      }
+#if BAG
+      int togo = node.items;
+      while (togo-- > 0)
+      {
+        modifycheck(origstamp);
+        yield return node.item;
+      }
+#else
+      modifycheck(origstamp);
+      yield return node.item;
+#endif
+      if (node.right != null)
+      {
+        SCG.IEnumerator<T> child = getEnumerator(node.right, origstamp);
+
+        while (child.MoveNext())
+        {
+          modifycheck(origstamp);
+          yield return child.Current;
+        }
+      }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="NoSuchItemException">If tree is empty</exception>
+    /// <returns></returns>
+    [Tested]
+    public override T Choose()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+
+      if (size == 0)
+        throw new NoSuchItemException();
+      return root.item;
+    }
+
+
+    /// <summary>
+    /// Create an enumerator for this tree
+    /// </summary>
+    /// <returns>The enumerator</returns>
+    [Tested]
+    public override SCG.IEnumerator<T> GetEnumerator()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+#if NCP
+      if (isSnapShot)
+        return new SnapEnumerator(this);
+#endif
+#if BAG
+      return getEnumerator(root, stamp);
+#else
+      return new Enumerator(this);
+#endif
+    }
+
+    #endregion
+
+    #region ISink<T> Members
+
+    /// <summary>
+    /// Add item to tree. If already there, return the found item in the second argument.
+    /// </summary>
+    /// <param name="item">Item to add</param>
+    /// <param name="founditem">item found</param>
+    /// <param name="update">whether item in node should be updated</param>
+    /// <param name="wasfound">true if found in bag, false if not found or tre is a set</param>
+    /// <returns>True if item was added</returns>
+    bool addIterative(T item, ref T founditem, bool update, out bool wasfound)
+    {
+      wasfound = false;
+      if (root == null)
+      {
+        root = new Node();
+        root.red = false;
+        blackdepth = 1;
+        root.item = item;
+#if NCP
+        root.generation = generation;
+#endif
+        return true;
+      }
+
+      stackcheck();
+
+      int level = 0;
+      Node cursor = root;
+
+      while (true)
+      {
+        int comp = comparer.Compare(cursor.item, item);
+
+        if (comp == 0)
+        {
+          founditem = cursor.item;
+#if BAG
+          wasfound = true;
+          bool nodeWasUpdated = true;
+#if NCP
+          Node.CopyNode(ref cursor, maxsnapid, generation);
+#endif
+          if (update)
+            cursor.item = item;
+          else
+          {
+            cursor.items++;
+            cursor.size++;
+          }
+#else
+          bool nodeWasUpdated = update;
+          if (update)
+          {
+#if NCP
+            Node.CopyNode(ref cursor, maxsnapid, generation);
+#endif
+            cursor.item = item;
+          }
+#endif
+
+          while (level-- > 0)
+          {
+            if (nodeWasUpdated)
+            {
+              Node kid = cursor;
+
+              cursor = path[level];
+#if NCP
+              Node.update(ref cursor, dirs[level] > 0, kid, maxsnapid, generation);
+#endif
+#if BAG
+              if (!update)
+                cursor.size++;
+#endif
+            }
+
+            path[level] = null;
+          }
+#if BAG
+          return !update;
+#else
+          if (update)
+            root = cursor;
+
+          return false;
+#endif
+        }
+
+        //else
+        Node child = comp > 0 ? cursor.left : cursor.right;
+
+        if (child == null)
+        {
+          child = new Node();
+          child.item = item;
+#if NCP
+          child.generation = generation;
+          Node.update(ref cursor, comp > 0, child, maxsnapid, generation);
+#else
+					if (comp > 0) { cursor.left = child; }
+					else { cursor.right = child; }
+#endif
+#if MAINTAIN_SIZE
+          cursor.size++;
+#endif
+          dirs[level] = comp;
+          break;
+        }
+        else
+        {
+          dirs[level] = comp;
+          path[level++] = cursor;
+          cursor = child;
+        }
+      }
+
+      //We have just added the red node child to "cursor"
+      while (cursor.red)
+      {
+        //take one step up:
+        Node child = cursor;
+
+        cursor = path[--level];
+        path[level] = null;
+#if NCP
+        Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);
+#endif
+#if MAINTAIN_SIZE
+        cursor.size++;
+#endif
+        int comp = dirs[level];
+        Node childsibling = comp > 0 ? cursor.right : cursor.left;
+
+        if (childsibling != null && childsibling.red)
+        {
+          //Promote
+          child.red = false;
+#if NCP
+          Node.update(ref cursor, comp < 0, childsibling, maxsnapid, generation);
+#endif
+          childsibling.red = false;
+
+          //color cursor red & take one step up the tree unless at root
+          if (level == 0)
+          {
+            root = cursor;
+            blackdepth++;
+            return true;
+          }
+          else
+          {
+            cursor.red = true;
+#if NCP
+            child = cursor;
+            cursor = path[--level];
+            Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);
+#endif
+            path[level] = null;
+#if MAINTAIN_SIZE
+            cursor.size++;
+#endif
+          }
+        }
+        else
+        {
+          //ROTATE!!!
+          int childcomp = dirs[level + 1];
+
+          cursor.red = true;
+          if (comp > 0)
+          {
+            if (childcomp > 0)
+            {//zagzag
+#if NCP
+              Node.update(ref cursor, true, child.right, maxsnapid, generation);
+              Node.update(ref child, false, cursor, maxsnapid, generation);
+#else
+							cursor.left = child.right;
+							child.right = cursor;
+#endif
+              cursor = child;
+            }
+            else
+            {//zagzig
+              Node badgrandchild = child.right;
+#if NCP
+              Node.update(ref cursor, true, badgrandchild.right, maxsnapid, generation);
+              Node.update(ref child, false, badgrandchild.left, maxsnapid, generation);
+              Node.CopyNode(ref badgrandchild, maxsnapid, generation);
+#else
+							cursor.left = badgrandchild.right;
+							child.right = badgrandchild.left;
+#endif
+              badgrandchild.left = child;
+              badgrandchild.right = cursor;
+              cursor = badgrandchild;
+            }
+          }
+          else
+          {//comp < 0
+            if (childcomp < 0)
+            {//zigzig
+#if NCP
+              Node.update(ref cursor, false, child.left, maxsnapid, generation);
+              Node.update(ref child, true, cursor, maxsnapid, generation);
+#else
+							cursor.right = child.left;
+							child.left = cursor;
+#endif
+              cursor = child;
+            }
+            else
+            {//zigzag
+              Node badgrandchild = child.left;
+#if NCP
+              Node.update(ref cursor, false, badgrandchild.left, maxsnapid, generation);
+              Node.update(ref child, true, badgrandchild.right, maxsnapid, generation);
+              Node.CopyNode(ref badgrandchild, maxsnapid, generation);
+#else
+							cursor.right = badgrandchild.left;
+							child.left = badgrandchild.right;
+#endif
+              badgrandchild.right = child;
+              badgrandchild.left = cursor;
+              cursor = badgrandchild;
+            }
+          }
+
+          cursor.red = false;
+
+#if MAINTAIN_SIZE
+          Node n;
+
+#if BAG
+          n = cursor.right;
+          cursor.size = n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items;
+          n = cursor.left;
+          n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items;
+          cursor.size += n.size + cursor.items;
+#else
+          n = cursor.right;
+          cursor.size = n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;
+          n = cursor.left;
+          n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;
+          cursor.size += n.size + 1;
+#endif
+#endif
+          if (level == 0)
+          {
+            root = cursor;
+            return true;
+          }
+          else
+          {
+            child = cursor;
+            cursor = path[--level];
+            path[level] = null;
+#if NCP
+            Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);
+#else
+						if (dirs[level] > 0)
+							cursor.left = child;
+						else
+							cursor.right = child;
+#endif
+#if MAINTAIN_SIZE
+            cursor.size++;
+#endif
+            break;
+          }
+        }
+      }
+#if NCP
+      bool stillmore = true;
+#endif
+      while (level > 0)
+      {
+        Node child = cursor;
+
+        cursor = path[--level];
+        path[level] = null;
+#if NCP
+        if (stillmore)
+          stillmore = Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);
+#endif
+#if MAINTAIN_SIZE
+        cursor.size++;
+#endif
+      }
+
+      root = cursor;
+      return true;
+    }
+
+
+    /// <summary>
+    /// Add an item to this collection if possible. If this collection has set
+    /// semantics, the item will be added if not already in the collection. If
+    /// bag semantics, the item will always be added.
+    /// </summary>
+    /// <param name="item">The item to add.</param>
+    /// <returns>True if item was added.</returns>
+    [Tested]
+    public bool Add(T item)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+
+      //Note: blackdepth of the tree is set inside addIterative
+      T jtem = default(T);
+      if (!add(item, ref jtem))
+        return false;
+      if (ActiveEvents != 0)
+        raiseForAdd(jtem);
+      return true;
+    }
+
+    /// <summary>
+    /// Add an item to this collection if possible. If this collection has set
+    /// semantics, the item will be added if not already in the collection. If
+    /// bag semantics, the item will always be added.
+    /// </summary>
+    /// <param name="item">The item to add.</param>
+    [Tested]
+    void SCG.ICollection<T>.Add(T item)
+    {
+        Add(item);
+    }
+
+    private bool add(T item, ref T j)
+    {
+      bool wasFound;
+
+      if (addIterative(item, ref j, false, out wasFound))
+      {
+        size++;
+        if (!wasFound)
+          j = item;
+        return true;
+      }
+      else
+        return false;
+    }
+
+    /// <summary>
+    /// Add the elements from another collection with a more specialized item type 
+    /// to this collection. If this
+    /// collection has set semantics, only items not already in the collection
+    /// will be added.
+    /// </summary>
+    /// <typeparam name="U">The type of items to add</typeparam>
+    /// <param name="items">The items to add</param>
+    [Tested]
+    public void AddAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+
+      int c = 0;
+      T j = default(T);
+      bool tmp;
+
+      bool raiseAdded = (ActiveEvents & EventTypeEnum.Added) != 0;
+      CircularQueue<T> wasAdded = raiseAdded ? new CircularQueue<T>() : null;
+
+      foreach (T i in items)
+        if (addIterative(i, ref j, false, out tmp))
+        {
+          c++;
+          if (raiseAdded)
+            wasAdded.Enqueue(tmp ? j : i);
+        }
+      if (c == 0)
+        return;
+
+      size += c;
+      //TODO: implement a RaiseForAddAll() method
+      if (raiseAdded)
+        foreach (T item in wasAdded)
+          raiseItemsAdded(item, 1);
+      if (((ActiveEvents & EventTypeEnum.Changed) != 0))
+        raiseCollectionChanged();
+    }
+
+
+    /// <summary>
+    /// Add all the items from another collection with an enumeration order that 
+    /// is increasing in the items. <para>The idea is that the implementation may use
+    /// a faster algorithm to merge the two collections.</para>
+    /// <exception cref="ArgumentException"/> if the enumerated items turns out
+    /// not to be in increasing order.
+    /// </summary>
+    /// <param name="items">The collection to add.</param>
+    /// <typeparam name="U"></typeparam>
+    [Tested]
+    public void AddSorted<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      if (size > 0)
+        AddAll(items);
+      else
+      {
+        if (!isValid)
+          throw new ViewDisposedException("Snapshot has been disposed");
+        updatecheck();
+        addSorted(items, true, true);
+      }
+    }
+
+    #region add-sorted helpers
+
+    //Create a RB tree from x+2^h-1  (x < 2^h, h>=1) nodes taken from a
+    //singly linked list of red nodes using only the right child refs.
+    //The x nodes at depth h+1 will be red, the rest black.
+    //(h is the blackdepth of the resulting tree)
+    static Node maketreer(ref Node rest, int blackheight, int maxred, int red)
+    {
+      if (blackheight == 1)
+      {
+        Node top = rest;
+
+        rest = rest.right;
+        if (red > 0)
+        {
+          top.right = null;
+          rest.left = top;
+          top = rest;
+#if BAG
+          top.size += top.left.size;
+#elif MAINTAIN_SIZE
+          top.size = 1 + red;
+#endif
+          rest = rest.right;
+          red--;
+        }
+
+        if (red > 0)
+        {
+#if BAG
+          top.size += rest.size;
+#endif
+          top.right = rest;
+          rest = rest.right;
+          top.right.right = null;
+        }
+        else
+          top.right = null;
+
+        top.red = false;
+        return top;
+      }
+      else
+      {
+        maxred >>= 1;
+
+        int lred = red > maxred ? maxred : red;
+        Node left = maketreer(ref rest, blackheight - 1, maxred, lred);
+        Node top = rest;
+
+        rest = rest.right;
+        top.left = left;
+        top.red = false;
+        top.right = maketreer(ref rest, blackheight - 1, maxred, red - lred);
+#if BAG
+        top.size = top.items + top.left.size + top.right.size;
+#elif MAINTAIN_SIZE
+        top.size = (maxred << 1) - 1 + red;
+#endif
+        return top;
+      }
+    }
+
+
+    void addSorted<U>(SCG.IEnumerable<U> items, bool safe, bool raise) where U : T
+    {
+      SCG.IEnumerator<U> e = items.GetEnumerator(); ;
+      if (size > 0)
+        throw new InternalException("This can't happen");
+
+      if (!e.MoveNext())
+        return;
+
+      //To count theCollect 
+      Node head = new Node(), tail = head;
+      int z = 1;
+      T lastitem = tail.item = e.Current;
+#if BAG
+      int ec = 0;
+#endif
+
+      while (e.MoveNext())
+      {
+#if BAG
+        T thisitem = e.Current;
+        int comp = comparer.Compare(lastitem, thisitem);
+        if (comp > 0)
+          throw new ArgumentException("Argument not sorted");
+        if (comp == 0)
+        {
+          tail.items++;
+          ec++;
+        }
+        else
+        {
+          tail.size = tail.items;
+          z++;
+          tail.right = new Node();
+          tail = tail.right;
+          lastitem = tail.item = thisitem;
+#if NCP
+          tail.generation = generation;
+#endif
+        }
+#else
+        z++;
+        tail.right = new Node();
+        tail = tail.right;
+        tail.item = e.Current;
+        if (safe)
+        {
+          if (comparer.Compare(lastitem, tail.item) >= 0)
+            throw new ArgumentException("Argument not sorted");
+
+          lastitem = tail.item;
+        }
+#if NCP
+        tail.generation = generation;
+#endif
+#endif
+      }
+#if BAG
+      tail.size = tail.items;
+#endif
+      int blackheight = 0, red = z, maxred = 1;
+
+      while (maxred <= red)
+      {
+        red -= maxred;
+        maxred <<= 1;
+        blackheight++;
+      }
+
+      root = TreeBag<T>.maketreer(ref head, blackheight, maxred, red);
+      blackdepth = blackheight;
+      size = z;
+#if BAG
+      size += ec;
+#endif
+
+      if (raise)
+      {
+        if ((ActiveEvents & EventTypeEnum.Added) != 0)
+        {
+          CircularQueue<T> wasAdded = new CircularQueue<T>();
+          foreach (T item in this)
+            wasAdded.Enqueue(item);
+          foreach (T item in wasAdded)
+            raiseItemsAdded(item, 1);
+        }
+        if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+          raiseCollectionChanged();
+      }
+      return;
+    }
+
+    #endregion
+
+#if BAG
+    /// <summary></summary>
+    /// <value>True since this collection has bag semantics.</value>
+    [Tested]
+    public bool AllowsDuplicates { [Tested]get { return true; } }
+#else
+    /// <summary></summary>
+    /// <value>False since this tree has set semantics.</value>
+    [Tested]
+    public bool AllowsDuplicates { [Tested]get { return false; } }
+#endif
+    /// <summary>
+    /// By convention this is true for any collection with set semantics.
+    /// </summary>
+    /// <value>True if only one representative of a group of equal items 
+    /// is kept in the collection together with the total count.</value>
+    public virtual bool DuplicatesByCounting { get { return true; } }
+
+    #endregion
+
+    #region IEditableCollection<T> Members
+
+
+    /// <summary>
+    /// The value is symbolic indicating the type of asymptotic complexity
+    /// in terms of the size of this collection (worst-case or amortized as
+    /// relevant).
+    /// </summary>
+    /// <value>Speed.Log</value>
+    [Tested]
+    public Speed ContainsSpeed { [Tested]get { return Speed.Log; } }
+
+    /// <summary>
+    /// Check if this collection contains (an item equivalent to according to the
+    /// itemequalityComparer) a particular value.
+    /// </summary>
+    /// <param name="item">The value to check for.</param>
+    /// <returns>True if the items is in this collection.</returns>
+    [Tested]
+    public bool Contains(T item)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      Node next; int comp = 0;
+
+      next = root;
+      while (next != null)
+      {
+        comp = comparer.Compare(next.item, item);
+        if (comp == 0)
+          return true;
+
+        next = comp < 0 ? right(next) : left(next);
+      }
+
+      return false;
+    }
+
+
+    //Variant for dictionary use
+    //Will return the actual matching item in the ref argument.
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, return in the ref argument (a
+    /// binary copy of) the actual value found.
+    /// </summary>
+    /// <param name="item">The value to look for.</param>
+    /// <returns>True if the items is in this collection.</returns>
+    [Tested]
+    public bool Find(ref T item)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      Node next; int comp = 0;
+
+      next = root;
+      while (next != null)
+      {
+        comp = comparer.Compare(next.item, item);
+        if (comp == 0)
+        {
+          item = next.item;
+          return true;
+        }
+
+        next = comp < 0 ? right(next) : left(next);
+      }
+
+      return false;
+    }
+
+
+    /// <summary>
+    /// Find or add the item to the tree. If the tree does not contain
+    /// an item equivalent to this item add it, else return the exisiting
+    /// one in the ref argument. 
+    ///
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns>True if item was found</returns>
+    [Tested]
+    public bool FindOrAdd(ref T item)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+      bool wasfound;
+
+      //Note: blackdepth of the tree is set inside addIterative
+      if (addIterative(item, ref item, false, out wasfound))
+      {
+        size++;
+        if (ActiveEvents != 0 && !wasfound)
+          raiseForAdd(item);
+        return wasfound;
+      }
+      else
+        return true;
+
+    }
+
+
+    //For dictionary use. 
+    //If found, the matching entry will be updated with the new item.
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// to with a binary copy of the supplied value. If the collection has bag semantics,
+    /// this updates all equivalent copies in
+    /// the collection.
+    /// </summary>
+    /// <param name="item">Value to update.</param>
+    /// <returns>True if the item was found and hence updated.</returns>
+    [Tested]
+    public bool Update(T item)
+    {
+      T olditem = item;
+      return Update(item, out olditem);
+    }
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// with a binary copy of the supplied value. If the collection has bag semantics,
+    /// this updates all equivalent copies in
+    /// the collection.
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public bool Update(T item, out T olditem)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+#if NCP
+      stackcheck();
+
+      int level = 0;
+#endif
+      Node cursor = root;
+      int comp = 0;
+
+      while (cursor != null)
+      {
+        comp = comparer.Compare(cursor.item, item);
+        if (comp == 0)
+        {
+#if NCP
+          Node.CopyNode(ref cursor, maxsnapid, generation);
+#endif
+          olditem = cursor.item;
+#if BAG
+          int items = cursor.items;
+#endif
+          cursor.item = item;
+#if NCP
+          while (level > 0)
+          {
+            Node child = cursor;
+
+            cursor = path[--level];
+            path[level] = null;
+#if NCP
+            Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);
+#else
+						if (Node.CopyNode(maxsnapid, ref cursor, generation))
+						{
+							if (dirs[level] > 0)
+								cursor.left = child;
+							else
+								cursor.right = child;
+						}
+#endif
+          }
+
+          root = cursor;
+#endif
+#if BAG
+          if (ActiveEvents != 0)
+            raiseForUpdate(item, olditem, items);
+#else
+          if (ActiveEvents != 0)
+            raiseForUpdate(item, olditem);
+#endif
+          return true;
+        }
+#if NCP
+        dirs[level] = comp;
+        path[level++] = cursor;
+#endif
+        cursor = comp < 0 ? cursor.right : cursor.left;
+      }
+
+      olditem = default(T);
+      return false;
+    }
+
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// with a binary copy of the supplied value; else add the value to the collection. 
+    ///
+    /// <i>NOTE: the bag implementation is currently wrong! ?????</i>
+    /// </summary>
+    /// <param name="item">Value to add or update.</param>
+    /// <returns>True if the item was found and updated (hence not added).</returns>
+    [Tested]
+    public bool UpdateOrAdd(T item)
+    { T olditem; return UpdateOrAdd(item, out olditem); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public bool UpdateOrAdd(T item, out T olditem)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+      bool wasfound;
+      olditem = default(T);
+
+
+      //Note: blackdepth of the tree is set inside addIterative
+      if (addIterative(item, ref olditem, true, out wasfound))
+      {
+        size++;
+        if (ActiveEvents != 0)
+          raiseForAdd(wasfound ? olditem : item);
+        return wasfound;
+      }
+      else
+      {
+#warning for bag implementation: count is wrong
+        if (ActiveEvents != 0)
+          raiseForUpdate(item, olditem, 1);
+        return true;
+      }
+    }
+
+
+    /// <summary>
+    /// Remove a particular item from this collection. If the collection has bag
+    /// semantics only one copy equivalent to the supplied item is removed. 
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    /// <returns>True if the item was found (and removed).</returns>
+    [Tested]
+    public bool Remove(T item)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+      if (root == null)
+        return false;
+
+      int junk;
+      bool retval = removeIterative(ref item, false, out junk);
+      if (ActiveEvents != 0 && retval)
+        raiseForRemove(item);
+      return retval;
+    }
+
+    /// <summary>
+    /// Remove a particular item from this collection if found. If the collection
+    /// has bag semantics only one copy equivalent to the supplied item is removed,
+    /// which one is implementation dependent. 
+    /// If an item was removed, report a binary copy of the actual item removed in 
+    /// the argument.
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    /// <param name="removeditem">The removed value.</param>
+    /// <returns>True if the item was found (and removed).</returns>
+    [Tested]
+    public bool Remove(T item, out T removeditem)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+      removeditem = item;
+      if (root == null)
+        return false;
+
+      int junk;
+      bool retval = removeIterative(ref removeditem, false, out junk);
+      if (ActiveEvents != 0 && retval)
+        raiseForRemove(item);
+      return retval;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item">input: item to remove; output: item actually removed</param>
+    /// <param name="all">If true, remove all copies</param>
+    /// <param name="wasRemoved"></param>
+    /// <returns></returns>
+    private bool removeIterative(ref T item, bool all, out int wasRemoved)
+    {
+      wasRemoved = 0;
+      //Stage 1: find item
+      stackcheck();
+
+      int level = 0, comp;
+      Node cursor = root;
+
+      while (true)
+      {
+        comp = comparer.Compare(cursor.item, item);
+        if (comp == 0)
+        {
+          item = cursor.item;
+#if BAG
+          if (!all && cursor.items > 1)
+          {
+#if NCP
+            Node.CopyNode(ref cursor, maxsnapid, generation);
+#endif
+            cursor.items--;
+            cursor.size--;
+            while (level-- > 0)
+            {
+              Node kid = cursor;
+
+              cursor = path[level];
+#if NCP
+              Node.update(ref cursor, dirs[level] > 0, kid, maxsnapid, generation);
+#endif
+              cursor.size--;
+              path[level] = null;
+            }
+            size--;
+            wasRemoved = 1;
+            return true;
+          }
+          wasRemoved = cursor.items;
+#else
+          wasRemoved = 1;
+#endif
+          break;
+        }
+
+        Node child = comp > 0 ? cursor.left : cursor.right;
+
+        if (child == null)
+          return false;
+
+        dirs[level] = comp;
+        path[level++] = cursor;
+        cursor = child;
+      }
+
+      return removeIterativePhase2(cursor, level);
+    }
+
+
+    private bool removeIterativePhase2(Node cursor, int level)
+    {
+      if (size == 1)
+      {
+        clear();
+        return true;
+      }
+
+#if BAG
+      int removedcount = cursor.items;
+      size -= removedcount;
+#else
+      //We are certain to remove one node:
+      size--;
+#endif
+      //Stage 2: if item's node has no null child, find predecessor
+      int level_of_item = level;
+
+      if (cursor.left != null && cursor.right != null)
+      {
+        dirs[level] = 1;
+        path[level++] = cursor;
+        cursor = cursor.left;
+        while (cursor.right != null)
+        {
+          dirs[level] = -1;
+          path[level++] = cursor;
+          cursor = cursor.right;
+        }
+#if NCP
+        Node.CopyNode(ref path[level_of_item], maxsnapid, generation);
+#endif
+        path[level_of_item].item = cursor.item;
+#if BAG
+        path[level_of_item].items = cursor.items;
+#endif
+      }
+
+      //Stage 3: splice out node to be removed
+      Node newchild = cursor.right == null ? cursor.left : cursor.right;
+      bool demote_or_rotate = newchild == null && !cursor.red;
+
+      //assert newchild.red 
+      if (newchild != null)
+      {
+        newchild.red = false;
+      }
+
+      if (level == 0)
+      {
+        root = newchild;
+        return true;
+      }
+
+      level--;
+      cursor = path[level];
+      path[level] = null;
+
+      int comp = dirs[level];
+      Node childsibling;
+#if NCP
+      Node.update(ref cursor, comp > 0, newchild, maxsnapid, generation);
+#else
+			if (comp > 0)
+				cursor.left = newchild;
+			else
+				cursor.right = newchild;
+#endif
+      childsibling = comp > 0 ? cursor.right : cursor.left;
+#if BAG
+      cursor.size -= removedcount;
+#elif MAINTAIN_SIZE
+      cursor.size--;
+#endif
+
+      //Stage 4: demote till we must rotate
+      Node farnephew = null, nearnephew = null;
+
+      while (demote_or_rotate)
+      {
+        if (childsibling.red)
+          break; //rotate 2+?
+
+        farnephew = comp > 0 ? childsibling.right : childsibling.left;
+        if (farnephew != null && farnephew.red)
+          break; //rotate 1b
+
+        nearnephew = comp > 0 ? childsibling.left : childsibling.right;
+        if (nearnephew != null && nearnephew.red)
+          break; //rotate 1c
+
+        //demote cursor
+        childsibling.red = true;
+        if (level == 0)
+        {
+          cursor.red = false;
+          blackdepth--;
+#if NCP
+          root = cursor;
+#endif
+          return true;
+        }
+        else if (cursor.red)
+        {
+          cursor.red = false;
+          demote_or_rotate = false;
+          break; //No rotation
+        }
+        else
+        {
+          Node child = cursor;
+
+          cursor = path[--level];
+          path[level] = null;
+          comp = dirs[level];
+          childsibling = comp > 0 ? cursor.right : cursor.left;
+#if NCP
+          Node.update(ref cursor, comp > 0, child, maxsnapid, generation);
+#endif
+#if BAG
+          cursor.size -= removedcount;
+#elif MAINTAIN_SIZE
+          cursor.size--;
+#endif
+        }
+      }
+
+      //Stage 5: rotate 
+      if (demote_or_rotate)
+      {
+        //At start:
+        //parent = cursor (temporary for swapping nodes)
+        //childsibling is the sibling of the updated child (x)
+        //cursor is always the top of the subtree
+        Node parent = cursor;
+
+        if (childsibling.red)
+        {//Case 2 and perhaps more. 
+          //The y.rank == px.rank >= x.rank+2 >=2 so both nephews are != null 
+          //(and black). The grandnephews are children of nearnephew
+          Node neargrandnephew, fargrandnephew;
+
+          if (comp > 0)
+          {
+            nearnephew = childsibling.left;
+            farnephew = childsibling.right;
+            neargrandnephew = nearnephew.left;
+            fargrandnephew = nearnephew.right;
+          }
+          else
+          {
+            nearnephew = childsibling.right;
+            farnephew = childsibling.left;
+            neargrandnephew = nearnephew.right;
+            fargrandnephew = nearnephew.left;
+          }
+
+          if (fargrandnephew != null && fargrandnephew.red)
+          {//Case 2+1b
+#if NCP
+            Node.CopyNode(ref nearnephew, maxsnapid, generation);
+
+            //The end result of this will always be e copy of parent
+            Node.update(ref parent, comp < 0, neargrandnephew, maxsnapid, generation);
+            Node.update(ref childsibling, comp > 0, nearnephew, maxsnapid, generation);
+#endif
+            if (comp > 0)
+            {
+              nearnephew.left = parent;
+              parent.right = neargrandnephew;
+            }
+            else
+            {
+              nearnephew.right = parent;
+              parent.left = neargrandnephew;
+            }
+
+            cursor = childsibling;
+            childsibling.red = false;
+            nearnephew.red = true;
+            fargrandnephew.red = false;
+#if BAG
+            cursor.size = parent.size;
+            nearnephew.size = cursor.size - cursor.items - farnephew.size;
+            parent.size = nearnephew.size - nearnephew.items - fargrandnephew.size;
+#elif MAINTAIN_SIZE
+            cursor.size = parent.size;
+            nearnephew.size = cursor.size - 1 - farnephew.size;
+            parent.size = nearnephew.size - 1 - fargrandnephew.size;
+#endif
+          }
+          else if (neargrandnephew != null && neargrandnephew.red)
+          {//Case 2+1c
+#if NCP
+            Node.CopyNode(ref neargrandnephew, maxsnapid, generation);
+#endif
+            if (comp > 0)
+            {
+#if NCP
+              Node.update(ref childsibling, true, neargrandnephew, maxsnapid, generation);
+              Node.update(ref nearnephew, true, neargrandnephew.right, maxsnapid, generation);
+              Node.update(ref parent, false, neargrandnephew.left, maxsnapid, generation);
+#else
+							childsibling.left = neargrandnephew;
+							nearnephew.left = neargrandnephew.right;
+							parent.right = neargrandnephew.left;
+#endif
+              neargrandnephew.left = parent;
+              neargrandnephew.right = nearnephew;
+            }
+            else
+            {
+#if NCP
+              Node.update(ref childsibling, false, neargrandnephew, maxsnapid, generation);
+              Node.update(ref nearnephew, false, neargrandnephew.left, maxsnapid, generation);
+              Node.update(ref parent, true, neargrandnephew.right, maxsnapid, generation);
+#else
+							childsibling.right = neargrandnephew;
+							nearnephew.right = neargrandnephew.left;
+							parent.left = neargrandnephew.right;
+#endif
+              neargrandnephew.right = parent;
+              neargrandnephew.left = nearnephew;
+            }
+
+            cursor = childsibling;
+            childsibling.red = false;
+#if BAG
+            cursor.size = parent.size;
+            parent.size = parent.items + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);
+            nearnephew.size = nearnephew.items + (nearnephew.left == null ? 0 : nearnephew.left.size) + (nearnephew.right == null ? 0 : nearnephew.right.size);
+            neargrandnephew.size = neargrandnephew.items + parent.size + nearnephew.size;
+#elif MAINTAIN_SIZE
+            cursor.size = parent.size;
+            parent.size = 1 + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);
+            nearnephew.size = 1 + (nearnephew.left == null ? 0 : nearnephew.left.size) + (nearnephew.right == null ? 0 : nearnephew.right.size);
+            neargrandnephew.size = 1 + parent.size + nearnephew.size;
+#endif
+          }
+          else
+          {//Case 2 only
+#if NCP
+            Node.update(ref parent, comp < 0, nearnephew, maxsnapid, generation);
+            Node.update(ref childsibling, comp > 0, parent, maxsnapid, generation);
+#else
+						if (comp > 0)
+						{
+							childsibling.left = parent;
+							parent.right = nearnephew;
+						}
+						else
+						{
+							childsibling.right = parent;
+							parent.left = nearnephew;
+						}
+#endif
+            cursor = childsibling;
+            childsibling.red = false;
+            nearnephew.red = true;
+#if BAG
+            cursor.size = parent.size;
+            parent.size -= farnephew.size + cursor.items;
+#elif MAINTAIN_SIZE
+            cursor.size = parent.size;
+            parent.size -= farnephew.size + 1;
+#endif
+          }
+        }
+        else if (farnephew != null && farnephew.red)
+        {//Case 1b
+          nearnephew = comp > 0 ? childsibling.left : childsibling.right;
+#if NCP
+          Node.update(ref parent, comp < 0, nearnephew, maxsnapid, generation);
+          Node.CopyNode(ref childsibling, maxsnapid, generation);
+          if (comp > 0)
+          {
+            childsibling.left = parent;
+            childsibling.right = farnephew;
+          }
+          else
+          {
+            childsibling.right = parent;
+            childsibling.left = farnephew;
+          }
+#else
+					if (comp > 0)
+					{
+						childsibling.left = parent;
+						parent.right = nearnephew;
+					}
+					else
+					{
+						childsibling.right = parent;
+						parent.left = nearnephew;
+					}
+#endif
+          cursor = childsibling;
+          cursor.red = parent.red;
+          parent.red = false;
+          farnephew.red = false;
+
+#if BAG
+          cursor.size = parent.size;
+          parent.size -= farnephew.size + cursor.items;
+#elif MAINTAIN_SIZE
+          cursor.size = parent.size;
+          parent.size -= farnephew.size + 1;
+#endif
+        }
+        else if (nearnephew != null && nearnephew.red)
+        {//Case 1c
+#if NCP
+          Node.CopyNode(ref nearnephew, maxsnapid, generation);
+#endif
+          if (comp > 0)
+          {
+#if NCP
+            Node.update(ref childsibling, true, nearnephew.right, maxsnapid, generation);
+            Node.update(ref parent, false, nearnephew.left, maxsnapid, generation);
+#else
+						childsibling.left = nearnephew.right;
+						parent.right = nearnephew.left;
+#endif
+            nearnephew.left = parent;
+            nearnephew.right = childsibling;
+          }
+          else
+          {
+#if NCP
+            Node.update(ref childsibling, false, nearnephew.left, maxsnapid, generation);
+            Node.update(ref parent, true, nearnephew.right, maxsnapid, generation);
+#else
+						childsibling.right = nearnephew.left;
+						parent.left = nearnephew.right;
+#endif
+            nearnephew.right = parent;
+            nearnephew.left = childsibling;
+          }
+
+          cursor = nearnephew;
+          cursor.red = parent.red;
+          parent.red = false;
+#if BAG
+          cursor.size = parent.size;
+          parent.size = parent.items + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);
+          childsibling.size = childsibling.items + (childsibling.left == null ? 0 : childsibling.left.size) + (childsibling.right == null ? 0 : childsibling.right.size);
+#elif MAINTAIN_SIZE
+          cursor.size = parent.size;
+          parent.size = 1 + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);
+          childsibling.size = 1 + (childsibling.left == null ? 0 : childsibling.left.size) + (childsibling.right == null ? 0 : childsibling.right.size);
+#endif
+        }
+        else
+        {//Case 1a can't happen
+          throw new InternalException("Case 1a can't happen here");
+        }
+
+        //Resplice cursor:
+        if (level == 0)
+        {
+          root = cursor;
+        }
+        else
+        {
+          Node swap = cursor;
+
+          cursor = path[--level];
+          path[level] = null;
+#if NCP
+          Node.update(ref cursor, dirs[level] > 0, swap, maxsnapid, generation);
+#else
+				
+					if (dirs[level] > 0)
+						cursor.left = swap;
+					else
+						cursor.right = swap;
+#endif
+#if BAG
+          cursor.size -= removedcount;
+#elif MAINTAIN_SIZE
+          cursor.size--;
+#endif
+        }
+      }
+
+      //Stage 6: fixup to the root
+      while (level > 0)
+      {
+        Node child = cursor;
+
+        cursor = path[--level];
+        path[level] = null;
+#if NCP
+        if (child != (dirs[level] > 0 ? cursor.left : cursor.right))
+          Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);
+#endif
+#if BAG
+        cursor.size -= removedcount;
+#elif MAINTAIN_SIZE
+        cursor.size--;
+#endif
+      }
+
+#if NCP
+      root = cursor;
+#endif
+      return true;
+    }
+
+
+    /// <summary>
+    /// Remove all items from this collection.
+    /// </summary>
+    [Tested]
+    public void Clear()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+      if (size == 0)
+        return;
+      int oldsize = size;
+      clear();
+      if ((ActiveEvents & EventTypeEnum.Cleared) != 0)
+        raiseCollectionCleared(true, oldsize);
+      if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+        raiseCollectionChanged();
+    }
+
+
+    private void clear()
+    {
+      size = 0;
+      root = null;
+      blackdepth = 0;
+    }
+
+
+    /// <summary>
+    /// Remove all items in another collection from this one. If this collection
+    /// has bag semantics, take multiplicities into account.
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to remove.</param>
+    [Tested]
+    public void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+
+      T jtem;
+
+      bool mustRaise = (ActiveEvents & (EventTypeEnum.Removed | EventTypeEnum.Changed)) != 0;
+      RaiseForRemoveAllHandler raiseHandler = mustRaise ? new RaiseForRemoveAllHandler(this) : null;
+
+      foreach (T item in items)
+      {
+        if (root == null)
+          break;
+
+        jtem = item;
+        int junk;
+        if (removeIterative(ref jtem, false, out junk) && mustRaise)
+          raiseHandler.Remove(jtem);
+      }
+      if (mustRaise)
+        raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// Remove all items not in some other collection from this one. If this collection
+    /// has bag semantics, take multiplicities into account.
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to retain.</param>
+    [Tested]
+    public void RetainAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+
+      //A much more efficient version is possible if items is sorted like this.
+      //Well, it is unclear how efficient it would be.
+      //We could use a marking method!?
+#warning how does this work together with persistence?
+      TreeBag<T> t = (TreeBag<T>)MemberwiseClone();
+
+      T jtem = default(T);
+      t.clear();
+      foreach (T item in items)
+        if (ContainsCount(item) > t.ContainsCount(item))
+        {
+          t.add(item, ref jtem);
+        }
+      if (size == t.size)
+        return;
+
+#warning improve (mainly for bag) by using a Node iterator instead of ItemMultiplicities()
+      CircularQueue<KeyValuePair<T, int>> wasRemoved = null;
+      if ((ActiveEvents & EventTypeEnum.Removed) != 0)
+      {
+        wasRemoved = new CircularQueue<KeyValuePair<T, int>>();
+        SCG.IEnumerator<KeyValuePair<T, int>> ie = ItemMultiplicities().GetEnumerator();
+        foreach (KeyValuePair<T, int> p in t.ItemMultiplicities())
+        {
+          //We know p.Key is in this!
+          while (ie.MoveNext())
+          {
+            if (comparer.Compare(ie.Current.Key, p.Key) == 0)
+            {
+#if BAG
+              int removed = ie.Current.Value - p.Value;
+              if (removed > 0)
+                wasRemoved.Enqueue(new KeyValuePair<T,int>(p.Key, removed));
+#endif
+              break;
+            }
+            else
+              wasRemoved.Enqueue(ie.Current);
+          }
+        }
+        while (ie.MoveNext())
+          wasRemoved.Enqueue(ie.Current);
+      }
+
+      root = t.root;
+      size = t.size;
+      blackdepth = t.blackdepth;
+      if (wasRemoved != null)
+        foreach (KeyValuePair<T, int> p in wasRemoved)
+          raiseItemsRemoved(p.Key, p.Value);
+      if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+        raiseCollectionChanged();
+    }
+
+    /// <summary>
+    /// Check if this collection contains all the values in another collection.
+    /// If this collection has bag semantics (<code>AllowsDuplicates==true</code>)
+    /// the check is made with respect to multiplicities, else multiplicities
+    /// are not taken into account.
+    /// </summary>
+    /// <param name="items">The </param>
+    /// <typeparam name="U"></typeparam>
+    /// <returns>True if all values in <code>items</code>is in this collection.</returns>
+    [Tested]
+    public bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      //TODO: fix bag implementation
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      //This is worst-case O(m*logn)
+      foreach (T item in items)
+        if (!Contains(item)) return false;
+
+      return true;
+    }
+
+
+    //Higher order:
+    /// <summary>
+    /// Create a new indexed sorted collection consisting of the items of this
+    /// indexed sorted collection satisfying a certain predicate.
+    /// </summary>
+    /// <param name="filter">The filter delegate defining the predicate.</param>
+    /// <returns>The new indexed sorted collection.</returns>
+    [Tested]
+    public IIndexedSorted<T> FindAll(Fun<T, bool> filter)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      TreeBag<T> res = new TreeBag<T>(comparer);
+      SCG.IEnumerator<T> e = GetEnumerator();
+      Node head = null, tail = null;
+      int z = 0;
+#if BAG
+      int ec = 0;
+#endif
+      while (e.MoveNext())
+      {
+        T thisitem = e.Current;
+#if BAG
+        //We could document that filter will only be called 
+        //once on each unique item. That might even be good for the user!
+        if (tail != null && comparer.Compare(thisitem, tail.item) == 0)
+        {
+          tail.items++;
+          ec++;
+          continue;
+        }
+#endif
+        if (filter(thisitem))
+        {
+          if (head == null)
+          {
+            head = tail = new Node();
+          }
+          else
+          {
+#if BAG
+            tail.size = tail.items;
+#endif
+            tail.right = new Node();
+            tail = tail.right;
+          }
+
+          tail.item = thisitem;
+          z++;
+        }
+      }
+#if BAG
+      if (tail != null)
+        tail.size = tail.items;
+#endif
+
+      if (z == 0)
+        return res;
+
+      int blackheight = 0, red = z, maxred = 1;
+
+      while (maxred <= red)
+      {
+        red -= maxred;
+        maxred <<= 1;
+        blackheight++;
+      }
+
+      res.root = TreeBag<T>.maketreer(ref head, blackheight, maxred, red);
+      res.blackdepth = blackheight;
+      res.size = z;
+#if BAG
+      res.size += ec;
+#endif
+      return res;
+    }
+
+
+    /// <summary>
+    /// Create a new indexed sorted collection consisting of the results of
+    /// mapping all items of this list.
+    /// <exception cref="ArgumentException"/> if the map is not increasing over 
+    /// the items of this collection (with respect to the two given comparison 
+    /// relations).
+    /// </summary>
+    /// <param name="mapper">The delegate definging the map.</param>
+    /// <param name="c">The comparion relation to use for the result.</param>
+    /// <returns>The new sorted collection.</returns>
+    [Tested]
+    public IIndexedSorted<V> Map<V>(Fun<T, V> mapper, SCG.IComparer<V> c)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      TreeBag<V> res = new TreeBag<V>(c);
+
+      if (size == 0)
+        return res;
+
+      SCG.IEnumerator<T> e = GetEnumerator();
+      TreeBag<V>.Node head = null, tail = null;
+      V oldv = default(V);
+      int z = 0;
+#if BAG
+      T lastitem = default(T);
+#endif
+      while (e.MoveNext())
+      {
+        T thisitem = e.Current;
+#if BAG
+        //We could document that mapper will only be called 
+        //once on each unique item. That might even be good for the user!
+        if (tail != null && comparer.Compare(thisitem, lastitem) == 0)
+        {
+          tail.items++;
+          continue;
+        }
+#endif
+        V newv = mapper(thisitem);
+
+        if (head == null)
+        {
+          head = tail = new TreeBag<V>.Node();
+          z++;
+        }
+        else
+        {
+          int comp = c.Compare(oldv, newv);
+#if BAG
+          if (comp == 0)
+          {
+            tail.items++;
+            continue;
+          }
+          if (comp > 0)
+#else
+          if (comp >= 0)
+#endif
+            throw new ArgumentException("mapper not monotonic");
+#if BAG
+          tail.size = tail.items;
+#endif
+          tail.right = new TreeBag<V>.Node();
+          tail = tail.right;
+          z++;
+        }
+#if BAG
+        lastitem = thisitem;
+#endif
+        tail.item = oldv = newv;
+      }
+
+#if BAG
+      tail.size = tail.items;
+#endif
+
+      int blackheight = 0, red = z, maxred = 1;
+
+      while (maxred <= red)
+      {
+        red -= maxred;
+        maxred <<= 1;
+        blackheight++;
+      }
+
+      res.root = TreeBag<V>.maketreer(ref head, blackheight, maxred, red);
+      res.blackdepth = blackheight;
+      res.size = size;
+      return res;
+    }
+
+
+    //below is the bag utility stuff
+    /// <summary>
+    /// Count the number of items of the collection equal to a particular value.
+    /// Returns 0 if and only if the value is not in the collection.
+    /// </summary>
+    /// <param name="item">The value to count.</param>
+    /// <returns>The number of copies found.</returns>
+    [Tested]
+    public int ContainsCount(T item)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+#if BAG
+      Node next; int comp = 0;
+
+      next = root;
+      while (next != null)
+      {
+        comp = comparer.Compare(next.item, item);
+        if (comp == 0)
+          return next.items;
+
+        next = comp < 0 ? right(next) : left(next);
+      }
+
+      return 0;
+#else
+      //Since we are strictly not AllowsDuplicates we just do
+      return Contains(item) ? 1 : 0;
+#endif
+    }
+
+#if BAG
+    //TODO: make work with snapshots
+    class Multiplicities : CollectionValueBase<KeyValuePair<T, int>>, ICollectionValue<KeyValuePair<T, int>>
+    {
+      TreeBag<T> treebag;
+      int origstamp;
+      internal Multiplicities(TreeBag<T> treebag) { this.treebag = treebag; this.origstamp = treebag.stamp; }
+      public override KeyValuePair<T, int> Choose() { return new KeyValuePair<T, int>(treebag.root.item, treebag.root.items); }
+
+      public override SCG.IEnumerator<KeyValuePair<T, int>> GetEnumerator()
+      {
+        return getEnumerator(treebag.root, origstamp); //TODO: NBNBNB
+      }
+
+      private SCG.IEnumerator<KeyValuePair<T, int>> getEnumerator(Node node, int origstamp)
+      {
+        if (node == null)
+          yield break;
+
+        if (node.left != null)
+        {
+          SCG.IEnumerator<KeyValuePair<T, int>> child = getEnumerator(node.left, origstamp);
+
+          while (child.MoveNext())
+          {
+            treebag.modifycheck(origstamp);
+            yield return child.Current;
+          }
+        }
+        yield return new KeyValuePair<T, int>(node.item, node.items);
+        if (node.right != null)
+        {
+          SCG.IEnumerator<KeyValuePair<T, int>> child = getEnumerator(node.right, origstamp);
+
+          while (child.MoveNext())
+          {
+            treebag.modifycheck(origstamp);
+            yield return child.Current;
+          }
+        }
+      }
+
+      public override bool IsEmpty { get { return treebag.IsEmpty; } }
+      public override int Count { get { int i = 0; foreach (KeyValuePair<T, int> p in this) i++; return i; } } //TODO: make better
+      public override Speed CountSpeed { get { return Speed.Linear; } } //TODO: make better
+    }
+#endif
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<T> UniqueItems()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+#if BAG
+      return new DropMultiplicity<T>(ItemMultiplicities());
+#else
+      return this;
+#endif
+    }
+
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+#if BAG
+      return new Multiplicities(this);
+#else
+      return new MultiplicityOne<T>(this);
+#endif
+    }
+
+    /// <summary>
+    /// Remove all items equivalent to a given value.
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    [Tested]
+    public void RemoveAllCopies(T item)
+    {
+#if BAG
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+      int removed;
+      if (removeIterative(ref item, true, out removed) && ActiveEvents != 0)
+      {
+        raiseForRemove(item, removed);
+      }
+#else
+      Remove(item);
+#endif
+    }
+
+
+    #endregion
+
+    #region IIndexed<T> Members
+
+    private Node findNode(int i)
+    {
+#if NCP
+      if (isSnapShot)
+        throw new NotSupportedException("Indexing not supported for snapshots");
+#endif
+#if MAINTAIN_SIZE
+      Node next = root;
+
+      if (i >= 0 && i < size)
+        while (true)
+        {
+          int j = next.left == null ? 0 : next.left.size;
+
+          if (i > j)
+          {
+#if BAG
+            i -= j + next.items;
+            if (i < 0)
+              return next;
+#else
+            i -= j + 1;
+#endif
+            next = next.right;
+          }
+          else if (i == j)
+            return next;
+          else
+            next = next.left;
+        }
+
+      throw new IndexOutOfRangeException();
+#else
+			throw new NotSupportedException();
+#endif
+    }
+
+
+    /// <summary>
+    /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+    /// &gt;= the size of the collection.
+    /// </summary>
+    /// <value>The i'th item of this list.</value>
+    /// <param name="i">the index to lookup</param>
+    [Tested]
+    public T this[int i] { [Tested]	get { return findNode(i).item; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual Speed IndexingSpeed { get { return Speed.Log; } }
+
+
+    //TODO: return -upper instead of -1 in case of not found
+    /// <summary>
+    /// Searches for an item in this indexed collection going forwards from the start.
+    /// </summary>
+    /// <param name="item">Item to search for.</param>
+    /// <returns>Index of first occurrence from start of the item
+    /// if found, else the two-complement 
+    /// (always negative) of the index at which the item would be put if it was added.</returns>
+    [Tested]
+    public int IndexOf(T item)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      int upper;
+      return indexOf(item, out upper);
+    }
+
+
+    private int indexOf(T item, out int upper)
+    {
+#if NCP
+      if (isSnapShot)
+        throw new NotSupportedException("Indexing not supported for snapshots");
+#endif
+#if MAINTAIN_SIZE
+      int ind = 0; Node next = root;
+
+      while (next != null)
+      {
+        int comp = comparer.Compare(item, next.item);
+
+        if (comp < 0)
+          next = next.left;
+        else
+        {
+          int leftcnt = next.left == null ? 0 : next.left.size;
+
+          if (comp == 0)
+          {
+#if BAG
+            upper = ind + leftcnt + next.items - 1;
+            return ind + leftcnt;
+#else
+            return upper = ind + leftcnt;
+#endif
+          }
+          else
+          {
+#if BAG
+            ind = ind + next.items + leftcnt;
+#else
+            ind = ind + 1 + leftcnt;
+#endif
+            next = next.right;
+          }
+        }
+      }
+#endif
+      upper = ~ind;
+      return ~ind;
+    }
+
+
+    /// <summary>
+    /// Searches for an item in the tree going backwords from the end.
+    /// </summary>
+    /// <param name="item">Item to search for.</param>
+    /// <returns>Index of last occurrence from the end of item if found, 
+    /// else the two-complement (always negative) of the index at which 
+    /// the item would be put if it was added.</returns>
+    [Tested]
+    public int LastIndexOf(T item)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+#if BAG
+      int res;
+      indexOf(item, out res);
+      return res;
+#else
+      //We have AllowsDuplicates==false for the set
+      return IndexOf(item);
+#endif
+    }
+
+
+    /// <summary>
+    /// Remove the item at a specific position of the list.
+    /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+    /// &gt;= the size of the collection.
+    /// </summary>
+    /// <param name="i">The index of the item to remove.</param>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public T RemoveAt(int i)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+      T retval = removeAt(i);
+      if (ActiveEvents != 0)
+        raiseForRemove(retval);
+      return retval;
+    }
+
+    T removeAt(int i)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+#if MAINTAIN_SIZE
+      if (i < 0 || i >= size)
+        throw new IndexOutOfRangeException("Index out of range for sequenced collectionvalue");
+
+      //We must follow the pattern of removeIterative()
+      while (dirs.Length < 2 * blackdepth)
+      {
+        dirs = new int[2 * dirs.Length];
+        path = new Node[2 * dirs.Length];
+      }
+
+      int level = 0;
+      Node cursor = root;
+
+      while (true)
+      {
+        int j = cursor.left == null ? 0 : cursor.left.size;
+
+        if (i > j)
+        {
+#if BAG
+          i -= j + cursor.items;
+          if (i < 0)
+            break;
+#else
+          i -= j + 1;
+#endif
+          dirs[level] = -1;
+          path[level++] = cursor;
+          cursor = cursor.right;
+        }
+        else if (i == j)
+          break;
+        else
+        {
+          dirs[level] = 1;
+          path[level++] = cursor;
+          cursor = cursor.left;
+        }
+      }
+
+      T retval = cursor.item;
+
+#if BAG
+      if (cursor.items > 1)
+      {
+        resplicebag(level, cursor);
+        size--;
+        return retval;
+      }
+#endif
+      removeIterativePhase2(cursor, level);
+      return retval;
+#else
+			throw new NotSupportedException();
+#endif
+    }
+
+#if BAG
+    private void resplicebag(int level, Node cursor)
+    {
+#if NCP
+      Node.CopyNode(ref cursor, maxsnapid, generation);
+#endif
+      cursor.items--;
+      cursor.size--;
+      while (level-- > 0)
+      {
+        Node kid = cursor;
+
+        cursor = path[level];
+#if NCP
+        Node.update(ref cursor, dirs[level] > 0, kid, maxsnapid, generation);
+#endif
+        cursor.size--;
+        path[level] = null;
+      }
+    }
+#endif
+    /// <summary>
+    /// Remove all items in an index interval.
+    /// <exception cref="IndexOutOfRangeException"/>???. 
+    /// </summary>
+    /// <param name="start">The index of the first item to remove.</param>
+    /// <param name="count">The number of items to remove.</param>
+    [Tested]
+    public void RemoveInterval(int start, int count)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      if (start < 0 || count < 0 || start + count > this.size)
+        throw new ArgumentOutOfRangeException();
+
+      updatecheck();
+
+      if (count == 0)
+        return;
+
+      //This is terrible for large count. We should split the tree at 
+      //the endpoints of the range and fuse the parts!
+      //We really need good internal destructive split and catenate functions!
+      //Alternative for large counts: rebuild tree using maketree()
+      for (int i = 0; i < count; i++)
+        removeAt(start);
+
+      if ((ActiveEvents & EventTypeEnum.Cleared) != 0)
+        raiseCollectionCleared(false, count);
+      if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+        raiseCollectionChanged();
+    }
+
+
+    /// <summary>
+    /// <exception cref="IndexOutOfRangeException"/>.
+    /// </summary>
+    /// <value>The directed collection of items in a specific index interval.</value>
+    /// <param name="start">The low index of the interval (inclusive).</param>
+    /// <param name="end">The high index of the interval (exclusive).</param>
+    [Tested]
+    public IDirectedCollectionValue<T> this[int start, int end]
+    {
+      [Tested]
+      get
+      {
+        checkRange(start, end - start);
+        return new Interval(this, start, end - start, true);
+      }
+    }
+
+    #region Interval nested class
+    class Interval : DirectedCollectionValueBase<T>, IDirectedCollectionValue<T>
+    {
+      int start, length, stamp;
+
+      bool forwards;
+
+      TreeBag<T> tree;
+
+
+      internal Interval(TreeBag<T> tree, int start, int count, bool forwards)
+      {
+#if NCP
+        if (tree.isSnapShot)
+          throw new NotSupportedException("Indexing not supported for snapshots");
+#endif
+        this.start = start; this.length = count; this.forwards = forwards;
+        this.tree = tree; this.stamp = tree.stamp;
+      }
+
+      public override bool IsEmpty { get { return length == 0; } }
+
+      [Tested]
+      public override int Count { [Tested]get { return length; } }
+
+
+      public override Speed CountSpeed { get { return Speed.Constant; } }
+
+
+      public override T Choose()
+      {
+        if (length == 0)
+          throw new NoSuchItemException();
+        return tree[start];
+      }
+
+      [Tested]
+      public override SCG.IEnumerator<T> GetEnumerator()
+      {
+#if MAINTAIN_SIZE
+        tree.modifycheck(stamp);
+#if BAG
+        int togo;
+#endif
+        Node cursor = tree.root;
+        Node[] path = new Node[2 * tree.blackdepth];
+        int level = 0, totaltogo = length;
+
+        if (totaltogo == 0)
+          yield break;
+
+        if (forwards)
+        {
+          int i = start;
+
+          while (true)
+          {
+            int j = cursor.left == null ? 0 : cursor.left.size;
+
+            if (i > j)
+            {
+#if BAG
+              i -= j + cursor.items;
+              if (i < 0)
+              {
+                togo = cursor.items + i;
+                break;
+              }
+#else
+              i -= j + 1;
+#endif
+              cursor = cursor.right;
+            }
+            else if (i == j)
+            {
+#if BAG
+              togo = cursor.items;
+#endif
+              break;
+            }
+            else
+            {
+              path[level++] = cursor;
+              cursor = cursor.left;
+            }
+          }
+
+          T current = cursor.item;
+
+          while (totaltogo-- > 0)
+          {
+            yield return current;
+            tree.modifycheck(stamp);
+#if BAG
+            if (--togo > 0)
+              continue;
+#endif
+            if (cursor.right != null)
+            {
+              path[level] = cursor = cursor.right;
+              while (cursor.left != null)
+                path[++level] = cursor = cursor.left;
+            }
+            else if (level == 0)
+              yield break;
+            else
+              cursor = path[--level];
+
+            current = cursor.item;
+#if BAG
+            togo = cursor.items;
+#endif
+          }
+        }
+        else
+        {
+          int i = start + length - 1;
+
+          while (true)
+          {
+            int j = cursor.left == null ? 0 : cursor.left.size;
+
+            if (i > j)
+            {
+#if BAG
+              if (i - j < cursor.items)
+              {
+                togo = i - j + 1;
+                break;
+              }
+              i -= j + cursor.items;
+#else
+              i -= j + 1;
+#endif
+              path[level++] = cursor;
+              cursor = cursor.right;
+            }
+            else if (i == j)
+            {
+#if BAG
+              togo = 1;
+#endif
+              break;
+            }
+            else
+            {
+              cursor = cursor.left;
+            }
+          }
+
+          T current = cursor.item;
+
+          while (totaltogo-- > 0)
+          {
+            yield return current;
+            tree.modifycheck(stamp);
+#if BAG
+            if (--togo > 0)
+              continue;
+#endif
+            if (cursor.left != null)
+            {
+              path[level] = cursor = cursor.left;
+              while (cursor.right != null)
+                path[++level] = cursor = cursor.right;
+            }
+            else if (level == 0)
+              yield break;
+            else
+              cursor = path[--level];
+
+            current = cursor.item;
+#if BAG
+            togo = cursor.items;
+#endif
+          }
+        }
+
+#else
+			throw new NotSupportedException();
+#endif
+      }
+
+
+      [Tested]
+      public override IDirectedCollectionValue<T> Backwards()
+      { return new Interval(tree, start, length, !forwards); }
+
+
+      [Tested]
+      IDirectedEnumerable<T> C5.IDirectedEnumerable<T>.Backwards()
+      { return Backwards(); }
+
+
+      [Tested]
+      public override EnumerationDirection Direction
+      {
+        [Tested]
+        get
+        {
+          return forwards ? EnumerationDirection.Forwards : EnumerationDirection.Backwards;
+        }
+      }
+    }
+    #endregion
+
+    /// <summary>
+    /// Create a collection containing the same items as this collection, but
+    /// whose enumerator will enumerate the items backwards. The new collection
+    /// will become invalid if the original is modified. Method typicaly used as in
+    /// <code>foreach (T x in coll.Backwards()) {...}</code>
+    /// </summary>
+    /// <returns>The backwards collection.</returns>
+    [Tested]
+    public override IDirectedCollectionValue<T> Backwards() { return RangeAll().Backwards(); }
+
+
+    [Tested]
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
+
+    #endregion
+
+    #region PriorityQueue Members
+
+    /// <summary>
+    /// The comparer object supplied at creation time for this collection
+    /// </summary>
+    /// <value>The comparer</value>
+    public SCG.IComparer<T> Comparer { get { return comparer; } }
+
+
+    /// <summary>
+    /// Find the current least item of this priority queue.
+    /// </summary>
+    /// <returns>The least item.</returns>
+    [Tested]
+    public T FindMin()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      if (size == 0)
+        throw new NoSuchItemException();
+      Node cursor = root, next = left(cursor);
+
+      while (next != null)
+      {
+        cursor = next;
+        next = left(cursor);
+      }
+
+      return cursor.item;
+    }
+
+
+    /// <summary>
+    /// Remove the least item from this  priority queue.
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public T DeleteMin()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+
+      //persistence guard?
+      if (size == 0)
+        throw new NoSuchItemException();
+
+      //We must follow the pattern of removeIterative()
+      stackcheck();
+
+      T retval = deleteMin();
+      if (ActiveEvents != 0)
+      {
+        raiseItemsRemoved(retval, 1);
+        raiseCollectionChanged();
+      }
+      return retval;
+    }
+
+    private T deleteMin()
+    {
+      int level = 0;
+      Node cursor = root;
+
+      while (cursor.left != null)
+      {
+        dirs[level] = 1;
+        path[level++] = cursor;
+        cursor = cursor.left;
+      }
+
+      T retval = cursor.item;
+
+#if BAG
+      if (cursor.items > 1)
+      {
+        resplicebag(level, cursor);
+        size--;
+        return retval;
+      }
+#endif
+      removeIterativePhase2(cursor, level);
+      return retval;
+    }
+
+
+    /// <summary>
+    /// Find the current largest item of this priority queue.
+    /// </summary>
+    /// <returns>The largest item.</returns>
+    [Tested]
+    public T FindMax()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      if (size == 0)
+        throw new NoSuchItemException();
+
+      Node cursor = root, next = right(cursor);
+
+      while (next != null)
+      {
+        cursor = next;
+        next = right(cursor);
+      }
+
+      return cursor.item;
+    }
+
+
+    /// <summary>
+    /// Remove the largest item from this  priority queue.
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public T DeleteMax()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      //persistence guard?
+      updatecheck();
+      if (size == 0)
+        throw new NoSuchItemException();
+
+      //We must follow the pattern of removeIterative()
+      stackcheck();
+
+      T retval = deleteMax();
+      if (ActiveEvents != 0)
+      {
+        raiseItemsRemoved(retval, 1);
+        raiseCollectionChanged();
+      }
+      return retval;
+    }
+
+    private T deleteMax()
+    {
+      int level = 0;
+      Node cursor = root;
+
+      while (cursor.right != null)
+      {
+        dirs[level] = -1;
+        path[level++] = cursor;
+        cursor = cursor.right;
+      }
+
+      T retval = cursor.item;
+
+#if BAG
+      if (cursor.items > 1)
+      {
+        resplicebag(level, cursor);
+        size--;
+        return retval;
+      }
+#endif
+      removeIterativePhase2(cursor, level);
+      return retval;
+    }
+    #endregion
+
+    #region ISorted<T> Members
+
+    /// <summary>
+    /// Find the strict predecessor of item in the sorted collection,
+    /// that is, the greatest item in the collection smaller than the item.
+    /// </summary>
+    /// <param name="item">The item to find the predecessor for.</param>
+    /// <param name="res">The predecessor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a predecessor; otherwise false.</returns>
+    public bool TryPredecessor(T item, out T res)
+    {
+        if (!isValid)
+            throw new ViewDisposedException("Snapshot has been disposed");
+        Node cursor = root, bestsofar = null;
+
+        while (cursor != null)
+        {
+            int comp = comparer.Compare(cursor.item, item);
+
+            if (comp < 0)
+            {
+                bestsofar = cursor;
+                cursor = right(cursor);
+            }
+            else if (comp == 0)
+            {
+                cursor = left(cursor);
+                while (cursor != null)
+                {
+                    bestsofar = cursor;
+                    cursor = right(cursor);
+                }
+            }
+            else
+                cursor = left(cursor);
+        }
+        if (bestsofar == null)
+        {
+            res = default(T);
+            return false;
+        }
+        else
+        {
+            res = bestsofar.item;
+            return true;
+        }
+    }
+
+
+    /// <summary>
+    /// Find the strict successor of item in the sorted collection,
+    /// that is, the least item in the collection greater than the supplied value.
+    /// </summary>
+    /// <param name="item">The item to find the successor for.</param>
+    /// <param name="res">The successor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a successor; otherwise false.</returns>
+    public bool TrySuccessor(T item, out T res)
+    {
+        if (!isValid)
+            throw new ViewDisposedException("Snapshot has been disposed");
+        Node cursor = root, bestsofar = null;
+
+        while (cursor != null)
+        {
+            int comp = comparer.Compare(cursor.item, item);
+
+            if (comp > 0)
+            {
+                bestsofar = cursor;
+                cursor = left(cursor);
+            }
+            else if (comp == 0)
+            {
+                cursor = right(cursor);
+                while (cursor != null)
+                {
+                    bestsofar = cursor;
+                    cursor = left(cursor);
+                }
+            }
+            else
+                cursor = right(cursor);
+        }
+
+        if (bestsofar == null)
+        {
+            res = default(T);
+            return false;
+        }
+        else
+        {
+            res = bestsofar.item;
+            return true;
+        }
+    }
+
+
+    /// <summary>
+    /// Find the weak predecessor of item in the sorted collection,
+    /// that is, the greatest item in the collection smaller than or equal to the item.
+    /// </summary>
+    /// <param name="item">The item to find the weak predecessor for.</param>
+    /// <param name="res">The weak predecessor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a weak predecessor; otherwise false.</returns>
+    public bool TryWeakPredecessor(T item, out T res)
+    {
+        if (!isValid)
+            throw new ViewDisposedException("Snapshot has been disposed");
+        Node cursor = root, bestsofar = null;
+
+        while (cursor != null)
+        {
+            int comp = comparer.Compare(cursor.item, item);
+
+            if (comp < 0)
+            {
+                bestsofar = cursor;
+                cursor = right(cursor);
+            }
+            else if (comp == 0)
+            {
+                res = cursor.item;
+                return true;
+            }
+            else
+                cursor = left(cursor);
+        }
+        if (bestsofar == null)
+        {
+            res = default(T);
+            return false;
+        }
+        else
+        {
+            res = bestsofar.item;
+            return true;
+        }
+    }
+
+
+    /// <summary>
+    /// Find the weak successor of item in the sorted collection,
+    /// that is, the least item in the collection greater than or equal to the supplied value.
+    /// </summary>
+    /// <param name="item">The item to find the weak successor for.</param>
+    /// <param name="res">The weak successor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a weak successor; otherwise false.</returns>
+    public bool TryWeakSuccessor(T item, out T res)
+    {
+        if (!isValid)
+            throw new ViewDisposedException("Snapshot has been disposed");
+        Node cursor = root, bestsofar = null;
+
+        while (cursor != null)
+        {
+            int comp = comparer.Compare(cursor.item, item);
+
+            if (comp == 0)
+            {
+                res = cursor.item;
+                return true;
+            }
+            else if (comp > 0)
+            {
+                bestsofar = cursor;
+                cursor = left(cursor);
+            }
+            else
+                cursor = right(cursor);
+        }
+
+        if (bestsofar == null)
+        {
+            res = default(T);
+            return false;
+        }
+        else
+        {
+            res = bestsofar.item;
+            return true;
+        }
+    }
+
+
+    /// <summary>
+    /// Find the strict predecessor in the sorted collection of a particular value,
+    /// i.e. the largest item in the collection less than the supplied value.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such element exists (the
+    /// supplied  value is less than or equal to the minimum of this collection.)</exception>
+    /// <param name="item">The item to find the predecessor for.</param>
+    /// <returns>The predecessor.</returns>
+    [Tested]
+    public T Predecessor(T item)
+    {
+        T res;
+        if (TryPredecessor(item, out res))
+            return res;
+        else
+            throw new NoSuchItemException();
+    }
+
+
+    /// <summary>
+    /// Find the weak predecessor in the sorted collection of a particular value,
+    /// i.e. the largest item in the collection less than or equal to the supplied value.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such element exists (the
+    /// supplied  value is less than the minimum of this collection.)</exception>
+    /// <param name="item">The item to find the weak predecessor for.</param>
+    /// <returns>The weak predecessor.</returns>
+    [Tested]
+    public T WeakPredecessor(T item)
+    {
+        T res;
+        if (TryWeakPredecessor(item, out res))
+            return res;
+        else
+            throw new NoSuchItemException();
+    }
+
+
+    /// <summary>
+    /// Find the strict successor in the sorted collection of a particular value,
+    /// i.e. the least item in the collection greater than the supplied value.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such element exists (the
+    /// supplied  value is greater than or equal to the maximum of this collection.)</exception>
+    /// <param name="item">The item to find the successor for.</param>
+    /// <returns>The successor.</returns>
+    [Tested]
+    public T Successor(T item)
+    {
+        T res;
+        if (TrySuccessor(item, out res))
+            return res;
+        else
+            throw new NoSuchItemException();
+    }
+
+
+    /// <summary>
+    /// Find the weak successor in the sorted collection of a particular value,
+    /// i.e. the least item in the collection greater than or equal to the supplied value.
+    /// <exception cref="NoSuchItemException"> if no such element exists (the
+    /// supplied  value is greater than the maximum of this collection.)</exception>
+    /// </summary>
+    /// <param name="item">The item to find the weak successor for.</param>
+    /// <returns>The weak successor.</returns>
+    [Tested]
+    public T WeakSuccessor(T item)
+    {
+        T res;
+        if (TryWeakSuccessor(item, out res))
+            return res;
+        else
+            throw new NoSuchItemException();
+    }
+
+   
+    /// <summary>
+    /// Query this sorted collection for items greater than or equal to a supplied value.
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive).</param>
+    /// <returns>The result directed collection.</returns>
+    [Tested]
+    public IDirectedCollectionValue<T> RangeFrom(T bot)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      return new Range(this, true, bot, false, default(T), EnumerationDirection.Forwards);
+    }
+
+
+    /// <summary>
+    /// Query this sorted collection for items between two supplied values.
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive).</param>
+    /// <param name="top">The upper bound (exclusive).</param>
+    /// <returns>The result directed collection.</returns>
+    [Tested]
+    public IDirectedCollectionValue<T> RangeFromTo(T bot, T top)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      return new Range(this, true, bot, true, top, EnumerationDirection.Forwards);
+    }
+
+
+    /// <summary>
+    /// Query this sorted collection for items less than a supplied value.
+    /// </summary>
+    /// <param name="top">The upper bound (exclusive).</param>
+    /// <returns>The result directed collection.</returns>
+    [Tested]
+    public IDirectedCollectionValue<T> RangeTo(T top)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      return new Range(this, false, default(T), true, top, EnumerationDirection.Forwards);
+    }
+
+
+    /// <summary>
+    /// Create a directed collection with the same items as this collection.
+    /// </summary>
+    /// <returns>The result directed collection.</returns>
+    [Tested]
+    public IDirectedCollectionValue<T> RangeAll()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      return new Range(this, false, default(T), false, default(T), EnumerationDirection.Forwards);
+    }
+
+
+    [Tested]
+    IDirectedEnumerable<T> ISorted<T>.RangeFrom(T bot) { return RangeFrom(bot); }
+
+
+    [Tested]
+    IDirectedEnumerable<T> ISorted<T>.RangeFromTo(T bot, T top) { return RangeFromTo(bot, top); }
+
+
+    [Tested]
+    IDirectedEnumerable<T> ISorted<T>.RangeTo(T top) { return RangeTo(top); }
+
+
+    //Utility for CountXxxx. Actually always called with strict = true.
+    private int countTo(T item, bool strict)
+    {
+#if NCP
+      if (isSnapShot)
+        throw new NotSupportedException("Indexing not supported for snapshots");
+#endif
+#if MAINTAIN_SIZE
+      int ind = 0, comp = 0; Node next = root;
+
+      while (next != null)
+      {
+        comp = comparer.Compare(item, next.item);
+        if (comp < 0)
+          next = next.left;
+        else
+        {
+          int leftcnt = next.left == null ? 0 : next.left.size;
+#if BAG
+          if (comp == 0)
+            return strict ? ind + leftcnt : ind + leftcnt + next.items;
+          else
+          {
+            ind = ind + next.items + leftcnt;
+            next = next.right;
+          }
+#else
+          if (comp == 0)
+            return strict ? ind + leftcnt : ind + leftcnt + 1;
+          else
+          {
+            ind = ind + 1 + leftcnt;
+            next = next.right;
+          }
+#endif
+        }
+      }
+
+      //if we get here, we are at the same side of the whole collection:
+      return ind;
+#else
+			throw new NotSupportedException("Code compiled w/o size!");
+#endif
+    }
+
+
+    /// <summary>
+    /// Perform a search in the sorted collection for the ranges in which a
+    /// non-increasing (i.e. weakly decrerasing) function from the item type to 
+    /// <code>int</code> is
+    /// negative, zero respectively positive. If the supplied cut function is
+    /// not non-increasing, the result of this call is undefined.
+    /// </summary>
+    /// <param name="c">The cut function <code>T</code> to <code>int</code>, given
+    /// as an <code>IComparable&lt;T&gt;</code> object, where the cut function is
+    /// the <code>c.CompareTo(T that)</code> method.</param>
+    /// <param name="low">Returns the largest item in the collection, where the
+    /// cut function is positive (if any).</param>
+    /// <param name="lowIsValid">True if the cut function is positive somewhere
+    /// on this collection.</param>
+    /// <param name="high">Returns the least item in the collection, where the
+    /// cut function is negative (if any).</param>
+    /// <param name="highIsValid">True if the cut function is negative somewhere
+    /// on this collection.</param>
+    /// <returns></returns>
+    [Tested]
+    public bool Cut(IComparable<T> c, out T low, out bool lowIsValid, out T high, out bool highIsValid)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      Node cursor = root, lbest = null, rbest = null;
+      bool res = false;
+
+      while (cursor != null)
+      {
+        int comp = c.CompareTo(cursor.item);
+
+        if (comp > 0)
+        {
+          lbest = cursor;
+          cursor = right(cursor);
+        }
+        else if (comp < 0)
+        {
+          rbest = cursor;
+          cursor = left(cursor);
+        }
+        else
+        {
+          res = true;
+
+          Node tmp = left(cursor);
+
+          while (tmp != null && c.CompareTo(tmp.item) == 0)
+            tmp = left(tmp);
+
+          if (tmp != null)
+          {
+            lbest = tmp;
+            tmp = right(tmp);
+            while (tmp != null)
+            {
+              if (c.CompareTo(tmp.item) > 0)
+              {
+                lbest = tmp;
+                tmp = right(tmp);
+              }
+              else
+                tmp = left(tmp);
+            }
+          }
+
+          tmp = right(cursor);
+          while (tmp != null && c.CompareTo(tmp.item) == 0)
+            tmp = right(tmp);
+
+          if (tmp != null)
+          {
+            rbest = tmp;
+            tmp = left(tmp);
+            while (tmp != null)
+            {
+              if (c.CompareTo(tmp.item) < 0)
+              {
+                rbest = tmp;
+                tmp = left(tmp);
+              }
+              else
+                tmp = right(tmp);
+            }
+          }
+
+          break;
+        }
+      }
+
+      if (highIsValid = (rbest != null))
+        high = rbest.item;
+      else
+        high = default(T);
+
+      if (lowIsValid = (lbest != null))
+        low = lbest.item;
+      else
+        low = default(T);
+
+      return res;
+    }
+
+
+    /// <summary>
+    /// Determine the number of items at or above a supplied threshold.
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive)</param>
+    /// <returns>The number of matcing items.</returns>
+    [Tested]
+    public int CountFrom(T bot)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      return size - countTo(bot, true);
+    }
+
+
+    /// <summary>
+    /// Determine the number of items between two supplied thresholds.
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive)</param>
+    /// <param name="top">The upper bound (exclusive)</param>
+    /// <returns>The number of matcing items.</returns>
+    [Tested]
+    public int CountFromTo(T bot, T top)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      if (comparer.Compare(bot, top) >= 0)
+        return 0;
+
+      return countTo(top, true) - countTo(bot, true);
+    }
+
+
+    /// <summary>
+    /// Determine the number of items below a supplied threshold.
+    /// </summary>
+    /// <param name="top">The upper bound (exclusive)</param>
+    /// <returns>The number of matcing items.</returns>
+    [Tested]
+    public int CountTo(T top)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      return countTo(top, true);
+    }
+
+
+    /// <summary>
+    /// Remove all items of this collection above or at a supplied threshold.
+    /// </summary>
+    /// <param name="low">The lower threshold (inclusive).</param>
+    [Tested]
+    public void RemoveRangeFrom(T low)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+
+      int count = CountFrom(low);
+
+      if (count == 0)
+        return;
+
+      stackcheck();
+      CircularQueue<T> wasRemoved = (ActiveEvents & EventTypeEnum.Removed) != 0 ? new CircularQueue<T>() : null;
+
+      for (int i = 0; i < count; i++)
+      {
+        T item = deleteMax();
+        if (wasRemoved != null)
+          wasRemoved.Enqueue(item);
+      }
+      if (wasRemoved != null)
+        raiseForRemoveAll(wasRemoved);
+      else if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+        raiseCollectionChanged();
+    }
+
+
+    /// <summary>
+    /// Remove all items of this collection between two supplied thresholds.
+    /// </summary>
+    /// <param name="low">The lower threshold (inclusive).</param>
+    /// <param name="hi">The upper threshold (exclusive).</param>
+    [Tested]
+    public void RemoveRangeFromTo(T low, T hi)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+
+      int count = CountFromTo(low, hi);
+
+      if (count == 0)
+        return;
+
+      CircularQueue<T> wasRemoved = (ActiveEvents & EventTypeEnum.Removed) != 0 ? new CircularQueue<T>() : null;
+      int junk;
+      for (int i = 0; i < count; i++)
+      {
+        T item = Predecessor(hi);
+        removeIterative(ref item, false, out junk);
+        if (wasRemoved != null)
+          wasRemoved.Enqueue(item);
+      }
+      if (wasRemoved != null)
+        raiseForRemoveAll(wasRemoved);
+      else if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+        raiseCollectionChanged();
+    }
+
+
+    /// <summary>
+    /// Remove all items of this collection below a supplied threshold.
+    /// </summary>
+    /// <param name="hi">The upper threshold (exclusive).</param>
+    [Tested]
+    public void RemoveRangeTo(T hi)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+
+      int count = CountTo(hi);
+
+      if (count == 0)
+        return;
+
+      stackcheck();
+      CircularQueue<T> wasRemoved = (ActiveEvents & EventTypeEnum.Removed) != 0 ? new CircularQueue<T>() : null;
+
+      for (int i = 0; i < count; i++)
+      {
+        T item = deleteMin();
+        if (wasRemoved != null)
+          wasRemoved.Enqueue(item);
+      }
+      if (wasRemoved != null)
+        raiseForRemoveAll(wasRemoved);
+      else if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+        raiseCollectionChanged();
+    }
+
+    #endregion
+
+    #region IPersistent<T> Members
+#if NCP
+    int maxsnapid { get { return snapList == null ? -1 : findLastLiveSnapShot(); } }
+
+    int findLastLiveSnapShot()
+    {
+      if (snapList == null)
+        return -1;
+      SnapRef lastLiveSnapRef = snapList.Prev;
+      object _snapshot = null;
+      while (lastLiveSnapRef != null && (_snapshot = lastLiveSnapRef.Tree.Target) == null)
+        lastLiveSnapRef = lastLiveSnapRef.Prev;
+      if (lastLiveSnapRef == null)
+      {
+        snapList = null;
+        return -1;
+      }
+      if (snapList.Prev != lastLiveSnapRef)
+      {
+        snapList.Prev = lastLiveSnapRef;
+        lastLiveSnapRef.Next = snapList;
+      }
+      return ((TreeBag<T>)_snapshot).generation;
+    }
+
+    [Serializable]
+    class SnapRef
+    {
+      public SnapRef Prev, Next;
+      public WeakReference Tree;
+      public SnapRef(TreeBag<T> tree) { Tree = new WeakReference(tree); }
+      public void Dispose()
+      {
+        Next.Prev = Prev;
+        if (Prev != null)
+          Prev.Next = Next;
+        Next = Prev = null;
+      }
+    }
+#endif
+
+    /// <summary>
+    /// If this tree is a snapshot, remove registration in base tree
+    /// </summary>
+    [Tested]
+    public void Dispose()
+    {
+#if NCP
+      if (!isValid)
+        return;
+      if (isSnapShot)
+      {
+        snapList.Dispose();
+        snapDispose();
+      }
+      else
+      {
+        if (snapList != null)
+        {
+          SnapRef someSnapRef = snapList.Prev;
+          while (someSnapRef != null)
+          {
+            TreeBag<T> lastsnap;
+            if ((lastsnap = someSnapRef.Tree.Target as TreeBag<T>) != null)
+              lastsnap.snapDispose();
+            someSnapRef = someSnapRef.Prev;
+          }
+        }
+        snapList = null;
+        Clear();
+      }
+#else
+      Clear();
+#endif
+    }
+
+    private void snapDispose()
+    {
+      root = null;
+      dirs = null;
+      path = null;
+      comparer = null;
+      isValid = false;
+      snapList = null;
+    }
+
+    /// <summary>
+    /// Make a (read-only) snapshot of this collection.
+    /// </summary>
+    /// <returns>The snapshot.</returns>
+    [Tested]
+    public ISorted<T> Snapshot()
+    {
+#if NCP
+      if (isSnapShot)
+        throw new InvalidOperationException("Cannot snapshot a snapshot");
+
+      TreeBag<T> res = (TreeBag<T>)MemberwiseClone();
+      SnapRef newSnapRef = new SnapRef(res);
+      res.isReadOnlyBase = true;
+      res.isSnapShot = true;
+      res.snapList = newSnapRef;
+
+      findLastLiveSnapShot();
+      if (snapList == null)
+        snapList = new SnapRef(this);
+      SnapRef lastLiveSnapRef = snapList.Prev;
+
+      newSnapRef.Prev = lastLiveSnapRef;
+      if (lastLiveSnapRef != null)
+        lastLiveSnapRef.Next = newSnapRef;
+      newSnapRef.Next = snapList;
+      snapList.Prev = newSnapRef;
+
+      generation++;
+
+      return res;
+#endif
+    }
+
+    #endregion
+
+    #region TreeBag.Range nested class
+
+    internal class Range : DirectedCollectionValueBase<T>, IDirectedCollectionValue<T>
+    {
+      //We actually need exclusive upper and lower bounds, and flags to 
+      //indicate whether the bound is present (we canot rely on default(T))
+      private int stamp, size;
+
+      private TreeBag<T> basis;
+
+      private T lowend, highend;
+
+      private bool haslowend, hashighend;
+
+      EnumerationDirection direction;
+
+
+      [Tested]
+      public Range(TreeBag<T> basis, bool haslowend, T lowend, bool hashighend, T highend, EnumerationDirection direction)
+      {
+        this.basis = basis;
+        stamp = basis.stamp;
+
+        //lowind will be const; should we cache highind?
+        this.lowend = lowend; //Inclusive
+        this.highend = highend;//Exclusive
+        this.haslowend = haslowend;
+        this.hashighend = hashighend;
+        this.direction = direction;
+        if (!basis.isSnapShot)
+          size = haslowend ?
+              (hashighend ? basis.CountFromTo(lowend, highend) : basis.CountFrom(lowend)) :
+              (hashighend ? basis.CountTo(highend) : basis.Count);
+      }
+
+      #region IEnumerable<T> Members
+
+
+      #region TreeBag.Range.Enumerator nested class
+
+      internal class Enumerator : SCG.IEnumerator<T>
+      {
+        #region Private Fields
+        private bool valid = false, ready = true;
+
+        private SCG.IComparer<T> comparer;
+
+        private T current;
+#if BAG
+        int togo;
+#endif
+
+        private Node cursor;
+
+        private Node[] path; // stack of nodes
+
+        private int level = 0;
+
+        private Range range;
+
+        private bool forwards;
+
+        #endregion
+        [Tested]
+        public Enumerator(Range range)
+        {
+          comparer = range.basis.comparer;
+          path = new Node[2 * range.basis.blackdepth];
+          this.range = range;
+          forwards = range.direction == EnumerationDirection.Forwards;
+          cursor = new Node();
+          if (forwards)
+            cursor.right = range.basis.root;
+          else
+            cursor.left = range.basis.root;
+          range.basis.modifycheck(range.stamp);
+        }
+
+
+        int compare(T i1, T i2) { return comparer.Compare(i1, i2); }
+
+
+        /// <summary>
+        /// Undefined if enumerator is not valid (MoveNext hash been called returning true)
+        /// </summary>
+        /// <value>The current value of the enumerator.</value>
+        [Tested]
+        public T Current
+        {
+          [Tested]
+          get
+          {
+            if (valid)
+              return current;
+            else
+              throw new InvalidOperationException();
+          }
+        }
+
+
+        //Maintain a stack of nodes that are roots of
+        //subtrees not completely exported yet. Invariant:
+        //The stack nodes together with their right subtrees
+        //consists of exactly the items we have not passed
+        //yet (the top of the stack holds current item).
+        /// <summary>
+        /// Move enumerator to next item in tree, or the first item if
+        /// this is the first call to MoveNext. 
+        /// <exception cref="CollectionModifiedException"/> if underlying tree was modified.
+        /// </summary>
+        /// <returns>True if enumerator is valid now</returns>
+        [Tested]
+        public bool MoveNext()
+        {
+          range.basis.modifycheck(range.stamp);
+          if (!ready)
+            return false;
+#if BAG
+          if (--togo > 0)
+            return true;
+#endif
+          if (forwards)
+          {
+            if (!valid && range.haslowend)
+            {
+              cursor = cursor.right;
+              while (cursor != null)
+              {
+                int comp = compare(cursor.item, range.lowend);
+
+                if (comp > 0)
+                {
+                  path[level++] = cursor;
+#if NCP
+                  cursor = range.basis.left(cursor);
+#else
+									cursor = cursor.left;
+#endif
+                }
+                else if (comp < 0)
+                {
+#if NCP
+                  cursor = range.basis.right(cursor);
+#else
+									cursor = cursor.right;
+#endif
+                }
+                else
+                {
+                  path[level] = cursor;
+                  break;
+                }
+              }
+
+              if (cursor == null)
+              {
+                if (level == 0)
+                  return valid = ready = false;
+                else
+                  cursor = path[--level];
+              }
+            }
+#if NCP
+            else if (range.basis.right(cursor) != null)
+            {
+              path[level] = cursor = range.basis.right(cursor);
+
+              Node next = range.basis.left(cursor);
+
+              while (next != null)
+              {
+                path[++level] = cursor = next;
+                next = range.basis.left(cursor);
+              }
+            }
+#else
+						else if (cursor.right != null)
+						{
+							path[level] = cursor = cursor.right;
+							while (cursor.left != null)
+								path[++level] = cursor = cursor.left;
+						}
+#endif
+            else if (level == 0)
+              return valid = ready = false;
+            else
+              cursor = path[--level];
+
+            current = cursor.item;
+            if (range.hashighend && compare(current, range.highend) >= 0)
+              return valid = ready = false;
+
+#if BAG
+            togo = cursor.items;
+#endif
+            return valid = true;
+          }
+          else
+          {
+            if (!valid && range.hashighend)
+            {
+              cursor = cursor.left;
+              while (cursor != null)
+              {
+                int comp = compare(cursor.item, range.highend);
+
+                if (comp < 0)
+                {
+                  path[level++] = cursor;
+#if NCP
+                  cursor = range.basis.right(cursor);
+#else
+									cursor = cursor.right;
+#endif
+                }
+                else
+                {
+#if NCP
+                  cursor = range.basis.left(cursor);
+#else
+									cursor = cursor.left;
+#endif
+                }
+              }
+
+              if (cursor == null)
+              {
+                if (level == 0)
+                  return valid = ready = false;
+                else
+                  cursor = path[--level];
+              }
+            }
+#if NCP
+            else if (range.basis.left(cursor) != null)
+            {
+              path[level] = cursor = range.basis.left(cursor);
+
+              Node next = range.basis.right(cursor);
+
+              while (next != null)
+              {
+                path[++level] = cursor = next;
+                next = range.basis.right(cursor);
+              }
+            }
+#else
+						else if (cursor.left != null)
+						{
+							path[level] = cursor = cursor.left;
+							while (cursor.right != null)
+								path[++level] = cursor = cursor.right;
+						}
+#endif
+            else if (level == 0)
+              return valid = ready = false;
+            else
+              cursor = path[--level];
+
+            current = cursor.item;
+            if (range.haslowend && compare(current, range.lowend) < 0)
+              return valid = ready = false;
+
+#if BAG
+            togo = cursor.items;
+#endif
+            return valid = true;
+          }
+        }
+
+
+        [Tested]
+        public void Dispose()
+        {
+          comparer = null;
+          current = default(T);
+          cursor = null;
+          path = null;
+          range = null;
+        }
+
+        #region IEnumerator Members
+
+        object System.Collections.IEnumerator.Current
+        {
+          get { return Current; }
+        }
+
+        bool System.Collections.IEnumerator.MoveNext()
+        {
+          return MoveNext();
+        }
+
+        void System.Collections.IEnumerator.Reset()
+        {
+          throw new Exception("The method or operation is not implemented.");
+        }
+
+        #endregion
+      }
+
+      #endregion
+
+
+      public override T Choose()
+      {
+        if (size == 0) throw new NoSuchItemException();
+        return lowend;
+      }
+
+      [Tested]
+      public override SCG.IEnumerator<T> GetEnumerator() { return new Enumerator(this); }
+
+
+      [Tested]
+      public override EnumerationDirection Direction { [Tested]get { return direction; } }
+
+
+      #endregion
+
+      #region Utility
+
+      bool inside(T item)
+      {
+        return (!haslowend || basis.comparer.Compare(item, lowend) >= 0) && (!hashighend || basis.comparer.Compare(item, highend) < 0);
+      }
+
+
+      void checkstamp()
+      {
+        if (stamp < basis.stamp)
+          throw new CollectionModifiedException();
+      }
+
+
+      void syncstamp() { stamp = basis.stamp; }
+
+      #endregion
+
+      [Tested]
+      public override IDirectedCollectionValue<T> Backwards()
+      {
+        Range b = (Range)MemberwiseClone();
+
+        b.direction = direction == EnumerationDirection.Forwards ? EnumerationDirection.Backwards : EnumerationDirection.Forwards;
+        return b;
+      }
+
+
+      [Tested]
+      IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
+
+
+      public override bool IsEmpty { get { return size == 0; } }
+
+      [Tested]
+      public override int Count { [Tested] get { return size; } }
+
+      //TODO: check that this is correct
+      public override Speed CountSpeed { get { return Speed.Constant; } }
+
+    }
+
+    #endregion
+
+    #region Diagnostics
+    /// <summary>
+    /// Display this node on the console, and recursively its subnodes.
+    /// </summary>
+    /// <param name="n">Node to display</param>
+    /// <param name="space">Indentation</param>
+    private void minidump(Node n, string space)
+    {
+      if (n == null)
+      {
+        //	System.Console.WriteLine(space + "null");
+      }
+      else
+      {
+        minidump(n.right, space + "  ");
+        Console.WriteLine(String.Format("{0} {4} (size={1}, items={8}, h={2}, gen={3}, id={6}){7}", space + n.item,
+#if MAINTAIN_SIZE
+ n.size,
+#else
+				0,
+#endif
+ 0,
+#if NCP
+ n.generation,
+#endif
+ n.red ? "RED" : "BLACK",
+ 0,
+ 0,
+#if NCP
+#if SEPARATE_EXTRA
+				n.extra == null ? "" : String.Format(" [extra: lg={0}, c={1}, i={2}]", n.extra.lastgeneration, n.extra.leftnode ? "L" : "R", n.extra.oldref == null ? "()" : "" + n.extra.oldref.item),
+#else
+ n.lastgeneration == -1 ? "" : String.Format(" [extra: lg={0}, c={1}, i={2}]", n.lastgeneration, n.leftnode ? "L" : "R", n.oldref == null ? "()" : "" + n.oldref.item),
+#endif
+#else
+				"",
+#endif
+#if BAG
+ n.items
+#else
+ 1
+#endif
+));
+        minidump(n.left, space + "  ");
+      }
+    }
+
+
+    /// <summary>
+    /// Print the tree structure to the console stdout.
+    /// </summary>
+    [Tested(via = "Sawtooth")]
+    public void dump() { dump(""); }
+
+
+    /// <summary>
+    /// Print the tree structure to the console stdout.
+    /// </summary>
+    [Tested(via = "Sawtooth")]
+    public void dump(string msg)
+    {
+      Console.WriteLine(String.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4})", msg, size, blackdepth,
+      0
+      ,
+#if NCP
+ generation
+#endif
+));
+      minidump(root, "");
+      check("", Console.Out); Console.WriteLine("<<<<<<<<<<<<<<<<<<<");
+    }
+
+
+    /// <summary>
+    /// Display this tree on the console.
+    /// </summary>
+    /// <param name="msg">Identifying string of this call to dump</param>
+    /// <param name="err">Extra (error)message to include</param>
+    void dump(string msg, string err)
+    {
+      Console.WriteLine(String.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4})", msg, size, blackdepth,
+      0
+      ,
+#if NCP
+ generation
+#endif
+));
+      minidump(root, ""); Console.Write(err);
+      Console.WriteLine("<<<<<<<<<<<<<<<<<<<");
+    }
+
+
+    /// <summary>
+    /// Print warning m on o if b is false.
+    /// </summary>
+    /// <param name="b">Condition that should hold</param>
+    /// <param name="n">Place (used for id display)</param>
+    /// <param name="m">Message</param>
+    /// <param name="o">Output stream</param>
+    /// <returns>b</returns>
+    bool massert(bool b, Node n, string m, System.IO.TextWriter o)
+    {
+      if (!b) o.WriteLine("*** Node (item={0}, id={1}): {2}", n.item,
+        0
+        , m);
+
+      return b;
+    }
+
+
+    bool rbminicheck(Node n, bool redp, System.IO.TextWriter o, out T min, out T max, out int blackheight)
+    {//Red-Black invariant
+      bool res = true;
+
+      res = massert(!(n.red && redp), n, "RED parent of RED node", o) && res;
+      res = massert(n.left == null || n.right != null || n.left.red, n, "Left child black, but right child empty", o) && res;
+      res = massert(n.right == null || n.left != null || n.right.red, n, "Right child black, but left child empty", o) && res;
+#if BAG
+      bool sb = n.size == (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items;
+
+      res = massert(sb, n, "Bad size", o) && res;
+#elif MAINTAIN_SIZE
+      bool sb = n.size == (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;
+
+      res = massert(sb, n, "Bad size", o) && res;
+#endif
+      min = max = n.item;
+
+      T otherext;
+      int lbh = 0, rbh = 0;
+
+      if (n.left != null)
+      {
+        res = rbminicheck(n.left, n.red, o, out min, out otherext, out lbh) && res;
+        res = massert(comparer.Compare(n.item, otherext) > 0, n, "Value not > all left children", o) && res;
+      }
+
+      if (n.right != null)
+      {
+        res = rbminicheck(n.right, n.red, o, out otherext, out max, out rbh) && res;
+        res = massert(comparer.Compare(n.item, otherext) < 0, n, "Value not < all right children", o) && res;
+      }
+
+      res = massert(rbh == lbh, n, "Different blackheights of children", o) && res;
+      blackheight = n.red ? rbh : rbh + 1;
+      return res;
+    }
+
+
+
+
+#if NCP
+
+    bool rbminisnapcheck(Node n, System.IO.TextWriter o, out int size, out T min, out T max)
+    {
+      bool res = true;
+
+      min = max = n.item;
+
+      int lsz = 0, rsz = 0;
+      T otherext;
+#if SEPARATE_EXTRA
+			Node.Extra extra = n.extra;
+			Node child = (extra != null && extra.lastgeneration >= treegen && extra.leftnode) ? extra.oldref : n.left;
+#else
+      Node child = (n.lastgeneration >= generation && n.leftnode) ? n.oldref : n.left;
+#endif
+      if (child != null)
+      {
+        res = rbminisnapcheck(child, o, out lsz, out min, out otherext) && res;
+        res = massert(comparer.Compare(n.item, otherext) > 0, n, "Value not > all left children", o) && res;
+      }
+
+#if SEPARATE_EXTRA
+			child = (extra != null && extra.lastgeneration >= treegen && !extra.leftnode) ? extra.oldref : n.right;
+#else
+      child = (n.lastgeneration >= generation && !n.leftnode) ? n.oldref : n.right;
+#endif
+      if (child != null)
+      {
+        res = rbminisnapcheck(child, o, out rsz, out otherext, out max) && res;
+        res = massert(comparer.Compare(n.item, otherext) < 0, n, "Value not < all right children", o) && res;
+      }
+#if BAG
+      size = n.items + lsz + rsz;
+#else
+      size = 1 + lsz + rsz;
+#endif
+      return res;
+    }
+#endif
+
+    /// <summary>
+    /// Checks red-black invariant. Dumps tree to console if bad
+    /// </summary>
+    /// <param name="name">Title of dump</param>
+    /// <returns>false if invariant violation</returns>
+    [Tested(via = "Sawtooth")]
+    public bool Check(string name)
+    {
+      System.Text.StringBuilder e = new System.Text.StringBuilder();
+      System.IO.TextWriter o = new System.IO.StringWriter(e);
+
+      if (!check(name, o))
+        return true;
+      else
+      {
+        dump(name, e.ToString());
+        return false;
+      }
+    }
+
+
+    /// <summary>
+    /// Checks red-black invariant. Dumps tree to console if bad
+    /// </summary>
+    /// <returns>false if invariant violation</returns>
+    [Tested]
+    public bool Check()
+    {
+      //return check("", System.IO.TextWriter.Null);
+      //Console.WriteLine("bamse");
+      if (!isValid)
+        return true;
+      return Check("-");
+    }
+
+
+    bool check(string msg, System.IO.TextWriter o)
+    {
+      if (root != null)
+      {
+        T max, min;
+        int blackheight;
+#if NCP
+        if (isSnapShot)
+        {
+          //Console.WriteLine("Im'a snapshot");
+          int thesize;
+          bool rv = rbminisnapcheck(root, o, out thesize, out min, out max);
+
+          rv = massert(size == thesize, root, "bad snapshot size", o) && rv;
+          return !rv;
+        }
+#endif
+        bool res = rbminicheck(root, false, o, out min, out max, out blackheight);
+        res = massert(blackheight == blackdepth, root, "bad blackh/d", o) && res;
+        res = massert(!root.red, root, "root is red", o) && res;
+#if MAINTAIN_SIZE
+        res = massert(root.size == size, root, "count!=root.size", o) && res;
+#endif
+        return !res;
+      }
+      else
+        return false;
+    }
+    #endregion
+
+    #region ICloneable Members
+
+    /// <summary>
+    /// Make a shallow copy of this TreeBag.
+    /// </summary>
+    /// <returns></returns>
+    public virtual object Clone()
+    {
+      TreeBag<T> clone = new TreeBag<T>(comparer, EqualityComparer);
+      //TODO: make sure the TreeBag AddSorted copies tree bags smartly!!!
+      clone.AddSorted(this);
+      return clone;
+    }
+
+    #endregion
+
+  }
+}
+
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/trees/RedBlackTreeDictionary.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/trees/RedBlackTreeDictionary.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/trees/RedBlackTreeDictionary.cs	(revision 3)
@@ -0,0 +1,81 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using SCG = System.Collections.Generic;
+
+namespace C5
+{
+  /// <summary>
+  /// A sorted generic dictionary based on a red-black tree set.
+  /// </summary>
+  [Serializable]
+  public class TreeDictionary<K, V> : SortedDictionaryBase<K, V>, IDictionary<K, V>, ISortedDictionary<K, V>
+  {
+
+    #region Constructors
+
+    /// <summary>
+    /// Create a red-black tree dictionary using the natural comparer for keys.
+    /// <exception cref="ArgumentException"/> if the key type K is not comparable.
+    /// </summary>
+    public TreeDictionary() : this(Comparer<K>.Default, EqualityComparer<K>.Default) { }
+
+    /// <summary>
+    /// Create a red-black tree dictionary using an external comparer for keys.
+    /// </summary>
+    /// <param name="comparer">The external comparer</param>
+    public TreeDictionary(SCG.IComparer<K> comparer) : this(comparer, new ComparerZeroHashCodeEqualityComparer<K>(comparer)) { }
+
+    TreeDictionary(SCG.IComparer<K> comparer, SCG.IEqualityComparer<K> equalityComparer) : base(comparer,equalityComparer)
+    {
+      pairs = sortedpairs = new TreeSet<KeyValuePair<K, V>>(new KeyValuePairComparer<K, V>(comparer));
+    }
+
+    #endregion
+
+    //TODO: put in interface
+    /// <summary>
+    /// Make a snapshot of the current state of this dictionary
+    /// </summary>
+    /// <returns>The snapshot</returns>
+    [Tested]
+    public SCG.IEnumerable<KeyValuePair<K, V>> Snapshot()
+    {
+      TreeDictionary<K, V> res = (TreeDictionary<K, V>)MemberwiseClone();
+
+      res.pairs = (TreeSet<KeyValuePair<K, V>>)((TreeSet<KeyValuePair<K, V>>)sortedpairs).Snapshot();
+      return res;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override object Clone()
+    {
+      TreeDictionary<K, V> clone = new TreeDictionary<K, V>(Comparer, EqualityComparer);
+      clone.sortedpairs.AddSorted(sortedpairs);
+      return clone;
+    }
+
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/trees/RedBlackTreeSet.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/trees/RedBlackTreeSet.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/trees/RedBlackTreeSet.cs	(revision 3)
@@ -0,0 +1,4595 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+#define MAINTAIN_SIZE
+#define BAGnot
+#define NCP
+
+#if BAG
+#if !MAINTAIN_SIZE
+#error  BAG defined without MAINTAIN_SIZE!
+#endif
+#endif
+
+
+using System;
+using SCG = System.Collections.Generic;
+
+// NOTE NOTE NOTE NOTE
+// This source file is used to produce both TreeSet<T> and TreeBag<T>
+// It should be copied to a file called TreeBag.cs in which all code mentions of 
+// TreeSet is changed to TreeBag and the preprocessor symbol BAG is defined.
+// NOTE: there may be problems with documentation comments.
+
+namespace C5
+{
+#if BAG
+  /// <summary>
+  /// An implementation of Red-Black trees as an indexed, sorted collection with bag semantics,
+  /// cf. <a href="litterature.htm#CLRS">CLRS</a>. (<see cref="T:C5.TreeSet`1"/> for an 
+  /// implementation with set semantics).
+  /// <br/>
+  /// The comparer (sorting order) may be either natural, because the item type is comparable 
+  /// (generic: <see cref="T:C5.IComparable`1"/> or non-generic: System.IComparable) or it can
+  /// be external and supplied by the user in the constructor.
+  /// <br/>
+  /// Each distinct item is only kept in one place in the tree - together with the number
+  /// of times it is a member of the bag. Thus, if two items that are equal according
+  /// </summary>
+#else
+  /// <summary>
+  /// An implementation of Red-Black trees as an indexed, sorted collection with set semantics,
+  /// cf. <a href="litterature.htm#CLRS">CLRS</a>. <see cref="T:C5.TreeBag`1"/> for a version 
+  /// with bag semantics. <see cref="T:C5.TreeDictionary`2"/> for a sorted dictionary 
+  /// based on this tree implementation.
+  /// <i>
+  /// The comparer (sorting order) may be either natural, because the item type is comparable 
+  /// (generic: <see cref="T:C5.IComparable`1"/> or non-generic: System.IComparable) or it can
+  /// be external and supplied by the user in the constructor.</i>
+  ///
+  /// <i>TODO: describe performance here</i>
+  /// <i>TODO: discuss persistence and its useful usage modes. Warn about the space
+  /// leak possible with other usage modes.</i>
+  /// </summary>
+#endif
+  [Serializable]
+  public class TreeSet<T> : SequencedBase<T>, IIndexedSorted<T>, IPersistentSorted<T>
+  {
+    #region Fields
+
+    SCG.IComparer<T> comparer;
+
+    Node root;
+
+    //TODO: wonder if we should remove that
+    int blackdepth = 0;
+
+    //We double these stacks for the iterative add and remove on demand
+    //TODO: refactor dirs[] into bool fields on Node (?)
+    private int[] dirs = new int[2];
+
+    private Node[] path = new Node[2];
+#if NCP
+    //TODO: refactor into separate class
+    bool isSnapShot = false;
+
+    int generation;
+
+    bool isValid = true;
+
+    SnapRef snapList;
+#endif
+    #endregion
+
+    #region Events
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public override EventTypeEnum ListenableEvents { get { return EventTypeEnum.Basic; } }
+
+    #endregion
+    #region Util
+
+    /// <summary>
+    /// Fetch the left child of n taking node-copying persistence into
+    /// account if relevant. 
+    /// </summary>
+    /// <param name="n"></param>
+    /// <returns></returns>
+    private Node left(Node n)
+    {
+#if NCP
+      if (isSnapShot)
+      {
+#if SEPARATE_EXTRA
+				Node.Extra e = n.extra;
+
+				if (e != null && e.lastgeneration >= treegen && e.leftnode)
+					return e.oldref;
+#else
+        if (n.lastgeneration >= generation && n.leftnode)
+          return n.oldref;
+#endif
+      }
+#endif
+      return n.left;
+    }
+
+
+    private Node right(Node n)
+    {
+#if NCP
+      if (isSnapShot)
+      {
+#if SEPARATE_EXTRA
+				Node.Extra e = n.extra;
+
+				if (e != null && e.lastgeneration >= treegen && !e.leftnode)
+					return e.oldref;
+#else
+        if (n.lastgeneration >= generation && !n.leftnode)
+          return n.oldref;
+#endif
+      }
+#endif
+      return n.right;
+    }
+
+
+    //This method should be called by methods that use the internal 
+    //traversal stack, unless certain that there is room enough
+    private void stackcheck()
+    {
+      while (dirs.Length < 2 * blackdepth)
+      {
+        dirs = new int[2 * dirs.Length];
+        path = new Node[2 * dirs.Length];
+      }
+    }
+
+    #endregion
+
+    #region Node nested class
+
+
+    /// <summary>
+    /// The type of node in a Red-Black binary tree
+    /// </summary>
+    [Serializable]
+    class Node
+    {
+      public bool red = true;
+
+      public T item;
+
+      public Node left;
+
+      public Node right;
+
+#if MAINTAIN_SIZE
+      public int size = 1;
+#endif
+
+#if BAG
+      public int items = 1;
+#endif
+
+#if NCP
+      //TODO: move everything into (separate) Extra
+      public int generation;
+#if SEPARATE_EXTRA
+			internal class Extra
+			{
+				public int lastgeneration;
+
+				public Node oldref;
+
+				public bool leftnode;
+
+				//public Node next;
+			}
+
+			public Extra extra;
+
+#else
+      public int lastgeneration = -1;
+
+      public Node oldref;
+
+      public bool leftnode;
+#endif
+
+      /// <summary>
+      /// Update a child pointer
+      /// </summary>
+      /// <param name="cursor"></param>
+      /// <param name="leftnode"></param>
+      /// <param name="child"></param>
+      /// <param name="maxsnapid"></param>
+      /// <param name="generation"></param>
+      /// <returns>True if node was *copied*</returns>
+      internal static bool update(ref Node cursor, bool leftnode, Node child, int maxsnapid, int generation)
+      {
+        Node oldref = leftnode ? cursor.left : cursor.right;
+
+        if (child == oldref)
+          return false;
+
+        bool retval = false;
+
+        if (cursor.generation <= maxsnapid)
+        {
+#if SEPARATE_EXTRA
+					if (cursor.extra == null)
+					{
+						Extra extra = cursor.extra = new Extra();	
+
+						extra.leftnode = leftnode;
+						extra.lastgeneration = maxsnapid;
+						extra.oldref = oldref;
+					}
+					else if (cursor.extra.leftnode != leftnode || cursor.extra.lastgeneration < maxsnapid)
+#else
+          if (cursor.lastgeneration == -1)
+          {
+            cursor.leftnode = leftnode;
+            cursor.lastgeneration = maxsnapid;
+            cursor.oldref = oldref;
+          }
+          else if (cursor.leftnode != leftnode || cursor.lastgeneration < maxsnapid)
+#endif
+          {
+            CopyNode(ref cursor, maxsnapid, generation);
+            retval = true;
+          }
+        }
+
+        if (leftnode)
+          cursor.left = child;
+        else
+          cursor.right = child;
+
+        return retval;
+      }
+
+
+      //If cursor.extra.lastgeneration==maxsnapid, the extra pointer will 
+      //always be used in the old copy of cursor. Therefore, after 
+      //making the clone, we should update the old copy by restoring
+      //the child pointer and setting extra to null.
+      //OTOH then we cannot clean up unused Extra objects unless we link
+      //them together in a doubly linked list.
+      public static bool CopyNode(ref Node cursor, int maxsnapid, int generation)
+      {
+        if (cursor.generation <= maxsnapid)
+        {
+          cursor = (Node)(cursor.MemberwiseClone());
+          cursor.generation = generation;
+#if SEPARATE_EXTRA
+					cursor.extra = null;
+#else
+          cursor.lastgeneration = -1;
+#endif
+          return true;
+        }
+        else
+          return false;
+      }
+
+#endif
+    }
+
+    #endregion
+
+    #region Constructors
+
+    /// <summary>
+    /// Create a red-black tree collection with natural comparer and item equalityComparer.
+    /// We assume that if <code>T</code> is comparable, its default equalityComparer 
+    /// will be compatible with the comparer.
+    /// </summary>
+    /// <exception cref="NotComparableException">If <code>T</code> is not comparable.
+    /// </exception>
+    public TreeSet() : this(Comparer<T>.Default, EqualityComparer<T>.Default) { }
+
+
+    /// <summary>
+    /// Create a red-black tree collection with an external comparer. 
+    /// <para>The itemequalityComparer will be a compatible 
+    /// <see cref="T:C5.ComparerZeroHashCodeEqualityComparer`1"/> since the 
+    /// default equalityComparer for T (<see cref="P:C5.EqualityComparer`1.Default"/>)
+    /// is unlikely to be compatible with the external comparer. This makes the
+    /// tree inadequate for use as item in a collection of unsequenced or sequenced sets or bags
+    /// (<see cref="T:C5.ICollection`1"/> and <see cref="T:C5.ISequenced`1"/>)
+    /// </para>
+    /// </summary>
+    /// <param name="comparer">The external comparer</param>
+    public TreeSet(SCG.IComparer<T> comparer) : this(comparer, new ComparerZeroHashCodeEqualityComparer<T>(comparer)) { }
+
+    /// <summary>
+    /// Create a red-black tree collection with an external comparer and an external
+    /// item equalityComparer, assumed consistent.
+    /// </summary>
+    /// <param name="comparer">The external comparer</param>
+    /// <param name="equalityComparer">The external item equalityComparer</param>
+    public TreeSet(SCG.IComparer<T> comparer, SCG.IEqualityComparer<T> equalityComparer)
+      : base(equalityComparer)
+    {
+      if (comparer == null)
+        throw new NullReferenceException("Item comparer cannot be null");
+      this.comparer = comparer;
+    }
+
+    #endregion
+
+    #region TreeSet.Enumerator nested class
+
+    /// <summary>
+    /// An enumerator for a red-black tree collection. Based on an explicit stack
+    /// of subtrees waiting to be enumerated. Currently only used for the tree set 
+    /// enumerators (tree bag enumerators use an iterator block based enumerator).
+    /// </summary>
+    internal class Enumerator : SCG.IEnumerator<T>
+    {
+      #region Private Fields
+      TreeSet<T> tree;
+
+      bool valid = false;
+
+      int stamp;
+
+      T current;
+
+      Node cursor;
+
+      Node[] path; // stack of nodes
+
+      int level = 0;
+      #endregion
+      /// <summary>
+      /// Create a tree enumerator
+      /// </summary>
+      /// <param name="tree">The red-black tree to enumerate</param>
+      public Enumerator(TreeSet<T> tree)
+      {
+        this.tree = tree;
+        stamp = tree.stamp;
+        path = new Node[2 * tree.blackdepth];
+        cursor = new Node();
+        cursor.right = tree.root;
+      }
+
+
+      /// <summary>
+      /// Undefined if enumerator is not valid (MoveNext hash been called returning true)
+      /// </summary>
+      /// <value>The current item of the enumerator.</value>
+      [Tested]
+      public T Current
+      {
+        [Tested]
+        get
+        {
+          if (valid)
+            return current;
+          else
+            throw new InvalidOperationException();
+        }
+      }
+
+
+      //Maintain a stack of nodes that are roots of
+      //subtrees not completely exported yet. Invariant:
+      //The stack nodes together with their right subtrees
+      //consists of exactly the items we have not passed
+      //yet (the top of the stack holds current item).
+      /// <summary>
+      /// Move enumerator to next item in tree, or the first item if
+      /// this is the first call to MoveNext. 
+      /// <exception cref="CollectionModifiedException"/> if underlying tree was modified.
+      /// </summary>
+      /// <returns>True if enumerator is valid now</returns>
+      [Tested]
+      public bool MoveNext()
+      {
+        tree.modifycheck(stamp);
+        if (cursor.right != null)
+        {
+          path[level] = cursor = cursor.right;
+          while (cursor.left != null)
+            path[++level] = cursor = cursor.left;
+        }
+        else if (level == 0)
+          return valid = false;
+        else
+          cursor = path[--level];
+
+        current = cursor.item;
+        return valid = true;
+      }
+
+
+      #region IDisposable Members for Enumerator
+
+      bool disposed;
+
+
+      /// <summary>
+      /// Call Dispose(true) and then suppress finalization of this enumerator.
+      /// </summary>
+      [Tested]
+      public void Dispose()
+      {
+        Dispose(true);
+        GC.SuppressFinalize(this);
+      }
+
+
+      /// <summary>
+      /// Remove the internal data (notably the stack array).
+      /// </summary>
+      /// <param name="disposing">True if called from Dispose(),
+      /// false if called from the finalizer</param>
+      protected virtual void Dispose(bool disposing)
+      {
+        if (!disposed)
+        {
+          if (disposing)
+          {
+          }
+
+          current = default(T);
+          cursor = null;
+          path = null;
+          disposed = true;
+        }
+      }
+
+
+      /// <summary>
+      /// Finalizer for enumerator
+      /// </summary>
+      ~Enumerator()
+      {
+        Dispose(false);
+      }
+      #endregion
+
+
+      #region IEnumerator Members
+
+      object System.Collections.IEnumerator.Current
+      {
+        get { return Current; }
+      }
+
+      bool System.Collections.IEnumerator.MoveNext()
+      {
+        return MoveNext();
+      }
+
+      void System.Collections.IEnumerator.Reset()
+      {
+        throw new Exception("The method or operation is not implemented.");
+      }
+
+      #endregion
+    }
+#if NCP
+    /// <summary>
+    /// An enumerator for a snapshot of a node copy persistent red-black tree
+    /// collection.
+    /// </summary>
+    internal class SnapEnumerator : SCG.IEnumerator<T>
+    {
+      #region Private Fields
+      TreeSet<T> tree;
+
+      bool valid = false;
+
+      int stamp;
+#if BAG
+      int togo;
+#endif
+
+      T current;
+
+      Node cursor;
+
+      Node[] path; // stack of nodes
+
+      int level;
+      #endregion
+
+      /// <summary>
+      /// Creta an enumerator for a snapshot of a node copy persistent red-black tree
+      /// collection
+      /// </summary>
+      /// <param name="tree">The snapshot</param>
+      public SnapEnumerator(TreeSet<T> tree)
+      {
+        this.tree = tree;
+        stamp = tree.stamp;
+        path = new Node[2 * tree.blackdepth];
+        cursor = new Node();
+        cursor.right = tree.root;
+      }
+
+
+      #region SCG.IEnumerator<T> Members
+
+      /// <summary>
+      /// Move enumerator to next item in tree, or the first item if
+      /// this is the first call to MoveNext. 
+      /// <exception cref="CollectionModifiedException"/> if underlying tree was modified.
+      /// </summary>
+      /// <returns>True if enumerator is valid now</returns>
+      [Tested]
+      public bool MoveNext()
+      {
+        tree.modifycheck(stamp);//???
+
+#if BAG
+        if (--togo > 0)
+          return true;
+#endif
+        Node next = tree.right(cursor);
+
+        if (next != null)
+        {
+          path[level] = cursor = next;
+          next = tree.left(cursor);
+          while (next != null)
+          {
+            path[++level] = cursor = next;
+            next = tree.left(cursor);
+          }
+        }
+        else if (level == 0)
+          return valid = false;
+        else
+          cursor = path[--level];
+
+#if BAG
+        togo = cursor.items;
+#endif
+        current = cursor.item;
+        return valid = true;
+      }
+
+
+      /// <summary>
+      /// Undefined if enumerator is not valid (MoveNext hash been called returning true)
+      /// </summary>
+      /// <value>The current value of the enumerator.</value>
+      [Tested]
+      public T Current
+      {
+        [Tested]
+        get
+        {
+          if (valid)
+            return current;
+          else
+            throw new InvalidOperationException();
+        }
+      }
+
+      #endregion
+
+      #region IDisposable Members
+
+      [Tested]
+      void System.IDisposable.Dispose()
+      {
+        tree = null;
+        valid = false;
+        current = default(T);
+        cursor = null;
+        path = null;
+      }
+
+      #endregion
+
+      #region IEnumerator Members
+
+      object System.Collections.IEnumerator.Current
+      {
+        get { return Current; }
+      }
+
+      bool System.Collections.IEnumerator.MoveNext()
+      {
+        return MoveNext();
+      }
+
+      void System.Collections.IEnumerator.Reset()
+      {
+        throw new Exception("The method or operation is not implemented.");
+      }
+
+      #endregion
+    }
+#endif
+    #endregion
+
+    #region IEnumerable<T> Members
+
+    private SCG.IEnumerator<T> getEnumerator(Node node, int origstamp)
+    {
+      if (node == null)
+        yield break;
+
+      if (node.left != null)
+      {
+        SCG.IEnumerator<T> child = getEnumerator(node.left, origstamp);
+
+        while (child.MoveNext())
+        {
+          modifycheck(origstamp);
+          yield return child.Current;
+        }
+      }
+#if BAG
+      int togo = node.items;
+      while (togo-- > 0)
+      {
+        modifycheck(origstamp);
+        yield return node.item;
+      }
+#else
+      modifycheck(origstamp);
+      yield return node.item;
+#endif
+      if (node.right != null)
+      {
+        SCG.IEnumerator<T> child = getEnumerator(node.right, origstamp);
+
+        while (child.MoveNext())
+        {
+          modifycheck(origstamp);
+          yield return child.Current;
+        }
+      }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="NoSuchItemException">If tree is empty</exception>
+    /// <returns></returns>
+    [Tested]
+    public override T Choose()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+
+      if (size == 0)
+        throw new NoSuchItemException();
+      return root.item;
+    }
+
+
+    /// <summary>
+    /// Create an enumerator for this tree
+    /// </summary>
+    /// <returns>The enumerator</returns>
+    [Tested]
+    public override SCG.IEnumerator<T> GetEnumerator()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+#if NCP
+      if (isSnapShot)
+        return new SnapEnumerator(this);
+#endif
+#if BAG
+      return getEnumerator(root, stamp);
+#else
+      return new Enumerator(this);
+#endif
+    }
+
+    #endregion
+
+    #region ISink<T> Members
+
+    /// <summary>
+    /// Add item to tree. If already there, return the found item in the second argument.
+    /// </summary>
+    /// <param name="item">Item to add</param>
+    /// <param name="founditem">item found</param>
+    /// <param name="update">whether item in node should be updated</param>
+    /// <param name="wasfound">true if found in bag, false if not found or tre is a set</param>
+    /// <returns>True if item was added</returns>
+    bool addIterative(T item, ref T founditem, bool update, out bool wasfound)
+    {
+      wasfound = false;
+      if (root == null)
+      {
+        root = new Node();
+        root.red = false;
+        blackdepth = 1;
+        root.item = item;
+#if NCP
+        root.generation = generation;
+#endif
+        return true;
+      }
+
+      stackcheck();
+
+      int level = 0;
+      Node cursor = root;
+
+      while (true)
+      {
+        int comp = comparer.Compare(cursor.item, item);
+
+        if (comp == 0)
+        {
+          founditem = cursor.item;
+#if BAG
+          wasfound = true;
+          bool nodeWasUpdated = true;
+#if NCP
+          Node.CopyNode(ref cursor, maxsnapid, generation);
+#endif
+          if (update)
+            cursor.item = item;
+          else
+          {
+            cursor.items++;
+            cursor.size++;
+          }
+#else
+          bool nodeWasUpdated = update;
+          if (update)
+          {
+#if NCP
+            Node.CopyNode(ref cursor, maxsnapid, generation);
+#endif
+            cursor.item = item;
+          }
+#endif
+
+          while (level-- > 0)
+          {
+            if (nodeWasUpdated)
+            {
+              Node kid = cursor;
+
+              cursor = path[level];
+#if NCP
+              Node.update(ref cursor, dirs[level] > 0, kid, maxsnapid, generation);
+#endif
+#if BAG
+              if (!update)
+                cursor.size++;
+#endif
+            }
+
+            path[level] = null;
+          }
+#if BAG
+          return !update;
+#else
+          if (update)
+            root = cursor;
+
+          return false;
+#endif
+        }
+
+        //else
+        Node child = comp > 0 ? cursor.left : cursor.right;
+
+        if (child == null)
+        {
+          child = new Node();
+          child.item = item;
+#if NCP
+          child.generation = generation;
+          Node.update(ref cursor, comp > 0, child, maxsnapid, generation);
+#else
+					if (comp > 0) { cursor.left = child; }
+					else { cursor.right = child; }
+#endif
+#if MAINTAIN_SIZE
+          cursor.size++;
+#endif
+          dirs[level] = comp;
+          break;
+        }
+        else
+        {
+          dirs[level] = comp;
+          path[level++] = cursor;
+          cursor = child;
+        }
+      }
+
+      //We have just added the red node child to "cursor"
+      while (cursor.red)
+      {
+        //take one step up:
+        Node child = cursor;
+
+        cursor = path[--level];
+        path[level] = null;
+#if NCP
+        Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);
+#endif
+#if MAINTAIN_SIZE
+        cursor.size++;
+#endif
+        int comp = dirs[level];
+        Node childsibling = comp > 0 ? cursor.right : cursor.left;
+
+        if (childsibling != null && childsibling.red)
+        {
+          //Promote
+          child.red = false;
+#if NCP
+          Node.update(ref cursor, comp < 0, childsibling, maxsnapid, generation);
+#endif
+          childsibling.red = false;
+
+          //color cursor red & take one step up the tree unless at root
+          if (level == 0)
+          {
+            root = cursor;
+            blackdepth++;
+            return true;
+          }
+          else
+          {
+            cursor.red = true;
+#if NCP
+            child = cursor;
+            cursor = path[--level];
+            Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);
+#endif
+            path[level] = null;
+#if MAINTAIN_SIZE
+            cursor.size++;
+#endif
+          }
+        }
+        else
+        {
+          //ROTATE!!!
+          int childcomp = dirs[level + 1];
+
+          cursor.red = true;
+          if (comp > 0)
+          {
+            if (childcomp > 0)
+            {//zagzag
+#if NCP
+              Node.update(ref cursor, true, child.right, maxsnapid, generation);
+              Node.update(ref child, false, cursor, maxsnapid, generation);
+#else
+							cursor.left = child.right;
+							child.right = cursor;
+#endif
+              cursor = child;
+            }
+            else
+            {//zagzig
+              Node badgrandchild = child.right;
+#if NCP
+              Node.update(ref cursor, true, badgrandchild.right, maxsnapid, generation);
+              Node.update(ref child, false, badgrandchild.left, maxsnapid, generation);
+              Node.CopyNode(ref badgrandchild, maxsnapid, generation);
+#else
+							cursor.left = badgrandchild.right;
+							child.right = badgrandchild.left;
+#endif
+              badgrandchild.left = child;
+              badgrandchild.right = cursor;
+              cursor = badgrandchild;
+            }
+          }
+          else
+          {//comp < 0
+            if (childcomp < 0)
+            {//zigzig
+#if NCP
+              Node.update(ref cursor, false, child.left, maxsnapid, generation);
+              Node.update(ref child, true, cursor, maxsnapid, generation);
+#else
+							cursor.right = child.left;
+							child.left = cursor;
+#endif
+              cursor = child;
+            }
+            else
+            {//zigzag
+              Node badgrandchild = child.left;
+#if NCP
+              Node.update(ref cursor, false, badgrandchild.left, maxsnapid, generation);
+              Node.update(ref child, true, badgrandchild.right, maxsnapid, generation);
+              Node.CopyNode(ref badgrandchild, maxsnapid, generation);
+#else
+							cursor.right = badgrandchild.left;
+							child.left = badgrandchild.right;
+#endif
+              badgrandchild.right = child;
+              badgrandchild.left = cursor;
+              cursor = badgrandchild;
+            }
+          }
+
+          cursor.red = false;
+
+#if MAINTAIN_SIZE
+          Node n;
+
+#if BAG
+          n = cursor.right;
+          cursor.size = n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items;
+          n = cursor.left;
+          n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items;
+          cursor.size += n.size + cursor.items;
+#else
+          n = cursor.right;
+          cursor.size = n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;
+          n = cursor.left;
+          n.size = (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;
+          cursor.size += n.size + 1;
+#endif
+#endif
+          if (level == 0)
+          {
+            root = cursor;
+            return true;
+          }
+          else
+          {
+            child = cursor;
+            cursor = path[--level];
+            path[level] = null;
+#if NCP
+            Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);
+#else
+						if (dirs[level] > 0)
+							cursor.left = child;
+						else
+							cursor.right = child;
+#endif
+#if MAINTAIN_SIZE
+            cursor.size++;
+#endif
+            break;
+          }
+        }
+      }
+#if NCP
+      bool stillmore = true;
+#endif
+      while (level > 0)
+      {
+        Node child = cursor;
+
+        cursor = path[--level];
+        path[level] = null;
+#if NCP
+        if (stillmore)
+          stillmore = Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);
+#endif
+#if MAINTAIN_SIZE
+        cursor.size++;
+#endif
+      }
+
+      root = cursor;
+      return true;
+    }
+
+
+    /// <summary>
+    /// Add an item to this collection if possible. If this collection has set
+    /// semantics, the item will be added if not already in the collection. If
+    /// bag semantics, the item will always be added.
+    /// </summary>
+    /// <param name="item">The item to add.</param>
+    /// <returns>True if item was added.</returns>
+    [Tested]
+    public bool Add(T item)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+
+      //Note: blackdepth of the tree is set inside addIterative
+      T jtem = default(T);
+      if (!add(item, ref jtem))
+        return false;
+      if (ActiveEvents != 0)
+        raiseForAdd(jtem);
+      return true;
+    }
+
+    /// <summary>
+    /// Add an item to this collection if possible. If this collection has set
+    /// semantics, the item will be added if not already in the collection. If
+    /// bag semantics, the item will always be added.
+    /// </summary>
+    /// <param name="item">The item to add.</param>
+    [Tested]
+    void SCG.ICollection<T>.Add(T item)
+    {
+        Add(item);
+    }
+
+    private bool add(T item, ref T j)
+    {
+      bool wasFound;
+
+      if (addIterative(item, ref j, false, out wasFound))
+      {
+        size++;
+        if (!wasFound)
+          j = item;
+        return true;
+      }
+      else
+        return false;
+    }
+
+    /// <summary>
+    /// Add the elements from another collection with a more specialized item type 
+    /// to this collection. If this
+    /// collection has set semantics, only items not already in the collection
+    /// will be added.
+    /// </summary>
+    /// <typeparam name="U">The type of items to add</typeparam>
+    /// <param name="items">The items to add</param>
+    [Tested]
+    public void AddAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+
+      int c = 0;
+      T j = default(T);
+      bool tmp;
+
+      bool raiseAdded = (ActiveEvents & EventTypeEnum.Added) != 0;
+      CircularQueue<T> wasAdded = raiseAdded ? new CircularQueue<T>() : null;
+
+      foreach (T i in items)
+        if (addIterative(i, ref j, false, out tmp))
+        {
+          c++;
+          if (raiseAdded)
+            wasAdded.Enqueue(tmp ? j : i);
+        }
+      if (c == 0)
+        return;
+
+      size += c;
+      //TODO: implement a RaiseForAddAll() method
+      if (raiseAdded)
+        foreach (T item in wasAdded)
+          raiseItemsAdded(item, 1);
+      if (((ActiveEvents & EventTypeEnum.Changed) != 0))
+        raiseCollectionChanged();
+    }
+
+
+    /// <summary>
+    /// Add all the items from another collection with an enumeration order that 
+    /// is increasing in the items. <para>The idea is that the implementation may use
+    /// a faster algorithm to merge the two collections.</para>
+    /// <exception cref="ArgumentException"/> if the enumerated items turns out
+    /// not to be in increasing order.
+    /// </summary>
+    /// <param name="items">The collection to add.</param>
+    /// <typeparam name="U"></typeparam>
+    [Tested]
+    public void AddSorted<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      if (size > 0)
+        AddAll(items);
+      else
+      {
+        if (!isValid)
+          throw new ViewDisposedException("Snapshot has been disposed");
+        updatecheck();
+        addSorted(items, true, true);
+      }
+    }
+
+    #region add-sorted helpers
+
+    //Create a RB tree from x+2^h-1  (x < 2^h, h>=1) nodes taken from a
+    //singly linked list of red nodes using only the right child refs.
+    //The x nodes at depth h+1 will be red, the rest black.
+    //(h is the blackdepth of the resulting tree)
+    static Node maketreer(ref Node rest, int blackheight, int maxred, int red)
+    {
+      if (blackheight == 1)
+      {
+        Node top = rest;
+
+        rest = rest.right;
+        if (red > 0)
+        {
+          top.right = null;
+          rest.left = top;
+          top = rest;
+#if BAG
+          top.size += top.left.size;
+#elif MAINTAIN_SIZE
+          top.size = 1 + red;
+#endif
+          rest = rest.right;
+          red--;
+        }
+
+        if (red > 0)
+        {
+#if BAG
+          top.size += rest.size;
+#endif
+          top.right = rest;
+          rest = rest.right;
+          top.right.right = null;
+        }
+        else
+          top.right = null;
+
+        top.red = false;
+        return top;
+      }
+      else
+      {
+        maxred >>= 1;
+
+        int lred = red > maxred ? maxred : red;
+        Node left = maketreer(ref rest, blackheight - 1, maxred, lred);
+        Node top = rest;
+
+        rest = rest.right;
+        top.left = left;
+        top.red = false;
+        top.right = maketreer(ref rest, blackheight - 1, maxred, red - lred);
+#if BAG
+        top.size = top.items + top.left.size + top.right.size;
+#elif MAINTAIN_SIZE
+        top.size = (maxred << 1) - 1 + red;
+#endif
+        return top;
+      }
+    }
+
+
+    void addSorted<U>(SCG.IEnumerable<U> items, bool safe, bool raise) where U : T
+    {
+      SCG.IEnumerator<U> e = items.GetEnumerator(); ;
+      if (size > 0)
+        throw new InternalException("This can't happen");
+
+      if (!e.MoveNext())
+        return;
+
+      //To count theCollect 
+      Node head = new Node(), tail = head;
+      int z = 1;
+      T lastitem = tail.item = e.Current;
+#if BAG
+      int ec = 0;
+#endif
+
+      while (e.MoveNext())
+      {
+#if BAG
+        T thisitem = e.Current;
+        int comp = comparer.Compare(lastitem, thisitem);
+        if (comp > 0)
+          throw new ArgumentException("Argument not sorted");
+        if (comp == 0)
+        {
+          tail.items++;
+          ec++;
+        }
+        else
+        {
+          tail.size = tail.items;
+          z++;
+          tail.right = new Node();
+          tail = tail.right;
+          lastitem = tail.item = thisitem;
+#if NCP
+          tail.generation = generation;
+#endif
+        }
+#else
+        z++;
+        tail.right = new Node();
+        tail = tail.right;
+        tail.item = e.Current;
+        if (safe)
+        {
+          if (comparer.Compare(lastitem, tail.item) >= 0)
+            throw new ArgumentException("Argument not sorted");
+
+          lastitem = tail.item;
+        }
+#if NCP
+        tail.generation = generation;
+#endif
+#endif
+      }
+#if BAG
+      tail.size = tail.items;
+#endif
+      int blackheight = 0, red = z, maxred = 1;
+
+      while (maxred <= red)
+      {
+        red -= maxred;
+        maxred <<= 1;
+        blackheight++;
+      }
+
+      root = TreeSet<T>.maketreer(ref head, blackheight, maxred, red);
+      blackdepth = blackheight;
+      size = z;
+#if BAG
+      size += ec;
+#endif
+
+      if (raise)
+      {
+        if ((ActiveEvents & EventTypeEnum.Added) != 0)
+        {
+          CircularQueue<T> wasAdded = new CircularQueue<T>();
+          foreach (T item in this)
+            wasAdded.Enqueue(item);
+          foreach (T item in wasAdded)
+            raiseItemsAdded(item, 1);
+        }
+        if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+          raiseCollectionChanged();
+      }
+      return;
+    }
+
+    #endregion
+
+#if BAG
+    /// <summary></summary>
+    /// <value>True since this collection has bag semantics.</value>
+    [Tested]
+    public bool AllowsDuplicates { [Tested]get { return true; } }
+#else
+    /// <summary></summary>
+    /// <value>False since this tree has set semantics.</value>
+    [Tested]
+    public bool AllowsDuplicates { [Tested]get { return false; } }
+#endif
+    /// <summary>
+    /// By convention this is true for any collection with set semantics.
+    /// </summary>
+    /// <value>True if only one representative of a group of equal items 
+    /// is kept in the collection together with the total count.</value>
+    public virtual bool DuplicatesByCounting { get { return true; } }
+
+    #endregion
+
+    #region IEditableCollection<T> Members
+
+
+    /// <summary>
+    /// The value is symbolic indicating the type of asymptotic complexity
+    /// in terms of the size of this collection (worst-case or amortized as
+    /// relevant).
+    /// </summary>
+    /// <value>Speed.Log</value>
+    [Tested]
+    public Speed ContainsSpeed { [Tested]get { return Speed.Log; } }
+
+    /// <summary>
+    /// Check if this collection contains (an item equivalent to according to the
+    /// itemequalityComparer) a particular value.
+    /// </summary>
+    /// <param name="item">The value to check for.</param>
+    /// <returns>True if the items is in this collection.</returns>
+    [Tested]
+    public bool Contains(T item)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      Node next; int comp = 0;
+
+      next = root;
+      while (next != null)
+      {
+        comp = comparer.Compare(next.item, item);
+        if (comp == 0)
+          return true;
+
+        next = comp < 0 ? right(next) : left(next);
+      }
+
+      return false;
+    }
+
+
+    //Variant for dictionary use
+    //Will return the actual matching item in the ref argument.
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, return in the ref argument (a
+    /// binary copy of) the actual value found.
+    /// </summary>
+    /// <param name="item">The value to look for.</param>
+    /// <returns>True if the items is in this collection.</returns>
+    [Tested]
+    public bool Find(ref T item)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      Node next; int comp = 0;
+
+      next = root;
+      while (next != null)
+      {
+        comp = comparer.Compare(next.item, item);
+        if (comp == 0)
+        {
+          item = next.item;
+          return true;
+        }
+
+        next = comp < 0 ? right(next) : left(next);
+      }
+
+      return false;
+    }
+
+
+    /// <summary>
+    /// Find or add the item to the tree. If the tree does not contain
+    /// an item equivalent to this item add it, else return the exisiting
+    /// one in the ref argument. 
+    ///
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns>True if item was found</returns>
+    [Tested]
+    public bool FindOrAdd(ref T item)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+      bool wasfound;
+
+      //Note: blackdepth of the tree is set inside addIterative
+      if (addIterative(item, ref item, false, out wasfound))
+      {
+        size++;
+        if (ActiveEvents != 0 && !wasfound)
+          raiseForAdd(item);
+        return wasfound;
+      }
+      else
+        return true;
+
+    }
+
+
+    //For dictionary use. 
+    //If found, the matching entry will be updated with the new item.
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// to with a binary copy of the supplied value. If the collection has bag semantics,
+    /// this updates all equivalent copies in
+    /// the collection.
+    /// </summary>
+    /// <param name="item">Value to update.</param>
+    /// <returns>True if the item was found and hence updated.</returns>
+    [Tested]
+    public bool Update(T item)
+    {
+      T olditem = item;
+      return Update(item, out olditem);
+    }
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// with a binary copy of the supplied value. If the collection has bag semantics,
+    /// this updates all equivalent copies in
+    /// the collection.
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public bool Update(T item, out T olditem)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+#if NCP
+      stackcheck();
+
+      int level = 0;
+#endif
+      Node cursor = root;
+      int comp = 0;
+
+      while (cursor != null)
+      {
+        comp = comparer.Compare(cursor.item, item);
+        if (comp == 0)
+        {
+#if NCP
+          Node.CopyNode(ref cursor, maxsnapid, generation);
+#endif
+          olditem = cursor.item;
+#if BAG
+          int items = cursor.items;
+#endif
+          cursor.item = item;
+#if NCP
+          while (level > 0)
+          {
+            Node child = cursor;
+
+            cursor = path[--level];
+            path[level] = null;
+#if NCP
+            Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);
+#else
+						if (Node.CopyNode(maxsnapid, ref cursor, generation))
+						{
+							if (dirs[level] > 0)
+								cursor.left = child;
+							else
+								cursor.right = child;
+						}
+#endif
+          }
+
+          root = cursor;
+#endif
+#if BAG
+          if (ActiveEvents != 0)
+            raiseForUpdate(item, olditem, items);
+#else
+          if (ActiveEvents != 0)
+            raiseForUpdate(item, olditem);
+#endif
+          return true;
+        }
+#if NCP
+        dirs[level] = comp;
+        path[level++] = cursor;
+#endif
+        cursor = comp < 0 ? cursor.right : cursor.left;
+      }
+
+      olditem = default(T);
+      return false;
+    }
+
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// with a binary copy of the supplied value; else add the value to the collection. 
+    ///
+    /// <i>NOTE: the bag implementation is currently wrong! ?????</i>
+    /// </summary>
+    /// <param name="item">Value to add or update.</param>
+    /// <returns>True if the item was found and updated (hence not added).</returns>
+    [Tested]
+    public bool UpdateOrAdd(T item)
+    { T olditem; return UpdateOrAdd(item, out olditem); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public bool UpdateOrAdd(T item, out T olditem)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+      bool wasfound;
+      olditem = default(T);
+
+
+      //Note: blackdepth of the tree is set inside addIterative
+      if (addIterative(item, ref olditem, true, out wasfound))
+      {
+        size++;
+        if (ActiveEvents != 0)
+          raiseForAdd(wasfound ? olditem : item);
+        return wasfound;
+      }
+      else
+      {
+#warning for bag implementation: count is wrong
+        if (ActiveEvents != 0)
+          raiseForUpdate(item, olditem, 1);
+        return true;
+      }
+    }
+
+
+    /// <summary>
+    /// Remove a particular item from this collection. If the collection has bag
+    /// semantics only one copy equivalent to the supplied item is removed. 
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    /// <returns>True if the item was found (and removed).</returns>
+    [Tested]
+    public bool Remove(T item)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+      if (root == null)
+        return false;
+
+      int junk;
+      bool retval = removeIterative(ref item, false, out junk);
+      if (ActiveEvents != 0 && retval)
+        raiseForRemove(item);
+      return retval;
+    }
+
+    /// <summary>
+    /// Remove a particular item from this collection if found. If the collection
+    /// has bag semantics only one copy equivalent to the supplied item is removed,
+    /// which one is implementation dependent. 
+    /// If an item was removed, report a binary copy of the actual item removed in 
+    /// the argument.
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    /// <param name="removeditem">The removed value.</param>
+    /// <returns>True if the item was found (and removed).</returns>
+    [Tested]
+    public bool Remove(T item, out T removeditem)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+      removeditem = item;
+      if (root == null)
+        return false;
+
+      int junk;
+      bool retval = removeIterative(ref removeditem, false, out junk);
+      if (ActiveEvents != 0 && retval)
+        raiseForRemove(item);
+      return retval;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item">input: item to remove; output: item actually removed</param>
+    /// <param name="all">If true, remove all copies</param>
+    /// <param name="wasRemoved"></param>
+    /// <returns></returns>
+    private bool removeIterative(ref T item, bool all, out int wasRemoved)
+    {
+      wasRemoved = 0;
+      //Stage 1: find item
+      stackcheck();
+
+      int level = 0, comp;
+      Node cursor = root;
+
+      while (true)
+      {
+        comp = comparer.Compare(cursor.item, item);
+        if (comp == 0)
+        {
+          item = cursor.item;
+#if BAG
+          if (!all && cursor.items > 1)
+          {
+#if NCP
+            Node.CopyNode(ref cursor, maxsnapid, generation);
+#endif
+            cursor.items--;
+            cursor.size--;
+            while (level-- > 0)
+            {
+              Node kid = cursor;
+
+              cursor = path[level];
+#if NCP
+              Node.update(ref cursor, dirs[level] > 0, kid, maxsnapid, generation);
+#endif
+              cursor.size--;
+              path[level] = null;
+            }
+            size--;
+            wasRemoved = 1;
+            return true;
+          }
+          wasRemoved = cursor.items;
+#else
+          wasRemoved = 1;
+#endif
+          break;
+        }
+
+        Node child = comp > 0 ? cursor.left : cursor.right;
+
+        if (child == null)
+          return false;
+
+        dirs[level] = comp;
+        path[level++] = cursor;
+        cursor = child;
+      }
+
+      return removeIterativePhase2(cursor, level);
+    }
+
+
+    private bool removeIterativePhase2(Node cursor, int level)
+    {
+      if (size == 1)
+      {
+        clear();
+        return true;
+      }
+
+#if BAG
+      int removedcount = cursor.items;
+      size -= removedcount;
+#else
+      //We are certain to remove one node:
+      size--;
+#endif
+      //Stage 2: if item's node has no null child, find predecessor
+      int level_of_item = level;
+
+      if (cursor.left != null && cursor.right != null)
+      {
+        dirs[level] = 1;
+        path[level++] = cursor;
+        cursor = cursor.left;
+        while (cursor.right != null)
+        {
+          dirs[level] = -1;
+          path[level++] = cursor;
+          cursor = cursor.right;
+        }
+#if NCP
+        Node.CopyNode(ref path[level_of_item], maxsnapid, generation);
+#endif
+        path[level_of_item].item = cursor.item;
+#if BAG
+        path[level_of_item].items = cursor.items;
+#endif
+      }
+
+      //Stage 3: splice out node to be removed
+      Node newchild = cursor.right == null ? cursor.left : cursor.right;
+      bool demote_or_rotate = newchild == null && !cursor.red;
+
+      //assert newchild.red 
+      if (newchild != null)
+      {
+        newchild.red = false;
+      }
+
+      if (level == 0)
+      {
+        root = newchild;
+        return true;
+      }
+
+      level--;
+      cursor = path[level];
+      path[level] = null;
+
+      int comp = dirs[level];
+      Node childsibling;
+#if NCP
+      Node.update(ref cursor, comp > 0, newchild, maxsnapid, generation);
+#else
+			if (comp > 0)
+				cursor.left = newchild;
+			else
+				cursor.right = newchild;
+#endif
+      childsibling = comp > 0 ? cursor.right : cursor.left;
+#if BAG
+      cursor.size -= removedcount;
+#elif MAINTAIN_SIZE
+      cursor.size--;
+#endif
+
+      //Stage 4: demote till we must rotate
+      Node farnephew = null, nearnephew = null;
+
+      while (demote_or_rotate)
+      {
+        if (childsibling.red)
+          break; //rotate 2+?
+
+        farnephew = comp > 0 ? childsibling.right : childsibling.left;
+        if (farnephew != null && farnephew.red)
+          break; //rotate 1b
+
+        nearnephew = comp > 0 ? childsibling.left : childsibling.right;
+        if (nearnephew != null && nearnephew.red)
+          break; //rotate 1c
+
+        //demote cursor
+        childsibling.red = true;
+        if (level == 0)
+        {
+          cursor.red = false;
+          blackdepth--;
+#if NCP
+          root = cursor;
+#endif
+          return true;
+        }
+        else if (cursor.red)
+        {
+          cursor.red = false;
+          demote_or_rotate = false;
+          break; //No rotation
+        }
+        else
+        {
+          Node child = cursor;
+
+          cursor = path[--level];
+          path[level] = null;
+          comp = dirs[level];
+          childsibling = comp > 0 ? cursor.right : cursor.left;
+#if NCP
+          Node.update(ref cursor, comp > 0, child, maxsnapid, generation);
+#endif
+#if BAG
+          cursor.size -= removedcount;
+#elif MAINTAIN_SIZE
+          cursor.size--;
+#endif
+        }
+      }
+
+      //Stage 5: rotate 
+      if (demote_or_rotate)
+      {
+        //At start:
+        //parent = cursor (temporary for swapping nodes)
+        //childsibling is the sibling of the updated child (x)
+        //cursor is always the top of the subtree
+        Node parent = cursor;
+
+        if (childsibling.red)
+        {//Case 2 and perhaps more. 
+          //The y.rank == px.rank >= x.rank+2 >=2 so both nephews are != null 
+          //(and black). The grandnephews are children of nearnephew
+          Node neargrandnephew, fargrandnephew;
+
+          if (comp > 0)
+          {
+            nearnephew = childsibling.left;
+            farnephew = childsibling.right;
+            neargrandnephew = nearnephew.left;
+            fargrandnephew = nearnephew.right;
+          }
+          else
+          {
+            nearnephew = childsibling.right;
+            farnephew = childsibling.left;
+            neargrandnephew = nearnephew.right;
+            fargrandnephew = nearnephew.left;
+          }
+
+          if (fargrandnephew != null && fargrandnephew.red)
+          {//Case 2+1b
+#if NCP
+            Node.CopyNode(ref nearnephew, maxsnapid, generation);
+
+            //The end result of this will always be e copy of parent
+            Node.update(ref parent, comp < 0, neargrandnephew, maxsnapid, generation);
+            Node.update(ref childsibling, comp > 0, nearnephew, maxsnapid, generation);
+#endif
+            if (comp > 0)
+            {
+              nearnephew.left = parent;
+              parent.right = neargrandnephew;
+            }
+            else
+            {
+              nearnephew.right = parent;
+              parent.left = neargrandnephew;
+            }
+
+            cursor = childsibling;
+            childsibling.red = false;
+            nearnephew.red = true;
+            fargrandnephew.red = false;
+#if BAG
+            cursor.size = parent.size;
+            nearnephew.size = cursor.size - cursor.items - farnephew.size;
+            parent.size = nearnephew.size - nearnephew.items - fargrandnephew.size;
+#elif MAINTAIN_SIZE
+            cursor.size = parent.size;
+            nearnephew.size = cursor.size - 1 - farnephew.size;
+            parent.size = nearnephew.size - 1 - fargrandnephew.size;
+#endif
+          }
+          else if (neargrandnephew != null && neargrandnephew.red)
+          {//Case 2+1c
+#if NCP
+            Node.CopyNode(ref neargrandnephew, maxsnapid, generation);
+#endif
+            if (comp > 0)
+            {
+#if NCP
+              Node.update(ref childsibling, true, neargrandnephew, maxsnapid, generation);
+              Node.update(ref nearnephew, true, neargrandnephew.right, maxsnapid, generation);
+              Node.update(ref parent, false, neargrandnephew.left, maxsnapid, generation);
+#else
+							childsibling.left = neargrandnephew;
+							nearnephew.left = neargrandnephew.right;
+							parent.right = neargrandnephew.left;
+#endif
+              neargrandnephew.left = parent;
+              neargrandnephew.right = nearnephew;
+            }
+            else
+            {
+#if NCP
+              Node.update(ref childsibling, false, neargrandnephew, maxsnapid, generation);
+              Node.update(ref nearnephew, false, neargrandnephew.left, maxsnapid, generation);
+              Node.update(ref parent, true, neargrandnephew.right, maxsnapid, generation);
+#else
+							childsibling.right = neargrandnephew;
+							nearnephew.right = neargrandnephew.left;
+							parent.left = neargrandnephew.right;
+#endif
+              neargrandnephew.right = parent;
+              neargrandnephew.left = nearnephew;
+            }
+
+            cursor = childsibling;
+            childsibling.red = false;
+#if BAG
+            cursor.size = parent.size;
+            parent.size = parent.items + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);
+            nearnephew.size = nearnephew.items + (nearnephew.left == null ? 0 : nearnephew.left.size) + (nearnephew.right == null ? 0 : nearnephew.right.size);
+            neargrandnephew.size = neargrandnephew.items + parent.size + nearnephew.size;
+#elif MAINTAIN_SIZE
+            cursor.size = parent.size;
+            parent.size = 1 + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);
+            nearnephew.size = 1 + (nearnephew.left == null ? 0 : nearnephew.left.size) + (nearnephew.right == null ? 0 : nearnephew.right.size);
+            neargrandnephew.size = 1 + parent.size + nearnephew.size;
+#endif
+          }
+          else
+          {//Case 2 only
+#if NCP
+            Node.update(ref parent, comp < 0, nearnephew, maxsnapid, generation);
+            Node.update(ref childsibling, comp > 0, parent, maxsnapid, generation);
+#else
+						if (comp > 0)
+						{
+							childsibling.left = parent;
+							parent.right = nearnephew;
+						}
+						else
+						{
+							childsibling.right = parent;
+							parent.left = nearnephew;
+						}
+#endif
+            cursor = childsibling;
+            childsibling.red = false;
+            nearnephew.red = true;
+#if BAG
+            cursor.size = parent.size;
+            parent.size -= farnephew.size + cursor.items;
+#elif MAINTAIN_SIZE
+            cursor.size = parent.size;
+            parent.size -= farnephew.size + 1;
+#endif
+          }
+        }
+        else if (farnephew != null && farnephew.red)
+        {//Case 1b
+          nearnephew = comp > 0 ? childsibling.left : childsibling.right;
+#if NCP
+          Node.update(ref parent, comp < 0, nearnephew, maxsnapid, generation);
+          Node.CopyNode(ref childsibling, maxsnapid, generation);
+          if (comp > 0)
+          {
+            childsibling.left = parent;
+            childsibling.right = farnephew;
+          }
+          else
+          {
+            childsibling.right = parent;
+            childsibling.left = farnephew;
+          }
+#else
+					if (comp > 0)
+					{
+						childsibling.left = parent;
+						parent.right = nearnephew;
+					}
+					else
+					{
+						childsibling.right = parent;
+						parent.left = nearnephew;
+					}
+#endif
+          cursor = childsibling;
+          cursor.red = parent.red;
+          parent.red = false;
+          farnephew.red = false;
+
+#if BAG
+          cursor.size = parent.size;
+          parent.size -= farnephew.size + cursor.items;
+#elif MAINTAIN_SIZE
+          cursor.size = parent.size;
+          parent.size -= farnephew.size + 1;
+#endif
+        }
+        else if (nearnephew != null && nearnephew.red)
+        {//Case 1c
+#if NCP
+          Node.CopyNode(ref nearnephew, maxsnapid, generation);
+#endif
+          if (comp > 0)
+          {
+#if NCP
+            Node.update(ref childsibling, true, nearnephew.right, maxsnapid, generation);
+            Node.update(ref parent, false, nearnephew.left, maxsnapid, generation);
+#else
+						childsibling.left = nearnephew.right;
+						parent.right = nearnephew.left;
+#endif
+            nearnephew.left = parent;
+            nearnephew.right = childsibling;
+          }
+          else
+          {
+#if NCP
+            Node.update(ref childsibling, false, nearnephew.left, maxsnapid, generation);
+            Node.update(ref parent, true, nearnephew.right, maxsnapid, generation);
+#else
+						childsibling.right = nearnephew.left;
+						parent.left = nearnephew.right;
+#endif
+            nearnephew.right = parent;
+            nearnephew.left = childsibling;
+          }
+
+          cursor = nearnephew;
+          cursor.red = parent.red;
+          parent.red = false;
+#if BAG
+          cursor.size = parent.size;
+          parent.size = parent.items + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);
+          childsibling.size = childsibling.items + (childsibling.left == null ? 0 : childsibling.left.size) + (childsibling.right == null ? 0 : childsibling.right.size);
+#elif MAINTAIN_SIZE
+          cursor.size = parent.size;
+          parent.size = 1 + (parent.left == null ? 0 : parent.left.size) + (parent.right == null ? 0 : parent.right.size);
+          childsibling.size = 1 + (childsibling.left == null ? 0 : childsibling.left.size) + (childsibling.right == null ? 0 : childsibling.right.size);
+#endif
+        }
+        else
+        {//Case 1a can't happen
+          throw new InternalException("Case 1a can't happen here");
+        }
+
+        //Resplice cursor:
+        if (level == 0)
+        {
+          root = cursor;
+        }
+        else
+        {
+          Node swap = cursor;
+
+          cursor = path[--level];
+          path[level] = null;
+#if NCP
+          Node.update(ref cursor, dirs[level] > 0, swap, maxsnapid, generation);
+#else
+				
+					if (dirs[level] > 0)
+						cursor.left = swap;
+					else
+						cursor.right = swap;
+#endif
+#if BAG
+          cursor.size -= removedcount;
+#elif MAINTAIN_SIZE
+          cursor.size--;
+#endif
+        }
+      }
+
+      //Stage 6: fixup to the root
+      while (level > 0)
+      {
+        Node child = cursor;
+
+        cursor = path[--level];
+        path[level] = null;
+#if NCP
+        if (child != (dirs[level] > 0 ? cursor.left : cursor.right))
+          Node.update(ref cursor, dirs[level] > 0, child, maxsnapid, generation);
+#endif
+#if BAG
+        cursor.size -= removedcount;
+#elif MAINTAIN_SIZE
+        cursor.size--;
+#endif
+      }
+
+#if NCP
+      root = cursor;
+#endif
+      return true;
+    }
+
+
+    /// <summary>
+    /// Remove all items from this collection.
+    /// </summary>
+    [Tested]
+    public void Clear()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+      if (size == 0)
+        return;
+      int oldsize = size;
+      clear();
+      if ((ActiveEvents & EventTypeEnum.Cleared) != 0)
+        raiseCollectionCleared(true, oldsize);
+      if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+        raiseCollectionChanged();
+    }
+
+
+    private void clear()
+    {
+      size = 0;
+      root = null;
+      blackdepth = 0;
+    }
+
+
+    /// <summary>
+    /// Remove all items in another collection from this one. If this collection
+    /// has bag semantics, take multiplicities into account.
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to remove.</param>
+    [Tested]
+    public void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+
+      T jtem;
+
+      bool mustRaise = (ActiveEvents & (EventTypeEnum.Removed | EventTypeEnum.Changed)) != 0;
+      RaiseForRemoveAllHandler raiseHandler = mustRaise ? new RaiseForRemoveAllHandler(this) : null;
+
+      foreach (T item in items)
+      {
+        if (root == null)
+          break;
+
+        jtem = item;
+        int junk;
+        if (removeIterative(ref jtem, false, out junk) && mustRaise)
+          raiseHandler.Remove(jtem);
+      }
+      if (mustRaise)
+        raiseHandler.Raise();
+    }
+
+    /// <summary>
+    /// Remove all items not in some other collection from this one. If this collection
+    /// has bag semantics, take multiplicities into account.
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to retain.</param>
+    [Tested]
+    public void RetainAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+
+      //A much more efficient version is possible if items is sorted like this.
+      //Well, it is unclear how efficient it would be.
+      //We could use a marking method!?
+#warning how does this work together with persistence?
+      TreeSet<T> t = (TreeSet<T>)MemberwiseClone();
+
+      T jtem = default(T);
+      t.clear();
+      foreach (T item in items)
+        if (ContainsCount(item) > t.ContainsCount(item))
+        {
+          t.add(item, ref jtem);
+        }
+      if (size == t.size)
+        return;
+
+#warning improve (mainly for bag) by using a Node iterator instead of ItemMultiplicities()
+      CircularQueue<KeyValuePair<T, int>> wasRemoved = null;
+      if ((ActiveEvents & EventTypeEnum.Removed) != 0)
+      {
+        wasRemoved = new CircularQueue<KeyValuePair<T, int>>();
+        SCG.IEnumerator<KeyValuePair<T, int>> ie = ItemMultiplicities().GetEnumerator();
+        foreach (KeyValuePair<T, int> p in t.ItemMultiplicities())
+        {
+          //We know p.Key is in this!
+          while (ie.MoveNext())
+          {
+            if (comparer.Compare(ie.Current.Key, p.Key) == 0)
+            {
+#if BAG
+              int removed = ie.Current.Value - p.Value;
+              if (removed > 0)
+                wasRemoved.Enqueue(new KeyValuePair<T,int>(p.Key, removed));
+#endif
+              break;
+            }
+            else
+              wasRemoved.Enqueue(ie.Current);
+          }
+        }
+        while (ie.MoveNext())
+          wasRemoved.Enqueue(ie.Current);
+      }
+
+      root = t.root;
+      size = t.size;
+      blackdepth = t.blackdepth;
+      if (wasRemoved != null)
+        foreach (KeyValuePair<T, int> p in wasRemoved)
+          raiseItemsRemoved(p.Key, p.Value);
+      if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+        raiseCollectionChanged();
+    }
+
+    /// <summary>
+    /// Check if this collection contains all the values in another collection.
+    /// If this collection has bag semantics (<code>AllowsDuplicates==true</code>)
+    /// the check is made with respect to multiplicities, else multiplicities
+    /// are not taken into account.
+    /// </summary>
+    /// <param name="items">The </param>
+    /// <typeparam name="U"></typeparam>
+    /// <returns>True if all values in <code>items</code>is in this collection.</returns>
+    [Tested]
+    public bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T
+    {
+      //TODO: fix bag implementation
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      //This is worst-case O(m*logn)
+      foreach (T item in items)
+        if (!Contains(item)) return false;
+
+      return true;
+    }
+
+
+    //Higher order:
+    /// <summary>
+    /// Create a new indexed sorted collection consisting of the items of this
+    /// indexed sorted collection satisfying a certain predicate.
+    /// </summary>
+    /// <param name="filter">The filter delegate defining the predicate.</param>
+    /// <returns>The new indexed sorted collection.</returns>
+    [Tested]
+    public IIndexedSorted<T> FindAll(Fun<T, bool> filter)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      TreeSet<T> res = new TreeSet<T>(comparer);
+      SCG.IEnumerator<T> e = GetEnumerator();
+      Node head = null, tail = null;
+      int z = 0;
+#if BAG
+      int ec = 0;
+#endif
+      while (e.MoveNext())
+      {
+        T thisitem = e.Current;
+#if BAG
+        //We could document that filter will only be called 
+        //once on each unique item. That might even be good for the user!
+        if (tail != null && comparer.Compare(thisitem, tail.item) == 0)
+        {
+          tail.items++;
+          ec++;
+          continue;
+        }
+#endif
+        if (filter(thisitem))
+        {
+          if (head == null)
+          {
+            head = tail = new Node();
+          }
+          else
+          {
+#if BAG
+            tail.size = tail.items;
+#endif
+            tail.right = new Node();
+            tail = tail.right;
+          }
+
+          tail.item = thisitem;
+          z++;
+        }
+      }
+#if BAG
+      if (tail != null)
+        tail.size = tail.items;
+#endif
+
+      if (z == 0)
+        return res;
+
+      int blackheight = 0, red = z, maxred = 1;
+
+      while (maxred <= red)
+      {
+        red -= maxred;
+        maxred <<= 1;
+        blackheight++;
+      }
+
+      res.root = TreeSet<T>.maketreer(ref head, blackheight, maxred, red);
+      res.blackdepth = blackheight;
+      res.size = z;
+#if BAG
+      res.size += ec;
+#endif
+      return res;
+    }
+
+
+    /// <summary>
+    /// Create a new indexed sorted collection consisting of the results of
+    /// mapping all items of this list.
+    /// <exception cref="ArgumentException"/> if the map is not increasing over 
+    /// the items of this collection (with respect to the two given comparison 
+    /// relations).
+    /// </summary>
+    /// <param name="mapper">The delegate definging the map.</param>
+    /// <param name="c">The comparion relation to use for the result.</param>
+    /// <returns>The new sorted collection.</returns>
+    [Tested]
+    public IIndexedSorted<V> Map<V>(Fun<T, V> mapper, SCG.IComparer<V> c)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      TreeSet<V> res = new TreeSet<V>(c);
+
+      if (size == 0)
+        return res;
+
+      SCG.IEnumerator<T> e = GetEnumerator();
+      TreeSet<V>.Node head = null, tail = null;
+      V oldv = default(V);
+      int z = 0;
+#if BAG
+      T lastitem = default(T);
+#endif
+      while (e.MoveNext())
+      {
+        T thisitem = e.Current;
+#if BAG
+        //We could document that mapper will only be called 
+        //once on each unique item. That might even be good for the user!
+        if (tail != null && comparer.Compare(thisitem, lastitem) == 0)
+        {
+          tail.items++;
+          continue;
+        }
+#endif
+        V newv = mapper(thisitem);
+
+        if (head == null)
+        {
+          head = tail = new TreeSet<V>.Node();
+          z++;
+        }
+        else
+        {
+          int comp = c.Compare(oldv, newv);
+#if BAG
+          if (comp == 0)
+          {
+            tail.items++;
+            continue;
+          }
+          if (comp > 0)
+#else
+          if (comp >= 0)
+#endif
+            throw new ArgumentException("mapper not monotonic");
+#if BAG
+          tail.size = tail.items;
+#endif
+          tail.right = new TreeSet<V>.Node();
+          tail = tail.right;
+          z++;
+        }
+#if BAG
+        lastitem = thisitem;
+#endif
+        tail.item = oldv = newv;
+      }
+
+#if BAG
+      tail.size = tail.items;
+#endif
+
+      int blackheight = 0, red = z, maxred = 1;
+
+      while (maxred <= red)
+      {
+        red -= maxred;
+        maxred <<= 1;
+        blackheight++;
+      }
+
+      res.root = TreeSet<V>.maketreer(ref head, blackheight, maxred, red);
+      res.blackdepth = blackheight;
+      res.size = size;
+      return res;
+    }
+
+
+    //below is the bag utility stuff
+    /// <summary>
+    /// Count the number of items of the collection equal to a particular value.
+    /// Returns 0 if and only if the value is not in the collection.
+    /// </summary>
+    /// <param name="item">The value to count.</param>
+    /// <returns>The number of copies found.</returns>
+    [Tested]
+    public int ContainsCount(T item)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+#if BAG
+      Node next; int comp = 0;
+
+      next = root;
+      while (next != null)
+      {
+        comp = comparer.Compare(next.item, item);
+        if (comp == 0)
+          return next.items;
+
+        next = comp < 0 ? right(next) : left(next);
+      }
+
+      return 0;
+#else
+      //Since we are strictly not AllowsDuplicates we just do
+      return Contains(item) ? 1 : 0;
+#endif
+    }
+
+#if BAG
+    //TODO: make work with snapshots
+    class Multiplicities : CollectionValueBase<KeyValuePair<T, int>>, ICollectionValue<KeyValuePair<T, int>>
+    {
+      TreeBag<T> treebag;
+      int origstamp;
+      internal Multiplicities(TreeBag<T> treebag) { this.treebag = treebag; this.origstamp = treebag.stamp; }
+      public override KeyValuePair<T, int> Choose() { return new KeyValuePair<T, int>(treebag.root.item, treebag.root.items); }
+
+      public override SCG.IEnumerator<KeyValuePair<T, int>> GetEnumerator()
+      {
+        return getEnumerator(treebag.root, origstamp); //TODO: NBNBNB
+      }
+
+      private SCG.IEnumerator<KeyValuePair<T, int>> getEnumerator(Node node, int origstamp)
+      {
+        if (node == null)
+          yield break;
+
+        if (node.left != null)
+        {
+          SCG.IEnumerator<KeyValuePair<T, int>> child = getEnumerator(node.left, origstamp);
+
+          while (child.MoveNext())
+          {
+            treebag.modifycheck(origstamp);
+            yield return child.Current;
+          }
+        }
+        yield return new KeyValuePair<T, int>(node.item, node.items);
+        if (node.right != null)
+        {
+          SCG.IEnumerator<KeyValuePair<T, int>> child = getEnumerator(node.right, origstamp);
+
+          while (child.MoveNext())
+          {
+            treebag.modifycheck(origstamp);
+            yield return child.Current;
+          }
+        }
+      }
+
+      public override bool IsEmpty { get { return treebag.IsEmpty; } }
+      public override int Count { get { int i = 0; foreach (KeyValuePair<T, int> p in this) i++; return i; } } //TODO: make better
+      public override Speed CountSpeed { get { return Speed.Linear; } } //TODO: make better
+    }
+#endif
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<T> UniqueItems()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+#if BAG
+      return new DropMultiplicity<T>(ItemMultiplicities());
+#else
+      return this;
+#endif
+    }
+
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+#if BAG
+      return new Multiplicities(this);
+#else
+      return new MultiplicityOne<T>(this);
+#endif
+    }
+
+    /// <summary>
+    /// Remove all items equivalent to a given value.
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    [Tested]
+    public void RemoveAllCopies(T item)
+    {
+#if BAG
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+      int removed;
+      if (removeIterative(ref item, true, out removed) && ActiveEvents != 0)
+      {
+        raiseForRemove(item, removed);
+      }
+#else
+      Remove(item);
+#endif
+    }
+
+
+    #endregion
+
+    #region IIndexed<T> Members
+
+    private Node findNode(int i)
+    {
+#if NCP
+      if (isSnapShot)
+        throw new NotSupportedException("Indexing not supported for snapshots");
+#endif
+#if MAINTAIN_SIZE
+      Node next = root;
+
+      if (i >= 0 && i < size)
+        while (true)
+        {
+          int j = next.left == null ? 0 : next.left.size;
+
+          if (i > j)
+          {
+#if BAG
+            i -= j + next.items;
+            if (i < 0)
+              return next;
+#else
+            i -= j + 1;
+#endif
+            next = next.right;
+          }
+          else if (i == j)
+            return next;
+          else
+            next = next.left;
+        }
+
+      throw new IndexOutOfRangeException();
+#else
+			throw new NotSupportedException();
+#endif
+    }
+
+
+    /// <summary>
+    /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+    /// &gt;= the size of the collection.
+    /// </summary>
+    /// <value>The i'th item of this list.</value>
+    /// <param name="i">the index to lookup</param>
+    [Tested]
+    public T this[int i] { [Tested]	get { return findNode(i).item; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual Speed IndexingSpeed { get { return Speed.Log; } }
+
+
+    //TODO: return -upper instead of -1 in case of not found
+    /// <summary>
+    /// Searches for an item in this indexed collection going forwards from the start.
+    /// </summary>
+    /// <param name="item">Item to search for.</param>
+    /// <returns>Index of first occurrence from start of the item
+    /// if found, else the two-complement 
+    /// (always negative) of the index at which the item would be put if it was added.</returns>
+    [Tested]
+    public int IndexOf(T item)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      int upper;
+      return indexOf(item, out upper);
+    }
+
+
+    private int indexOf(T item, out int upper)
+    {
+#if NCP
+      if (isSnapShot)
+        throw new NotSupportedException("Indexing not supported for snapshots");
+#endif
+#if MAINTAIN_SIZE
+      int ind = 0; Node next = root;
+
+      while (next != null)
+      {
+        int comp = comparer.Compare(item, next.item);
+
+        if (comp < 0)
+          next = next.left;
+        else
+        {
+          int leftcnt = next.left == null ? 0 : next.left.size;
+
+          if (comp == 0)
+          {
+#if BAG
+            upper = ind + leftcnt + next.items - 1;
+            return ind + leftcnt;
+#else
+            return upper = ind + leftcnt;
+#endif
+          }
+          else
+          {
+#if BAG
+            ind = ind + next.items + leftcnt;
+#else
+            ind = ind + 1 + leftcnt;
+#endif
+            next = next.right;
+          }
+        }
+      }
+#endif
+      upper = ~ind;
+      return ~ind;
+    }
+
+
+    /// <summary>
+    /// Searches for an item in the tree going backwords from the end.
+    /// </summary>
+    /// <param name="item">Item to search for.</param>
+    /// <returns>Index of last occurrence from the end of item if found, 
+    /// else the two-complement (always negative) of the index at which 
+    /// the item would be put if it was added.</returns>
+    [Tested]
+    public int LastIndexOf(T item)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+#if BAG
+      int res;
+      indexOf(item, out res);
+      return res;
+#else
+      //We have AllowsDuplicates==false for the set
+      return IndexOf(item);
+#endif
+    }
+
+
+    /// <summary>
+    /// Remove the item at a specific position of the list.
+    /// <exception cref="IndexOutOfRangeException"/> if i is negative or
+    /// &gt;= the size of the collection.
+    /// </summary>
+    /// <param name="i">The index of the item to remove.</param>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public T RemoveAt(int i)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+      T retval = removeAt(i);
+      if (ActiveEvents != 0)
+        raiseForRemove(retval);
+      return retval;
+    }
+
+    T removeAt(int i)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+#if MAINTAIN_SIZE
+      if (i < 0 || i >= size)
+        throw new IndexOutOfRangeException("Index out of range for sequenced collectionvalue");
+
+      //We must follow the pattern of removeIterative()
+      while (dirs.Length < 2 * blackdepth)
+      {
+        dirs = new int[2 * dirs.Length];
+        path = new Node[2 * dirs.Length];
+      }
+
+      int level = 0;
+      Node cursor = root;
+
+      while (true)
+      {
+        int j = cursor.left == null ? 0 : cursor.left.size;
+
+        if (i > j)
+        {
+#if BAG
+          i -= j + cursor.items;
+          if (i < 0)
+            break;
+#else
+          i -= j + 1;
+#endif
+          dirs[level] = -1;
+          path[level++] = cursor;
+          cursor = cursor.right;
+        }
+        else if (i == j)
+          break;
+        else
+        {
+          dirs[level] = 1;
+          path[level++] = cursor;
+          cursor = cursor.left;
+        }
+      }
+
+      T retval = cursor.item;
+
+#if BAG
+      if (cursor.items > 1)
+      {
+        resplicebag(level, cursor);
+        size--;
+        return retval;
+      }
+#endif
+      removeIterativePhase2(cursor, level);
+      return retval;
+#else
+			throw new NotSupportedException();
+#endif
+    }
+
+#if BAG
+    private void resplicebag(int level, Node cursor)
+    {
+#if NCP
+      Node.CopyNode(ref cursor, maxsnapid, generation);
+#endif
+      cursor.items--;
+      cursor.size--;
+      while (level-- > 0)
+      {
+        Node kid = cursor;
+
+        cursor = path[level];
+#if NCP
+        Node.update(ref cursor, dirs[level] > 0, kid, maxsnapid, generation);
+#endif
+        cursor.size--;
+        path[level] = null;
+      }
+    }
+#endif
+    /// <summary>
+    /// Remove all items in an index interval.
+    /// <exception cref="IndexOutOfRangeException"/>???. 
+    /// </summary>
+    /// <param name="start">The index of the first item to remove.</param>
+    /// <param name="count">The number of items to remove.</param>
+    [Tested]
+    public void RemoveInterval(int start, int count)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      if (start < 0 || count < 0 || start + count > this.size)
+        throw new ArgumentOutOfRangeException();
+
+      updatecheck();
+
+      if (count == 0)
+        return;
+
+      //This is terrible for large count. We should split the tree at 
+      //the endpoints of the range and fuse the parts!
+      //We really need good internal destructive split and catenate functions!
+      //Alternative for large counts: rebuild tree using maketree()
+      for (int i = 0; i < count; i++)
+        removeAt(start);
+
+      if ((ActiveEvents & EventTypeEnum.Cleared) != 0)
+        raiseCollectionCleared(false, count);
+      if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+        raiseCollectionChanged();
+    }
+
+
+    /// <summary>
+    /// <exception cref="IndexOutOfRangeException"/>.
+    /// </summary>
+    /// <value>The directed collection of items in a specific index interval.</value>
+    /// <param name="start">The low index of the interval (inclusive).</param>
+    /// <param name="end">The high index of the interval (exclusive).</param>
+    [Tested]
+    public IDirectedCollectionValue<T> this[int start, int end]
+    {
+      [Tested]
+      get
+      {
+        checkRange(start, end - start);
+        return new Interval(this, start, end - start, true);
+      }
+    }
+
+    #region Interval nested class
+    class Interval : DirectedCollectionValueBase<T>, IDirectedCollectionValue<T>
+    {
+      int start, length, stamp;
+
+      bool forwards;
+
+      TreeSet<T> tree;
+
+
+      internal Interval(TreeSet<T> tree, int start, int count, bool forwards)
+      {
+#if NCP
+        if (tree.isSnapShot)
+          throw new NotSupportedException("Indexing not supported for snapshots");
+#endif
+        this.start = start; this.length = count; this.forwards = forwards;
+        this.tree = tree; this.stamp = tree.stamp;
+      }
+
+      public override bool IsEmpty { get { return length == 0; } }
+
+      [Tested]
+      public override int Count { [Tested]get { return length; } }
+
+
+      public override Speed CountSpeed { get { return Speed.Constant; } }
+
+
+      public override T Choose()
+      {
+        if (length == 0)
+          throw new NoSuchItemException();
+        return tree[start];
+      }
+
+      [Tested]
+      public override SCG.IEnumerator<T> GetEnumerator()
+      {
+#if MAINTAIN_SIZE
+        tree.modifycheck(stamp);
+#if BAG
+        int togo;
+#endif
+        Node cursor = tree.root;
+        Node[] path = new Node[2 * tree.blackdepth];
+        int level = 0, totaltogo = length;
+
+        if (totaltogo == 0)
+          yield break;
+
+        if (forwards)
+        {
+          int i = start;
+
+          while (true)
+          {
+            int j = cursor.left == null ? 0 : cursor.left.size;
+
+            if (i > j)
+            {
+#if BAG
+              i -= j + cursor.items;
+              if (i < 0)
+              {
+                togo = cursor.items + i;
+                break;
+              }
+#else
+              i -= j + 1;
+#endif
+              cursor = cursor.right;
+            }
+            else if (i == j)
+            {
+#if BAG
+              togo = cursor.items;
+#endif
+              break;
+            }
+            else
+            {
+              path[level++] = cursor;
+              cursor = cursor.left;
+            }
+          }
+
+          T current = cursor.item;
+
+          while (totaltogo-- > 0)
+          {
+            yield return current;
+            tree.modifycheck(stamp);
+#if BAG
+            if (--togo > 0)
+              continue;
+#endif
+            if (cursor.right != null)
+            {
+              path[level] = cursor = cursor.right;
+              while (cursor.left != null)
+                path[++level] = cursor = cursor.left;
+            }
+            else if (level == 0)
+              yield break;
+            else
+              cursor = path[--level];
+
+            current = cursor.item;
+#if BAG
+            togo = cursor.items;
+#endif
+          }
+        }
+        else
+        {
+          int i = start + length - 1;
+
+          while (true)
+          {
+            int j = cursor.left == null ? 0 : cursor.left.size;
+
+            if (i > j)
+            {
+#if BAG
+              if (i - j < cursor.items)
+              {
+                togo = i - j + 1;
+                break;
+              }
+              i -= j + cursor.items;
+#else
+              i -= j + 1;
+#endif
+              path[level++] = cursor;
+              cursor = cursor.right;
+            }
+            else if (i == j)
+            {
+#if BAG
+              togo = 1;
+#endif
+              break;
+            }
+            else
+            {
+              cursor = cursor.left;
+            }
+          }
+
+          T current = cursor.item;
+
+          while (totaltogo-- > 0)
+          {
+            yield return current;
+            tree.modifycheck(stamp);
+#if BAG
+            if (--togo > 0)
+              continue;
+#endif
+            if (cursor.left != null)
+            {
+              path[level] = cursor = cursor.left;
+              while (cursor.right != null)
+                path[++level] = cursor = cursor.right;
+            }
+            else if (level == 0)
+              yield break;
+            else
+              cursor = path[--level];
+
+            current = cursor.item;
+#if BAG
+            togo = cursor.items;
+#endif
+          }
+        }
+
+#else
+			throw new NotSupportedException();
+#endif
+      }
+
+
+      [Tested]
+      public override IDirectedCollectionValue<T> Backwards()
+      { return new Interval(tree, start, length, !forwards); }
+
+
+      [Tested]
+      IDirectedEnumerable<T> C5.IDirectedEnumerable<T>.Backwards()
+      { return Backwards(); }
+
+
+      [Tested]
+      public override EnumerationDirection Direction
+      {
+        [Tested]
+        get
+        {
+          return forwards ? EnumerationDirection.Forwards : EnumerationDirection.Backwards;
+        }
+      }
+    }
+    #endregion
+
+    /// <summary>
+    /// Create a collection containing the same items as this collection, but
+    /// whose enumerator will enumerate the items backwards. The new collection
+    /// will become invalid if the original is modified. Method typicaly used as in
+    /// <code>foreach (T x in coll.Backwards()) {...}</code>
+    /// </summary>
+    /// <returns>The backwards collection.</returns>
+    [Tested]
+    public override IDirectedCollectionValue<T> Backwards() { return RangeAll().Backwards(); }
+
+
+    [Tested]
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
+
+    #endregion
+
+    #region PriorityQueue Members
+
+    /// <summary>
+    /// The comparer object supplied at creation time for this collection
+    /// </summary>
+    /// <value>The comparer</value>
+    public SCG.IComparer<T> Comparer { get { return comparer; } }
+
+
+    /// <summary>
+    /// Find the current least item of this priority queue.
+    /// </summary>
+    /// <returns>The least item.</returns>
+    [Tested]
+    public T FindMin()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      if (size == 0)
+        throw new NoSuchItemException();
+      Node cursor = root, next = left(cursor);
+
+      while (next != null)
+      {
+        cursor = next;
+        next = left(cursor);
+      }
+
+      return cursor.item;
+    }
+
+
+    /// <summary>
+    /// Remove the least item from this  priority queue.
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public T DeleteMin()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+
+      //persistence guard?
+      if (size == 0)
+        throw new NoSuchItemException();
+
+      //We must follow the pattern of removeIterative()
+      stackcheck();
+
+      T retval = deleteMin();
+      if (ActiveEvents != 0)
+      {
+        raiseItemsRemoved(retval, 1);
+        raiseCollectionChanged();
+      }
+      return retval;
+    }
+
+    private T deleteMin()
+    {
+      int level = 0;
+      Node cursor = root;
+
+      while (cursor.left != null)
+      {
+        dirs[level] = 1;
+        path[level++] = cursor;
+        cursor = cursor.left;
+      }
+
+      T retval = cursor.item;
+
+#if BAG
+      if (cursor.items > 1)
+      {
+        resplicebag(level, cursor);
+        size--;
+        return retval;
+      }
+#endif
+      removeIterativePhase2(cursor, level);
+      return retval;
+    }
+
+
+    /// <summary>
+    /// Find the current largest item of this priority queue.
+    /// </summary>
+    /// <returns>The largest item.</returns>
+    [Tested]
+    public T FindMax()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      if (size == 0)
+        throw new NoSuchItemException();
+
+      Node cursor = root, next = right(cursor);
+
+      while (next != null)
+      {
+        cursor = next;
+        next = right(cursor);
+      }
+
+      return cursor.item;
+    }
+
+
+    /// <summary>
+    /// Remove the largest item from this  priority queue.
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    [Tested]
+    public T DeleteMax()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      //persistence guard?
+      updatecheck();
+      if (size == 0)
+        throw new NoSuchItemException();
+
+      //We must follow the pattern of removeIterative()
+      stackcheck();
+
+      T retval = deleteMax();
+      if (ActiveEvents != 0)
+      {
+        raiseItemsRemoved(retval, 1);
+        raiseCollectionChanged();
+      }
+      return retval;
+    }
+
+    private T deleteMax()
+    {
+      int level = 0;
+      Node cursor = root;
+
+      while (cursor.right != null)
+      {
+        dirs[level] = -1;
+        path[level++] = cursor;
+        cursor = cursor.right;
+      }
+
+      T retval = cursor.item;
+
+#if BAG
+      if (cursor.items > 1)
+      {
+        resplicebag(level, cursor);
+        size--;
+        return retval;
+      }
+#endif
+      removeIterativePhase2(cursor, level);
+      return retval;
+    }
+    #endregion
+
+    #region ISorted<T> Members
+
+    /// <summary>
+    /// Find the strict predecessor of item in the sorted collection,
+    /// that is, the greatest item in the collection smaller than the item.
+    /// </summary>
+    /// <param name="item">The item to find the predecessor for.</param>
+    /// <param name="res">The predecessor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a predecessor; otherwise false.</returns>
+    public bool TryPredecessor(T item, out T res)
+    {
+        if (!isValid)
+            throw new ViewDisposedException("Snapshot has been disposed");
+        Node cursor = root, bestsofar = null;
+
+        while (cursor != null)
+        {
+            int comp = comparer.Compare(cursor.item, item);
+
+            if (comp < 0)
+            {
+                bestsofar = cursor;
+                cursor = right(cursor);
+            }
+            else if (comp == 0)
+            {
+                cursor = left(cursor);
+                while (cursor != null)
+                {
+                    bestsofar = cursor;
+                    cursor = right(cursor);
+                }
+            }
+            else
+                cursor = left(cursor);
+        }
+        if (bestsofar == null)
+        {
+            res = default(T);
+            return false;
+        }
+        else
+        {
+            res = bestsofar.item;
+            return true;
+        }
+    }
+
+
+    /// <summary>
+    /// Find the strict successor of item in the sorted collection,
+    /// that is, the least item in the collection greater than the supplied value.
+    /// </summary>
+    /// <param name="item">The item to find the successor for.</param>
+    /// <param name="res">The successor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a successor; otherwise false.</returns>
+    public bool TrySuccessor(T item, out T res)
+    {
+        if (!isValid)
+            throw new ViewDisposedException("Snapshot has been disposed");
+        Node cursor = root, bestsofar = null;
+
+        while (cursor != null)
+        {
+            int comp = comparer.Compare(cursor.item, item);
+
+            if (comp > 0)
+            {
+                bestsofar = cursor;
+                cursor = left(cursor);
+            }
+            else if (comp == 0)
+            {
+                cursor = right(cursor);
+                while (cursor != null)
+                {
+                    bestsofar = cursor;
+                    cursor = left(cursor);
+                }
+            }
+            else
+                cursor = right(cursor);
+        }
+
+        if (bestsofar == null)
+        {
+            res = default(T);
+            return false;
+        }
+        else
+        {
+            res = bestsofar.item;
+            return true;
+        }
+    }
+
+
+    /// <summary>
+    /// Find the weak predecessor of item in the sorted collection,
+    /// that is, the greatest item in the collection smaller than or equal to the item.
+    /// </summary>
+    /// <param name="item">The item to find the weak predecessor for.</param>
+    /// <param name="res">The weak predecessor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a weak predecessor; otherwise false.</returns>
+    public bool TryWeakPredecessor(T item, out T res)
+    {
+        if (!isValid)
+            throw new ViewDisposedException("Snapshot has been disposed");
+        Node cursor = root, bestsofar = null;
+
+        while (cursor != null)
+        {
+            int comp = comparer.Compare(cursor.item, item);
+
+            if (comp < 0)
+            {
+                bestsofar = cursor;
+                cursor = right(cursor);
+            }
+            else if (comp == 0)
+            {
+                res = cursor.item;
+                return true;
+            }
+            else
+                cursor = left(cursor);
+        }
+        if (bestsofar == null)
+        {
+            res = default(T);
+            return false;
+        }
+        else
+        {
+            res = bestsofar.item;
+            return true;
+        }
+    }
+
+
+    /// <summary>
+    /// Find the weak successor of item in the sorted collection,
+    /// that is, the least item in the collection greater than or equal to the supplied value.
+    /// </summary>
+    /// <param name="item">The item to find the weak successor for.</param>
+    /// <param name="res">The weak successor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a weak successor; otherwise false.</returns>
+    public bool TryWeakSuccessor(T item, out T res)
+    {
+        if (!isValid)
+            throw new ViewDisposedException("Snapshot has been disposed");
+        Node cursor = root, bestsofar = null;
+
+        while (cursor != null)
+        {
+            int comp = comparer.Compare(cursor.item, item);
+
+            if (comp == 0)
+            {
+                res = cursor.item;
+                return true;
+            }
+            else if (comp > 0)
+            {
+                bestsofar = cursor;
+                cursor = left(cursor);
+            }
+            else
+                cursor = right(cursor);
+        }
+
+        if (bestsofar == null)
+        {
+            res = default(T);
+            return false;
+        }
+        else
+        {
+            res = bestsofar.item;
+            return true;
+        }
+    }
+
+
+    /// <summary>
+    /// Find the strict predecessor in the sorted collection of a particular value,
+    /// i.e. the largest item in the collection less than the supplied value.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such element exists (the
+    /// supplied  value is less than or equal to the minimum of this collection.)</exception>
+    /// <param name="item">The item to find the predecessor for.</param>
+    /// <returns>The predecessor.</returns>
+    [Tested]
+    public T Predecessor(T item)
+    {
+        T res;
+        if (TryPredecessor(item, out res))
+            return res;
+        else
+            throw new NoSuchItemException();
+    }
+
+
+    /// <summary>
+    /// Find the weak predecessor in the sorted collection of a particular value,
+    /// i.e. the largest item in the collection less than or equal to the supplied value.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such element exists (the
+    /// supplied  value is less than the minimum of this collection.)</exception>
+    /// <param name="item">The item to find the weak predecessor for.</param>
+    /// <returns>The weak predecessor.</returns>
+    [Tested]
+    public T WeakPredecessor(T item)
+    {
+        T res;
+        if (TryWeakPredecessor(item, out res))
+            return res;
+        else
+            throw new NoSuchItemException();
+    }
+
+
+    /// <summary>
+    /// Find the strict successor in the sorted collection of a particular value,
+    /// i.e. the least item in the collection greater than the supplied value.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such element exists (the
+    /// supplied  value is greater than or equal to the maximum of this collection.)</exception>
+    /// <param name="item">The item to find the successor for.</param>
+    /// <returns>The successor.</returns>
+    [Tested]
+    public T Successor(T item)
+    {
+        T res;
+        if (TrySuccessor(item, out res))
+            return res;
+        else
+            throw new NoSuchItemException();
+    }
+
+
+    /// <summary>
+    /// Find the weak successor in the sorted collection of a particular value,
+    /// i.e. the least item in the collection greater than or equal to the supplied value.
+    /// <exception cref="NoSuchItemException"> if no such element exists (the
+    /// supplied  value is greater than the maximum of this collection.)</exception>
+    /// </summary>
+    /// <param name="item">The item to find the weak successor for.</param>
+    /// <returns>The weak successor.</returns>
+    [Tested]
+    public T WeakSuccessor(T item)
+    {
+        T res;
+        if (TryWeakSuccessor(item, out res))
+            return res;
+        else
+            throw new NoSuchItemException();
+    }
+
+   
+    /// <summary>
+    /// Query this sorted collection for items greater than or equal to a supplied value.
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive).</param>
+    /// <returns>The result directed collection.</returns>
+    [Tested]
+    public IDirectedCollectionValue<T> RangeFrom(T bot)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      return new Range(this, true, bot, false, default(T), EnumerationDirection.Forwards);
+    }
+
+
+    /// <summary>
+    /// Query this sorted collection for items between two supplied values.
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive).</param>
+    /// <param name="top">The upper bound (exclusive).</param>
+    /// <returns>The result directed collection.</returns>
+    [Tested]
+    public IDirectedCollectionValue<T> RangeFromTo(T bot, T top)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      return new Range(this, true, bot, true, top, EnumerationDirection.Forwards);
+    }
+
+
+    /// <summary>
+    /// Query this sorted collection for items less than a supplied value.
+    /// </summary>
+    /// <param name="top">The upper bound (exclusive).</param>
+    /// <returns>The result directed collection.</returns>
+    [Tested]
+    public IDirectedCollectionValue<T> RangeTo(T top)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      return new Range(this, false, default(T), true, top, EnumerationDirection.Forwards);
+    }
+
+
+    /// <summary>
+    /// Create a directed collection with the same items as this collection.
+    /// </summary>
+    /// <returns>The result directed collection.</returns>
+    [Tested]
+    public IDirectedCollectionValue<T> RangeAll()
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      return new Range(this, false, default(T), false, default(T), EnumerationDirection.Forwards);
+    }
+
+
+    [Tested]
+    IDirectedEnumerable<T> ISorted<T>.RangeFrom(T bot) { return RangeFrom(bot); }
+
+
+    [Tested]
+    IDirectedEnumerable<T> ISorted<T>.RangeFromTo(T bot, T top) { return RangeFromTo(bot, top); }
+
+
+    [Tested]
+    IDirectedEnumerable<T> ISorted<T>.RangeTo(T top) { return RangeTo(top); }
+
+
+    //Utility for CountXxxx. Actually always called with strict = true.
+    private int countTo(T item, bool strict)
+    {
+#if NCP
+      if (isSnapShot)
+        throw new NotSupportedException("Indexing not supported for snapshots");
+#endif
+#if MAINTAIN_SIZE
+      int ind = 0, comp = 0; Node next = root;
+
+      while (next != null)
+      {
+        comp = comparer.Compare(item, next.item);
+        if (comp < 0)
+          next = next.left;
+        else
+        {
+          int leftcnt = next.left == null ? 0 : next.left.size;
+#if BAG
+          if (comp == 0)
+            return strict ? ind + leftcnt : ind + leftcnt + next.items;
+          else
+          {
+            ind = ind + next.items + leftcnt;
+            next = next.right;
+          }
+#else
+          if (comp == 0)
+            return strict ? ind + leftcnt : ind + leftcnt + 1;
+          else
+          {
+            ind = ind + 1 + leftcnt;
+            next = next.right;
+          }
+#endif
+        }
+      }
+
+      //if we get here, we are at the same side of the whole collection:
+      return ind;
+#else
+			throw new NotSupportedException("Code compiled w/o size!");
+#endif
+    }
+
+
+    /// <summary>
+    /// Perform a search in the sorted collection for the ranges in which a
+    /// non-increasing (i.e. weakly decrerasing) function from the item type to 
+    /// <code>int</code> is
+    /// negative, zero respectively positive. If the supplied cut function is
+    /// not non-increasing, the result of this call is undefined.
+    /// </summary>
+    /// <param name="c">The cut function <code>T</code> to <code>int</code>, given
+    /// as an <code>IComparable&lt;T&gt;</code> object, where the cut function is
+    /// the <code>c.CompareTo(T that)</code> method.</param>
+    /// <param name="low">Returns the largest item in the collection, where the
+    /// cut function is positive (if any).</param>
+    /// <param name="lowIsValid">True if the cut function is positive somewhere
+    /// on this collection.</param>
+    /// <param name="high">Returns the least item in the collection, where the
+    /// cut function is negative (if any).</param>
+    /// <param name="highIsValid">True if the cut function is negative somewhere
+    /// on this collection.</param>
+    /// <returns></returns>
+    [Tested]
+    public bool Cut(IComparable<T> c, out T low, out bool lowIsValid, out T high, out bool highIsValid)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      Node cursor = root, lbest = null, rbest = null;
+      bool res = false;
+
+      while (cursor != null)
+      {
+        int comp = c.CompareTo(cursor.item);
+
+        if (comp > 0)
+        {
+          lbest = cursor;
+          cursor = right(cursor);
+        }
+        else if (comp < 0)
+        {
+          rbest = cursor;
+          cursor = left(cursor);
+        }
+        else
+        {
+          res = true;
+
+          Node tmp = left(cursor);
+
+          while (tmp != null && c.CompareTo(tmp.item) == 0)
+            tmp = left(tmp);
+
+          if (tmp != null)
+          {
+            lbest = tmp;
+            tmp = right(tmp);
+            while (tmp != null)
+            {
+              if (c.CompareTo(tmp.item) > 0)
+              {
+                lbest = tmp;
+                tmp = right(tmp);
+              }
+              else
+                tmp = left(tmp);
+            }
+          }
+
+          tmp = right(cursor);
+          while (tmp != null && c.CompareTo(tmp.item) == 0)
+            tmp = right(tmp);
+
+          if (tmp != null)
+          {
+            rbest = tmp;
+            tmp = left(tmp);
+            while (tmp != null)
+            {
+              if (c.CompareTo(tmp.item) < 0)
+              {
+                rbest = tmp;
+                tmp = left(tmp);
+              }
+              else
+                tmp = right(tmp);
+            }
+          }
+
+          break;
+        }
+      }
+
+      if (highIsValid = (rbest != null))
+        high = rbest.item;
+      else
+        high = default(T);
+
+      if (lowIsValid = (lbest != null))
+        low = lbest.item;
+      else
+        low = default(T);
+
+      return res;
+    }
+
+
+    /// <summary>
+    /// Determine the number of items at or above a supplied threshold.
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive)</param>
+    /// <returns>The number of matcing items.</returns>
+    [Tested]
+    public int CountFrom(T bot)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      return size - countTo(bot, true);
+    }
+
+
+    /// <summary>
+    /// Determine the number of items between two supplied thresholds.
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive)</param>
+    /// <param name="top">The upper bound (exclusive)</param>
+    /// <returns>The number of matcing items.</returns>
+    [Tested]
+    public int CountFromTo(T bot, T top)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      if (comparer.Compare(bot, top) >= 0)
+        return 0;
+
+      return countTo(top, true) - countTo(bot, true);
+    }
+
+
+    /// <summary>
+    /// Determine the number of items below a supplied threshold.
+    /// </summary>
+    /// <param name="top">The upper bound (exclusive)</param>
+    /// <returns>The number of matcing items.</returns>
+    [Tested]
+    public int CountTo(T top)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      return countTo(top, true);
+    }
+
+
+    /// <summary>
+    /// Remove all items of this collection above or at a supplied threshold.
+    /// </summary>
+    /// <param name="low">The lower threshold (inclusive).</param>
+    [Tested]
+    public void RemoveRangeFrom(T low)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+
+      int count = CountFrom(low);
+
+      if (count == 0)
+        return;
+
+      stackcheck();
+      CircularQueue<T> wasRemoved = (ActiveEvents & EventTypeEnum.Removed) != 0 ? new CircularQueue<T>() : null;
+
+      for (int i = 0; i < count; i++)
+      {
+        T item = deleteMax();
+        if (wasRemoved != null)
+          wasRemoved.Enqueue(item);
+      }
+      if (wasRemoved != null)
+        raiseForRemoveAll(wasRemoved);
+      else if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+        raiseCollectionChanged();
+    }
+
+
+    /// <summary>
+    /// Remove all items of this collection between two supplied thresholds.
+    /// </summary>
+    /// <param name="low">The lower threshold (inclusive).</param>
+    /// <param name="hi">The upper threshold (exclusive).</param>
+    [Tested]
+    public void RemoveRangeFromTo(T low, T hi)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+
+      int count = CountFromTo(low, hi);
+
+      if (count == 0)
+        return;
+
+      CircularQueue<T> wasRemoved = (ActiveEvents & EventTypeEnum.Removed) != 0 ? new CircularQueue<T>() : null;
+      int junk;
+      for (int i = 0; i < count; i++)
+      {
+        T item = Predecessor(hi);
+        removeIterative(ref item, false, out junk);
+        if (wasRemoved != null)
+          wasRemoved.Enqueue(item);
+      }
+      if (wasRemoved != null)
+        raiseForRemoveAll(wasRemoved);
+      else if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+        raiseCollectionChanged();
+    }
+
+
+    /// <summary>
+    /// Remove all items of this collection below a supplied threshold.
+    /// </summary>
+    /// <param name="hi">The upper threshold (exclusive).</param>
+    [Tested]
+    public void RemoveRangeTo(T hi)
+    {
+      if (!isValid)
+        throw new ViewDisposedException("Snapshot has been disposed");
+      updatecheck();
+
+      int count = CountTo(hi);
+
+      if (count == 0)
+        return;
+
+      stackcheck();
+      CircularQueue<T> wasRemoved = (ActiveEvents & EventTypeEnum.Removed) != 0 ? new CircularQueue<T>() : null;
+
+      for (int i = 0; i < count; i++)
+      {
+        T item = deleteMin();
+        if (wasRemoved != null)
+          wasRemoved.Enqueue(item);
+      }
+      if (wasRemoved != null)
+        raiseForRemoveAll(wasRemoved);
+      else if ((ActiveEvents & EventTypeEnum.Changed) != 0)
+        raiseCollectionChanged();
+    }
+
+    #endregion
+
+    #region IPersistent<T> Members
+#if NCP
+    int maxsnapid { get { return snapList == null ? -1 : findLastLiveSnapShot(); } }
+
+    int findLastLiveSnapShot()
+    {
+      if (snapList == null)
+        return -1;
+      SnapRef lastLiveSnapRef = snapList.Prev;
+      object _snapshot = null;
+      while (lastLiveSnapRef != null && (_snapshot = lastLiveSnapRef.Tree.Target) == null)
+        lastLiveSnapRef = lastLiveSnapRef.Prev;
+      if (lastLiveSnapRef == null)
+      {
+        snapList = null;
+        return -1;
+      }
+      if (snapList.Prev != lastLiveSnapRef)
+      {
+        snapList.Prev = lastLiveSnapRef;
+        lastLiveSnapRef.Next = snapList;
+      }
+      return ((TreeSet<T>)_snapshot).generation;
+    }
+
+    [Serializable]
+    class SnapRef
+    {
+      public SnapRef Prev, Next;
+      public WeakReference Tree;
+      public SnapRef(TreeSet<T> tree) { Tree = new WeakReference(tree); }
+      public void Dispose()
+      {
+        Next.Prev = Prev;
+        if (Prev != null)
+          Prev.Next = Next;
+        Next = Prev = null;
+      }
+    }
+#endif
+
+    /// <summary>
+    /// If this tree is a snapshot, remove registration in base tree
+    /// </summary>
+    [Tested]
+    public void Dispose()
+    {
+#if NCP
+      if (!isValid)
+        return;
+      if (isSnapShot)
+      {
+        snapList.Dispose();
+        snapDispose();
+      }
+      else
+      {
+        if (snapList != null)
+        {
+          SnapRef someSnapRef = snapList.Prev;
+          while (someSnapRef != null)
+          {
+            TreeSet<T> lastsnap;
+            if ((lastsnap = someSnapRef.Tree.Target as TreeSet<T>) != null)
+              lastsnap.snapDispose();
+            someSnapRef = someSnapRef.Prev;
+          }
+        }
+        snapList = null;
+        Clear();
+      }
+#else
+      Clear();
+#endif
+    }
+
+    private void snapDispose()
+    {
+      root = null;
+      dirs = null;
+      path = null;
+      comparer = null;
+      isValid = false;
+      snapList = null;
+    }
+
+    /// <summary>
+    /// Make a (read-only) snapshot of this collection.
+    /// </summary>
+    /// <returns>The snapshot.</returns>
+    [Tested]
+    public ISorted<T> Snapshot()
+    {
+#if NCP
+      if (isSnapShot)
+        throw new InvalidOperationException("Cannot snapshot a snapshot");
+
+      TreeSet<T> res = (TreeSet<T>)MemberwiseClone();
+      SnapRef newSnapRef = new SnapRef(res);
+      res.isReadOnlyBase = true;
+      res.isSnapShot = true;
+      res.snapList = newSnapRef;
+
+      findLastLiveSnapShot();
+      if (snapList == null)
+        snapList = new SnapRef(this);
+      SnapRef lastLiveSnapRef = snapList.Prev;
+
+      newSnapRef.Prev = lastLiveSnapRef;
+      if (lastLiveSnapRef != null)
+        lastLiveSnapRef.Next = newSnapRef;
+      newSnapRef.Next = snapList;
+      snapList.Prev = newSnapRef;
+
+      generation++;
+
+      return res;
+#endif
+    }
+
+    #endregion
+
+    #region TreeSet.Range nested class
+
+    internal class Range : DirectedCollectionValueBase<T>, IDirectedCollectionValue<T>
+    {
+      //We actually need exclusive upper and lower bounds, and flags to 
+      //indicate whether the bound is present (we canot rely on default(T))
+      private int stamp, size;
+
+      private TreeSet<T> basis;
+
+      private T lowend, highend;
+
+      private bool haslowend, hashighend;
+
+      EnumerationDirection direction;
+
+
+      [Tested]
+      public Range(TreeSet<T> basis, bool haslowend, T lowend, bool hashighend, T highend, EnumerationDirection direction)
+      {
+        this.basis = basis;
+        stamp = basis.stamp;
+
+        //lowind will be const; should we cache highind?
+        this.lowend = lowend; //Inclusive
+        this.highend = highend;//Exclusive
+        this.haslowend = haslowend;
+        this.hashighend = hashighend;
+        this.direction = direction;
+        if (!basis.isSnapShot)
+          size = haslowend ?
+              (hashighend ? basis.CountFromTo(lowend, highend) : basis.CountFrom(lowend)) :
+              (hashighend ? basis.CountTo(highend) : basis.Count);
+      }
+
+      #region IEnumerable<T> Members
+
+
+      #region TreeSet.Range.Enumerator nested class
+
+      internal class Enumerator : SCG.IEnumerator<T>
+      {
+        #region Private Fields
+        private bool valid = false, ready = true;
+
+        private SCG.IComparer<T> comparer;
+
+        private T current;
+#if BAG
+        int togo;
+#endif
+
+        private Node cursor;
+
+        private Node[] path; // stack of nodes
+
+        private int level = 0;
+
+        private Range range;
+
+        private bool forwards;
+
+        #endregion
+        [Tested]
+        public Enumerator(Range range)
+        {
+          comparer = range.basis.comparer;
+          path = new Node[2 * range.basis.blackdepth];
+          this.range = range;
+          forwards = range.direction == EnumerationDirection.Forwards;
+          cursor = new Node();
+          if (forwards)
+            cursor.right = range.basis.root;
+          else
+            cursor.left = range.basis.root;
+          range.basis.modifycheck(range.stamp);
+        }
+
+
+        int compare(T i1, T i2) { return comparer.Compare(i1, i2); }
+
+
+        /// <summary>
+        /// Undefined if enumerator is not valid (MoveNext hash been called returning true)
+        /// </summary>
+        /// <value>The current value of the enumerator.</value>
+        [Tested]
+        public T Current
+        {
+          [Tested]
+          get
+          {
+            if (valid)
+              return current;
+            else
+              throw new InvalidOperationException();
+          }
+        }
+
+
+        //Maintain a stack of nodes that are roots of
+        //subtrees not completely exported yet. Invariant:
+        //The stack nodes together with their right subtrees
+        //consists of exactly the items we have not passed
+        //yet (the top of the stack holds current item).
+        /// <summary>
+        /// Move enumerator to next item in tree, or the first item if
+        /// this is the first call to MoveNext. 
+        /// <exception cref="CollectionModifiedException"/> if underlying tree was modified.
+        /// </summary>
+        /// <returns>True if enumerator is valid now</returns>
+        [Tested]
+        public bool MoveNext()
+        {
+          range.basis.modifycheck(range.stamp);
+          if (!ready)
+            return false;
+#if BAG
+          if (--togo > 0)
+            return true;
+#endif
+          if (forwards)
+          {
+            if (!valid && range.haslowend)
+            {
+              cursor = cursor.right;
+              while (cursor != null)
+              {
+                int comp = compare(cursor.item, range.lowend);
+
+                if (comp > 0)
+                {
+                  path[level++] = cursor;
+#if NCP
+                  cursor = range.basis.left(cursor);
+#else
+									cursor = cursor.left;
+#endif
+                }
+                else if (comp < 0)
+                {
+#if NCP
+                  cursor = range.basis.right(cursor);
+#else
+									cursor = cursor.right;
+#endif
+                }
+                else
+                {
+                  path[level] = cursor;
+                  break;
+                }
+              }
+
+              if (cursor == null)
+              {
+                if (level == 0)
+                  return valid = ready = false;
+                else
+                  cursor = path[--level];
+              }
+            }
+#if NCP
+            else if (range.basis.right(cursor) != null)
+            {
+              path[level] = cursor = range.basis.right(cursor);
+
+              Node next = range.basis.left(cursor);
+
+              while (next != null)
+              {
+                path[++level] = cursor = next;
+                next = range.basis.left(cursor);
+              }
+            }
+#else
+						else if (cursor.right != null)
+						{
+							path[level] = cursor = cursor.right;
+							while (cursor.left != null)
+								path[++level] = cursor = cursor.left;
+						}
+#endif
+            else if (level == 0)
+              return valid = ready = false;
+            else
+              cursor = path[--level];
+
+            current = cursor.item;
+            if (range.hashighend && compare(current, range.highend) >= 0)
+              return valid = ready = false;
+
+#if BAG
+            togo = cursor.items;
+#endif
+            return valid = true;
+          }
+          else
+          {
+            if (!valid && range.hashighend)
+            {
+              cursor = cursor.left;
+              while (cursor != null)
+              {
+                int comp = compare(cursor.item, range.highend);
+
+                if (comp < 0)
+                {
+                  path[level++] = cursor;
+#if NCP
+                  cursor = range.basis.right(cursor);
+#else
+									cursor = cursor.right;
+#endif
+                }
+                else
+                {
+#if NCP
+                  cursor = range.basis.left(cursor);
+#else
+									cursor = cursor.left;
+#endif
+                }
+              }
+
+              if (cursor == null)
+              {
+                if (level == 0)
+                  return valid = ready = false;
+                else
+                  cursor = path[--level];
+              }
+            }
+#if NCP
+            else if (range.basis.left(cursor) != null)
+            {
+              path[level] = cursor = range.basis.left(cursor);
+
+              Node next = range.basis.right(cursor);
+
+              while (next != null)
+              {
+                path[++level] = cursor = next;
+                next = range.basis.right(cursor);
+              }
+            }
+#else
+						else if (cursor.left != null)
+						{
+							path[level] = cursor = cursor.left;
+							while (cursor.right != null)
+								path[++level] = cursor = cursor.right;
+						}
+#endif
+            else if (level == 0)
+              return valid = ready = false;
+            else
+              cursor = path[--level];
+
+            current = cursor.item;
+            if (range.haslowend && compare(current, range.lowend) < 0)
+              return valid = ready = false;
+
+#if BAG
+            togo = cursor.items;
+#endif
+            return valid = true;
+          }
+        }
+
+
+        [Tested]
+        public void Dispose()
+        {
+          comparer = null;
+          current = default(T);
+          cursor = null;
+          path = null;
+          range = null;
+        }
+
+        #region IEnumerator Members
+
+        object System.Collections.IEnumerator.Current
+        {
+          get { return Current; }
+        }
+
+        bool System.Collections.IEnumerator.MoveNext()
+        {
+          return MoveNext();
+        }
+
+        void System.Collections.IEnumerator.Reset()
+        {
+          throw new Exception("The method or operation is not implemented.");
+        }
+
+        #endregion
+      }
+
+      #endregion
+
+
+      public override T Choose()
+      {
+        if (size == 0) throw new NoSuchItemException();
+        return lowend;
+      }
+
+      [Tested]
+      public override SCG.IEnumerator<T> GetEnumerator() { return new Enumerator(this); }
+
+
+      [Tested]
+      public override EnumerationDirection Direction { [Tested]get { return direction; } }
+
+
+      #endregion
+
+      #region Utility
+
+      bool inside(T item)
+      {
+        return (!haslowend || basis.comparer.Compare(item, lowend) >= 0) && (!hashighend || basis.comparer.Compare(item, highend) < 0);
+      }
+
+
+      void checkstamp()
+      {
+        if (stamp < basis.stamp)
+          throw new CollectionModifiedException();
+      }
+
+
+      void syncstamp() { stamp = basis.stamp; }
+
+      #endregion
+
+      [Tested]
+      public override IDirectedCollectionValue<T> Backwards()
+      {
+        Range b = (Range)MemberwiseClone();
+
+        b.direction = direction == EnumerationDirection.Forwards ? EnumerationDirection.Backwards : EnumerationDirection.Forwards;
+        return b;
+      }
+
+
+      [Tested]
+      IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
+
+
+      public override bool IsEmpty { get { return size == 0; } }
+
+      [Tested]
+      public override int Count { [Tested] get { return size; } }
+
+      //TODO: check that this is correct
+      public override Speed CountSpeed { get { return Speed.Constant; } }
+
+    }
+
+    #endregion
+
+    #region Diagnostics
+    /// <summary>
+    /// Display this node on the console, and recursively its subnodes.
+    /// </summary>
+    /// <param name="n">Node to display</param>
+    /// <param name="space">Indentation</param>
+    private void minidump(Node n, string space)
+    {
+      if (n == null)
+      {
+        //	System.Console.WriteLine(space + "null");
+      }
+      else
+      {
+        minidump(n.right, space + "  ");
+        Console.WriteLine(String.Format("{0} {4} (size={1}, items={8}, h={2}, gen={3}, id={6}){7}", space + n.item,
+#if MAINTAIN_SIZE
+ n.size,
+#else
+				0,
+#endif
+ 0,
+#if NCP
+ n.generation,
+#endif
+ n.red ? "RED" : "BLACK",
+ 0,
+ 0,
+#if NCP
+#if SEPARATE_EXTRA
+				n.extra == null ? "" : String.Format(" [extra: lg={0}, c={1}, i={2}]", n.extra.lastgeneration, n.extra.leftnode ? "L" : "R", n.extra.oldref == null ? "()" : "" + n.extra.oldref.item),
+#else
+ n.lastgeneration == -1 ? "" : String.Format(" [extra: lg={0}, c={1}, i={2}]", n.lastgeneration, n.leftnode ? "L" : "R", n.oldref == null ? "()" : "" + n.oldref.item),
+#endif
+#else
+				"",
+#endif
+#if BAG
+ n.items
+#else
+ 1
+#endif
+));
+        minidump(n.left, space + "  ");
+      }
+    }
+
+
+    /// <summary>
+    /// Print the tree structure to the console stdout.
+    /// </summary>
+    [Tested(via = "Sawtooth")]
+    public void dump() { dump(""); }
+
+
+    /// <summary>
+    /// Print the tree structure to the console stdout.
+    /// </summary>
+    [Tested(via = "Sawtooth")]
+    public void dump(string msg)
+    {
+      Console.WriteLine(String.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4})", msg, size, blackdepth,
+      0
+      ,
+#if NCP
+ generation
+#endif
+));
+      minidump(root, "");
+      check("", Console.Out); Console.WriteLine("<<<<<<<<<<<<<<<<<<<");
+    }
+
+
+    /// <summary>
+    /// Display this tree on the console.
+    /// </summary>
+    /// <param name="msg">Identifying string of this call to dump</param>
+    /// <param name="err">Extra (error)message to include</param>
+    void dump(string msg, string err)
+    {
+      Console.WriteLine(String.Format(">>>>>>>>>>>>>>>>>>> dump {0} (count={1}, blackdepth={2}, depth={3}, gen={4})", msg, size, blackdepth,
+      0
+      ,
+#if NCP
+ generation
+#endif
+));
+      minidump(root, ""); Console.Write(err);
+      Console.WriteLine("<<<<<<<<<<<<<<<<<<<");
+    }
+
+
+    /// <summary>
+    /// Print warning m on o if b is false.
+    /// </summary>
+    /// <param name="b">Condition that should hold</param>
+    /// <param name="n">Place (used for id display)</param>
+    /// <param name="m">Message</param>
+    /// <param name="o">Output stream</param>
+    /// <returns>b</returns>
+    bool massert(bool b, Node n, string m, System.IO.TextWriter o)
+    {
+      if (!b) o.WriteLine("*** Node (item={0}, id={1}): {2}", n.item,
+        0
+        , m);
+
+      return b;
+    }
+
+
+    bool rbminicheck(Node n, bool redp, System.IO.TextWriter o, out T min, out T max, out int blackheight)
+    {//Red-Black invariant
+      bool res = true;
+
+      res = massert(!(n.red && redp), n, "RED parent of RED node", o) && res;
+      res = massert(n.left == null || n.right != null || n.left.red, n, "Left child black, but right child empty", o) && res;
+      res = massert(n.right == null || n.left != null || n.right.red, n, "Right child black, but left child empty", o) && res;
+#if BAG
+      bool sb = n.size == (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + n.items;
+
+      res = massert(sb, n, "Bad size", o) && res;
+#elif MAINTAIN_SIZE
+      bool sb = n.size == (n.left == null ? 0 : n.left.size) + (n.right == null ? 0 : n.right.size) + 1;
+
+      res = massert(sb, n, "Bad size", o) && res;
+#endif
+      min = max = n.item;
+
+      T otherext;
+      int lbh = 0, rbh = 0;
+
+      if (n.left != null)
+      {
+        res = rbminicheck(n.left, n.red, o, out min, out otherext, out lbh) && res;
+        res = massert(comparer.Compare(n.item, otherext) > 0, n, "Value not > all left children", o) && res;
+      }
+
+      if (n.right != null)
+      {
+        res = rbminicheck(n.right, n.red, o, out otherext, out max, out rbh) && res;
+        res = massert(comparer.Compare(n.item, otherext) < 0, n, "Value not < all right children", o) && res;
+      }
+
+      res = massert(rbh == lbh, n, "Different blackheights of children", o) && res;
+      blackheight = n.red ? rbh : rbh + 1;
+      return res;
+    }
+
+
+
+
+#if NCP
+
+    bool rbminisnapcheck(Node n, System.IO.TextWriter o, out int size, out T min, out T max)
+    {
+      bool res = true;
+
+      min = max = n.item;
+
+      int lsz = 0, rsz = 0;
+      T otherext;
+#if SEPARATE_EXTRA
+			Node.Extra extra = n.extra;
+			Node child = (extra != null && extra.lastgeneration >= treegen && extra.leftnode) ? extra.oldref : n.left;
+#else
+      Node child = (n.lastgeneration >= generation && n.leftnode) ? n.oldref : n.left;
+#endif
+      if (child != null)
+      {
+        res = rbminisnapcheck(child, o, out lsz, out min, out otherext) && res;
+        res = massert(comparer.Compare(n.item, otherext) > 0, n, "Value not > all left children", o) && res;
+      }
+
+#if SEPARATE_EXTRA
+			child = (extra != null && extra.lastgeneration >= treegen && !extra.leftnode) ? extra.oldref : n.right;
+#else
+      child = (n.lastgeneration >= generation && !n.leftnode) ? n.oldref : n.right;
+#endif
+      if (child != null)
+      {
+        res = rbminisnapcheck(child, o, out rsz, out otherext, out max) && res;
+        res = massert(comparer.Compare(n.item, otherext) < 0, n, "Value not < all right children", o) && res;
+      }
+#if BAG
+      size = n.items + lsz + rsz;
+#else
+      size = 1 + lsz + rsz;
+#endif
+      return res;
+    }
+#endif
+
+    /// <summary>
+    /// Checks red-black invariant. Dumps tree to console if bad
+    /// </summary>
+    /// <param name="name">Title of dump</param>
+    /// <returns>false if invariant violation</returns>
+    [Tested(via = "Sawtooth")]
+    public bool Check(string name)
+    {
+      System.Text.StringBuilder e = new System.Text.StringBuilder();
+      System.IO.TextWriter o = new System.IO.StringWriter(e);
+
+      if (!check(name, o))
+        return true;
+      else
+      {
+        dump(name, e.ToString());
+        return false;
+      }
+    }
+
+
+    /// <summary>
+    /// Checks red-black invariant. Dumps tree to console if bad
+    /// </summary>
+    /// <returns>false if invariant violation</returns>
+    [Tested]
+    public bool Check()
+    {
+      //return check("", System.IO.TextWriter.Null);
+      //Console.WriteLine("bamse");
+      if (!isValid)
+        return true;
+      return Check("-");
+    }
+
+
+    bool check(string msg, System.IO.TextWriter o)
+    {
+      if (root != null)
+      {
+        T max, min;
+        int blackheight;
+#if NCP
+        if (isSnapShot)
+        {
+          //Console.WriteLine("Im'a snapshot");
+          int thesize;
+          bool rv = rbminisnapcheck(root, o, out thesize, out min, out max);
+
+          rv = massert(size == thesize, root, "bad snapshot size", o) && rv;
+          return !rv;
+        }
+#endif
+        bool res = rbminicheck(root, false, o, out min, out max, out blackheight);
+        res = massert(blackheight == blackdepth, root, "bad blackh/d", o) && res;
+        res = massert(!root.red, root, "root is red", o) && res;
+#if MAINTAIN_SIZE
+        res = massert(root.size == size, root, "count!=root.size", o) && res;
+#endif
+        return !res;
+      }
+      else
+        return false;
+    }
+    #endregion
+
+    #region ICloneable Members
+
+    /// <summary>
+    /// Make a shallow copy of this TreeSet.
+    /// </summary>
+    /// <returns></returns>
+    public virtual object Clone()
+    {
+      TreeSet<T> clone = new TreeSet<T>(comparer, EqualityComparer);
+      //TODO: make sure the TreeBag AddSorted copies tree bags smartly!!!
+      clone.AddSorted(this);
+      return clone;
+    }
+
+    #endregion
+
+  }
+}
+
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/AssemblyInfo.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/AssemblyInfo.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/AssemblyInfo.cs	(revision 3)
@@ -0,0 +1,84 @@
+/*
+ Copyright (c) 2003-2007 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System;
+
+//
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly: AssemblyTitle("C5: Copenhagen Comprehensive Collection Classes for CLI")]
+[assembly: AssemblyDescription("This is a build of release 1.1.0")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("(c) 2003-2008 Niels Kokholm and Peter Sestoft")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+//
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+
+[assembly: AssemblyVersion("1.1.0")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the 
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing. 
+//
+// Notes: 
+//   (*) If no key is specified, the assembly is not signed.
+//   (*) KeyName refers to a key that has been installed in the Crypto Service
+//       Provider (CSP) on your machine. KeyFile refers to a file which contains
+//       a key.
+//   (*) If the KeyFile and the KeyName values are both specified, the 
+//       following processing occurs:
+//       (1) If the KeyName can be found in the CSP, that key is used.
+//       (2) If the KeyName does not exist and the KeyFile does exist, the key 
+//           in the KeyFile is installed into the CSP and used.
+//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+//       When specifying the KeyFile, the location of the KeyFile should be
+//       relative to the project output directory which is
+//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+//       located in the project directory, you would specify the AssemblyKeyFile 
+//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+//       documentation for more information on this.
+//
+#if STRONGNAME
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("..\\..\\..\\c5.snk")]
+#endif
+//[assembly: AssemblyKeyName("")]
+
+[assembly: CLSCompliant(true)]
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Attributes.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Attributes.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Attributes.cs	(revision 3)
@@ -0,0 +1,48 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+namespace C5
+{
+  /// <summary>
+  /// A custom attribute to mark methods and properties as being tested 
+  /// sufficiently in the regression test suite.
+  /// </summary>
+  [AttributeUsage(AttributeTargets.All, AllowMultiple = true)]
+  public sealed class TestedAttribute : Attribute
+  {
+
+    /// <summary>
+    /// Optional reference to test case
+    /// </summary>
+    [Tested]
+    public string via;
+
+
+    /// <summary>
+    /// Pretty print attribute value
+    /// </summary>
+    /// <returns>"Tested via " + via</returns>
+    [Tested]
+    public override string ToString() { return "Tested via " + via; }
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Builtin.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Builtin.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Builtin.cs	(revision 3)
@@ -0,0 +1,574 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+namespace C5
+{
+  #region char comparer and equality comparer
+  class CharComparer : SCG.IComparer<char>
+  {
+    public int Compare(char item1, char item2) { 
+      return item1 > item2 ? 1 : item1 < item2 ? -1 : 0; 
+    }
+  }
+
+  /// <summary>
+  /// An equality comparer for type char, also known as System.Char.
+  /// </summary>
+  public class CharEqualityComparer : SCG.IEqualityComparer<char>
+  {
+    static CharEqualityComparer cached = new CharEqualityComparer();
+    CharEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public static CharEqualityComparer Default { get { return cached ?? (cached = new CharEqualityComparer()); } }
+
+    /// <summary>
+    /// Get the hash code of this char
+    /// </summary>
+    /// <param name="item">The char</param>
+    /// <returns>The same</returns>
+    public int GetHashCode(char item) { return item.GetHashCode(); }
+
+
+    /// <summary>
+    /// Check if two chars are equal
+    /// </summary>
+    /// <param name="item1">first char</param>
+    /// <param name="item2">second char</param>
+    /// <returns>True if equal</returns>
+    public bool Equals(char item1, char item2) { return item1 == item2; }
+  }
+  #endregion
+  
+  #region sbyte comparer and equality comparer
+  [Serializable]
+  class SByteComparer : SCG.IComparer<sbyte>
+  {
+    [Tested]
+    public int Compare(sbyte item1, sbyte item2) { 
+      return item1 > item2 ? 1 : item1 < item2 ? -1 : 0; 
+    }
+  }
+
+  /// <summary>
+  /// An equality comparer for type sbyte, also known as System.SByte. 
+  /// <para>This class is a singleton and the instance can be accessed
+  /// via the static <see cref="P:C5.SByteEqualityComparer.Default"/> property</para>
+  /// </summary>
+  [Serializable]
+  public class SByteEqualityComparer : SCG.IEqualityComparer<sbyte>
+  {
+    static SByteEqualityComparer cached;
+    SByteEqualityComparer() { }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    [Tested]
+    public static SByteEqualityComparer Default { get { return cached ?? (cached = new SByteEqualityComparer()); } }
+    /// <summary>
+    /// Get the hash code of this sbyte, that is, itself
+    /// </summary>
+    /// <param name="item">The sbyte</param>
+    /// <returns>The same</returns>
+    [Tested]
+    public int GetHashCode(sbyte item) { return item.GetHashCode(); }
+
+
+    /// <summary>
+    /// Determine whether two sbytes are equal
+    /// </summary>
+    /// <param name="item1">first sbyte</param>
+    /// <param name="item2">second sbyte</param>
+    /// <returns>True if equal</returns>
+    [Tested]
+    public bool Equals(sbyte item1, sbyte item2) { return item1 == item2; }
+  }
+
+  #endregion
+
+  #region byte comparer and equality comparer
+  class ByteComparer : SCG.IComparer<byte>
+  {
+    public int Compare(byte item1, byte item2) { 
+      return item1 > item2 ? 1 : item1 < item2 ? -1 : 0; 
+    }
+  }
+
+  /// <summary>
+  /// An equality comparer for type byte, also known as System.Byte.
+  /// <para>This class is a singleton and the instance can be accessed
+  /// via the <see cref="P:C5.ByteEqualityComparer.Default"/> property</para>
+  /// </summary>
+  public class ByteEqualityComparer : SCG.IEqualityComparer<byte>
+  {
+    static ByteEqualityComparer cached = new ByteEqualityComparer();
+    ByteEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public static ByteEqualityComparer Default { get { return cached ?? (cached = new ByteEqualityComparer()); } }
+    /// <summary>
+    /// Get the hash code of this byte, i.e. itself
+    /// </summary>
+    /// <param name="item">The byte</param>
+    /// <returns>The same</returns>
+    public int GetHashCode(byte item) { return item.GetHashCode(); }
+
+    /// <summary>
+    /// Check if two bytes are equal
+    /// </summary>
+    /// <param name="item1">first byte</param>
+    /// <param name="item2">second byte</param>
+    /// <returns>True if equal</returns>
+    public bool Equals(byte item1, byte item2) { return item1 == item2; }
+  }
+  #endregion
+
+  #region short comparer and equality comparer
+  [Serializable]
+  class ShortComparer : SCG.IComparer<short>
+  {
+    [Tested]
+    public int Compare(short item1, short item2) { 
+      return item1 > item2 ? 1 : item1 < item2 ? -1 : 0; 
+    }
+  }
+
+  /// <summary>
+  /// An equality comparer for type short, also known as System.Int16. 
+  /// <para>This class is a singleton and the instance can be accessed
+  /// via the static <see cref="P:C5.ShortEqualityComparer.Default"/> property</para>
+  /// </summary>
+  [Serializable]
+  public class ShortEqualityComparer : SCG.IEqualityComparer<short>
+  {
+    static ShortEqualityComparer cached;
+    ShortEqualityComparer() { }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    [Tested]
+    public static ShortEqualityComparer Default { get { return cached ?? (cached = new ShortEqualityComparer()); } }
+    /// <summary>
+    /// Get the hash code of this short, that is, itself
+    /// </summary>
+    /// <param name="item">The short</param>
+    /// <returns>The same</returns>
+    [Tested]
+    public int GetHashCode(short item) { return item.GetHashCode(); }
+
+
+    /// <summary>
+    /// Determine whether two shorts are equal
+    /// </summary>
+    /// <param name="item1">first short</param>
+    /// <param name="item2">second short</param>
+    /// <returns>True if equal</returns>
+    [Tested]
+    public bool Equals(short item1, short item2) { return item1 == item2; }
+  }
+
+  #endregion
+
+  #region ushort comparer and equality comparer
+  [Serializable]
+  class UShortComparer : SCG.IComparer<ushort>
+  {
+    [Tested]
+    public int Compare(ushort item1, ushort item2)
+    {
+      return item1 > item2 ? 1 : item1 < item2 ? -1 : 0;
+    }
+  }
+
+  /// <summary>
+  /// An equality comparer for type ushort, also known as System.UInt16. 
+  /// <para>This class is a singleton and the instance can be accessed
+  /// via the static <see cref="P:C5.UShortEqualityComparer.Default"/> property</para>
+  /// </summary>
+  [Serializable]
+  public class UShortEqualityComparer : SCG.IEqualityComparer<ushort>
+  {
+    static UShortEqualityComparer cached;
+    UShortEqualityComparer() { }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    [Tested]
+    public static UShortEqualityComparer Default { get { return cached ?? (cached = new UShortEqualityComparer()); } }
+    /// <summary>
+    /// Get the hash code of this ushort, that is, itself
+    /// </summary>
+    /// <param name="item">The ushort</param>
+    /// <returns>The same</returns>
+    [Tested]
+    public int GetHashCode(ushort item) { return item.GetHashCode(); }
+
+
+    /// <summary>
+    /// Determine whether two ushorts are equal
+    /// </summary>
+    /// <param name="item1">first ushort</param>
+    /// <param name="item2">second ushort</param>
+    /// <returns>True if equal</returns>
+    [Tested]
+    public bool Equals(ushort item1, ushort item2) { return item1 == item2; }
+  }
+
+  #endregion
+
+  #region int comparer and equality comparer
+  [Serializable]
+  class IntComparer : SCG.IComparer<int>
+  {
+    [Tested]
+    public int Compare(int item1, int item2) { 
+      return item1 > item2 ? 1 : item1 < item2 ? -1 : 0; 
+    }
+  }
+
+  /// <summary>
+  /// An equality comparer for type int, also known as System.Int32. 
+  /// <para>This class is a singleton and the instance can be accessed
+  /// via the static <see cref="P:C5.IntEqualityComparer.Default"/> property</para>
+  /// </summary>
+  [Serializable]
+  public class IntEqualityComparer : SCG.IEqualityComparer<int>
+  {
+    static IntEqualityComparer cached;
+    IntEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    [Tested]
+    public static IntEqualityComparer Default { get { return cached ?? (cached = new IntEqualityComparer()); } }
+    /// <summary>
+    /// Get the hash code of this integer, that is, itself
+    /// </summary>
+    /// <param name="item">The integer</param>
+    /// <returns>The same</returns>
+    [Tested]
+    public int GetHashCode(int item) { return item; }
+
+
+    /// <summary>
+    /// Determine whether two integers are equal
+    /// </summary>
+    /// <param name="item1">first integer</param>
+    /// <param name="item2">second integer</param>
+    /// <returns>True if equal</returns>
+    [Tested]
+    public bool Equals(int item1, int item2) { return item1 == item2; }
+  }
+
+  #endregion
+
+  #region uint comparer and equality comparer
+  [Serializable]
+  class UIntComparer : SCG.IComparer<uint>
+  {
+    [Tested]
+    public int Compare(uint item1, uint item2)
+    {
+      return item1 > item2 ? 1 : item1 < item2 ? -1 : 0;
+    }
+  }
+
+  /// <summary>
+  /// An equality comparer for type uint, also known as System.UInt32. 
+  /// <para>This class is a singleton and the instance can be accessed
+  /// via the static <see cref="P:C5.UIntEqualityComparer.Default"/> property</para>
+  /// </summary>
+  [Serializable]
+  public class UIntEqualityComparer : SCG.IEqualityComparer<uint>
+  {
+    static UIntEqualityComparer cached;
+    UIntEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    [Tested]
+    public static UIntEqualityComparer Default { get { return cached ?? (cached = new UIntEqualityComparer()); } }
+    /// <summary>
+    /// Get the hash code of this unsigned integer
+    /// </summary>
+    /// <param name="item">The integer</param>
+    /// <returns>The same bit pattern as a signed integer</returns>
+    [Tested]
+    public int GetHashCode(uint item) { return item.GetHashCode(); }
+
+
+    /// <summary>
+    /// Determine whether two unsigned integers are equal
+    /// </summary>
+    /// <param name="item1">first unsigned integer</param>
+    /// <param name="item2">second unsigned integer</param>
+    /// <returns>True if equal</returns>
+    [Tested]
+    public bool Equals(uint item1, uint item2) { return item1 == item2; }
+  }
+
+  #endregion
+
+  #region long comparer and equality comparer
+  [Serializable]
+  class LongComparer : SCG.IComparer<long>
+  {
+    [Tested]
+    public int Compare(long item1, long item2)
+    {
+      return item1 > item2 ? 1 : item1 < item2 ? -1 : 0;
+    }
+  }
+
+  /// <summary>
+  /// An equality comparer for type long, also known as System.Int64. 
+  /// <para>This class is a singleton and the instance can be accessed
+  /// via the static <see cref="P:C5.LongEqualityComparer.Default"/> property</para>
+  /// </summary>
+  [Serializable]
+  public class LongEqualityComparer : SCG.IEqualityComparer<long>
+  {
+    static LongEqualityComparer cached;
+    LongEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    [Tested]
+    public static LongEqualityComparer Default { get { return cached ?? (cached = new LongEqualityComparer()); } }
+    /// <summary>
+    /// Get the hash code of this long integer
+    /// </summary>
+    /// <param name="item">The long integer</param>
+    /// <returns>The hash code</returns>
+    [Tested]
+    public int GetHashCode(long item) { return item.GetHashCode(); }
+
+
+    /// <summary>
+    /// Determine whether two long integers are equal
+    /// </summary>
+    /// <param name="item1">first long integer</param>
+    /// <param name="item2">second long integer</param>
+    /// <returns>True if equal</returns>
+    [Tested]
+    public bool Equals(long item1, long item2) { return item1 == item2; }
+  }
+
+  #endregion
+
+  #region ulong comparer and equality comparer
+  [Serializable]
+  class ULongComparer : SCG.IComparer<ulong>
+  {
+    [Tested]
+    public int Compare(ulong item1, ulong item2)
+    {
+      return item1 > item2 ? 1 : item1 < item2 ? -1 : 0;
+    }
+  }
+
+  /// <summary>
+  /// An equality comparer for type uint, also known as System.UInt64. 
+  /// <para>This class is a singleton and the instance can be accessed
+  /// via the static <see cref="P:C5.ULongEqualityComparer.Default"/> property</para>
+  /// </summary>
+  [Serializable]
+  public class ULongEqualityComparer : SCG.IEqualityComparer<ulong>
+  {
+    static ULongEqualityComparer cached;
+    ULongEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    [Tested]
+    public static ULongEqualityComparer Default { get { return cached ?? (cached = new ULongEqualityComparer()); } }
+    /// <summary>
+    /// Get the hash code of this unsigned long integer
+    /// </summary>
+    /// <param name="item">The unsigned long integer</param>
+    /// <returns>The hash code</returns>
+    [Tested]
+    public int GetHashCode(ulong item) { return item.GetHashCode(); }
+
+
+    /// <summary>
+    /// Determine whether two unsigned long integers are equal
+    /// </summary>
+    /// <param name="item1">first unsigned long integer</param>
+    /// <param name="item2">second unsigned long integer</param>
+    /// <returns>True if equal</returns>
+    [Tested]
+    public bool Equals(ulong item1, ulong item2) { return item1 == item2; }
+  }
+
+  #endregion
+
+  #region float comparer and equality comparer
+  class FloatComparer : SCG.IComparer<float>
+  {
+    public int Compare(float item1, float item2)
+    {
+      return item1 > item2 ? 1 : item1 < item2 ? -1 : 0;
+    }
+  }
+
+  /// <summary>
+  /// An equality comparer for type float, also known as System.Single. 
+  /// <para>This class is a singleton and the instance can be accessed
+  /// via the static <see cref="P:C5.FloatEqualityComparer.Default"/> property</para>
+  /// </summary>
+  public class FloatEqualityComparer : SCG.IEqualityComparer<float>
+  {
+    static FloatEqualityComparer cached;
+    FloatEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    [Tested]
+    public static FloatEqualityComparer Default { get { return cached ?? (cached = new FloatEqualityComparer()); } }
+    /// <summary>
+    /// Get the hash code of this float
+    /// </summary>
+    /// <param name="item">The float</param>
+    /// <returns>The same</returns>
+    [Tested]
+    public int GetHashCode(float item) { return item.GetHashCode(); }
+
+
+    /// <summary>
+    /// Check if two floats are equal
+    /// </summary>
+    /// <param name="item1">first float</param>
+    /// <param name="item2">second float</param>
+    /// <returns>True if equal</returns>
+    [Tested]
+    public bool Equals(float item1, float item2) { return item1 == item2; }
+  }
+  #endregion
+
+  #region double comparer and equality comparer
+  class DoubleComparer : SCG.IComparer<double>
+  {
+    public int Compare(double item1, double item2) { 
+      return item1 > item2 ? 1 : item1 < item2 ? -1 : 0; 
+    }
+  }
+
+  /// <summary>
+  /// An equality comparer for type double, also known as System.Double.
+  /// <para>This class is a singleton and the instance can be accessed
+  /// via the static <see cref="P:C5.DoubleEqualityComparer.Default"/> property</para>
+  /// </summary>
+  public class DoubleEqualityComparer : SCG.IEqualityComparer<double>
+  {
+    static DoubleEqualityComparer cached;
+    DoubleEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    [Tested]
+    public static DoubleEqualityComparer Default { get { return cached ?? (cached = new DoubleEqualityComparer()); } }
+    /// <summary>
+    /// Get the hash code of this double
+    /// </summary>
+    /// <param name="item">The double</param>
+    /// <returns>The same</returns>
+    [Tested]
+    public int GetHashCode(double item) { return item.GetHashCode(); }
+
+
+    /// <summary>
+    /// Check if two doubles are equal
+    /// </summary>
+    /// <param name="item1">first double</param>
+    /// <param name="item2">second double</param>
+    /// <returns>True if equal</returns>
+    [Tested]
+    public bool Equals(double item1, double item2) { return item1 == item2; }
+  }
+  #endregion
+
+  #region decimal comparer and equality comparer
+  [Serializable]
+  class DecimalComparer : SCG.IComparer<decimal>
+  {
+    [Tested]
+    public int Compare(decimal item1, decimal item2)
+    {
+      return item1 > item2 ? 1 : item1 < item2 ? -1 : 0;
+    }
+  }
+
+  /// <summary>
+  /// An equality comparer for type decimal, also known as System.Decimal. 
+  /// <para>This class is a singleton and the instance can be accessed
+  /// via the static <see cref="P:C5.DecimalEqualityComparer.Default"/> property</para>
+  /// </summary>
+  [Serializable]
+  public class DecimalEqualityComparer : SCG.IEqualityComparer<decimal>
+  {
+    static DecimalEqualityComparer cached;
+    DecimalEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    [Tested]
+    public static DecimalEqualityComparer Default { get { return cached ?? (cached = new DecimalEqualityComparer()); } }
+    /// <summary>
+    /// Get the hash code of this decimal.
+    /// </summary>
+    /// <param name="item">The decimal</param>
+    /// <returns>The hash code</returns>
+    [Tested]
+    public int GetHashCode(decimal item) { return item.GetHashCode(); }
+
+
+    /// <summary>
+    /// Determine whether two decimals are equal
+    /// </summary>
+    /// <param name="item1">first decimal</param>
+    /// <param name="item2">second decimal</param>
+    /// <returns>True if equal</returns>
+    [Tested]
+    public bool Equals(decimal item1, decimal item2) { return item1 == item2; }
+  }
+
+  #endregion
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/C5.csproj
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/C5.csproj	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/C5.csproj	(revision 3)
@@ -0,0 +1,121 @@
+﻿<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <RootNamespace>C5</RootNamespace>
+    <NoStandardLibraries>false</NoStandardLibraries>
+    <AssemblyName>C5</AssemblyName>
+    <SignAssembly>false</SignAssembly>
+    <AssemblyOriginatorKeyFile>
+    </AssemblyOriginatorKeyFile>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <UpgradeBackupLocation>
+    </UpgradeBackupLocation>
+    <OldToolsVersion>2.0</OldToolsVersion>
+    <StartupObject>
+    </StartupObject>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+    <DocumentationFile>c5.xml</DocumentationFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugSnk|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\DebugSnk\</OutputPath>
+    <DefineConstants>TRACE;DEBUG;STRONGNAME</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSnk|AnyCPU' ">
+    <OutputPath>bin\ReleaseSnk\</OutputPath>
+    <DefineConstants>TRACE;STRONGNAME</DefineConstants>
+    <Optimize>true</Optimize>
+    <DebugType>pdbonly</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+    <ErrorReport>prompt</ErrorReport>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System">
+    </Reference>
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="arrays\CircularQueue.cs" />
+    <Compile Include="arrays\HashedArrayList.cs" />
+    <Compile Include="AssemblyInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Attributes.cs" />
+    <Compile Include="Builtin.cs" />
+    <Compile Include="Comparer.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Delegates.cs" />
+    <Compile Include="Enums.cs" />
+    <Compile Include="Exceptions.cs" />
+    <Compile Include="Formatting.cs" />
+    <Compile Include="Hashers.cs" />
+    <Compile Include="Events.cs" />
+    <Compile Include="Collections.cs">
+    </Compile>
+    <Compile Include="Dictionaries.cs">
+    </Compile>
+    <Compile Include="Interfaces.cs">
+    </Compile>
+    <Compile Include="linkedlists\HashedLinkedList.cs" />
+    <Compile Include="Random.cs" />
+    <Compile Include="Records.cs" />
+    <Compile Include="Sorting.cs" />
+    <Compile Include="ViewSupport.cs" />
+    <Compile Include="MappedEnumerators.cs" />
+    <Compile Include="WrappedArray.cs" />
+    <Compile Include="Wrappers.cs">
+    </Compile>
+    <Compile Include="arrays\ArrayList.cs">
+    </Compile>
+    <Compile Include="arrays\SortedArray.cs">
+    </Compile>
+    <Compile Include="hashing\HashBag.cs">
+    </Compile>
+    <Compile Include="hashing\HashDictionary.cs">
+    </Compile>
+    <Compile Include="hashing\HashTable.cs">
+    </Compile>
+    <Compile Include="heaps\IntervalHeap.cs">
+    </Compile>
+    <Compile Include="linkedlists\LinkedList.cs">
+    </Compile>
+    <Compile Include="trees\RedBlackTreeSet.cs">
+    </Compile>
+    <Compile Include="trees\RedBlackTreeBag.cs">
+    </Compile>
+    <Compile Include="trees\RedBlackTreeDictionary.cs">
+    </Compile>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
+  <PropertyGroup>
+    <PreBuildEvent>"$(SolutionDir)PreProcess\$(OutDir)PreProcess.exe"</PreBuildEvent>
+    <PostBuildEvent>
+    </PostBuildEvent>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Collections.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Collections.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Collections.cs	(revision 3)
@@ -0,0 +1,1512 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+#define IMPROVED_COLLECTION_HASHFUNCTION
+
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+namespace C5
+{
+  /// <summary>
+  /// A base class for implementing an IEnumerable&lt;T&gt;
+  /// </summary>
+  [Serializable]
+  public abstract class EnumerableBase<T> : SCG.IEnumerable<T>
+  {
+    /// <summary>
+    /// Create an enumerator for this collection.
+    /// </summary>
+    /// <returns>The enumerator</returns>
+    public abstract SCG.IEnumerator<T> GetEnumerator();
+
+    /// <summary>
+    /// Count the number of items in an enumerable by enumeration
+    /// </summary>
+    /// <param name="items">The enumerable to count</param>
+    /// <returns>The size of the enumerable</returns>
+    [Tested]
+    protected static int countItems(SCG.IEnumerable<T> items)
+    {
+      ICollectionValue<T> jtems = items as ICollectionValue<T>;
+
+      if (jtems != null)
+        return jtems.Count;
+
+      int count = 0;
+
+      using (SCG.IEnumerator<T> e = items.GetEnumerator())
+        while (e.MoveNext()) count++;
+
+      return count;
+    }
+
+    #region IEnumerable Members
+
+    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+    {
+      return GetEnumerator();
+    }
+
+    #endregion
+  }
+
+
+  /// <summary>
+  /// Base class for classes implementing ICollectionValue[T]
+  /// </summary>
+  [Serializable]
+  public abstract class CollectionValueBase<T> : EnumerableBase<T>, ICollectionValue<T>, IShowable
+  {
+    #region Event handling
+    EventBlock<T> eventBlock;
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual EventTypeEnum ListenableEvents { get { return 0; } }
+
+    /// <summary>
+    /// A flag bitmap of the events currently subscribed to by this collection.
+    /// </summary>
+    /// <value></value>
+    public virtual EventTypeEnum ActiveEvents { get { return eventBlock == null ? 0 : eventBlock.events; } }
+
+    private void checkWillListen(EventTypeEnum eventType)
+    {
+      if ((ListenableEvents & eventType) == 0)
+        throw new UnlistenableEventException();
+    }
+
+    /// <summary>
+    /// The change event. Will be raised for every change operation on the collection.
+    /// </summary>
+    public virtual event CollectionChangedHandler<T> CollectionChanged
+    {
+      add { checkWillListen(EventTypeEnum.Changed); (eventBlock ?? (eventBlock = new EventBlock<T>())).CollectionChanged += value; }
+      remove
+      {
+        checkWillListen(EventTypeEnum.Changed);
+        if (eventBlock != null)
+        {
+          eventBlock.CollectionChanged -= value;
+          if (eventBlock.events == 0) eventBlock = null;
+        }
+      }
+    }
+    /// <summary>
+    /// Fire the CollectionChanged event
+    /// </summary>
+    protected virtual void raiseCollectionChanged()
+    { if (eventBlock != null) eventBlock.raiseCollectionChanged(this); }
+
+    /// <summary>
+    /// The clear event. Will be raised for every Clear operation on the collection.
+    /// </summary>
+    public virtual event CollectionClearedHandler<T> CollectionCleared
+    {
+      add { checkWillListen(EventTypeEnum.Cleared); (eventBlock ?? (eventBlock = new EventBlock<T>())).CollectionCleared += value; }
+      remove
+      {
+        checkWillListen(EventTypeEnum.Cleared);
+        if (eventBlock != null)
+        {
+          eventBlock.CollectionCleared -= value;
+          if (eventBlock.events == 0) eventBlock = null;
+        }
+      }
+    }
+    /// <summary>
+    /// Fire the CollectionCleared event
+    /// </summary>
+    protected virtual void raiseCollectionCleared(bool full, int count)
+    { if (eventBlock != null) eventBlock.raiseCollectionCleared(this, full, count); }
+
+    /// <summary>
+    /// Fire the CollectionCleared event
+    /// </summary>
+    protected virtual void raiseCollectionCleared(bool full, int count, int? offset)
+    { if (eventBlock != null) eventBlock.raiseCollectionCleared(this, full, count, offset); }
+
+    /// <summary>
+    /// The item added  event. Will be raised for every individual addition to the collection.
+    /// </summary>
+    public virtual event ItemsAddedHandler<T> ItemsAdded
+    {
+      add { checkWillListen(EventTypeEnum.Added); (eventBlock ?? (eventBlock = new EventBlock<T>())).ItemsAdded += value; }
+      remove
+      {
+        checkWillListen(EventTypeEnum.Added);
+        if (eventBlock != null)
+        {
+          eventBlock.ItemsAdded -= value;
+          if (eventBlock.events == 0) eventBlock = null;
+        }
+      }
+    }
+    /// <summary>
+    /// Fire the ItemsAdded event
+    /// </summary>
+    /// <param name="item">The item that was added</param>
+    /// <param name="count"></param>
+    protected virtual void raiseItemsAdded(T item, int count)
+    { if (eventBlock != null) eventBlock.raiseItemsAdded(this, item, count); }
+
+    /// <summary>
+    /// The item removed event. Will be raised for every individual removal from the collection.
+    /// </summary>
+    public virtual event ItemsRemovedHandler<T> ItemsRemoved
+    {
+      add { checkWillListen(EventTypeEnum.Removed); (eventBlock ?? (eventBlock = new EventBlock<T>())).ItemsRemoved += value; }
+      remove
+      {
+        checkWillListen(EventTypeEnum.Removed);
+        if (eventBlock != null)
+        {
+          eventBlock.ItemsRemoved -= value;
+          if (eventBlock.events == 0) eventBlock = null;
+        }
+      }
+    }
+    /// <summary>
+    /// Fire the ItemsRemoved event
+    /// </summary>
+    /// <param name="item">The item that was removed</param>
+    /// <param name="count"></param>
+    protected virtual void raiseItemsRemoved(T item, int count)
+    { if (eventBlock != null) eventBlock.raiseItemsRemoved(this, item, count); }
+
+    /// <summary>
+    /// The item added  event. Will be raised for every individual addition to the collection.
+    /// </summary>
+    public virtual event ItemInsertedHandler<T> ItemInserted
+    {
+      add { checkWillListen(EventTypeEnum.Inserted); (eventBlock ?? (eventBlock = new EventBlock<T>())).ItemInserted += value; }
+      remove
+      {
+        checkWillListen(EventTypeEnum.Inserted);
+        if (eventBlock != null)
+        {
+          eventBlock.ItemInserted -= value;
+          if (eventBlock.events == 0) eventBlock = null;
+        }
+      }
+    }
+    /// <summary>
+    /// Fire the ItemInserted event
+    /// </summary>
+    /// <param name="item">The item that was added</param>
+    /// <param name="index"></param>
+    protected virtual void raiseItemInserted(T item, int index)
+    { if (eventBlock != null) eventBlock.raiseItemInserted(this, item, index); }
+
+    /// <summary>
+    /// The item removed event. Will be raised for every individual removal from the collection.
+    /// </summary>
+    public virtual event ItemRemovedAtHandler<T> ItemRemovedAt
+    {
+      add { checkWillListen(EventTypeEnum.RemovedAt); (eventBlock ?? (eventBlock = new EventBlock<T>())).ItemRemovedAt += value; }
+      remove
+      {
+        checkWillListen(EventTypeEnum.RemovedAt);
+        if (eventBlock != null)
+        {
+          eventBlock.ItemRemovedAt -= value;
+          if (eventBlock.events == 0) eventBlock = null;
+        }
+      }
+    }
+    /// <summary> 
+    /// Fire the ItemRemovedAt event
+    /// </summary>
+    /// <param name="item">The item that was removed</param>
+    /// <param name="index"></param>
+    protected virtual void raiseItemRemovedAt(T item, int index)
+    { if (eventBlock != null) eventBlock.raiseItemRemovedAt(this, item, index); }
+
+    #region Event support for IList
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="index"></param>
+    /// <param name="value"></param>
+    /// <param name="item"></param>
+    protected virtual void raiseForSetThis(int index, T value, T item)
+    {
+      if (ActiveEvents != 0)
+      {
+        raiseItemsRemoved(item, 1);
+        raiseItemRemovedAt(item, index);
+        raiseItemsAdded(value, 1);
+        raiseItemInserted(value, index);
+        raiseCollectionChanged();
+      }
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="i"></param>
+    /// <param name="item"></param>
+    protected virtual void raiseForInsert(int i, T item)
+    {
+      if (ActiveEvents != 0)
+      {
+        raiseItemInserted(item, i);
+        raiseItemsAdded(item, 1);
+        raiseCollectionChanged();
+      }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    protected void raiseForRemove(T item)
+    {
+      if (ActiveEvents != 0)
+      {
+        raiseItemsRemoved(item, 1);
+        raiseCollectionChanged();
+      }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="count"></param>
+    protected void raiseForRemove(T item, int count)
+    {
+      if (ActiveEvents != 0)
+      {
+        raiseItemsRemoved(item, count);
+        raiseCollectionChanged();
+      }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="index"></param>
+    /// <param name="item"></param>
+    protected void raiseForRemoveAt(int index, T item)
+    {
+      if (ActiveEvents != 0)
+      {
+        raiseItemRemovedAt(item, index);
+        raiseItemsRemoved(item, 1);
+        raiseCollectionChanged();
+      }
+    }
+
+    #endregion
+
+    #region Event  Support for ICollection
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="newitem"></param>
+    /// <param name="olditem"></param>
+    protected virtual void raiseForUpdate(T newitem, T olditem)
+    {
+      if (ActiveEvents != 0)
+      {
+        raiseItemsRemoved(olditem, 1);
+        raiseItemsAdded(newitem, 1);
+        raiseCollectionChanged();
+      }
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="newitem"></param>
+    /// <param name="olditem"></param>
+    /// <param name="count"></param>
+    protected virtual void raiseForUpdate(T newitem, T olditem, int count)
+    {
+      if (ActiveEvents != 0)
+      {
+        raiseItemsRemoved(olditem, count);
+        raiseItemsAdded(newitem, count);
+        raiseCollectionChanged();
+      }
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    protected virtual void raiseForAdd(T item)
+    {
+      if (ActiveEvents != 0)
+      {
+        raiseItemsAdded(item, 1);
+        raiseCollectionChanged();
+      }
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="wasRemoved"></param>
+    protected virtual void raiseForRemoveAll(ICollectionValue<T> wasRemoved)
+    {
+      if ((ActiveEvents & EventTypeEnum.Removed) != 0)
+        foreach (T item in wasRemoved)
+          raiseItemsRemoved(item, 1);
+      if (wasRemoved != null && wasRemoved.Count > 0)
+        raiseCollectionChanged();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    protected class RaiseForRemoveAllHandler
+    {
+      CollectionValueBase<T> collection;
+      CircularQueue<T> wasRemoved;
+      bool wasChanged = false;
+
+      /// <summary>
+      /// 
+      /// </summary>
+      /// <param name="collection"></param>
+      public RaiseForRemoveAllHandler(CollectionValueBase<T> collection)
+      {
+        this.collection = collection;
+        mustFireRemoved = (collection.ActiveEvents & EventTypeEnum.Removed) != 0;
+        MustFire = (collection.ActiveEvents & (EventTypeEnum.Removed | EventTypeEnum.Changed)) != 0;
+      }
+
+      bool mustFireRemoved;
+      /// <summary>
+      /// 
+      /// </summary>
+      public readonly bool MustFire;
+
+      /// <summary>
+      /// 
+      /// </summary>
+      /// <param name="item"></param>
+      public void Remove(T item)
+      {
+        if (mustFireRemoved)
+        {
+          if (wasRemoved == null)
+            wasRemoved = new CircularQueue<T>();
+          wasRemoved.Enqueue(item);
+        }
+        if (!wasChanged)
+          wasChanged = true;
+      }
+
+      /// <summary>
+      /// 
+      /// </summary>
+      public void Raise()
+      {
+        if (wasRemoved != null)
+          foreach (T item in wasRemoved)
+            collection.raiseItemsRemoved(item, 1);
+        if (wasChanged)
+          collection.raiseCollectionChanged();
+      }
+    }
+    #endregion
+
+    #endregion
+
+    /// <summary>
+    /// Check if collection is empty.
+    /// </summary>
+    /// <value>True if empty</value>
+    public abstract bool IsEmpty { get;}
+
+    /// <summary>
+    /// The number of items in this collection.
+    /// </summary>
+    /// <value></value>
+    public abstract int Count { get;}
+
+    /// <summary>
+    /// The value is symbolic indicating the type of asymptotic complexity
+    /// in terms of the size of this collection (worst-case or amortized as
+    /// relevant).
+    /// </summary>
+    /// <value>A characterization of the speed of the 
+    /// <code>Count</code> property in this collection.</value>
+    public abstract Speed CountSpeed { get; }
+
+    /// <summary>
+    /// Copy the items of this collection to part of an array.
+    /// </summary>
+    /// <exception cref="ArgumentOutOfRangeException"> if <code>index</code> 
+    /// is not a valid index
+    /// into the array (i.e. negative or greater than the size of the array)
+    /// or the array does not have room for the items.</exception>
+    /// <param name="array">The array to copy to.</param>
+    /// <param name="index">The starting index.</param>
+    [Tested]
+    public virtual void CopyTo(T[] array, int index)
+    {
+      if (index < 0 || index + Count > array.Length)
+        throw new ArgumentOutOfRangeException();
+
+      foreach (T item in this) array[index++] = item;
+    }
+
+    /// <summary>
+    /// Create an array with the items of this collection (in the same order as an
+    /// enumerator would output them).
+    /// </summary>
+    /// <returns>The array</returns>
+    //[Tested]
+    public virtual T[] ToArray()
+    {
+      T[] res = new T[Count];
+      int i = 0;
+
+      foreach (T item in this) res[i++] = item;
+
+      return res;
+    }
+
+    /// <summary>
+    /// Apply an single argument action, <see cref="T:C5.Act`1"/> to this enumerable
+    /// </summary>
+    /// <param name="action">The action delegate</param>
+    [Tested]
+    public virtual void Apply(Act<T> action)
+    {
+      foreach (T item in this)
+        action(item);
+    }
+
+
+    /// <summary>
+    /// Check if there exists an item  that satisfies a
+    /// specific predicate in this collection.
+    /// </summary>
+    /// <param name="predicate">A delegate 
+    /// (<see cref="T:C5.Fun`2"/> with <code>R = bool</code>) 
+    /// defining the predicate</param>
+    /// <returns>True if such an item exists</returns>
+    [Tested]
+    public virtual bool Exists(Fun<T, bool> predicate)
+    {
+      foreach (T item in this)
+        if (predicate(item))
+          return true;
+
+      return false;
+    }
+
+    /// <summary>
+    /// Check if there exists an item  that satisfies a
+    /// specific predicate in this collection and return the first one in enumeration order.
+    /// </summary>
+    /// <param name="predicate">A delegate 
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
+    /// <param name="item"></param>
+    /// <returns>True is such an item exists</returns>
+    public virtual bool Find(Fun<T, bool> predicate, out T item)
+    {
+      foreach (T jtem in this)
+        if (predicate(jtem))
+        {
+          item = jtem;
+          return true;
+        }
+      item = default(T);
+      return false;
+    }
+
+    /// <summary>
+    /// Check if all items in this collection satisfies a specific predicate.
+    /// </summary>
+    /// <param name="predicate">A delegate 
+    /// (<see cref="T:C5.Fun`2"/> with <code>R = bool</code>) 
+    /// defining the predicate</param>
+    /// <returns>True if all items satisfies the predicate</returns>
+    [Tested]
+    public virtual bool All(Fun<T, bool> predicate)
+    {
+      foreach (T item in this)
+        if (!predicate(item))
+          return false;
+
+      return true;
+    }
+
+    /// <summary>
+    /// Create an enumerable, enumerating the items of this collection that satisfies 
+    /// a certain condition.
+    /// </summary>
+    /// <param name="predicate">A delegate 
+    /// (<see cref="T:C5.Fun`2"/> with <code>R = bool</code>) 
+    /// defining the predicate</param>
+    /// <returns>The filtered enumerable</returns>
+    public virtual SCG.IEnumerable<T> Filter(Fun<T, bool> predicate)
+    {
+      foreach (T item in this)
+        if (predicate(item))
+          yield return item;
+    }
+
+    /// <summary>
+    /// Choose some item of this collection. 
+    /// </summary>
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>
+    /// <returns></returns>
+    public abstract T Choose();
+
+
+    /// <summary>
+    /// Create an enumerator for this collection.
+    /// </summary>
+    /// <returns>The enumerator</returns>
+    public override abstract SCG.IEnumerator<T> GetEnumerator();
+
+    #region IShowable Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="stringbuilder"></param>
+    /// <param name="rest"></param>
+    /// <param name="formatProvider"></param>
+    /// <returns></returns>
+    public virtual bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
+    {
+      return Showing.ShowCollectionValue<T>(this, stringbuilder, ref rest, formatProvider);
+    }
+    #endregion
+
+    #region IFormattable Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="format"></param>
+    /// <param name="formatProvider"></param>
+    /// <returns></returns>
+    public virtual string ToString(string format, IFormatProvider formatProvider)
+    {
+      return Showing.ShowString(this, format, formatProvider);
+    }
+
+    #endregion
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override string ToString()
+    {
+      return ToString(null, null);
+    }
+
+  }
+
+  /// <summary>
+  /// 
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  public abstract class DirectedCollectionValueBase<T> : CollectionValueBase<T>, IDirectedCollectionValue<T>
+  {
+    /// <summary>
+    /// <code>Forwards</code> if same, else <code>Backwards</code>
+    /// </summary>
+    /// <value>The enumeration direction relative to the original collection.</value>
+    public virtual EnumerationDirection Direction { [Tested]get { return EnumerationDirection.Forwards; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public abstract IDirectedCollectionValue<T> Backwards();
+
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return this.Backwards(); }
+
+    /// <summary>
+    /// Check if there exists an item  that satisfies a
+    /// specific predicate in this collection and return the first one in enumeration order.
+    /// </summary>
+    /// <param name="predicate">A delegate 
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
+    /// <param name="item"></param>
+    /// <returns>True is such an item exists</returns>
+    public virtual bool FindLast(Fun<T, bool> predicate, out T item)
+    {
+      foreach (T jtem in Backwards())
+        if (predicate(jtem))
+        {
+          item = jtem;
+          return true;
+        }
+      item = default(T);
+      return false;
+    }
+  }
+
+  /// <summary>
+  /// Base class (abstract) for ICollection implementations.
+  /// </summary>
+  [Serializable]
+  public abstract class CollectionBase<T> : CollectionValueBase<T>
+  {
+    #region Fields
+
+    /// <summary>
+    /// The underlying field of the ReadOnly property
+    /// </summary>
+    protected bool isReadOnlyBase = false;
+
+    /// <summary>
+    /// The current stamp value
+    /// </summary>
+    protected int stamp;
+
+    /// <summary>
+    /// The number of items in the collection
+    /// </summary>
+    protected int size;
+
+    /// <summary>
+    /// The item equalityComparer of the collection
+    /// </summary>
+    protected readonly SCG.IEqualityComparer<T> itemequalityComparer;
+
+    int iUnSequencedHashCode, iUnSequencedHashCodeStamp = -1;
+
+    #endregion
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="itemequalityComparer"></param>
+    protected CollectionBase(SCG.IEqualityComparer<T> itemequalityComparer)
+    {
+      if (itemequalityComparer == null)
+        throw new NullReferenceException("Item EqualityComparer cannot be null.");
+      this.itemequalityComparer = itemequalityComparer;
+    }
+
+    #region Util
+
+    /// <summary>
+    /// Utility method for range checking.
+    /// </summary>
+    /// <exception cref="ArgumentOutOfRangeException"> if the start or count is negative or
+    ///  if the range does not fit within collection size.</exception>
+    /// <param name="start">start of range</param>
+    /// <param name="count">size of range</param>
+    [Tested]
+    protected void checkRange(int start, int count)
+    {
+      if (start < 0 || count < 0 || start + count > size)
+        throw new ArgumentOutOfRangeException();
+    }
+
+
+    /// <summary>
+    /// Compute the unsequenced hash code of a collection
+    /// </summary>
+    /// <param name="items">The collection to compute hash code for</param>
+    /// <param name="itemequalityComparer">The item equalityComparer</param>
+    /// <returns>The hash code</returns>
+    [Tested]
+    public static int ComputeHashCode(ICollectionValue<T> items, SCG.IEqualityComparer<T> itemequalityComparer)
+    {
+      int h = 0;
+
+#if IMPROVED_COLLECTION_HASHFUNCTION
+      //But still heuristic: 
+      //Note: the three odd factors should really be random, 
+      //but there will be a problem with serialization/deserialization!
+      //Two products is too few
+      foreach (T item in items)
+      {
+        uint h1 = (uint)itemequalityComparer.GetHashCode(item);
+
+        h += (int)((h1 * 1529784657 + 1) ^ (h1 * 2912831877) ^ (h1 * 1118771817 + 2));
+      }
+
+      return h;
+      /*
+            The pairs (-1657792980, -1570288808) and (1862883298, -272461342) gives the same
+            unsequenced hashcode with this hashfunction. The pair was found with code like
+
+            HashDictionary<int, int[]> set = new HashDictionary<int, int[]>();
+            Random rnd = new C5Random(12345);
+            while (true)
+            {
+                int[] a = new int[2];
+                a[0] = rnd.Next(); a[1] = rnd.Next();
+                int h = unsequencedhashcode(a);
+                int[] b = a;
+                if (set.FindOrAdd(h, ref b))
+                {
+                    Console.WriteLine("Code {5}, Pair ({1},{2}) number {0} matched other pair ({3},{4})", set.Count, a[0], a[1], b[0], b[1], h);
+                }
+            }
+            */
+#else
+            foreach (T item in items)
+				h ^= itemequalityComparer.GetHashCode(item);
+
+			return (items.Count << 16) + h;
+#endif
+    }
+
+    static Type isortedtype = typeof(ISorted<T>);
+
+    /// <summary>
+    /// Examine if collection1 and collection2 are equal as unsequenced collections
+    /// using the specified item equalityComparer (assumed compatible with the two collections).
+    /// </summary>
+    /// <param name="collection1">The first collection</param>
+    /// <param name="collection2">The second collection</param>
+    /// <param name="itemequalityComparer">The item equalityComparer to use for comparison</param>
+    /// <returns>True if equal</returns>
+    [Tested]
+    public static bool StaticEquals(ICollection<T> collection1, ICollection<T> collection2, SCG.IEqualityComparer<T> itemequalityComparer)
+    {
+      if (object.ReferenceEquals(collection1, collection2))
+        return true;
+
+      // bug20070227:
+      if (collection1 == null || collection2 == null)
+        return false;
+
+      if (collection1.Count != collection2.Count)
+        return false;
+
+      //This way we might run through both enumerations twice, but
+      //probably not (if the hash codes are good)
+      //TODO: check equal equalityComparers, at least here!
+      if (collection1.GetUnsequencedHashCode() != collection2.GetUnsequencedHashCode())
+        return false;
+
+      //TODO: move this to the sorted implementation classes? 
+      //Really depends on speed of InstanceOfType: we could save a cast
+      {
+        ISorted<T> stit, stat;
+        if ((stit = collection1 as ISorted<T>) != null && (stat = collection2 as ISorted<T>) != null && stit.Comparer == stat.Comparer)
+        {
+          using (SCG.IEnumerator<T> dat = collection2.GetEnumerator(), dit = collection1.GetEnumerator())
+          {
+            while (dit.MoveNext())
+            {
+              dat.MoveNext();
+              if (!itemequalityComparer.Equals(dit.Current, dat.Current))
+                return false;
+            }
+            return true;
+          }
+        }
+      }
+
+      if (!collection1.AllowsDuplicates && (collection2.AllowsDuplicates || collection2.ContainsSpeed >= collection1.ContainsSpeed))
+      {
+        foreach (T x in collection1) if (!collection2.Contains(x)) return false;
+      }
+      else if (!collection2.AllowsDuplicates)
+      {
+        foreach (T x in collection2) if (!collection1.Contains(x)) return false;
+      }
+      // Now tit.AllowsDuplicates && tat.AllowsDuplicates
+      else if (collection1.DuplicatesByCounting && collection2.DuplicatesByCounting)
+      {
+        foreach (T item in collection2) if (collection1.ContainsCount(item) != collection2.ContainsCount(item)) return false;
+      }
+      else
+      {
+        //To avoid an O(n^2) algorithm, we make an aux hashtable to hold the count of items
+        HashDictionary<T, int> dict = new HashDictionary<T, int>();
+        foreach (T item in collection2)
+        {
+          int count = 1;
+          if (dict.FindOrAdd(item, ref count))
+            dict[item] = count + 1;
+        }
+        foreach (T item in collection1)
+        {
+          int count;
+          if (dict.Find(item, out count) && count > 0)
+            dict[item] = count - 1;
+          else
+            return false;
+        }
+        return true;
+      }
+
+      return true;
+    }
+
+
+    /// <summary>
+    /// Get the unsequenced collection hash code of this collection: from the cached 
+    /// value if present and up to date, else (re)compute.
+    /// </summary>
+    /// <returns>The hash code</returns>
+    public virtual int GetUnsequencedHashCode()
+    {
+      if (iUnSequencedHashCodeStamp == stamp)
+        return iUnSequencedHashCode;
+
+      iUnSequencedHashCode = ComputeHashCode(this, itemequalityComparer);
+      iUnSequencedHashCodeStamp = stamp;
+      return iUnSequencedHashCode;
+    }
+
+
+    /// <summary>
+    /// Check if the contents of otherCollection is equal to the contents of this
+    /// in the unsequenced sense.  Uses the item equality comparer of this collection
+    /// </summary>
+    /// <param name="otherCollection">The collection to compare to.</param>
+    /// <returns>True if  equal</returns>
+    public virtual bool UnsequencedEquals(ICollection<T> otherCollection)
+    {
+      return otherCollection != null && StaticEquals((ICollection<T>)this, otherCollection, itemequalityComparer);
+    }
+
+
+    /// <summary>
+    /// Check if the collection has been modified since a specified time, expressed as a stamp value.
+    /// </summary>
+    /// <exception cref="CollectionModifiedException"> if this collection has been updated 
+    /// since a target time</exception>
+    /// <param name="thestamp">The stamp identifying the target time</param>
+    protected virtual void modifycheck(int thestamp)
+    {
+      if (this.stamp != thestamp)
+        throw new CollectionModifiedException();
+    }
+
+
+    /// <summary>
+    /// Check if it is valid to perform update operations, and if so increment stamp.
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException">If colection is read-only</exception>
+    protected virtual void updatecheck()
+    {
+      if (isReadOnlyBase)
+        throw new ReadOnlyCollectionException();
+
+      stamp++;
+    }
+
+    #endregion
+
+    #region ICollection<T> members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>True if this collection is read only</value>
+    [Tested]
+    public virtual bool IsReadOnly { [Tested]get { return isReadOnlyBase; } }
+
+    #endregion
+
+    #region ICollectionValue<T> members
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>The size of this collection</value>
+    [Tested]
+    public override int Count { [Tested]get { return size; } }
+
+    /// <summary>
+    /// The value is symbolic indicating the type of asymptotic complexity
+    /// in terms of the size of this collection (worst-case or amortized as
+    /// relevant).
+    /// </summary>
+    /// <value>A characterization of the speed of the 
+    /// <code>Count</code> property in this collection.</value>
+    public override Speed CountSpeed { get { return Speed.Constant; } }
+
+
+    #endregion
+
+    #region IExtensible<T> members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual SCG.IEqualityComparer<T> EqualityComparer { get { return itemequalityComparer; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>True if this collection is empty</value>
+    [Tested]
+    public override bool IsEmpty { [Tested]get { return size == 0; } }
+
+    #endregion
+
+    #region IEnumerable<T> Members
+    /// <summary>
+    /// Create an enumerator for this collection.
+    /// </summary>
+    /// <returns>The enumerator</returns>
+    public override abstract SCG.IEnumerator<T> GetEnumerator();
+    #endregion
+  }
+
+  /// <summary>
+  /// 
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  [Serializable]
+  public abstract class DirectedCollectionBase<T> : CollectionBase<T>, IDirectedCollectionValue<T>
+  {
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="itemequalityComparer"></param>
+    protected DirectedCollectionBase(SCG.IEqualityComparer<T> itemequalityComparer) : base(itemequalityComparer) { }
+    /// <summary>
+    /// <code>Forwards</code> if same, else <code>Backwards</code>
+    /// </summary>
+    /// <value>The enumeration direction relative to the original collection.</value>
+    public virtual EnumerationDirection Direction { [Tested]get { return EnumerationDirection.Forwards; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public abstract IDirectedCollectionValue<T> Backwards();
+
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return this.Backwards(); }
+
+    /// <summary>
+    /// Check if there exists an item  that satisfies a
+    /// specific predicate in this collection and return the first one in enumeration order.
+    /// </summary>
+    /// <param name="predicate">A delegate 
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
+    /// <param name="item"></param>
+    /// <returns>True is such an item exists</returns>
+    public virtual bool FindLast(Fun<T, bool> predicate, out T item)
+    {
+      foreach (T jtem in Backwards())
+        if (predicate(jtem))
+        {
+          item = jtem;
+          return true;
+        }
+      item = default(T);
+      return false;
+    }
+  }
+
+  /// <summary>
+  /// Base class (abstract) for sequenced collection implementations.
+  /// </summary>
+  [Serializable]
+  public abstract class SequencedBase<T> : DirectedCollectionBase<T>, IDirectedCollectionValue<T>
+  {
+    #region Fields
+
+    int iSequencedHashCode, iSequencedHashCodeStamp = -1;
+
+    #endregion
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="itemequalityComparer"></param>
+    protected SequencedBase(SCG.IEqualityComparer<T> itemequalityComparer) : base(itemequalityComparer) { }
+
+    #region Util
+
+    //TODO: make random for release
+    const int HASHFACTOR = 31;
+
+    /// <summary>
+    /// Compute the unsequenced hash code of a collection
+    /// </summary>
+    /// <param name="items">The collection to compute hash code for</param>
+    /// <param name="itemequalityComparer">The item equalityComparer</param>
+    /// <returns>The hash code</returns>
+    [Tested]
+    public static int ComputeHashCode(ISequenced<T> items, SCG.IEqualityComparer<T> itemequalityComparer)
+    {
+      //NOTE: It must be possible to devise a much stronger combined hashcode, 
+      //but unfortunately, it has to be universal. OR we could use a (strong)
+      //family and initialise its parameter randomly at load time of this class!
+      //(We would not want to have yet a flag to check for invalidation?!)
+      //NBNBNB: the current hashcode has the very bad property that items with hashcode 0
+      // is ignored.
+      int iIndexedHashCode = 0;
+
+      foreach (T item in items)
+        iIndexedHashCode = iIndexedHashCode * HASHFACTOR + itemequalityComparer.GetHashCode(item);
+
+      return iIndexedHashCode;
+    }
+
+
+    /// <summary>
+    /// Examine if tit and tat are equal as sequenced collections
+    /// using the specified item equalityComparer (assumed compatible with the two collections).
+    /// </summary>
+    /// <param name="collection1">The first collection</param>
+    /// <param name="collection2">The second collection</param>
+    /// <param name="itemequalityComparer">The item equalityComparer to use for comparison</param>
+    /// <returns>True if equal</returns>
+    [Tested]
+    public static bool StaticEquals(ISequenced<T> collection1, ISequenced<T> collection2, SCG.IEqualityComparer<T> itemequalityComparer)
+    {
+      if (object.ReferenceEquals(collection1, collection2))
+        return true;
+
+      if (collection1.Count != collection2.Count)
+        return false;
+
+      //This way we might run through both enumerations twice, but
+      //probably not (if the hash codes are good)
+      if (collection1.GetSequencedHashCode() != collection2.GetSequencedHashCode())
+        return false;
+
+      using (SCG.IEnumerator<T> dat = collection2.GetEnumerator(), dit = collection1.GetEnumerator())
+      {
+        while (dit.MoveNext())
+        {
+          dat.MoveNext();
+          if (!itemequalityComparer.Equals(dit.Current, dat.Current))
+            return false;
+        }
+      }
+
+      return true;
+    }
+
+
+    /// <summary>
+    /// Get the sequenced collection hash code of this collection: from the cached 
+    /// value if present and up to date, else (re)compute.
+    /// </summary>
+    /// <returns>The hash code</returns>
+    public virtual int GetSequencedHashCode()
+    {
+      if (iSequencedHashCodeStamp == stamp)
+        return iSequencedHashCode;
+
+      iSequencedHashCode = ComputeHashCode((ISequenced<T>)this, itemequalityComparer);
+      iSequencedHashCodeStamp = stamp;
+      return iSequencedHashCode;
+    }
+
+
+    /// <summary>
+    /// Check if the contents of that is equal to the contents of this
+    /// in the sequenced sense. Using the item equalityComparer of this collection.
+    /// </summary>
+    /// <param name="otherCollection">The collection to compare to.</param>
+    /// <returns>True if  equal</returns>
+    public virtual bool SequencedEquals(ISequenced<T> otherCollection)
+    {
+      return StaticEquals((ISequenced<T>)this, otherCollection, itemequalityComparer);
+    }
+
+
+    #endregion
+
+    /// <summary>
+    /// Create an enumerator for this collection.
+    /// </summary>
+    /// <returns>The enumerator</returns>
+    public override abstract SCG.IEnumerator<T> GetEnumerator();
+
+    /// <summary>
+    /// <code>Forwards</code> if same, else <code>Backwards</code>
+    /// </summary>
+    /// <value>The enumeration direction relative to the original collection.</value>
+    [Tested]
+    public override EnumerationDirection Direction { [Tested]get { return EnumerationDirection.Forwards; } }
+
+    /// <summary>
+    /// Check if there exists an item  that satisfies a
+    /// specific predicate in this collection and return the index of the first one.
+    /// </summary>
+    /// <param name="predicate">A delegate 
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
+    /// <returns>the index, if found, a negative value else</returns>
+    public int FindIndex(Fun<T, bool> predicate)
+    {
+      int index = 0;
+      foreach (T item in this)
+      {
+        if (predicate(item))
+          return index;
+        index++;
+      }
+      return -1;
+    }
+
+    /// <summary>
+    /// Check if there exists an item  that satisfies a
+    /// specific predicate in this collection and return the index of the last one.
+    /// </summary>
+    /// <param name="predicate">A delegate 
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
+    /// <returns>the index, if found, a negative value else</returns>
+    public int FindLastIndex(Fun<T, bool> predicate)
+    {
+      int index = Count - 1;
+      foreach (T item in Backwards())
+      {
+        if (predicate(item))
+          return index;
+        index--;
+      }
+      return -1;
+    }
+
+  }
+
+
+  /// <summary>
+  /// Base class for collection classes of dynamic array type implementations.
+  /// </summary>
+  [Serializable]
+  public abstract class ArrayBase<T> : SequencedBase<T>
+  {
+    #region Fields
+    /// <summary>
+    /// The actual internal array container. Will be extended on demand.
+    /// </summary>
+    protected T[] array;
+
+    /// <summary>
+    /// The offset into the internal array container of the first item. The offset is 0 for a 
+    /// base dynamic array and may be positive for an updatable view into a base dynamic array.
+    /// </summary>
+    protected int offset;
+    #endregion
+
+    #region Util
+    /// <summary>
+    /// Double the size of the internal array.
+    /// </summary>
+    protected virtual void expand()
+    {
+      expand(2 * array.Length, size);
+    }
+
+
+    /// <summary>
+    /// Expand the internal array container.
+    /// </summary>
+    /// <param name="newcapacity">The new size of the internal array - 
+    /// will be rounded upwards to a power of 2.</param>
+    /// <param name="newsize">The (new) size of the (base) collection.</param>
+    protected virtual void expand(int newcapacity, int newsize)
+    {
+      Debug.Assert(newcapacity >= newsize);
+
+      int newlength = array.Length;
+
+      while (newlength < newcapacity) newlength *= 2;
+
+      T[] newarray = new T[newlength];
+
+      Array.Copy(array, newarray, newsize);
+      array = newarray;
+    }
+
+
+    /// <summary>
+    /// Insert an item at a specific index, moving items to the right
+    /// upwards and expanding the array if necessary.
+    /// </summary>
+    /// <param name="i">The index at which to insert.</param>
+    /// <param name="item">The item to insert.</param>
+    protected virtual void insert(int i, T item)
+    {
+      if (size == array.Length)
+        expand();
+
+      if (i < size)
+        Array.Copy(array, i, array, i + 1, size - i);
+
+      array[i] = item;
+      size++;
+    }
+
+    #endregion
+
+    #region Constructors
+
+    /// <summary>
+    /// Create an empty ArrayBase object.
+    /// </summary>
+    /// <param name="capacity">The initial capacity of the internal array container.
+    /// Will be rounded upwards to the nearest power of 2 greater than or equal to 8.</param>
+    /// <param name="itemequalityComparer">The item equalityComparer to use, primarily for item equality</param>
+    protected ArrayBase(int capacity, SCG.IEqualityComparer<T> itemequalityComparer)
+      : base(itemequalityComparer)
+    {
+      int newlength = 8;
+      while (newlength < capacity) newlength *= 2;
+      array = new T[newlength];
+    }
+
+    #endregion
+
+    #region IIndexed members
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ArgumentOutOfRangeException">If the arguments does not describe a 
+    /// valid range in the indexed collection, cf. <see cref="M:C5.CollectionBase`1.checkRange(System.Int32,System.Int32)"/>.</exception>
+    /// <value>The directed collection of items in a specific index interval.</value>
+    /// <param name="start">The low index of the interval (inclusive).</param>
+    /// <param name="count">The size of the range.</param>
+    [Tested]
+    public virtual IDirectedCollectionValue<T> this[int start, int count]
+    {
+      [Tested]
+      get
+      {
+        checkRange(start, count);
+        return new Range(this, start, count, true);
+      }
+    }
+
+    #endregion
+
+    #region IEditableCollection members
+    /// <summary>
+    /// Remove all items and reset size of internal array container.
+    /// </summary>
+    [Tested]
+    public virtual void Clear()
+    {
+      updatecheck();
+      array = new T[8];
+      size = 0;
+    }
+
+
+    /// <summary>
+    /// Create an array containing (copies) of the items of this collection in enumeration order.
+    /// </summary>
+    /// <returns>The new array</returns>
+    [Tested]
+    public override T[] ToArray()
+    {
+      T[] res = new T[size];
+
+      Array.Copy(array, offset, res, 0, size);
+      return res;
+    }
+
+
+    /// <summary>
+    /// Perform an internal consistency (invariant) test on the array base.
+    /// </summary>
+    /// <returns>True if test succeeds.</returns>
+    [Tested]
+    public virtual bool Check()
+    {
+      bool retval = true;
+
+      if (size > array.Length)
+      {
+        Console.WriteLine("Bad size ({0}) > array.Length ({1})", size, array.Length);
+        return false;
+      }
+
+      for (int i = 0; i < size; i++)
+      {
+        if ((object)(array[i]) == null)
+        {
+          Console.WriteLine("Bad element: null at index {0}", i);
+          return false;
+        }
+      }
+
+      return retval;
+    }
+
+    #endregion
+
+    #region IDirectedCollection<T> Members
+
+    /// <summary>
+    /// Create a directed collection with the same contents as this one, but 
+    /// opposite enumeration sequence.
+    /// </summary>
+    /// <returns>The mirrored collection.</returns>
+    [Tested]
+    public override IDirectedCollectionValue<T> Backwards() { return this[0, size].Backwards(); }
+
+    #endregion
+
+    /// <summary>
+    /// Choose some item of this collection. The result is the last item in the internal array,
+    /// making it efficient to remove.
+    /// </summary>
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>
+    /// <returns></returns>
+    public override T Choose() { if (size > 0) return array[size - 1]; throw new NoSuchItemException(); }
+
+    #region IEnumerable<T> Members
+    /// <summary>
+    /// Create an enumerator for this array based collection.
+    /// </summary>
+    /// <returns>The enumerator</returns>
+    [Tested]
+    public override SCG.IEnumerator<T> GetEnumerator()
+    {
+      int thestamp = stamp, theend = size + offset, thestart = offset;
+
+      for (int i = thestart; i < theend; i++)
+      {
+        modifycheck(thestamp);
+        yield return array[i];
+      }
+    }
+    #endregion
+
+    #region Range nested class
+    /// <summary>
+    /// A helper class for defining results of interval queries on array based collections.
+    /// </summary>
+    protected class Range : DirectedCollectionValueBase<T>, IDirectedCollectionValue<T>
+    {
+      int start, count, delta, stamp;
+
+      ArrayBase<T> thebase;
+
+
+      internal Range(ArrayBase<T> thebase, int start, int count, bool forwards)
+      {
+        this.thebase = thebase; stamp = thebase.stamp;
+        delta = forwards ? 1 : -1;
+        this.start = start + thebase.offset; this.count = count;
+      }
+
+      /// <summary>
+      /// 
+      /// </summary>
+      /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>
+      /// <value>True if this collection is empty.</value>
+      public override bool IsEmpty { get { thebase.modifycheck(stamp); return count == 0; } }
+
+
+      /// <summary>
+      /// 
+      /// </summary>
+      /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>
+      /// <value>The number of items in the range</value>
+      [Tested]
+      public override int Count { [Tested]get { thebase.modifycheck(stamp); return count; } }
+
+      /// <summary>
+      /// The value is symbolic indicating the type of asymptotic complexity
+      /// in terms of the size of this collection (worst-case or amortized as
+      /// relevant).
+      /// </summary>
+      /// <value>A characterization of the speed of the 
+      /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>
+      /// <code>Count</code> property in this collection.</value>
+      public override Speed CountSpeed { get { thebase.modifycheck(stamp); return Speed.Constant; } }
+
+      /// <summary>
+      /// Choose some item of this collection. 
+      /// </summary>
+      /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>
+      /// <exception cref="NoSuchItemException">if range is empty.</exception>
+      /// <returns></returns>
+      public override T Choose()
+      {
+        thebase.modifycheck(stamp);
+        if (count == 0)
+          throw new NoSuchItemException();
+        return thebase.array[start];
+      }
+
+
+      /// <summary>
+      /// Create an enumerator for this range of an array based collection.
+      /// </summary>
+      /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>
+      /// <returns>The enumerator</returns>
+      [Tested]
+      public override SCG.IEnumerator<T> GetEnumerator()
+      {
+        for (int i = 0; i < count; i++)
+        {
+          thebase.modifycheck(stamp);
+          yield return thebase.array[start + delta * i];
+        }
+      }
+
+
+      /// <summary>
+      /// Create a araay collection range with the same contents as this one, but 
+      /// opposite enumeration sequence.
+      /// </summary>
+      /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>
+      /// <returns>The mirrored collection.</returns>
+      [Tested]
+      public override IDirectedCollectionValue<T> Backwards()
+      {
+        thebase.modifycheck(stamp);
+
+        Range res = (Range)MemberwiseClone();
+
+        res.delta = -delta;
+        res.start = start + (count - 1) * delta;
+        return res;
+      }
+
+
+      IDirectedEnumerable<T> C5.IDirectedEnumerable<T>.Backwards()
+      {
+        return Backwards();
+      }
+
+
+      /// <summary>
+      /// <code>Forwards</code> if same, else <code>Backwards</code>
+      /// </summary>
+      /// <exception cref="CollectionModifiedException">if underlying collection has been modified.</exception>
+      /// <value>The enumeration direction relative to the original collection.</value>
+      [Tested]
+      public override EnumerationDirection Direction
+      {
+        [Tested]
+        get
+        {
+          thebase.modifycheck(stamp);
+          return delta > 0 ? EnumerationDirection.Forwards : EnumerationDirection.Backwards;
+        }
+      }
+    }
+    #endregion
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Comparer.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Comparer.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Comparer.cs	(revision 3)
@@ -0,0 +1,181 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using C5;
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+
+namespace C5
+{
+  /// <summary>
+  /// A default item comparer for an item type that is either generic (IComparable&lt;T&gt;)
+  /// or ordinarily (System.IComparable) comparable.
+  /// </summary>
+  public static class Comparer<T>
+  {
+    readonly static Type naturalComparerO = typeof(NaturalComparerO<>);
+
+    readonly static Type naturalComparer = typeof(NaturalComparer<>);
+
+    static SCG.IComparer<T> cachedComparer = null;
+
+    /// <summary>
+    /// Create a default comparer. 
+    /// <para>The IComparer[T] object is constructed when this class is initialised, i.e. 
+    /// its static constructors called. Thus, the property will be the same object 
+    /// for the duration of an invocation of the runtime, but a value serialized in 
+    /// another invocation and deserialized here will not be the same object.</para>
+    /// </summary>
+    /// <exception cref="NotComparableException">If T is not comparable</exception>
+    /// <value>The comparer</value>
+    [Tested]
+    public static SCG.IComparer<T> Default
+    {
+      get
+      {
+        if (cachedComparer != null)
+          return cachedComparer;
+
+        Type t = typeof(T);
+
+        if (t.IsValueType)
+        {
+          if (t.Equals(typeof(char)))
+            return cachedComparer = (SCG.IComparer<T>)(new CharComparer());
+
+          if (t.Equals(typeof(sbyte)))
+            return cachedComparer = (SCG.IComparer<T>)(new SByteComparer());
+
+          if (t.Equals(typeof(byte)))
+            return cachedComparer = (SCG.IComparer<T>)(new ByteComparer());
+
+          if (t.Equals(typeof(short)))
+            return cachedComparer = (SCG.IComparer<T>)(new ShortComparer());
+
+          if (t.Equals(typeof(ushort)))
+            return cachedComparer = (SCG.IComparer<T>)(new UShortComparer());
+
+          if (t.Equals(typeof(int)))
+            return cachedComparer = (SCG.IComparer<T>)(new IntComparer());
+
+          if (t.Equals(typeof(uint)))
+            return cachedComparer = (SCG.IComparer<T>)(new UIntComparer());
+
+          if (t.Equals(typeof(long)))
+            return cachedComparer = (SCG.IComparer<T>)(new LongComparer());
+
+          if (t.Equals(typeof(ulong)))
+            return cachedComparer = (SCG.IComparer<T>)(new ULongComparer());
+
+          if (t.Equals(typeof(float)))
+            return cachedComparer = (SCG.IComparer<T>)(new FloatComparer());
+
+          if (t.Equals(typeof(double)))
+            return cachedComparer = (SCG.IComparer<T>)(new DoubleComparer());
+
+          if (t.Equals(typeof(decimal)))
+            return cachedComparer = (SCG.IComparer<T>)(new DecimalComparer());
+        }
+
+        if (typeof(IComparable<T>).IsAssignableFrom(t))
+        {
+          Type c = naturalComparer.MakeGenericType(new Type[] { t });
+
+          return cachedComparer = (SCG.IComparer<T>)(c.GetConstructor(System.Type.EmptyTypes).Invoke(null));
+        }
+
+        if (t.GetInterface("System.IComparable") != null)
+        {
+          Type c = naturalComparerO.MakeGenericType(new Type[] { t });
+
+          return cachedComparer = (SCG.IComparer<T>)(c.GetConstructor(System.Type.EmptyTypes).Invoke(null));
+        }
+
+        throw new NotComparableException(String.Format("Cannot make comparer for type {0}", t));
+      }
+    }
+  }
+
+  /// <summary>
+  /// A natural generic IComparer for an IComparable&lt;T&gt; item type
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  [Serializable]
+  public class NaturalComparer<T> : SCG.IComparer<T>
+      where T : IComparable<T>
+  {
+    /// <summary>
+    /// Compare two items
+    /// </summary>
+    /// <param name="item1">First item</param>
+    /// <param name="item2">Second item</param>
+    /// <returns>item1 &lt;=&gt; item2</returns>
+    [Tested]
+    public int Compare(T item1, T item2) { return item1 != null ? item1.CompareTo(item2) : item2 != null ? -1 : 0; }
+  }
+
+  /// <summary>
+  /// A natural generic IComparer for a System.IComparable item type
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  [Serializable]
+  public class NaturalComparerO<T> : SCG.IComparer<T> where T : System.IComparable
+  {
+    /// <summary>
+    /// Compare two items
+    /// </summary>
+    /// <param name="item1">First item</param>
+    /// <param name="item2">Second item</param>
+    /// <returns>item1 &lt;=&gt; item2</returns>
+    [Tested]
+    public int Compare(T item1, T item2) { return item1 != null ? item1.CompareTo(item2) : item2 != null ? -1 : 0; }
+  }
+
+  /// <summary>
+  /// A generic comparer for type T based on a Comparison[T] delegate
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  [Serializable]
+  public class DelegateComparer<T> : SCG.IComparer<T>
+  {
+    readonly Comparison<T> cmp;
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="comparison"></param>
+    public DelegateComparer(Comparison<T> comparison)
+    {
+      if (comparison == null)
+        throw new NullReferenceException("Comparison cannot be null");
+      this.cmp = comparison;
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item1">First item</param>
+    /// <param name="item2">Second item</param>
+    /// <returns>item1 &lt;=&gt; item2</returns>
+    public int Compare(T item1, T item2) { return cmp(item1, item2); }
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Delegates.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Delegates.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Delegates.cs	(revision 3)
@@ -0,0 +1,131 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using C5;
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Diagnostics;
+
+#pragma warning disable 1711
+namespace C5
+{
+  /// <summary>
+  /// 
+  /// </summary>
+  public delegate void Act();
+  /// <summary>
+  /// <para>
+  /// The type Act[T] corresponds to System.Action[T] in the .Net
+  /// Framework class library.
+  ///</para>
+  /// </summary>
+  /// <typeparam name="A1"></typeparam>
+  /// <param name="x1"></param>
+  public delegate void Act<A1>(A1 x1);
+  /// <summary>
+  /// 
+  /// </summary>
+  /// <typeparam name="A1"></typeparam>
+  /// <typeparam name="A2"></typeparam>
+  /// <param name="x1"></param>
+  /// <param name="x2"></param>
+  public delegate void Act<A1, A2>(A1 x1, A2 x2);
+  /// <summary>
+  /// 
+  /// </summary>
+  /// <typeparam name="A1"></typeparam>
+  /// <typeparam name="A2"></typeparam>
+  /// <typeparam name="A3"></typeparam>
+  /// <param name="x1"></param>
+  /// <param name="x2"></param>
+  /// <param name="x3"></param>
+  public delegate void Act<A1, A2, A3>(A1 x1, A2 x2, A3 x3);
+  /// <summary>
+  /// 
+  /// </summary>
+  /// <typeparam name="A1"></typeparam>
+  /// <typeparam name="A2"></typeparam>
+  /// <typeparam name="A3"></typeparam>
+  /// <typeparam name="A4"></typeparam>
+  /// <param name="x1"></param>
+  /// <param name="x2"></param>
+  /// <param name="x3"></param>
+  /// <param name="x4"></param>
+  public delegate void Act<A1, A2, A3, A4>(A1 x1, A2 x2, A3 x3, A4 x4);
+
+  /// <summary>
+  /// 
+  /// </summary>
+  /// <typeparam name="R"></typeparam>
+  /// <returns></returns>
+  public delegate R Fun<R>();
+  /// <summary>
+  /// Delegate type Fun[A1,R] is the type of functions (methods) from A1
+  /// to R, used to compute some transformation for a given collection
+  /// item. 
+  /// <para>
+  /// The type Fun[T,U] corresponds to System.Converter[T,U] in the .Net
+  /// Framework class library, and the type Fun[T,bool] corresponds
+  /// System.Predicate[T] in the .Net Framework class library.</para>
+  /// </summary>
+  /// <typeparam name="A1"></typeparam>
+  /// <typeparam name="R"></typeparam>
+  /// <param name="x1"></param>
+  /// <returns></returns>
+  public delegate R Fun<A1, R>(A1 x1);
+  /// <summary>
+  /// 
+  /// </summary>
+  /// <typeparam name="A1"></typeparam>
+  /// <typeparam name="A2"></typeparam>
+  /// <typeparam name="R"></typeparam>
+  /// <param name="x1"></param>
+  /// <param name="x2"></param>
+  /// <returns></returns>
+  public delegate R Fun<A1, A2, R>(A1 x1, A2 x2);
+  /// <summary>
+  /// 
+  /// </summary>
+  /// <typeparam name="A1"></typeparam>
+  /// <typeparam name="A2"></typeparam>
+  /// <typeparam name="A3"></typeparam>
+  /// <typeparam name="R"></typeparam>
+  /// <param name="x1"></param>
+  /// <param name="x2"></param>
+  /// <param name="x3"></param>
+  /// <returns></returns>
+  public delegate R Fun<A1, A2, A3, R>(A1 x1, A2 x2, A3 x3);
+  /// <summary>
+  /// 
+  /// </summary>
+  /// <typeparam name="A1"></typeparam>
+  /// <typeparam name="A2"></typeparam>
+  /// <typeparam name="A3"></typeparam>
+  /// <typeparam name="A4"></typeparam>
+  /// <typeparam name="R"></typeparam>
+  /// <param name="x1"></param>
+  /// <param name="x2"></param>
+  /// <param name="x3"></param>
+  /// <param name="x4"></param>
+  /// <returns></returns>
+  public delegate R Fun<A1, A2, A3, A4, R>(A1 x1, A2 x2, A3 x3, A4 x4);
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Dictionaries.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Dictionaries.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Dictionaries.cs	(revision 3)
@@ -0,0 +1,1383 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+namespace C5
+{
+  /// <summary>
+  /// An entry in a dictionary from K to V.
+  /// </summary>
+  [Serializable]
+  public struct KeyValuePair<K, V> : IEquatable<KeyValuePair<K, V>>, IShowable
+  {
+    /// <summary>
+    /// The key field of the entry
+    /// </summary>
+    public K Key;
+
+    /// <summary>
+    /// The value field of the entry
+    /// </summary>
+    public V Value;
+
+    /// <summary>
+    /// Create an entry with specified key and value
+    /// </summary>
+    /// <param name="key">The key</param>
+    /// <param name="value">The value</param>
+    public KeyValuePair(K key, V value) { Key = key; Value = value; }
+
+
+    /// <summary>
+    /// Create an entry with a specified key. The value will be the default value of type <code>V</code>.
+    /// </summary>
+    /// <param name="key">The key</param>
+    public KeyValuePair(K key) { Key = key; Value = default(V); }
+
+
+    /// <summary>
+    /// Pretty print an entry
+    /// </summary>
+    /// <returns>(key, value)</returns>
+    [Tested]
+    public override string ToString() { return "(" + Key + ", " + Value + ")"; }
+
+
+    /// <summary>
+    /// Check equality of entries. 
+    /// </summary>
+    /// <param name="obj">The other object</param>
+    /// <returns>True if obj is an entry of the same type and has the same key and value</returns>
+    [Tested]
+    public override bool Equals(object obj)
+    {
+      if (!(obj is KeyValuePair<K, V>))
+        return false;
+      KeyValuePair<K, V> other = (KeyValuePair<K, V>)obj;
+      return Equals(other);
+    }
+
+
+    /// <summary>
+    /// Get the hash code of the pair.
+    /// </summary>
+    /// <returns>The hash code</returns>
+    [Tested]
+    public override int GetHashCode() { return EqualityComparer<K>.Default.GetHashCode(Key) + 13984681 * EqualityComparer<V>.Default.GetHashCode(Value); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="other"></param>
+    /// <returns></returns>
+    public bool Equals(KeyValuePair<K, V> other)
+    {
+      return EqualityComparer<K>.Default.Equals(Key, other.Key) && EqualityComparer<V>.Default.Equals(Value, other.Value);
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="pair1"></param>
+    /// <param name="pair2"></param>
+    /// <returns></returns>
+    public static bool operator ==(KeyValuePair<K, V> pair1, KeyValuePair<K, V> pair2) { return pair1.Equals(pair2); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="pair1"></param>
+    /// <param name="pair2"></param>
+    /// <returns></returns>
+    public static bool operator !=(KeyValuePair<K, V> pair1, KeyValuePair<K, V> pair2) { return !pair1.Equals(pair2); }
+
+    #region IShowable Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="stringbuilder"></param>
+    /// <param name="formatProvider"></param>
+    /// <param name="rest"></param>
+    /// <returns></returns>
+    public bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
+    {
+      if (rest < 0)
+        return false;
+      if (!Showing.Show(Key, stringbuilder, ref rest, formatProvider))
+        return false;
+      stringbuilder.Append(" => ");
+      rest -= 4;
+      if (!Showing.Show(Value, stringbuilder, ref rest, formatProvider))
+        return false;
+      return rest >= 0;
+    }
+    #endregion
+
+    #region IFormattable Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="format"></param>
+    /// <param name="formatProvider"></param>
+    /// <returns></returns>
+    public string ToString(string format, IFormatProvider formatProvider)
+    {
+      return Showing.ShowString(this, format, formatProvider);
+    }
+
+    #endregion
+  }
+
+
+
+  /// <summary>
+  /// Default comparer for dictionary entries in a sorted dictionary.
+  /// Entry comparisons only look at keys and uses an externally defined comparer for that.
+  /// </summary>
+  [Serializable]
+  public class KeyValuePairComparer<K, V> : SCG.IComparer<KeyValuePair<K, V>>
+  {
+    SCG.IComparer<K> comparer;
+
+
+    /// <summary>
+    /// Create an entry comparer for a item comparer of the keys
+    /// </summary>
+    /// <param name="comparer">Comparer of keys</param>
+    public KeyValuePairComparer(SCG.IComparer<K> comparer)
+    {
+      if (comparer == null)
+        throw new NullReferenceException();
+      this.comparer = comparer;
+    }
+
+
+    /// <summary>
+    /// Compare two entries
+    /// </summary>
+    /// <param name="entry1">First entry</param>
+    /// <param name="entry2">Second entry</param>
+    /// <returns>The result of comparing the keys</returns>
+    [Tested]
+    public int Compare(KeyValuePair<K, V> entry1, KeyValuePair<K, V> entry2)
+    { return comparer.Compare(entry1.Key, entry2.Key); }
+  }
+
+
+
+  /// <summary>
+  /// Default equalityComparer for dictionary entries.
+  /// Operations only look at keys and uses an externaly defined equalityComparer for that.
+  /// </summary>
+  [Serializable]
+  public sealed class KeyValuePairEqualityComparer<K, V> : SCG.IEqualityComparer<KeyValuePair<K, V>>
+  {
+    SCG.IEqualityComparer<K> keyequalityComparer;
+
+
+    /// <summary>
+    /// Create an entry equalityComparer using the default equalityComparer for keys
+    /// </summary>
+    public KeyValuePairEqualityComparer() { keyequalityComparer = EqualityComparer<K>.Default; }
+
+
+    /// <summary>
+    /// Create an entry equalityComparer from a specified item equalityComparer for the keys
+    /// </summary>
+    /// <param name="keyequalityComparer">The key equalityComparer</param>
+    public KeyValuePairEqualityComparer(SCG.IEqualityComparer<K> keyequalityComparer)
+    {
+      if (keyequalityComparer == null)
+        throw new NullReferenceException("Key equality comparer cannot be null");
+      this.keyequalityComparer = keyequalityComparer;
+    }
+
+
+    /// <summary>
+    /// Get the hash code of the entry
+    /// </summary>
+    /// <param name="entry">The entry</param>
+    /// <returns>The hash code of the key</returns>
+    [Tested]
+    public int GetHashCode(KeyValuePair<K, V> entry) { return keyequalityComparer.GetHashCode(entry.Key); }
+
+
+    /// <summary>
+    /// Test two entries for equality
+    /// </summary>
+    /// <param name="entry1">First entry</param>
+    /// <param name="entry2">Second entry</param>
+    /// <returns>True if keys are equal</returns>
+    [Tested]
+    public bool Equals(KeyValuePair<K, V> entry1, KeyValuePair<K, V> entry2)
+    { return keyequalityComparer.Equals(entry1.Key, entry2.Key); }
+  }
+
+
+
+  /// <summary>
+  /// A base class for implementing a dictionary based on a set collection implementation.
+  /// <i>See the source code for <see cref="T:C5.HashDictionary`2"/> for an example</i>
+  /// 
+  /// </summary>
+  [Serializable]
+  public abstract class DictionaryBase<K, V> : CollectionValueBase<KeyValuePair<K, V>>, IDictionary<K, V>
+  {
+    /// <summary>
+    /// The set collection of entries underlying this dictionary implementation
+    /// </summary>
+    protected ICollection<KeyValuePair<K, V>> pairs;
+
+    SCG.IEqualityComparer<K> keyequalityComparer;
+
+    #region Events
+    ProxyEventBlock<KeyValuePair<K, V>> eventBlock;
+
+    /// <summary>
+    /// The change event. Will be raised for every change operation on the collection.
+    /// </summary>
+    public override event CollectionChangedHandler<KeyValuePair<K, V>> CollectionChanged
+    {
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<KeyValuePair<K, V>>(this, pairs))).CollectionChanged += value; }
+      remove { if (eventBlock != null) eventBlock.CollectionChanged -= value; }
+    }
+
+    /// <summary>
+    /// The change event. Will be raised for every change operation on the collection.
+    /// </summary>
+    public override event CollectionClearedHandler<KeyValuePair<K, V>> CollectionCleared
+    {
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<KeyValuePair<K, V>>(this, pairs))).CollectionCleared += value; }
+      remove { if (eventBlock != null) eventBlock.CollectionCleared -= value; }
+    }
+
+    /// <summary>
+    /// The item added  event. Will be raised for every individual addition to the collection.
+    /// </summary>
+    public override event ItemsAddedHandler<KeyValuePair<K, V>> ItemsAdded
+    {
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<KeyValuePair<K, V>>(this, pairs))).ItemsAdded += value; }
+      remove { if (eventBlock != null) eventBlock.ItemsAdded -= value; }
+    }
+
+    /// <summary>
+    /// The item added  event. Will be raised for every individual removal from the collection.
+    /// </summary>
+    public override event ItemsRemovedHandler<KeyValuePair<K, V>> ItemsRemoved
+    {
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<KeyValuePair<K, V>>(this, pairs))).ItemsRemoved += value; }
+      remove { if (eventBlock != null) eventBlock.ItemsRemoved -= value; }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public override EventTypeEnum ListenableEvents
+    {
+      get
+      {
+        return EventTypeEnum.Basic;
+      }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public override EventTypeEnum ActiveEvents
+    {
+      get
+      {
+        return pairs.ActiveEvents;
+      }
+    }
+
+    #endregion
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="keyequalityComparer"></param>
+    protected DictionaryBase(SCG.IEqualityComparer<K> keyequalityComparer)
+    {
+      if (keyequalityComparer == null)
+        throw new NullReferenceException("Key equality comparer cannot be null");
+      this.keyequalityComparer = keyequalityComparer;
+    }
+
+    #region IDictionary<K,V> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual SCG.IEqualityComparer<K> EqualityComparer { get { return keyequalityComparer; } }
+
+
+    /// <summary>
+    /// Add a new (key, value) pair (a mapping) to the dictionary.
+    /// </summary>
+    /// <exception cref="DuplicateNotAllowedException"> if there already is an entry with the same key. </exception>
+    /// <param name="key">Key to add</param>
+    /// <param name="value">Value to add</param>
+    [Tested]
+    public virtual void Add(K key, V value)
+    {
+      KeyValuePair<K, V> p = new KeyValuePair<K, V>(key, value);
+
+      if (!pairs.Add(p))
+        throw new DuplicateNotAllowedException("Key being added: '" + key + "'");
+    }
+
+    /// <summary>
+    /// Add the entries from a collection of <see cref="T:C5.KeyValuePair`2"/> pairs to this dictionary.
+    /// <para><b>TODO: add restrictions L:K and W:V when the .Net SDK allows it </b></para>
+    /// </summary>
+    /// <exception cref="DuplicateNotAllowedException"> 
+    /// If the input contains duplicate keys or a key already present in this dictionary.</exception>
+    /// <param name="entries"></param>
+    public virtual void AddAll<L, W>(SCG.IEnumerable<KeyValuePair<L, W>> entries)
+      where L : K
+      where W : V
+    {
+      foreach (KeyValuePair<L, W> pair in entries)
+      {
+        KeyValuePair<K, V> p = new KeyValuePair<K, V>(pair.Key, pair.Value);
+        if (!pairs.Add(p))
+          throw new DuplicateNotAllowedException("Key being added: '" + pair.Key + "'");
+      }
+    }
+
+    /// <summary>
+    /// Remove an entry with a given key from the dictionary
+    /// </summary>
+    /// <param name="key">The key of the entry to remove</param>
+    /// <returns>True if an entry was found (and removed)</returns>
+    [Tested]
+    public virtual bool Remove(K key)
+    {
+      KeyValuePair<K, V> p = new KeyValuePair<K, V>(key);
+
+      return pairs.Remove(p);
+    }
+
+
+    /// <summary>
+    /// Remove an entry with a given key from the dictionary and report its value.
+    /// </summary>
+    /// <param name="key">The key of the entry to remove</param>
+    /// <param name="value">On exit, the value of the removed entry</param>
+    /// <returns>True if an entry was found (and removed)</returns>
+    [Tested]
+    public virtual bool Remove(K key, out V value)
+    {
+      KeyValuePair<K, V> p = new KeyValuePair<K, V>(key);
+
+      if (pairs.Remove(p, out p))
+      {
+        value = p.Value;
+        return true;
+      }
+      else
+      {
+        value = default(V);
+        return false;
+      }
+    }
+
+
+    /// <summary>
+    /// Remove all entries from the dictionary
+    /// </summary>
+    [Tested]
+    public virtual void Clear() { pairs.Clear(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual Speed ContainsSpeed { get { return pairs.ContainsSpeed; } }
+
+    /// <summary>
+    /// Check if there is an entry with a specified key
+    /// </summary>
+    /// <param name="key">The key to look for</param>
+    /// <returns>True if key was found</returns>
+    [Tested]
+    public virtual bool Contains(K key)
+    {
+      KeyValuePair<K, V> p = new KeyValuePair<K, V>(key);
+
+      return pairs.Contains(p);
+    }
+
+    [Serializable]
+    class LiftedEnumerable<H> : SCG.IEnumerable<KeyValuePair<K, V>> where H : K
+    {
+      SCG.IEnumerable<H> keys;
+      public LiftedEnumerable(SCG.IEnumerable<H> keys) { this.keys = keys; }
+      public SCG.IEnumerator<KeyValuePair<K, V>> GetEnumerator() { foreach (H key in keys) yield return new KeyValuePair<K, V>(key); }
+
+      #region IEnumerable Members
+
+      System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+      {
+        throw new Exception("The method or operation is not implemented.");
+      }
+
+      #endregion
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="keys"></param>
+    /// <returns></returns>
+    public virtual bool ContainsAll<H>(SCG.IEnumerable<H> keys) where H : K
+    {
+      return pairs.ContainsAll(new LiftedEnumerable<H>(keys));
+    }
+
+    /// <summary>
+    /// Check if there is an entry with a specified key and report the corresponding
+    /// value if found. This can be seen as a safe form of "val = this[key]".
+    /// </summary>
+    /// <param name="key">The key to look for</param>
+    /// <param name="value">On exit, the value of the entry</param>
+    /// <returns>True if key was found</returns>
+    [Tested]
+    public virtual bool Find(K key, out V value)
+    {
+      return Find(ref key, out value);
+    }
+    /// <summary>
+    /// Check if there is an entry with a specified key and report the corresponding
+    /// value if found. This can be seen as a safe form of "val = this[key]".
+    /// </summary>
+    /// <param name="key">The key to look for</param>
+    /// <param name="value">On exit, the value of the entry</param>
+    /// <returns>True if key was found</returns>
+    public virtual bool Find(ref K key, out V value)
+    {
+      KeyValuePair<K, V> p = new KeyValuePair<K, V>(key);
+
+      if (pairs.Find(ref p))
+      {
+        key = p.Key;
+        value = p.Value;
+        return true;
+      }
+      else
+      {
+        value = default(V);
+        return false;
+      }
+    }
+
+
+    /// <summary>
+    /// Look for a specific key in the dictionary and if found replace the value with a new one.
+    /// This can be seen as a non-adding version of "this[key] = val".
+    /// </summary>
+    /// <param name="key">The key to look for</param>
+    /// <param name="value">The new value</param>
+    /// <returns>True if key was found</returns>
+    [Tested]
+    public virtual bool Update(K key, V value)
+    {
+      KeyValuePair<K, V> p = new KeyValuePair<K, V>(key, value);
+
+      return pairs.Update(p);
+    }
+
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="key"></param>
+    /// <param name="value"></param>
+    /// <param name="oldvalue"></param>
+    /// <returns></returns>
+    public virtual bool Update(K key, V value, out V oldvalue)
+    {
+      KeyValuePair<K, V> p = new KeyValuePair<K, V>(key, value);
+
+      bool retval = pairs.Update(p, out p);
+      oldvalue = p.Value;
+      return retval;
+    }
+
+
+    /// <summary>
+    /// Look for a specific key in the dictionary. If found, report the corresponding value,
+    /// else add an entry with the key and the supplied value.
+    /// </summary>
+    /// <param name="key">On entry the key to look for</param>
+    /// <param name="value">On entry the value to add if the key is not found.
+    /// On exit the value found if any.</param>
+    /// <returns>True if key was found</returns>
+    [Tested]
+    public virtual bool FindOrAdd(K key, ref V value)
+    {
+      KeyValuePair<K, V> p = new KeyValuePair<K, V>(key, value);
+
+      if (!pairs.FindOrAdd(ref p))
+        return false;
+      else
+      {
+        value = p.Value;
+        //key = p.key;
+        return true;
+      }
+    }
+
+
+    /// <summary>
+    /// Update value in dictionary corresponding to key if found, else add new entry.
+    /// More general than "this[key] = val;" by reporting if key was found.
+    /// </summary>
+    /// <param name="key">The key to look for</param>
+    /// <param name="value">The value to add or replace with.</param>
+    /// <returns>True if entry was updated.</returns>
+    [Tested]
+    public virtual bool UpdateOrAdd(K key, V value)
+    {
+      return pairs.UpdateOrAdd(new KeyValuePair<K, V>(key, value));
+    }
+
+
+    /// <summary>
+    /// Update value in dictionary corresponding to key if found, else add new entry.
+    /// More general than "this[key] = val;" by reporting if key was found and the old value if any.
+    /// </summary>
+    /// <param name="key"></param>
+    /// <param name="value"></param>
+    /// <param name="oldvalue"></param>
+    /// <returns></returns>
+    public virtual bool UpdateOrAdd(K key, V value, out V oldvalue)
+    {
+      KeyValuePair<K, V> p = new KeyValuePair<K, V>(key, value);
+      bool retval = pairs.UpdateOrAdd(p, out p);
+      oldvalue = p.Value;
+      return retval;
+    }
+
+
+
+    #region Keys,Values support classes
+    [Serializable]
+    internal class ValuesCollection : CollectionValueBase<V>, ICollectionValue<V>
+    {
+      ICollection<KeyValuePair<K, V>> pairs;
+
+
+      internal ValuesCollection(ICollection<KeyValuePair<K, V>> pairs)
+      { this.pairs = pairs; }
+
+
+      public override V Choose() { return pairs.Choose().Value; }
+
+      [Tested]
+      public override SCG.IEnumerator<V> GetEnumerator()
+      {
+        //Updatecheck is performed by the pairs enumerator
+        foreach (KeyValuePair<K, V> p in pairs)
+          yield return p.Value;
+      }
+
+      public override bool IsEmpty { get { return pairs.IsEmpty; } }
+
+      [Tested]
+      public override int Count { [Tested]get { return pairs.Count; } }
+
+      public override Speed CountSpeed { get { return Speed.Constant; } }
+    }
+
+
+
+    [Serializable]
+    internal class KeysCollection : CollectionValueBase<K>, ICollectionValue<K>
+    {
+      ICollection<KeyValuePair<K, V>> pairs;
+
+
+      internal KeysCollection(ICollection<KeyValuePair<K, V>> pairs)
+      { this.pairs = pairs; }
+
+      public override K Choose() { return pairs.Choose().Key; }
+
+      [Tested]
+      public override SCG.IEnumerator<K> GetEnumerator()
+      {
+        foreach (KeyValuePair<K, V> p in pairs)
+          yield return p.Key;
+      }
+
+      public override bool IsEmpty { get { return pairs.IsEmpty; } }
+
+      [Tested]
+      public override int Count { [Tested]get { return pairs.Count; } }
+
+      public override Speed CountSpeed { get { return pairs.CountSpeed; } }
+    }
+    #endregion
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>A collection containg the all the keys of the dictionary</value>
+    [Tested]
+    public virtual ICollectionValue<K> Keys { [Tested]get { return new KeysCollection(pairs); } }
+
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>A collection containing all the values of the dictionary</value>
+    [Tested]
+    public virtual ICollectionValue<V> Values { [Tested]get { return new ValuesCollection(pairs); } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public virtual Fun<K, V> Fun { get { return delegate(K k) { return this[k]; }; } }
+
+    /// <summary>
+    /// Indexer by key for dictionary. 
+    /// <para>The get method will throw an exception if no entry is found. </para>
+    /// <para>The set method behaves like <see cref="M:C5.DictionaryBase`2.UpdateOrAdd(`0,`1)"/>.</para>
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> On get if no entry is found. </exception>
+    /// <value>The value corresponding to the key</value>
+    [Tested]
+    public virtual V this[K key]
+    {
+      [Tested]
+      get
+      {
+        KeyValuePair<K, V> p = new KeyValuePair<K, V>(key);
+
+        if (pairs.Find(ref p))
+          return p.Value;
+        else
+          throw new NoSuchItemException("Key '" + key.ToString() + "' not present in Dictionary");
+      }
+      [Tested]
+      set
+      { pairs.UpdateOrAdd(new KeyValuePair<K, V>(key, value)); }
+    }
+
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>True if dictionary is read  only</value>
+    [Tested]
+    public virtual bool IsReadOnly { [Tested]get { return pairs.IsReadOnly; } }
+
+
+    /// <summary>
+    /// Check the integrity of the internal data structures of this dictionary.
+    /// </summary>
+    /// <returns>True if check does not fail.</returns>
+    [Tested]
+    public virtual bool Check() { return pairs.Check(); }
+
+    #endregion
+
+    #region ICollectionValue<KeyValuePair<K,V>> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>True if this collection is empty.</value>
+    public override bool IsEmpty { get { return pairs.IsEmpty; } }
+
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>The number of entrues in the dictionary</value>
+    [Tested]
+    public override int Count { [Tested]get { return pairs.Count; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>The number of entrues in the dictionary</value>
+    [Tested]
+    public override Speed CountSpeed { [Tested]get { return pairs.CountSpeed; } }
+
+    /// <summary>
+    /// Choose some entry in this Dictionary. 
+    /// </summary>
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>
+    /// <returns></returns>
+    public override KeyValuePair<K, V> Choose() { return pairs.Choose(); }
+
+    /// <summary>
+    /// Create an enumerator for the collection of entries of the dictionary
+    /// </summary>
+    /// <returns>The enumerator</returns>
+    [Tested]
+    public override SCG.IEnumerator<KeyValuePair<K, V>> GetEnumerator()
+    {
+      return pairs.GetEnumerator(); ;
+    }
+
+    #endregion
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="stringbuilder"></param>
+    /// <param name="rest"></param>
+    /// <param name="formatProvider"></param>
+    /// <returns></returns>
+    public override bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
+    {
+      return Showing.ShowDictionary<K, V>(this, stringbuilder, ref rest, formatProvider);
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public abstract object Clone();
+
+  }
+
+  /// <summary>
+  /// A base class for implementing a sorted dictionary based on a sorted set collection implementation.
+  /// <i>See the source code for <see cref="T:C5.TreeDictionary`2"/> for an example</i>
+  /// 
+  /// </summary>
+  [Serializable]
+  public abstract class SortedDictionaryBase<K, V> : DictionaryBase<K, V>, ISortedDictionary<K, V>
+  {
+    #region Fields
+
+    /// <summary>
+    /// 
+    /// </summary>
+    protected ISorted<KeyValuePair<K, V>> sortedpairs;
+    SCG.IComparer<K> keycomparer;
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="keycomparer"></param>
+    /// <param name="keyequalityComparer"></param>
+    protected SortedDictionaryBase(SCG.IComparer<K> keycomparer, SCG.IEqualityComparer<K> keyequalityComparer) : base(keyequalityComparer) { this.keycomparer = keycomparer; }
+
+    #endregion
+
+    #region ISortedDictionary<K,V> Members
+
+    /// <summary>
+    /// The key comparer used by this dictionary.
+    /// </summary>
+    /// <value></value>
+    public SCG.IComparer<K> Comparer { get { return keycomparer; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public new ISorted<K> Keys { get { return new SortedKeysCollection(this, sortedpairs, keycomparer, EqualityComparer); } }
+
+    /// <summary>
+    /// Find the entry in the dictionary whose key is the
+    /// predecessor of the specified key.
+    /// </summary>
+    /// <param name="key">The key</param>
+    /// <param name="res">The predecessor, if any</param>
+    /// <returns>True if key has a predecessor</returns>
+    [Tested]
+    public bool TryPredecessor(K key, out KeyValuePair<K, V> res)
+    {
+      return sortedpairs.TryPredecessor(new KeyValuePair<K, V>(key), out res);
+    }
+
+    /// <summary>
+    /// Find the entry in the dictionary whose key is the
+    /// successor of the specified key.
+    /// </summary>
+    /// <param name="key">The key</param>
+    /// <param name="res">The successor, if any</param>
+    /// <returns>True if the key has a successor</returns>
+    [Tested]
+    public bool TrySuccessor(K key, out KeyValuePair<K, V> res)
+    {
+      return sortedpairs.TrySuccessor(new KeyValuePair<K, V>(key), out res);
+    }
+
+    /// <summary>
+    /// Find the entry in the dictionary whose key is the
+    /// weak predecessor of the specified key.
+    /// </summary>
+    /// <param name="key">The key</param>
+    /// <param name="res">The predecessor, if any</param>
+    /// <returns>True if key has a weak predecessor</returns>
+    [Tested]
+    public bool TryWeakPredecessor(K key, out KeyValuePair<K, V> res)
+    {
+      return sortedpairs.TryWeakPredecessor(new KeyValuePair<K, V>(key), out res);
+    }
+
+    /// <summary>
+    /// Find the entry in the dictionary whose key is the
+    /// weak successor of the specified key.
+    /// </summary>
+    /// <param name="key">The key</param>
+    /// <param name="res">The weak successor, if any</param>
+    /// <returns>True if the key has a weak successor</returns>
+    [Tested]
+    public bool TryWeakSuccessor(K key, out KeyValuePair<K, V> res)
+    {
+      return sortedpairs.TryWeakSuccessor(new KeyValuePair<K, V>(key), out res);
+    }
+
+    /// <summary>
+    /// Get the entry in the dictionary whose key is the
+    /// predecessor of the specified key.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"></exception>
+    /// <param name="key">The key</param>
+    /// <returns>The entry</returns>
+    [Tested]
+    public KeyValuePair<K, V> Predecessor(K key)
+    {
+      return sortedpairs.Predecessor(new KeyValuePair<K, V>(key));
+    }
+
+    /// <summary>
+    /// Get the entry in the dictionary whose key is the
+    /// successor of the specified key.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"></exception>
+    /// <param name="key">The key</param>
+    /// <returns>The entry</returns>
+    [Tested]
+    public KeyValuePair<K, V> Successor(K key)
+    {
+      return sortedpairs.Successor(new KeyValuePair<K, V>(key));
+    }
+
+    /// <summary>
+    /// Get the entry in the dictionary whose key is the
+    /// weak predecessor of the specified key.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"></exception>
+    /// <param name="key">The key</param>
+    /// <returns>The entry</returns>
+    [Tested]
+    public KeyValuePair<K, V> WeakPredecessor(K key)
+    {
+      return sortedpairs.WeakPredecessor(new KeyValuePair<K, V>(key));
+    }
+
+    /// <summary>
+    /// Get the entry in the dictionary whose key is the
+    /// weak successor of the specified key.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"></exception>
+    /// <param name="key">The key</param>
+    /// <returns>The entry</returns>
+    [Tested]
+    public KeyValuePair<K, V> WeakSuccessor(K key)
+    {
+      return sortedpairs.WeakSuccessor(new KeyValuePair<K, V>(key));
+    }
+
+    #endregion
+
+    #region ISortedDictionary<K,V> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public KeyValuePair<K, V> FindMin()
+    {
+      return sortedpairs.FindMin();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public KeyValuePair<K, V> DeleteMin()
+    {
+      return sortedpairs.DeleteMin();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public KeyValuePair<K, V> FindMax()
+    {
+      return sortedpairs.FindMax();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public KeyValuePair<K, V> DeleteMax()
+    {
+      return sortedpairs.DeleteMax();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="cutter"></param>
+    /// <param name="lowEntry"></param>
+    /// <param name="lowIsValid"></param>
+    /// <param name="highEntry"></param>
+    /// <param name="highIsValid"></param>
+    /// <returns></returns>
+    public bool Cut(IComparable<K> cutter, out KeyValuePair<K, V> lowEntry, out bool lowIsValid, out KeyValuePair<K, V> highEntry, out bool highIsValid)
+    {
+      return sortedpairs.Cut(new KeyValuePairComparable(cutter), out lowEntry, out lowIsValid, out highEntry, out highIsValid);
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="bot"></param>
+    /// <returns></returns>
+    public IDirectedEnumerable<KeyValuePair<K, V>> RangeFrom(K bot)
+    {
+      return sortedpairs.RangeFrom(new KeyValuePair<K, V>(bot));
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="bot"></param>
+    /// <param name="top"></param>
+    /// <returns></returns>
+    public IDirectedEnumerable<KeyValuePair<K, V>> RangeFromTo(K bot, K top)
+    {
+      return sortedpairs.RangeFromTo(new KeyValuePair<K, V>(bot), new KeyValuePair<K, V>(top));
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="top"></param>
+    /// <returns></returns>
+    public IDirectedEnumerable<KeyValuePair<K, V>> RangeTo(K top)
+    {
+      return sortedpairs.RangeTo(new KeyValuePair<K, V>(top));
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public IDirectedCollectionValue<KeyValuePair<K, V>> RangeAll()
+    {
+      return sortedpairs.RangeAll();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="items"></param>
+    public void AddSorted(SCG.IEnumerable<KeyValuePair<K, V>> items)
+    {
+      sortedpairs.AddSorted(items);
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="lowKey"></param>
+    public void RemoveRangeFrom(K lowKey)
+    {
+      sortedpairs.RemoveRangeFrom(new KeyValuePair<K, V>(lowKey));
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="lowKey"></param>
+    /// <param name="highKey"></param>
+    public void RemoveRangeFromTo(K lowKey, K highKey)
+    {
+      sortedpairs.RemoveRangeFromTo(new KeyValuePair<K, V>(lowKey), new KeyValuePair<K, V>(highKey));
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="highKey"></param>
+    public void RemoveRangeTo(K highKey)
+    {
+      sortedpairs.RemoveRangeTo(new KeyValuePair<K, V>(highKey));
+    }
+
+    #endregion
+    [Serializable]
+    class KeyValuePairComparable : IComparable<KeyValuePair<K, V>>
+    {
+      IComparable<K> cutter;
+
+      internal KeyValuePairComparable(IComparable<K> cutter) { this.cutter = cutter; }
+
+      public int CompareTo(KeyValuePair<K, V> other) { return cutter.CompareTo(other.Key); }
+
+      public bool Equals(KeyValuePair<K, V> other) { return cutter.Equals(other.Key); }
+    }
+
+    [Serializable]
+    class ProjectedDirectedEnumerable : MappedDirectedEnumerable<KeyValuePair<K, V>, K>
+    {
+      public ProjectedDirectedEnumerable(IDirectedEnumerable<KeyValuePair<K, V>> directedpairs) : base(directedpairs) { }
+
+      public override K Map(KeyValuePair<K, V> pair) { return pair.Key; }
+
+    }
+
+    [Serializable]
+    class ProjectedDirectedCollectionValue : MappedDirectedCollectionValue<KeyValuePair<K, V>, K>
+    {
+      public ProjectedDirectedCollectionValue(IDirectedCollectionValue<KeyValuePair<K, V>> directedpairs) : base(directedpairs) { }
+
+      public override K Map(KeyValuePair<K, V> pair) { return pair.Key; }
+
+    }
+
+    [Serializable]
+    class SortedKeysCollection : SequencedBase<K>, ISorted<K>
+    {
+      ISortedDictionary<K, V> sorteddict;
+      //TODO: eliminate this. Only problem is the Find method because we lack method on dictionary that also 
+      //      returns the actual key.
+      ISorted<KeyValuePair<K, V>> sortedpairs;
+      SCG.IComparer<K> comparer;
+
+      internal SortedKeysCollection(ISortedDictionary<K, V> sorteddict, ISorted<KeyValuePair<K, V>> sortedpairs, SCG.IComparer<K> comparer, SCG.IEqualityComparer<K> itemequalityComparer)
+        : base(itemequalityComparer)
+      {
+        this.sorteddict = sorteddict;
+        this.sortedpairs = sortedpairs;
+        this.comparer = comparer;
+      }
+
+      public override K Choose() { return sorteddict.Choose().Key; }
+
+      public override SCG.IEnumerator<K> GetEnumerator()
+      {
+        foreach (KeyValuePair<K, V> p in sorteddict)
+          yield return p.Key;
+      }
+
+      public override bool IsEmpty { get { return sorteddict.IsEmpty; } }
+
+      public override int Count { [Tested]get { return sorteddict.Count; } }
+
+      public override Speed CountSpeed { get { return sorteddict.CountSpeed; } }
+
+      #region ISorted<K> Members
+
+      public K FindMin() { return sorteddict.FindMin().Key; }
+
+      public K DeleteMin() { throw new ReadOnlyCollectionException(); }
+
+      public K FindMax() { return sorteddict.FindMax().Key; }
+
+      public K DeleteMax() { throw new ReadOnlyCollectionException(); }
+
+      public SCG.IComparer<K> Comparer { get { return comparer; } }
+
+      public bool TryPredecessor(K item, out K res)
+      {
+          KeyValuePair<K, V> pRes;
+          bool success = sorteddict.TryPredecessor(item, out pRes);
+          res = pRes.Key;
+          return success;
+      }
+
+      public bool TrySuccessor(K item, out K res)
+      {
+          KeyValuePair<K, V> pRes;
+          bool success = sorteddict.TrySuccessor(item, out pRes);
+          res = pRes.Key;
+          return success;
+      }
+
+      public bool TryWeakPredecessor(K item, out K res)
+      {
+          KeyValuePair<K, V> pRes;
+          bool success = sorteddict.TryWeakPredecessor(item, out pRes);
+          res = pRes.Key;
+          return success;
+      }
+
+      public bool TryWeakSuccessor(K item, out K res)
+      {
+          KeyValuePair<K, V> pRes;
+          bool success = sorteddict.TryWeakSuccessor(item, out pRes);
+          res = pRes.Key;
+          return success;
+      }
+
+      public K Predecessor(K item) { return sorteddict.Predecessor(item).Key; }
+
+      public K Successor(K item) { return sorteddict.Successor(item).Key; }
+
+      public K WeakPredecessor(K item) { return sorteddict.WeakPredecessor(item).Key; }
+
+      public K WeakSuccessor(K item) { return sorteddict.WeakSuccessor(item).Key; }
+
+      public bool Cut(IComparable<K> c, out K low, out bool lowIsValid, out K high, out bool highIsValid)
+      {
+        KeyValuePair<K, V> lowpair, highpair;
+        bool retval = sorteddict.Cut(c, out lowpair, out lowIsValid, out highpair, out highIsValid);
+        low = lowpair.Key;
+        high = highpair.Key;
+        return retval;
+      }
+
+      public IDirectedEnumerable<K> RangeFrom(K bot)
+      {
+        return new ProjectedDirectedEnumerable(sorteddict.RangeFrom(bot));
+      }
+
+      public IDirectedEnumerable<K> RangeFromTo(K bot, K top)
+      {
+        return new ProjectedDirectedEnumerable(sorteddict.RangeFromTo(bot, top));
+      }
+
+      public IDirectedEnumerable<K> RangeTo(K top)
+      {
+        return new ProjectedDirectedEnumerable(sorteddict.RangeTo(top));
+      }
+
+      public IDirectedCollectionValue<K> RangeAll()
+      {
+        return new ProjectedDirectedCollectionValue(sorteddict.RangeAll());
+      }
+
+      public void AddSorted<U>(SCG.IEnumerable<U> items) where U : K { throw new ReadOnlyCollectionException(); }
+
+      public void RemoveRangeFrom(K low) { throw new ReadOnlyCollectionException(); }
+
+      public void RemoveRangeFromTo(K low, K hi) { throw new ReadOnlyCollectionException(); }
+
+      public void RemoveRangeTo(K hi) { throw new ReadOnlyCollectionException(); }
+      #endregion
+
+      #region ICollection<K> Members
+      public Speed ContainsSpeed { get { return sorteddict.ContainsSpeed; } }
+
+      public bool Contains(K key) { return sorteddict.Contains(key); ;      }
+
+      public int ContainsCount(K item) { return sorteddict.Contains(item) ? 1 : 0; }
+
+      /// <summary>
+      /// 
+      /// </summary>
+      /// <returns></returns>
+      public virtual ICollectionValue<K> UniqueItems()
+      {
+        return this;
+      }
+
+      /// <summary>
+      /// 
+      /// </summary>
+      /// <returns></returns>
+      public virtual ICollectionValue<KeyValuePair<K, int>> ItemMultiplicities()
+      {
+        return new MultiplicityOne<K>(this);
+      }
+
+
+      public bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : K
+      {
+        //TODO: optimize?
+        foreach (K item in items)
+          if (!sorteddict.Contains(item))
+            return false;
+        return true;
+      }
+
+      public bool Find(ref K item)
+      {
+        KeyValuePair<K, V> p = new KeyValuePair<K, V>(item);
+        bool retval = sortedpairs.Find(ref p);
+        item = p.Key;
+        return retval;
+      }
+
+      public bool FindOrAdd(ref K item) { throw new ReadOnlyCollectionException(); }
+
+      public bool Update(K item) { throw new ReadOnlyCollectionException(); }
+
+      public bool Update(K item, out K olditem) { throw new ReadOnlyCollectionException(); }
+
+      public bool UpdateOrAdd(K item) { throw new ReadOnlyCollectionException(); }
+
+      public bool UpdateOrAdd(K item, out K olditem) { throw new ReadOnlyCollectionException(); }
+
+      public bool Remove(K item) { throw new ReadOnlyCollectionException(); }
+
+      public bool Remove(K item, out K removeditem) { throw new ReadOnlyCollectionException(); }
+
+      public void RemoveAllCopies(K item) { throw new ReadOnlyCollectionException(); }
+
+      public void RemoveAll<U>(SCG.IEnumerable<U> items) where U : K { throw new ReadOnlyCollectionException(); }
+
+      public void Clear() { throw new ReadOnlyCollectionException(); }
+
+      public void RetainAll<U>(SCG.IEnumerable<U> items) where U : K { throw new ReadOnlyCollectionException(); }
+
+      #endregion
+
+      #region IExtensible<K> Members
+      public override bool IsReadOnly { get { return true; } }
+
+      public bool AllowsDuplicates { get { return false; } }
+
+      public bool DuplicatesByCounting { get { return true; } }
+
+      public bool Add(K item) { throw new ReadOnlyCollectionException(); }
+
+      void SCG.ICollection<K>.Add(K item) { throw new ReadOnlyCollectionException(); }
+
+      public void AddAll(System.Collections.Generic.IEnumerable<K> items) { throw new ReadOnlyCollectionException(); }
+
+      public void AddAll<U>(System.Collections.Generic.IEnumerable<U> items) where U : K { throw new ReadOnlyCollectionException(); }
+
+      public bool Check() { return sorteddict.Check(); }
+
+      #endregion
+
+      #region IDirectedCollectionValue<K> Members
+
+      public override IDirectedCollectionValue<K> Backwards()
+      {
+        return RangeAll().Backwards();
+      }
+
+      #endregion
+
+      #region IDirectedEnumerable<K> Members
+
+      IDirectedEnumerable<K> IDirectedEnumerable<K>.Backwards() { return Backwards(); }
+      #endregion
+
+      #region ICloneable Members
+
+      //TODO: test
+      /// <summary>
+      /// Make a shallow copy of this SortedKeysCollection.
+      /// </summary>
+      /// <returns></returns>
+      public virtual object Clone()
+      {
+        //
+        SortedArrayDictionary<K, V> dictclone = new SortedArrayDictionary<K, V>(sortedpairs.Count, comparer, EqualityComparer);
+        SortedArray<KeyValuePair<K, V>> sortedpairsclone = (SortedArray<KeyValuePair<K, V>>)(dictclone.sortedpairs);
+        foreach (K key in sorteddict.Keys)
+        {
+          sortedpairsclone.Add(new KeyValuePair<K, V>(key, default(V)));
+        }
+        return new SortedKeysCollection(dictclone, sortedpairsclone, comparer, EqualityComparer);
+      }
+
+      #endregion
+
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="stringbuilder"></param>
+    /// <param name="rest"></param>
+    /// <param name="formatProvider"></param>
+    /// <returns></returns>
+    public override bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
+    {
+      return Showing.ShowDictionary<K, V>(this, stringbuilder, ref rest, formatProvider);
+    }
+
+  }
+
+  [Serializable]
+  class SortedArrayDictionary<K, V> : SortedDictionaryBase<K, V>, IDictionary<K, V>, ISortedDictionary<K, V>
+  {
+    #region Constructors
+
+    public SortedArrayDictionary() : this(Comparer<K>.Default, EqualityComparer<K>.Default) { }
+
+    /// <summary>
+    /// Create a red-black tree dictionary using an external comparer for keys.
+    /// </summary>
+    /// <param name="comparer">The external comparer</param>
+    public SortedArrayDictionary(SCG.IComparer<K> comparer) : this(comparer, new ComparerZeroHashCodeEqualityComparer<K>(comparer)) { }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="comparer"></param>
+    /// <param name="equalityComparer"></param>
+    public SortedArrayDictionary(SCG.IComparer<K> comparer, SCG.IEqualityComparer<K> equalityComparer)
+      : base(comparer, equalityComparer)
+    {
+      pairs = sortedpairs = new SortedArray<KeyValuePair<K, V>>(new KeyValuePairComparer<K, V>(comparer));
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="comparer"></param>
+    /// <param name="equalityComparer"></param>
+    /// <param name="capacity"></param>
+    public SortedArrayDictionary(int capacity, SCG.IComparer<K> comparer, SCG.IEqualityComparer<K> equalityComparer)
+      : base(comparer, equalityComparer)
+    {
+      pairs = sortedpairs = new SortedArray<KeyValuePair<K, V>>(capacity, new KeyValuePairComparer<K, V>(comparer));
+    }
+    #endregion
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override object Clone()
+    {
+      SortedArrayDictionary<K, V> clone = new SortedArrayDictionary<K, V>(Comparer, EqualityComparer);
+      clone.sortedpairs.AddSorted(sortedpairs);
+      return clone;
+    }
+
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Enums.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Enums.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Enums.cs	(revision 3)
@@ -0,0 +1,98 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+namespace C5
+{
+
+  /// <summary>
+  /// The symbolic characterization of the speed of lookups for a collection.
+  /// The values may refer to worst-case, amortized and/or expected asymtotic 
+  /// complexity wrt. the collection size.
+  /// </summary>
+  public enum Speed : short
+  {
+    /// <summary>
+    /// Counting the collection with the <code>Count property</code> may not return
+    /// (for a synthetic and potentially infinite collection).
+    /// </summary>
+    PotentiallyInfinite = 1,
+    /// <summary>
+    /// Lookup operations like <code>Contains(T item)</code> or the <code>Count</code>
+    /// property may take time O(n),
+    /// where n is the size of the collection.
+    /// </summary>
+    Linear = 2,
+    /// <summary>
+    /// Lookup operations like <code>Contains(T item)</code> or the <code>Count</code>
+    /// property  takes time O(log n),
+    /// where n is the size of the collection.
+    /// </summary>
+    Log = 3,
+    /// <summary>
+    /// Lookup operations like <code>Contains(T item)</code> or the <code>Count</code>
+    /// property  takes time O(1),
+    /// where n is the size of the collection.
+    /// </summary>
+    Constant = 4
+  }
+  /*
+  /// <summary>
+  /// 
+  /// </summary>
+  public enum ItemEqualityTypeEnum
+  {
+    /// <summary>
+    /// Only an Equals(T,T)
+    /// </summary>
+    Equator, 
+    /// <summary>
+    /// Equals(T,T) and GetHashCode(T)
+    /// </summary>
+    HashingEqualityComparer, 
+    /// <summary>
+    /// Compare(T,T)
+    /// </summary>
+    Comparer, 
+    /// <summary>
+    /// Compatible Compare(T,T) and GetHashCode(T)
+    /// </summary>
+    Both
+  }
+*/
+
+  /// <summary>
+  /// Direction of enumeration order relative to original collection.
+  /// </summary>
+  public enum EnumerationDirection
+  {
+    /// <summary>
+    /// Same direction
+    /// </summary>
+    Forwards,
+    /// <summary>
+    /// Opposite direction
+    /// </summary>
+    Backwards
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Events.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Events.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Events.cs	(revision 3)
@@ -0,0 +1,532 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+
+namespace C5
+{
+  /// <summary>
+  /// 
+  /// </summary>
+  [Flags]
+  public enum EventTypeEnum
+  {
+    /// <summary>
+    /// 
+    /// </summary>
+    None = 0x00000000,
+    /// <summary>
+    /// 
+    /// </summary>
+    Changed = 0x00000001,
+    /// <summary>
+    /// 
+    /// </summary>
+    Cleared = 0x00000002,
+    /// <summary>
+    /// 
+    /// </summary>
+    Added = 0x00000004,
+    /// <summary>
+    /// 
+    /// </summary>
+    Removed = 0x00000008,
+    /// <summary>
+    /// 
+    /// </summary>
+    Basic = 0x0000000f,
+    /// <summary>
+    /// 
+    /// </summary>
+    Inserted = 0x00000010,
+    /// <summary>
+    /// 
+    /// </summary>
+    RemovedAt = 0x00000020,
+    /// <summary>
+    /// 
+    /// </summary>
+    All = 0x0000003f
+  }
+
+  /// <summary>
+  /// Holds the real events for a collection
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  [Serializable]
+  internal sealed class EventBlock<T>
+  {
+    internal EventTypeEnum events;
+
+    event CollectionChangedHandler<T> collectionChanged;
+    internal event CollectionChangedHandler<T> CollectionChanged
+    {
+      add
+      {
+        collectionChanged += value;
+        events |= EventTypeEnum.Changed;
+      }
+      remove
+      {
+        collectionChanged -= value;
+        if (collectionChanged == null)
+          events &= ~EventTypeEnum.Changed;
+      }
+    }
+    internal void raiseCollectionChanged(object sender)
+    { if (collectionChanged != null) collectionChanged(sender); }
+
+    event CollectionClearedHandler<T> collectionCleared;
+    internal event CollectionClearedHandler<T> CollectionCleared
+    {
+      add
+      {
+        collectionCleared += value;
+        events |= EventTypeEnum.Cleared;
+      }
+      remove
+      {
+        collectionCleared -= value;
+        if (collectionCleared == null)
+          events &= ~EventTypeEnum.Cleared;
+      }
+    }
+    internal void raiseCollectionCleared(object sender, bool full, int count)
+    { if (collectionCleared != null) collectionCleared(sender, new ClearedEventArgs(full, count)); }
+    internal void raiseCollectionCleared(object sender, bool full, int count, int? start)
+    { if (collectionCleared != null) collectionCleared(sender, new ClearedRangeEventArgs(full, count, start)); }
+
+    event ItemsAddedHandler<T> itemsAdded;
+    internal event ItemsAddedHandler<T> ItemsAdded
+    {
+      add
+      {
+        itemsAdded += value;
+        events |= EventTypeEnum.Added;
+      }
+      remove
+      {
+        itemsAdded -= value;
+        if (itemsAdded == null)
+          events &= ~EventTypeEnum.Added;
+      }
+    }
+    internal void raiseItemsAdded(object sender, T item, int count)
+    { if (itemsAdded != null) itemsAdded(sender, new ItemCountEventArgs<T>(item, count)); }
+
+    event ItemsRemovedHandler<T> itemsRemoved;
+    internal event ItemsRemovedHandler<T> ItemsRemoved
+    {
+      add
+      {
+        itemsRemoved += value;
+        events |= EventTypeEnum.Removed;
+      }
+      remove
+      {
+        itemsRemoved -= value;
+        if (itemsRemoved == null)
+          events &= ~EventTypeEnum.Removed;
+      }
+    }
+    internal void raiseItemsRemoved(object sender, T item, int count)
+    { if (itemsRemoved != null) itemsRemoved(sender, new ItemCountEventArgs<T>(item, count)); }
+
+    event ItemInsertedHandler<T> itemInserted;
+    internal event ItemInsertedHandler<T> ItemInserted
+    {
+      add
+      {
+        itemInserted += value;
+        events |= EventTypeEnum.Inserted;
+      }
+      remove
+      {
+        itemInserted -= value;
+        if (itemInserted == null)
+          events &= ~EventTypeEnum.Inserted;
+      }
+    }
+    internal void raiseItemInserted(object sender, T item, int index)
+    { if (itemInserted != null) itemInserted(sender, new ItemAtEventArgs<T>(item, index)); }
+
+    event ItemRemovedAtHandler<T> itemRemovedAt;
+    internal event ItemRemovedAtHandler<T> ItemRemovedAt
+    {
+      add
+      {
+        itemRemovedAt += value;
+        events |= EventTypeEnum.RemovedAt;
+      }
+      remove
+      {
+        itemRemovedAt -= value;
+        if (itemRemovedAt == null)
+          events &= ~EventTypeEnum.RemovedAt;
+      }
+    }
+    internal void raiseItemRemovedAt(object sender, T item, int index)
+    { if (itemRemovedAt != null) itemRemovedAt(sender, new ItemAtEventArgs<T>(item, index)); }
+  }
+
+  /// <summary>
+  /// Tentative, to conserve memory in GuardedCollectionValueBase
+  /// This should really be nested in Guarded collection value, only have a guardereal field
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  [Serializable]
+  internal sealed class ProxyEventBlock<T>
+  {
+    ICollectionValue<T> proxy, real;
+
+    internal ProxyEventBlock(ICollectionValue<T> proxy, ICollectionValue<T> real)
+    { this.proxy = proxy; this.real = real; }
+
+    event CollectionChangedHandler<T> collectionChanged;
+    CollectionChangedHandler<T> collectionChangedProxy;
+    internal event CollectionChangedHandler<T> CollectionChanged
+    {
+      add
+      {
+        if (collectionChanged == null)
+        {
+          if (collectionChangedProxy == null)
+            collectionChangedProxy = delegate(object sender) { collectionChanged(proxy); };
+          real.CollectionChanged += collectionChangedProxy;
+        }
+        collectionChanged += value;
+      }
+      remove
+      {
+        collectionChanged -= value;
+        if (collectionChanged == null)
+          real.CollectionChanged -= collectionChangedProxy;
+      }
+    }
+
+    event CollectionClearedHandler<T> collectionCleared;
+    CollectionClearedHandler<T> collectionClearedProxy;
+    internal event CollectionClearedHandler<T> CollectionCleared
+    {
+      add
+      {
+        if (collectionCleared == null)
+        {
+          if (collectionClearedProxy == null)
+            collectionClearedProxy = delegate(object sender, ClearedEventArgs e) { collectionCleared(proxy, e); };
+          real.CollectionCleared += collectionClearedProxy;
+        }
+        collectionCleared += value;
+      }
+      remove
+      {
+        collectionCleared -= value;
+        if (collectionCleared == null)
+          real.CollectionCleared -= collectionClearedProxy;
+      }
+    }
+
+    event ItemsAddedHandler<T> itemsAdded;
+    ItemsAddedHandler<T> itemsAddedProxy;
+    internal event ItemsAddedHandler<T> ItemsAdded
+    {
+      add
+      {
+        if (itemsAdded == null)
+        {
+          if (itemsAddedProxy == null)
+            itemsAddedProxy = delegate(object sender, ItemCountEventArgs<T> e) { itemsAdded(proxy, e); };
+          real.ItemsAdded += itemsAddedProxy;
+        }
+        itemsAdded += value;
+      }
+      remove
+      {
+        itemsAdded -= value;
+        if (itemsAdded == null)
+          real.ItemsAdded -= itemsAddedProxy;
+      }
+    }
+
+    event ItemInsertedHandler<T> itemInserted;
+    ItemInsertedHandler<T> itemInsertedProxy;
+    internal event ItemInsertedHandler<T> ItemInserted
+    {
+      add
+      {
+        if (itemInserted == null)
+        {
+          if (itemInsertedProxy == null)
+            itemInsertedProxy = delegate(object sender, ItemAtEventArgs<T> e) { itemInserted(proxy, e); };
+          real.ItemInserted += itemInsertedProxy;
+        }
+        itemInserted += value;
+      }
+      remove
+      {
+        itemInserted -= value;
+        if (itemInserted == null)
+          real.ItemInserted -= itemInsertedProxy;
+      }
+    }
+
+    event ItemsRemovedHandler<T> itemsRemoved;
+    ItemsRemovedHandler<T> itemsRemovedProxy;
+    internal event ItemsRemovedHandler<T> ItemsRemoved
+    {
+      add
+      {
+        if (itemsRemoved == null)
+        {
+          if (itemsRemovedProxy == null)
+            itemsRemovedProxy = delegate(object sender, ItemCountEventArgs<T> e) { itemsRemoved(proxy, e); };
+          real.ItemsRemoved += itemsRemovedProxy;
+        }
+        itemsRemoved += value;
+      }
+      remove
+      {
+        itemsRemoved -= value;
+        if (itemsRemoved == null)
+          real.ItemsRemoved -= itemsRemovedProxy;
+      }
+    }
+
+    event ItemRemovedAtHandler<T> itemRemovedAt;
+    ItemRemovedAtHandler<T> itemRemovedAtProxy;
+    internal event ItemRemovedAtHandler<T> ItemRemovedAt
+    {
+      add
+      {
+        if (itemRemovedAt == null)
+        {
+          if (itemRemovedAtProxy == null)
+            itemRemovedAtProxy = delegate(object sender, ItemAtEventArgs<T> e) { itemRemovedAt(proxy, e); };
+          real.ItemRemovedAt += itemRemovedAtProxy;
+        }
+        itemRemovedAt += value;
+      }
+      remove
+      {
+        itemRemovedAt -= value;
+        if (itemRemovedAt == null)
+          real.ItemRemovedAt -= itemRemovedAtProxy;
+      }
+    }
+  }
+
+  /// <summary>
+  /// 
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  public class ItemAtEventArgs<T> : EventArgs
+  {
+    /// <summary>
+    /// 
+    /// </summary>
+    public readonly T Item;
+    /// <summary>
+    /// 
+    /// </summary>
+    public readonly int Index;
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="index"></param>
+    public ItemAtEventArgs(T item, int index) { Item = item; Index = index; }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override string ToString()
+    {
+      return String.Format("(ItemAtEventArgs {0} '{1}')", Index, Item);
+    }
+  }
+
+  /// <summary>
+  /// 
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  public class ItemCountEventArgs<T> : EventArgs
+  {
+    /// <summary>
+    /// 
+    /// </summary>
+    public readonly T Item;
+    /// <summary>
+    /// 
+    /// </summary>
+    public readonly int Count;
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="count"></param>
+    /// <param name="item"></param>
+    public ItemCountEventArgs(T item, int count) { Item = item; Count = count; }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override string ToString()
+    {
+      return String.Format("(ItemCountEventArgs {0} '{1}')", Count, Item);
+    }
+  }
+
+
+
+  /// <summary>
+  /// 
+  /// </summary>
+  public class ClearedEventArgs : EventArgs
+  {
+    /// <summary>
+    /// 
+    /// </summary>
+    public readonly bool Full;
+    /// <summary>
+    /// 
+    /// </summary>
+    public readonly int Count;
+    /// <summary>
+    /// 
+    /// </summary>
+    /// 
+    /// <param name="full">True if the operation cleared all of the collection</param>
+    /// <param name="count">The number of items removed by the clear.</param>
+    public ClearedEventArgs(bool full, int count) { Full = full; Count = count; }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override string ToString()
+    {
+      return String.Format("(ClearedEventArgs {0} {1})", Count, Full);
+    }
+  }
+
+  /// <summary>
+  /// 
+  /// </summary>
+  public class ClearedRangeEventArgs : ClearedEventArgs
+  {
+    //WE could let this be of type int? to  allow 
+    /// <summary>
+    /// 
+    /// </summary>
+    public readonly int? Start;
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="full"></param>
+    /// <param name="count"></param>
+    /// <param name="start"></param>
+    public ClearedRangeEventArgs(bool full, int count, int? start) : base(full,count) { Start = start; }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override string ToString()
+    {
+      return String.Format("(ClearedRangeEventArgs {0} {1} {2})", Count, Full, Start);
+    }
+  }
+
+  /// <summary>
+  /// The type of event raised after an operation on a collection has changed its contents.
+  /// Normally, a multioperation like AddAll, 
+  /// <see cref="M:C5.IExtensible`1.AddAll(System.Collections.Generic.IEnumerable{`0})"/> 
+  /// will only fire one CollectionChanged event. Any operation that changes the collection
+  /// must fire CollectionChanged as its last event.
+  /// </summary>
+  public delegate void CollectionChangedHandler<T>(object sender);
+
+  /// <summary>
+  /// The type of event raised after the Clear() operation on a collection.
+  /// <para/>
+  /// Note: The Clear() operation will not fire ItemsRemoved events. 
+  /// </summary>
+  /// <param name="sender"></param>
+  /// <param name="eventArgs"></param>
+  public delegate void CollectionClearedHandler<T>(object sender, ClearedEventArgs eventArgs);
+
+  /// <summary>
+  /// The type of event raised after an item has been added to a collection.
+  /// The event will be raised at a point of time, where the collection object is 
+  /// in an internally consistent state and before the corresponding CollectionChanged 
+  /// event is raised.
+  /// <para/>
+  /// Note: an Update operation will fire an ItemsRemoved and an ItemsAdded event.
+  /// <para/>
+  /// Note: When an item is inserted into a list (<see cref="T:C5.IList`1"/>), both
+  /// ItemInserted and ItemsAdded events will be fired.
+  /// </summary>
+  /// <param name="sender"></param>
+  /// <param name="eventArgs">An object with the item that was added</param>
+  public delegate void ItemsAddedHandler<T>(object sender, ItemCountEventArgs<T> eventArgs);
+
+  /// <summary>
+  /// The type of event raised after an item has been removed from a collection.
+  /// The event will be raised at a point of time, where the collection object is 
+  /// in an internally consistent state and before the corresponding CollectionChanged 
+  /// event is raised.
+  /// <para/>
+  /// Note: The Clear() operation will not fire ItemsRemoved events. 
+  /// <para/>
+  /// Note: an Update operation will fire an ItemsRemoved and an ItemsAdded event.
+  /// <para/>
+  /// Note: When an item is removed from a list by the RemoveAt operation, both an 
+  /// ItemsRemoved and an ItemRemovedAt event will be fired.
+  /// </summary>
+  /// <param name="sender"></param>
+  /// <param name="eventArgs">An object with the item that was removed</param>
+  public delegate void ItemsRemovedHandler<T>(object sender, ItemCountEventArgs<T> eventArgs);
+
+  /// <summary>
+  /// The type of event raised after an item has been inserted into a list by an Insert, 
+  /// InsertFirst or InsertLast operation.
+  /// The event will be raised at a point of time, where the collection object is 
+  /// in an internally consistent state and before the corresponding CollectionChanged 
+  /// event is raised.
+  /// <para/>
+  /// Note: an ItemsAdded event will also be fired.
+  /// </summary>
+  /// <param name="sender"></param>
+  /// <param name="eventArgs"></param>
+  public delegate void ItemInsertedHandler<T>(object sender, ItemAtEventArgs<T> eventArgs);
+
+  /// <summary>
+  /// The type of event raised after an item has been removed from a list by a RemoveAt(int i)
+  /// operation (or RemoveFirst(), RemoveLast(), Remove() operation).
+  /// The event will be raised at a point of time, where the collection object is 
+  /// in an internally consistent state and before the corresponding CollectionChanged 
+  /// event is raised.
+  /// <para/>
+  /// Note: an ItemRemoved event will also be fired.
+  /// </summary>
+  /// <param name="sender"></param>
+  /// <param name="eventArgs"></param>
+  public delegate void ItemRemovedAtHandler<T>(object sender, ItemAtEventArgs<T> eventArgs);
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Exceptions.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Exceptions.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Exceptions.cs	(revision 3)
@@ -0,0 +1,244 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+
+namespace C5
+{
+  /// <summary>
+  /// An exception to throw from library code when an internal inconsistency is encountered.
+  /// </summary>
+  public class InternalException : Exception
+  {
+    internal InternalException(string message) : base(message) { }
+  }
+
+  /// <summary>
+  /// An exception thrown by an update operation on a Read-Only collection or dictionary.
+  /// <para>This exception will be thrown unconditionally when an update operation 
+  /// (method or set property) is called. No check is made to see if the update operation, 
+  /// if allowed, would actually change the collection. </para>
+  /// </summary>
+  [Serializable]
+  public class ReadOnlyCollectionException : Exception
+  {
+    /// <summary>
+    /// Create a simple exception with no further explanation.
+    /// </summary>
+    public ReadOnlyCollectionException() : base() { }
+    /// <summary>
+    /// Create the exception with an explanation of the reason.
+    /// </summary>
+    /// <param name="message"></param>
+    public ReadOnlyCollectionException(string message) : base(message) { }
+  }
+
+  /// <summary>
+  /// 
+  /// </summary>
+  [Serializable]
+  public class FixedSizeCollectionException : Exception
+  {
+    /// <summary>
+    /// Create a simple exception with no further explanation.
+    /// </summary>
+    public FixedSizeCollectionException() : base() { }
+    /// <summary>
+    /// Create the exception with an explanation of the reason.
+    /// </summary>
+    /// <param name="message"></param>
+    public FixedSizeCollectionException(string message) : base(message) { }
+  }
+
+  /// <summary>
+  /// 
+  /// </summary>
+  [Serializable]
+  public class UnlistenableEventException : Exception
+  {
+    /// <summary>
+    /// Create a simple exception with no further explanation.
+    /// </summary>
+    public UnlistenableEventException() : base() { }
+    /// <summary>
+    /// Create the exception with an explanation of the reason.
+    /// </summary>
+    /// <param name="message"></param>
+    public UnlistenableEventException(string message) : base(message) { }
+  }
+
+  /// <summary>
+  /// An exception thrown by enumerators, range views etc. when accessed after 
+  /// the underlying collection has been modified.
+  /// </summary>
+  [Serializable]
+  public class CollectionModifiedException : Exception
+  {
+    /// <summary>
+    /// Create a simple exception with no further explanation.
+    /// </summary>
+    public CollectionModifiedException() : base() { }
+    /// <summary>
+    /// Create the exception with an explanation of the reason.
+    /// </summary>
+    /// <param name="message"></param>
+    public CollectionModifiedException(string message) : base(message) { }
+  }
+
+  /// <summary>
+  /// An excption thrown when trying to access a view (a list view on a <see cref="T:C5.IList`1"/> or 
+  /// a snapshot on a <see cref="T:C5.IPersistentSorted`1"/>)
+  /// that has been invalidated by some earlier operation.
+  /// <para>
+  /// The typical scenario is a view on a list that hash been invalidated by a call to 
+  /// Sort, Reverse or Shuffle on some other, overlapping view or the whole list.
+  /// </para>
+  /// </summary>
+  [Serializable]
+  public class ViewDisposedException : Exception
+  {
+    /// <summary>
+    /// Create a simple exception with no further explanation.
+    /// </summary>
+    public ViewDisposedException() : base() { }
+    /// <summary>
+    /// Create the exception with an explanation of the reason.
+    /// </summary>
+    /// <param name="message"></param>
+    public ViewDisposedException(string message) : base(message) { }
+  }
+
+  /// <summary>
+  /// An exception thrown by a lookup or lookup with update operation that does not 
+  /// find the lookup item and has no other means to communicate failure.
+  /// <para>The typical scenario is a lookup by key in a dictionary with an indexer,
+  /// see e.g. <see cref="P:C5.IDictionary`2.Item(`0)"/></para>
+  /// </summary>
+  [Serializable]
+  public class NoSuchItemException : Exception
+  {
+    /// <summary>
+    /// Create a simple exception with no further explanation.
+    /// </summary>
+    public NoSuchItemException() : base() { }
+    /// <summary>
+    /// Create the exception with an explanation of the reason.
+    /// </summary>
+    /// <param name="message"></param>
+    public NoSuchItemException(string message) : base(message) { }
+  }
+
+  /// <summary>
+  /// An exception thrown by an operation on a list (<see cref="T:C5.IList`1"/>)
+  /// that only makes sense for a view, not for an underlying list.
+  /// </summary>
+  [Serializable]
+  public class NotAViewException : Exception
+  {
+    /// <summary>
+    /// Create a simple exception with no further explanation.
+    /// </summary>
+    public NotAViewException() : base() { }
+    /// <summary>
+    /// Create the exception with an explanation of the reason.
+    /// </summary>
+    /// <param name="message"></param>
+    public NotAViewException(string message) : base(message) { }
+  }
+
+  /// <summary>
+  /// An exception thrown when an operation attempts to create a duplicate in a collection with set semantics 
+  /// (<see cref="P:C5.IExtensible`1.AllowsDuplicates"/> is false) or attempts to create a duplicate key in a dictionary.
+  /// <para>With collections this can only happen with Insert operations on lists, since the Add operations will
+  /// not try to create duplictes and either ignore the failure or report it in a bool return value.
+  /// </para>
+  /// <para>With dictionaries this can happen with the <see cref="M:C5.IDictionary`2.Add(`0,`1)"/> metod.</para>
+  /// </summary>
+  [Serializable]
+  public class DuplicateNotAllowedException : Exception
+  {
+    /// <summary>
+    /// Create a simple exception with no further explanation.
+    /// </summary>
+    public DuplicateNotAllowedException() : base() { }
+    /// <summary>
+    /// Create the exception with an explanation of the reason.
+    /// </summary>
+    /// <param name="message"></param>
+    public DuplicateNotAllowedException(string message) : base(message) { }
+  }
+
+  /// <summary>
+  /// 
+  /// </summary>
+  [Serializable]
+  public class InvalidPriorityQueueHandleException : Exception
+  {
+    /// <summary>
+    /// Create a simple exception with no further explanation.
+    /// </summary>
+    public InvalidPriorityQueueHandleException() : base() { }
+    /// <summary>
+    /// Create the exception with an explanation of the reason.
+    /// </summary>
+    /// <param name="message"></param>
+    public InvalidPriorityQueueHandleException(string message) : base(message) { }
+  }
+
+  /// <summary>
+  /// An exception thrown by an operation that need to construct a natural
+  /// comparer for a type.
+  /// </summary>
+  [Serializable]
+  public class NotComparableException : Exception
+  {
+    /// <summary>
+    /// Create a simple exception with no further explanation.
+    /// </summary>
+    public NotComparableException() : base() { }
+    /// <summary>
+    /// Create the exception with an explanation of the reason.
+    /// </summary>
+    /// <param name="message"></param>
+    public NotComparableException(string message) : base(message) { }
+  }
+
+  /// <summary>
+  /// An exception thrown by operations on a list that expects an argument
+  /// that is a view on the same underlying list.
+  /// </summary>
+  [Serializable]
+  public class IncompatibleViewException : Exception
+  {
+    /// <summary>
+    /// Create a simple exception with no further explanation.
+    /// </summary>
+    public IncompatibleViewException() : base() { }
+    /// <summary>
+    /// Create the exception with an explanation of the reason.
+    /// </summary>
+    /// <param name="message"></param>
+    public IncompatibleViewException(string message) : base(message) { }
+  }
+
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Formatting.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Formatting.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Formatting.cs	(revision 3)
@@ -0,0 +1,249 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using C5;
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Diagnostics;
+using System.Text;
+
+namespace C5
+{
+  /// <summary>
+  /// <i>(Describe usage of "L:300" format string.)</i>
+  /// </summary>
+  public interface IShowable : IFormattable
+  {
+    //TODO: wonder if we should use TextWriters instead of StringBuilders?
+    /// <summary>
+    /// Format <code>this</code> using at most approximately <code>rest</code> chars and 
+    /// append the result, possibly truncated, to stringbuilder.
+    /// Subtract the actual number of used chars from <code>rest</code>.
+    /// </summary>
+    /// <param name="stringbuilder"></param>
+    /// <param name="rest"></param>
+    /// <param name="formatProvider"></param>
+    /// <returns>True if the appended formatted string was complete (not truncated).</returns>
+    bool Show(StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider);
+  }
+  // ------------------------------------------------------------
+
+  // Static helper methods for Showing collections 
+
+  /// <summary>
+  /// 
+  /// </summary>
+  public static class Showing
+  {
+    /// <summary>
+    /// Show  <code>Object obj</code> by appending it to <code>stringbuilder</code>
+    /// </summary>
+    /// <param name="obj"></param>
+    /// <param name="stringbuilder"></param>
+    /// <param name="rest"></param>
+    /// <param name="formatProvider"></param>
+    /// <returns>True if <code>obj</code> was shown completely.</returns>
+    public static bool Show(Object obj, StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
+    {
+      IShowable showable;
+      if (rest <= 0)
+        return false;
+      else if ((showable = obj as IShowable) != null)
+        return showable.Show(stringbuilder, ref rest, formatProvider);
+      int oldLength = stringbuilder.Length;
+      stringbuilder.AppendFormat(formatProvider, "{0}", obj);
+      rest -= (stringbuilder.Length - oldLength);
+      return true;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="showable"></param>
+    /// <param name="format"></param>
+    /// <param name="formatProvider"></param>
+    /// <returns></returns>
+    public static String ShowString(IShowable showable, String format, IFormatProvider formatProvider)
+    {
+      int rest = maxLength(format);
+      StringBuilder sb = new StringBuilder();
+      showable.Show(sb, ref rest, formatProvider);
+      return sb.ToString();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="format"></param>
+    /// <returns></returns>
+    static int maxLength(String format)
+    {
+      //TODO: validate format string
+      if (format == null)
+        return 80;
+      if (format.Length > 1 && format.StartsWith("L"))
+      {
+        return int.Parse(format.Substring(1));
+      }
+      else
+        return int.MaxValue;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <typeparam name="T"></typeparam>
+    /// <param name="items"></param>
+    /// <param name="stringbuilder"></param>
+    /// <param name="rest"></param>
+    /// <param name="formatProvider"></param>
+    /// <returns>True if collection was shown completely</returns>
+    public static bool ShowCollectionValue<T>(ICollectionValue<T> items, StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
+    {
+      string startdelim = "{ ", enddelim = " }";
+      bool showIndexes = false;
+      bool showMultiplicities = false;
+      //TODO: do not test here at run time, but select code at compile time
+      //      perhaps by delivering the print type to this metod
+      IList<T> list;
+      ICollection<T> coll = items as ICollection<T>;
+      if ((list = items as IList<T>) != null)
+      {
+        startdelim = "[ ";
+        enddelim = " ]";
+        //TODO: should have been (items as IIndexed<T>).IndexingSpeed
+        showIndexes = list.IndexingSpeed == Speed.Constant;
+      }
+      else if (coll != null)
+      {
+        if (coll.AllowsDuplicates)
+        {
+          startdelim = "{{ ";
+          enddelim = " }}";
+          if (coll.DuplicatesByCounting)
+            showMultiplicities = true;
+        }
+      }
+
+      stringbuilder.Append(startdelim);
+      rest -= 2 * startdelim.Length;
+      bool first = true;
+      bool complete = true;
+      int index = 0;
+
+      if (showMultiplicities)
+      {
+        foreach (KeyValuePair<T, int> p in coll.ItemMultiplicities())
+        {
+          complete = false;
+          if (rest <= 0)
+            break;
+          if (first)
+            first = false;
+          else
+          {
+            stringbuilder.Append(", ");
+            rest -= 2;
+          }
+          if (complete = Showing.Show(p.Key, stringbuilder, ref rest, formatProvider))
+          {
+            string multiplicityString = string.Format("(*{0})", p.Value);
+            stringbuilder.Append(multiplicityString);
+            rest -= multiplicityString.Length;
+          }
+        }
+      }
+      else
+      {
+        foreach (T x in items)
+        {
+          complete = false;
+          if (rest <= 0)
+            break;
+          if (first)
+            first = false;
+          else
+          {
+            stringbuilder.Append(", ");
+            rest -= 2;
+          }
+          if (showIndexes)
+          {
+            string indexString = string.Format("{0}:", index++);
+            stringbuilder.Append(indexString);
+            rest -= indexString.Length;
+          }
+          complete = Showing.Show(x, stringbuilder, ref rest, formatProvider);
+        }
+      }
+      if (!complete)
+      {
+        stringbuilder.Append("...");
+        rest -= 3;
+      }
+      stringbuilder.Append(enddelim);
+      return complete;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <typeparam name="K"></typeparam>
+    /// <typeparam name="V"></typeparam>
+    /// 
+    /// <param name="dictionary"></param>
+    /// <param name="stringbuilder"></param>
+    /// <param name="formatProvider"></param>
+    /// <param name="rest"></param>
+    /// <returns></returns>
+    public static bool ShowDictionary<K, V>(IDictionary<K, V> dictionary, StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
+    {
+      bool sorted = dictionary is ISortedDictionary<K, V>;
+      stringbuilder.Append(sorted ? "[ " : "{ ");
+      rest -= 4;				   // Account for "( " and " )"
+      bool first = true;
+      bool complete = true;
+
+      foreach (KeyValuePair<K, V> p in dictionary)
+      {
+        complete = false;
+        if (rest <= 0)
+          break;
+        if (first)
+          first = false;
+        else
+        {
+          stringbuilder.Append(", ");
+          rest -= 2;
+        }
+        complete = Showing.Show(p, stringbuilder, ref rest, formatProvider);
+      }
+      if (!complete)
+      {
+        stringbuilder.Append("...");
+        rest -= 3;
+      }
+      stringbuilder.Append(sorted ? " ]" : " }");
+      return complete;
+    }
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Hashers.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Hashers.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Hashers.cs	(revision 3)
@@ -0,0 +1,523 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using C5;
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+
+namespace C5
+{
+  /// <summary>
+  /// Utility class for building default generic equalityComparers.
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  public static class EqualityComparer<T>
+  {
+    readonly static Type isequenced = typeof(ISequenced<>);
+
+    readonly static Type icollection = typeof(ICollection<>);
+
+    readonly static Type orderedcollectionequalityComparer = typeof(SequencedCollectionEqualityComparer<,>);
+
+    readonly static Type unorderedcollectionequalityComparer = typeof(UnsequencedCollectionEqualityComparer<,>);
+
+    readonly static Type equalityequalityComparer = typeof(EquatableEqualityComparer<>);
+
+    readonly static Type iequalitytype = typeof(IEquatable<T>);
+
+    static SCG.IEqualityComparer<T> cachedDefault = null;
+
+    //TODO: find the right word for initialized+invocation 
+    /// <summary>
+    /// A default generic equality comparer for type T. The procedure is as follows:
+    /// <list>
+    /// <item>If T is a primitive type (char, sbyte, byte, short, ushort, int, uint, float, double, decimal), 
+    /// the equalityComparer will be a standard equalityComparer for that type</item>
+    /// <item>If the actual generic argument T implements the generic interface
+    /// <see cref="T:C5.ISequenced`1"/> for some value W of its generic parameter T,
+    /// the equalityComparer will be <see cref="T:C5.SequencedCollectionEqualityComparer`2"/></item>
+    /// <item>If the actual generic argument T implements 
+    /// <see cref="T:C5.ICollection`1"/> for some value W of its generic parameter T,
+    /// the equalityComparer will be <see cref="T:C5.UnsequencedCollectionEqualityComparer`2"/></item>
+    /// <item>If T is a type implementing <see cref="T:C5.IEquatable`1"/>, the equalityComparer
+    /// will be <see cref="T:C5.EquatableEqualityComparer`1"/></item>
+    /// <item>If T is a type not implementing <see cref="T:C5.IEquatable`1"/>, the equalityComparer
+    /// will be <see cref="T:C5.NaturalEqualityComparer`1"/> </item>
+    /// </list>   
+    /// The <see cref="T:C5.IEqualityComparer`1"/> object is constructed when this class is initialised, i.e. 
+    /// its static constructors called. Thus, the property will be the same object 
+    /// for the duration of an invocation of the runtime, but a value serialized in 
+    /// another invocation and deserialized here will not be the same object.
+    /// </summary>
+    /// <value></value>
+    public static SCG.IEqualityComparer<T> Default
+    {
+      get
+      {
+        if (cachedDefault != null)
+          return cachedDefault;
+
+        Type t = typeof(T);
+
+        if (t.IsValueType)
+        {
+          if (t.Equals(typeof(char)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(CharEqualityComparer.Default);
+
+          if (t.Equals(typeof(sbyte)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(SByteEqualityComparer.Default);
+
+          if (t.Equals(typeof(byte)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(ByteEqualityComparer.Default);
+
+          if (t.Equals(typeof(short)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(ShortEqualityComparer.Default);
+
+          if (t.Equals(typeof(ushort)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(UShortEqualityComparer.Default);
+          
+          if (t.Equals(typeof(int)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(IntEqualityComparer.Default);
+
+          if (t.Equals(typeof(uint)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(UIntEqualityComparer.Default);
+
+          if (t.Equals(typeof(long)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(LongEqualityComparer.Default);
+
+          if (t.Equals(typeof(ulong)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(ULongEqualityComparer.Default);
+
+          if (t.Equals(typeof(float)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(FloatEqualityComparer.Default);
+          
+          if (t.Equals(typeof(double)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(DoubleEqualityComparer.Default);
+
+          if (t.Equals(typeof(decimal)))
+            return cachedDefault = (SCG.IEqualityComparer<T>)(DecimalEqualityComparer.Default);
+        }
+        Type[] interfaces = t.GetInterfaces();
+        if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(isequenced))
+          return createAndCache(orderedcollectionequalityComparer.MakeGenericType(new Type[] { t, t.GetGenericArguments()[0] }));
+        foreach (Type ty in interfaces)
+        {
+          if (ty.IsGenericType && ty.GetGenericTypeDefinition().Equals(isequenced))
+            return createAndCache(orderedcollectionequalityComparer.MakeGenericType(new Type[] { t, ty.GetGenericArguments()[0] }));
+        }
+        if (t.IsGenericType && t.GetGenericTypeDefinition().Equals(icollection))
+          return createAndCache(unorderedcollectionequalityComparer.MakeGenericType(new Type[] { t, t.GetGenericArguments()[0] }));
+        foreach (Type ty in interfaces)
+        {
+          if (ty.IsGenericType && ty.GetGenericTypeDefinition().Equals(icollection))
+            return createAndCache(unorderedcollectionequalityComparer.MakeGenericType(new Type[] { t, ty.GetGenericArguments()[0] }));
+        }
+        if (iequalitytype.IsAssignableFrom(t))
+          return createAndCache(equalityequalityComparer.MakeGenericType(new Type[] { t }));
+        else
+          return cachedDefault = NaturalEqualityComparer<T>.Default;
+      }
+    }
+    static SCG.IEqualityComparer<T> createAndCache(Type equalityComparertype)
+    {
+      return cachedDefault = (SCG.IEqualityComparer<T>)(equalityComparertype.GetProperty("Default", BindingFlags.Static | BindingFlags.Public).GetValue(null, null));
+    }
+  }
+
+  /// <summary>
+  /// A default item equalityComparer calling through to
+  /// the GetHashCode and Equals methods inherited from System.Object.
+  /// </summary>
+  [Serializable]
+  public sealed class NaturalEqualityComparer<T> : SCG.IEqualityComparer<T>
+  {
+    static NaturalEqualityComparer<T> cached;
+    NaturalEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public static NaturalEqualityComparer<T> Default { get { return cached ?? (cached = new NaturalEqualityComparer<T>()); } }
+    //TODO: check if null check is reasonable
+    //Answer: if we have struct C<T> { T t; int i;} and implement GetHashCode as
+    //the sum of hashcodes, and T may be any type, we cannot make the null check 
+    //inside the definition of C<T> in a reasonable way.
+    /// <summary>
+    /// Get the hash code with respect to this item equalityComparer
+    /// </summary>
+    /// <param name="item">The item</param>
+    /// <returns>The hash code</returns>
+    [Tested]
+    public int GetHashCode(T item) { return item == null ? 0 : item.GetHashCode(); }
+
+    /// <summary>
+    /// Check if two items are equal with respect to this item equalityComparer
+    /// </summary>
+    /// <param name="item1">first item</param>
+    /// <param name="item2">second item</param>
+    /// <returns>True if equal</returns>
+    [Tested]
+    public bool Equals(T item1, T item2)
+    {
+      return item1 == null ? item2 == null : item1.Equals(item2);
+    }
+  }
+
+  /// <summary>
+  /// A default equality comparer for a type T that implements System.IEquatable<typeparamref name="T"/>. 
+  /// 
+  /// The equality comparer forwards calls to GetHashCode and Equals to the IEquatable methods 
+  /// on T, so Equals(T) is called, not Equals(object). 
+  /// This will save boxing abd unboxing if T is a value type
+  /// and in general saves a runtime type check.
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  [Serializable]
+  public class EquatableEqualityComparer<T> : SCG.IEqualityComparer<T> where T : IEquatable<T>
+  {
+    static EquatableEqualityComparer<T> cached = new EquatableEqualityComparer<T>();
+    EquatableEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public static EquatableEqualityComparer<T> Default { 
+      get { return cached ?? (cached = new EquatableEqualityComparer<T>()); } 
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public int GetHashCode(T item) { return item == null ? 0 : item.GetHashCode(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item1"></param>
+    /// <param name="item2"></param>
+    /// <returns></returns>
+    public bool Equals(T item1, T item2) { return item1 == null ? item2 == null : item1.Equals(item2); }
+  }
+
+  /// <summary>
+  /// A equalityComparer for a reference type that uses reference equality for equality and the hash code from object as hash code.
+  /// </summary>
+  /// <typeparam name="T">The item type. Must be a reference type.</typeparam>
+  [Serializable]
+  public class ReferenceEqualityComparer<T> : SCG.IEqualityComparer<T> where T : class
+  {
+    static ReferenceEqualityComparer<T> cached;
+    ReferenceEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public static ReferenceEqualityComparer<T> Default { 
+      get { return cached ?? (cached = new ReferenceEqualityComparer<T>()); } 
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public int GetHashCode(T item)
+    {
+      return System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode(item);
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="i1"></param>
+    /// <param name="i2"></param>
+    /// <returns></returns>
+    public bool Equals(T i1, T i2)
+    {
+      return object.ReferenceEquals(i1, i2);
+    }
+  }
+
+  /// <summary>
+  /// An equalityComparer compatible with a given comparer. All hash codes are 0, 
+  /// meaning that anything based on hash codes will be quite inefficient.
+  /// <para><b>Note: this will give a new EqualityComparer each time created!</b></para>
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  [Serializable]
+  public class ComparerZeroHashCodeEqualityComparer<T> : SCG.IEqualityComparer<T>
+  {
+    SCG.IComparer<T> comparer;
+    /// <summary>
+    /// Create a trivial <see cref="T:C5.IEqualityComparer`1"/> compatible with the 
+    /// <see cref="T:C5.IComparer`1"/> <code>comparer</code>
+    /// </summary>
+    /// <param name="comparer"></param>
+    public ComparerZeroHashCodeEqualityComparer(SCG.IComparer<T> comparer)
+    {
+      if (comparer == null)
+        throw new NullReferenceException("Comparer cannot be null");
+      this.comparer = comparer;
+    }
+    /// <summary>
+    /// A trivial, inefficient hash fuction. Compatible with any equality relation.
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns>0</returns>
+    public int GetHashCode(T item) { return 0; }
+    /// <summary>
+    /// Equality of two items as defined by the comparer.
+    /// </summary>
+    /// <param name="item1"></param>
+    /// <param name="item2"></param>
+    /// <returns></returns>
+    public bool Equals(T item1, T item2) { return comparer.Compare(item1, item2) == 0; }
+  }
+
+  /// <summary>
+  /// Prototype for a sequenced equalityComparer for something (T) that implements ISequenced[W].
+  /// This will use ISequenced[W] specific implementations of the equality comparer operations.
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  /// <typeparam name="W"></typeparam>
+  [Serializable]
+  public class SequencedCollectionEqualityComparer<T, W> : SCG.IEqualityComparer<T>
+      where T : ISequenced<W>
+  {
+    static SequencedCollectionEqualityComparer<T, W> cached;
+    SequencedCollectionEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public static SequencedCollectionEqualityComparer<T, W> Default { 
+      get { return cached ?? (cached = new SequencedCollectionEqualityComparer<T, W>()); } 
+    }
+    /// <summary>
+    /// Get the hash code with respect to this sequenced equalityComparer
+    /// </summary>
+    /// <param name="collection">The collection</param>
+    /// <returns>The hash code</returns>
+    [Tested]
+    public int GetHashCode(T collection) { return collection.GetSequencedHashCode(); }
+
+    /// <summary>
+    /// Check if two items are equal with respect to this sequenced equalityComparer
+    /// </summary>
+    /// <param name="collection1">first collection</param>
+    /// <param name="collection2">second collection</param>
+    /// <returns>True if equal</returns>
+    [Tested]
+    public bool Equals(T collection1, T collection2) { return collection1 == null ? collection2 == null : collection1.SequencedEquals(collection2); }
+  }
+
+  /// <summary>
+  /// Prototype for an unsequenced equalityComparer for something (T) that implements ICollection[W]
+  /// This will use ICollection[W] specific implementations of the equalityComparer operations
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  /// <typeparam name="W"></typeparam>
+  [Serializable]
+  public class UnsequencedCollectionEqualityComparer<T, W> : SCG.IEqualityComparer<T>
+      where T : ICollection<W>
+  {
+    static UnsequencedCollectionEqualityComparer<T, W> cached;
+    UnsequencedCollectionEqualityComparer() { }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public static UnsequencedCollectionEqualityComparer<T, W> Default { get { return cached ?? (cached = new UnsequencedCollectionEqualityComparer<T, W>()); } }
+    /// <summary>
+    /// Get the hash code with respect to this unsequenced equalityComparer
+    /// </summary>
+    /// <param name="collection">The collection</param>
+    /// <returns>The hash code</returns>
+    [Tested]
+    public int GetHashCode(T collection) { return collection.GetUnsequencedHashCode(); }
+
+
+    /// <summary>
+    /// Check if two collections are equal with respect to this unsequenced equalityComparer
+    /// </summary>
+    /// <param name="collection1">first collection</param>
+    /// <param name="collection2">second collection</param>
+    /// <returns>True if equal</returns>
+    [Tested]
+    public bool Equals(T collection1, T collection2) { return collection1 == null ? collection2 == null : collection1.UnsequencedEquals(collection2); }
+  }
+
+}
+
+
+#if EXPERIMENTAL
+namespace C5.EqualityComparerBuilder
+{
+
+  /// <summary>
+  /// IEqualityComparer factory class: examines at instatiation time if T is an
+  /// interface implementing "int GetHashCode()" and "bool Equals(T)".
+  /// If those are not present, MakeEqualityComparer will return a default equalityComparer,
+  /// else this class will implement IequalityComparer[T] via Invoke() on the
+  /// reflected method infos.
+  /// </summary>
+  public class ByInvoke<T> : SCG.IEqualityComparer<T>
+  {
+    internal static readonly System.Reflection.MethodInfo hinfo, einfo;
+
+
+    static ByInvoke()
+    {
+      Type t = typeof(T);
+
+      if (!t.IsInterface) return;
+
+      BindingFlags f = BindingFlags.Public | BindingFlags.Instance;
+
+      hinfo = t.GetMethod("GetHashCode", f, null, new Type[0], null);
+      einfo = t.GetMethod("Equals", f, null, new Type[1] { t }, null);
+    }
+
+
+    private ByInvoke() { }
+
+/// <summary>
+/// 
+/// </summary>
+/// <returns></returns>
+    public static SCG.IEqualityComparer<T> MakeEqualityComparer()
+    {
+      if (hinfo != null && einfo != null)
+        return new ByInvoke<T>();
+      else
+        return NaturalEqualityComparer<T>.Default;
+    }
+
+/// <summary>
+/// 
+/// </summary>
+/// <param name="item"></param>
+/// <returns></returns>
+    public int GetHashCode(T item)
+    {
+      return (int)(hinfo.Invoke(item, null));
+    }
+
+/// <summary>
+/// 
+/// </summary>
+/// <param name="i1"></param>
+/// <param name="i2"></param>
+/// <returns></returns>
+    public bool Equals(T i1, T i2)
+    {
+      return (bool)(einfo.Invoke(i1, new object[1] { i2 }));
+    }
+  }
+
+
+
+  /// <summary>
+  /// Like ByInvoke, but tries to build a equalityComparer by RTCG to
+  /// avoid the Invoke() overhead. 
+  /// </summary>
+  public class ByRTCG
+  {
+    private static ModuleBuilder moduleBuilder;
+
+    private static AssemblyBuilder assemblyBuilder;
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="hinfo"></param>
+    /// <param name="einfo"></param>
+    /// <returns></returns>
+    public static SCG.IEqualityComparer<T> CreateEqualityComparer<T>(MethodInfo hinfo, MethodInfo einfo)
+    {
+      if (moduleBuilder == null)
+      {
+        string assmname = "LeFake";
+        string filename = assmname + ".dll";
+        AssemblyName assemblyName = new AssemblyName("LeFake");
+        AppDomain appdomain = AppDomain.CurrentDomain;
+        AssemblyBuilderAccess acc = AssemblyBuilderAccess.RunAndSave;
+
+        assemblyBuilder = appdomain.DefineDynamicAssembly(assemblyName, acc);
+        moduleBuilder = assemblyBuilder.DefineDynamicModule(assmname, filename);
+      }
+
+      Type t = typeof(T);
+      Type o_t = typeof(object);
+      Type h_t = typeof(SCG.IEqualityComparer<T>);
+      Type i_t = typeof(int);
+      //TODO: protect uid for thread safety!
+      string name = "C5.Dynamic.EqualityComparer_" + Guid.NewGuid().ToString();
+      TypeAttributes tatt = TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Sealed;
+      TypeBuilder tb = moduleBuilder.DefineType(name, tatt, o_t, new Type[1] { h_t });
+      MethodAttributes matt = MethodAttributes.Public | MethodAttributes.Virtual;
+      MethodBuilder mb = tb.DefineMethod("GetHashCode", matt, i_t, new Type[1] { t });
+      ILGenerator ilg = mb.GetILGenerator();
+
+      ilg.Emit(OpCodes.Ldarg_1);
+      ilg.Emit(OpCodes.Callvirt, hinfo);
+      ilg.Emit(OpCodes.Ret);
+      mb = tb.DefineMethod("Equals", matt, typeof(bool), new Type[2] { t, t });
+      ilg = mb.GetILGenerator();
+      ilg.Emit(OpCodes.Ldarg_1);
+      ilg.Emit(OpCodes.Ldarg_2);
+      ilg.Emit(OpCodes.Callvirt, einfo);
+      ilg.Emit(OpCodes.Ret);
+
+      Type equalityComparer_t = tb.CreateType();
+      object equalityComparer = equalityComparer_t.GetConstructor(new Type[0]).Invoke(null);
+
+      return (SCG.IEqualityComparer<T>)equalityComparer;
+    }
+
+/// <summary>
+/// 
+/// </summary>
+/// <typeparam name="T"></typeparam>
+/// <returns></returns>
+    public static SCG.IEqualityComparer<T> build<T>()
+    {
+      MethodInfo hinfo = ByInvoke<T>.hinfo, einfo = ByInvoke<T>.einfo;
+
+      if (hinfo != null && einfo != null)
+        return CreateEqualityComparer<T>(hinfo, einfo);
+      else
+        return EqualityComparer<T>.Default;
+    }
+
+/// <summary>
+/// 
+/// </summary>
+    public void dump()
+    {
+      assemblyBuilder.Save("LeFake.dll");
+    }
+  }
+}
+#endif
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Interfaces.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Interfaces.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Interfaces.cs	(revision 3)
@@ -0,0 +1,2059 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using SCG = System.Collections.Generic;
+namespace C5
+{
+  /// <summary>
+  /// A generic collection, that can be enumerated backwards.
+  /// </summary>
+  public interface IDirectedEnumerable<T> : SCG.IEnumerable<T>
+  {
+    /// <summary>
+    /// Create a collection containing the same items as this collection, but
+    /// whose enumerator will enumerate the items backwards. The new collection
+    /// will become invalid if the original is modified. Method typically used as in
+    /// <code>foreach (T x in coll.Backwards()) {...}</code>
+    /// </summary>
+    /// <returns>The backwards collection.</returns>
+    IDirectedEnumerable<T> Backwards();
+
+
+    /// <summary>
+    /// <code>Forwards</code> if same, else <code>Backwards</code>
+    /// </summary>
+    /// <value>The enumeration direction relative to the original collection.</value>
+    EnumerationDirection Direction { get;}
+  }
+
+  /// <summary>
+  /// A generic collection that may be enumerated and can answer
+  /// efficiently how many items it contains. Like <code>IEnumerable&lt;T&gt;</code>,
+  /// this interface does not prescribe any operations to initialize or update the 
+  /// collection. The main usage for this interface is to be the return type of 
+  /// query operations on generic collection.
+  /// </summary>
+  public interface ICollectionValue<T> : SCG.IEnumerable<T>, IShowable
+  {
+    /// <summary>
+    /// A flag bitmap of the events subscribable to by this collection.
+    /// </summary>
+    /// <value></value>
+    EventTypeEnum ListenableEvents { get;}
+
+    /// <summary>
+    /// A flag bitmap of the events currently subscribed to by this collection.
+    /// </summary>
+    /// <value></value>
+    EventTypeEnum ActiveEvents { get;}
+
+    /// <summary>
+    /// The change event. Will be raised for every change operation on the collection.
+    /// </summary>
+    event CollectionChangedHandler<T> CollectionChanged;
+
+    /// <summary>
+    /// The change event. Will be raised for every clear operation on the collection.
+    /// </summary>
+    event CollectionClearedHandler<T> CollectionCleared;
+
+    /// <summary>
+    /// The item added  event. Will be raised for every individual addition to the collection.
+    /// </summary>
+    event ItemsAddedHandler<T> ItemsAdded;
+
+    /// <summary>
+    /// The item inserted  event. Will be raised for every individual insertion to the collection.
+    /// </summary>
+    event ItemInsertedHandler<T> ItemInserted;
+
+    /// <summary>
+    /// The item removed event. Will be raised for every individual removal from the collection.
+    /// </summary>
+    event ItemsRemovedHandler<T> ItemsRemoved;
+
+    /// <summary>
+    /// The item removed at event. Will be raised for every individual removal at from the collection.
+    /// </summary>
+    event ItemRemovedAtHandler<T> ItemRemovedAt;
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>True if this collection is empty.</value>
+    bool IsEmpty { get;}
+
+    /// <summary>
+    /// </summary>
+    /// <value>The number of items in this collection</value>
+    int Count { get;}
+
+    /// <summary>
+    /// The value is symbolic indicating the type of asymptotic complexity
+    /// in terms of the size of this collection (worst-case or amortized as
+    /// relevant).
+    /// </summary>
+    /// <value>A characterization of the speed of the 
+    /// <code>Count</code> property in this collection.</value>
+    Speed CountSpeed { get;}
+
+    /// <summary>
+    /// Copy the items of this collection to a contiguous part of an array.
+    /// </summary>
+    /// <param name="array">The array to copy to</param>
+    /// <param name="index">The index at which to copy the first item</param>
+    void CopyTo(T[] array, int index);
+
+    /// <summary>
+    /// Create an array with the items of this collection (in the same order as an
+    /// enumerator would output them).
+    /// </summary>
+    /// <returns>The array</returns>
+    T[] ToArray();
+
+    /// <summary>
+    /// Apply a delegate to all items of this collection.
+    /// </summary>
+    /// <param name="action">The delegate to apply</param>
+    void Apply(Act<T> action);
+
+
+    /// <summary>
+    /// Check if there exists an item  that satisfies a
+    /// specific predicate in this collection.
+    /// </summary>
+    /// <param name="predicate">A  delegate 
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
+    /// <returns>True is such an item exists</returns>
+    bool Exists(Fun<T, bool> predicate);
+
+    /// <summary>
+    /// Check if there exists an item  that satisfies a
+    /// specific predicate in this collection and return the first one in enumeration order.
+    /// </summary>
+    /// <param name="predicate">A delegate 
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
+    /// <param name="item"></param>
+    /// <returns>True is such an item exists</returns>
+    bool Find(Fun<T, bool> predicate, out T item);
+
+
+    /// <summary>
+    /// Check if all items in this collection satisfies a specific predicate.
+    /// </summary>
+    /// <param name="predicate">A delegate 
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
+    /// <returns>True if all items satisfies the predicate</returns>
+    bool All(Fun<T, bool> predicate);
+
+    /// <summary>
+    /// Choose some item of this collection. 
+    /// <para>Implementations must assure that the item 
+    /// returned may be efficiently removed.</para>
+    /// <para>Implementors may decide to implement this method in a way such that repeated
+    /// calls do not necessarily give the same result, i.e. so that the result of the following 
+    /// test is undetermined:
+    /// <code>coll.Choose() == coll.Choose()</code></para>
+    /// </summary>
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>
+    /// <returns></returns>
+    T Choose();
+
+    /// <summary>
+    /// Create an enumerable, enumerating the items of this collection that satisfies 
+    /// a certain condition.
+    /// </summary>
+    /// <param name="filter">The T->bool filter delegate defining the condition</param>
+    /// <returns>The filtered enumerable</returns>
+    SCG.IEnumerable<T> Filter(Fun<T, bool> filter);
+  }
+
+
+
+  /// <summary>
+  /// A sized generic collection, that can be enumerated backwards.
+  /// </summary>
+  public interface IDirectedCollectionValue<T> : ICollectionValue<T>, IDirectedEnumerable<T>
+  {
+    /// <summary>
+    /// Create a collection containing the same items as this collection, but
+    /// whose enumerator will enumerate the items backwards. The new collection
+    /// will become invalid if the original is modified. Method typically used as in
+    /// <code>foreach (T x in coll.Backwards()) {...}</code>
+    /// </summary>
+    /// <returns>The backwards collection.</returns>
+    new IDirectedCollectionValue<T> Backwards();
+
+    /// <summary>
+    /// Check if there exists an item  that satisfies a
+    /// specific predicate in this collection and return the first one in enumeration order.
+    /// </summary>
+    /// <param name="predicate">A delegate 
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
+    /// <param name="item"></param>
+    /// <returns>True is such an item exists</returns>
+    bool FindLast(Fun<T, bool> predicate, out T item);
+  }
+
+
+  /// <summary>
+  /// A generic collection to which one may add items. This is just the intersection
+  /// of the main stream generic collection interfaces and the priority queue interface,
+  /// <see cref="T:C5.ICollection`1"/> and <see cref="T:C5.IPriorityQueue`1"/>.
+  /// </summary>
+  public interface IExtensible<T> : ICollectionValue<T>, ICloneable
+  {
+    /// <summary>
+    /// If true any call of an updating operation will throw an
+    /// <code>ReadOnlyCollectionException</code>
+    /// </summary>
+    /// <value>True if this collection is read-only.</value>
+    bool IsReadOnly { get;}
+
+    //TODO: wonder where the right position of this is
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>False if this collection has set semantics, true if bag semantics.</value>
+    bool AllowsDuplicates { get;}
+
+    //TODO: wonder where the right position of this is. And the semantics.
+    /// <summary>
+    /// (Here should be a discussion of the role of equalityComparers. Any ). 
+    /// </summary>
+    /// <value>The equalityComparer used by this collection to check equality of items. 
+    /// Or null (????) if collection does not check equality at all or uses a comparer.</value>
+    SCG.IEqualityComparer<T> EqualityComparer { get;}
+
+    //ItemEqualityTypeEnum ItemEqualityType {get ;}
+
+    //TODO: find a good name
+
+    /// <summary>
+    /// By convention this is true for any collection with set semantics.
+    /// </summary>
+    /// <value>True if only one representative of a group of equal items 
+    /// is kept in the collection together with the total count.</value>
+    bool DuplicatesByCounting { get;}
+
+    /// <summary>
+    /// Add an item to this collection if possible. If this collection has set
+    /// semantics, the item will be added if not already in the collection. If
+    /// bag semantics, the item will always be added.
+    /// </summary>
+    /// <param name="item">The item to add.</param>
+    /// <returns>True if item was added.</returns>
+    bool Add(T item);
+
+    /// <summary>
+    /// Add the elements from another collection with a more specialized item type 
+    /// to this collection. If this
+    /// collection has set semantics, only items not already in the collection
+    /// will be added.
+    /// </summary>
+    /// <typeparam name="U">The type of items to add</typeparam>
+    /// <param name="items">The items to add</param>
+    void AddAll<U>(SCG.IEnumerable<U> items) where U : T;
+
+    //void Clear(); // for priority queue
+    //int Count why not?
+    /// <summary>
+    /// Check the integrity of the internal data structures of this collection.
+    /// <i>This is only relevant for developers of the library</i>
+    /// </summary>
+    /// <returns>True if check was passed.</returns>
+    bool Check();
+  }
+
+  /// <summary>
+  /// The simplest interface of a main stream generic collection
+  /// with lookup, insertion and removal operations. 
+  /// </summary>
+  public interface ICollection<T> : IExtensible<T>, SCG.ICollection<T>
+  {
+    //This is somewhat similar to the RandomAccess marker itf in java
+    /// <summary>
+    /// The value is symbolic indicating the type of asymptotic complexity
+    /// in terms of the size of this collection (worst-case or amortized as
+    /// relevant). 
+    /// <para>See <see cref="T:C5.Speed"/> for the set of symbols.</para>
+    /// </summary>
+    /// <value>A characterization of the speed of lookup operations
+    /// (<code>Contains()</code> etc.) of the implementation of this collection.</value>
+    Speed ContainsSpeed { get;}
+
+    /// <summary>
+    /// </summary>
+    /// <value>The number of items in this collection</value>
+    new int Count { get; }
+
+    /// <summary>
+    /// If true any call of an updating operation will throw an
+    /// <code>ReadOnlyCollectionException</code>
+    /// </summary>
+    /// <value>True if this collection is read-only.</value>
+    new bool IsReadOnly { get; }
+
+    /// <summary>
+    /// Add an item to this collection if possible. If this collection has set
+    /// semantics, the item will be added if not already in the collection. If
+    /// bag semantics, the item will always be added.
+    /// </summary>
+    /// <param name="item">The item to add.</param>
+    /// <returns>True if item was added.</returns>
+    new bool Add(T item);
+
+    /// <summary>
+    /// Copy the items of this collection to a contiguous part of an array.
+    /// </summary>
+    /// <param name="array">The array to copy to</param>
+    /// <param name="index">The index at which to copy the first item</param>
+    new void CopyTo(T[] array, int index);
+
+    /// <summary>
+    /// The unordered collection hashcode is defined as the sum of 
+    /// <code>h(hashcode(item))</code> over the items
+    /// of the collection, where the function <code>h</code> is a function from 
+    /// int to int of the form <code> t -> (a0*t+b0)^(a1*t+b1)^(a2*t+b2)</code>, where 
+    /// the ax and bx are the same for all collection classes. 
+    /// <para>The current implementation uses fixed values for the ax and bx, 
+    /// specified as constants in the code.</para>
+    /// </summary>
+    /// <returns>The unordered hashcode of this collection.</returns>
+    int GetUnsequencedHashCode();
+
+
+    /// <summary>
+    /// Compare the contents of this collection to another one without regards to
+    /// the sequence order. The comparison will use this collection's itemequalityComparer
+    /// to compare individual items.
+    /// </summary>
+    /// <param name="otherCollection">The collection to compare to.</param>
+    /// <returns>True if this collection and that contains the same items.</returns>
+    bool UnsequencedEquals(ICollection<T> otherCollection);
+
+
+    /// <summary>
+    /// Check if this collection contains (an item equivalent to according to the
+    /// itemequalityComparer) a particular value.
+    /// </summary>
+    /// <param name="item">The value to check for.</param>
+    /// <returns>True if the items is in this collection.</returns>
+    new bool Contains(T item);
+
+
+    /// <summary>
+    /// Count the number of items of the collection equal to a particular value.
+    /// Returns 0 if and only if the value is not in the collection.
+    /// </summary>
+    /// <param name="item">The value to count.</param>
+    /// <returns>The number of copies found.</returns>
+    int ContainsCount(T item);
+
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    ICollectionValue<T> UniqueItems();
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities();
+
+    /// <summary>
+    /// Check whether this collection contains all the values in another collection.
+    /// If this collection has bag semantics (<code>AllowsDuplicates==true</code>)
+    /// the check is made with respect to multiplicities, else multiplicities
+    /// are not taken into account.
+    /// </summary>
+    /// <param name="items">The </param>
+    /// <typeparam name="U"></typeparam>
+    /// <returns>True if all values in <code>items</code>is in this collection.</returns>
+    bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T;
+
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, return in the ref argument (a
+    /// binary copy of) the actual value found.
+    /// </summary>
+    /// <param name="item">The value to look for.</param>
+    /// <returns>True if the items is in this collection.</returns>
+    bool Find(ref T item);
+
+
+    //This should probably just be bool Add(ref T item); !!!
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, return in the ref argument (a
+    /// binary copy of) the actual value found. Else, add the item to the collection.
+    /// </summary>
+    /// <param name="item">The value to look for.</param>
+    /// <returns>True if the item was found (hence not added).</returns>
+    bool FindOrAdd(ref T item);
+
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// with a (binary copy of) the supplied value. If the collection has bag semantics,
+    /// it depends on the value of DuplicatesByCounting if this updates all equivalent copies in
+    /// the collection or just one.
+    /// </summary>
+    /// <param name="item">Value to update.</param>
+    /// <returns>True if the item was found and hence updated.</returns>
+    bool Update(T item);
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// with a (binary copy of) the supplied value. If the collection has bag semantics,
+    /// it depends on the value of DuplicatesByCounting if this updates all equivalent copies in
+    /// the collection or just one.
+    /// </summary>
+    /// <param name="item">Value to update.</param>
+    /// <param name="olditem">On output the olditem, if found.</param>
+    /// <returns>True if the item was found and hence updated.</returns>
+    bool Update(T item, out T olditem);
+
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// to with a binary copy of the supplied value; else add the value to the collection. 
+    /// </summary>
+    /// <param name="item">Value to add or update.</param>
+    /// <returns>True if the item was found and updated (hence not added).</returns>
+    bool UpdateOrAdd(T item);
+
+
+    /// <summary>
+    /// Check if this collection contains an item equivalent according to the
+    /// itemequalityComparer to a particular value. If so, update the item in the collection 
+    /// to with a binary copy of the supplied value; else add the value to the collection. 
+    /// </summary>
+    /// <param name="item">Value to add or update.</param>
+    /// <param name="olditem">On output the olditem, if found.</param>
+    /// <returns>True if the item was found and updated (hence not added).</returns>
+    bool UpdateOrAdd(T item, out T olditem);
+
+    /// <summary>
+    /// Remove a particular item from this collection. If the collection has bag
+    /// semantics only one copy equivalent to the supplied item is removed. 
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    /// <returns>True if the item was found (and removed).</returns>
+    new bool Remove(T item);
+
+
+    /// <summary>
+    /// Remove a particular item from this collection if found. If the collection
+    /// has bag semantics only one copy equivalent to the supplied item is removed,
+    /// which one is implementation dependent. 
+    /// If an item was removed, report a binary copy of the actual item removed in 
+    /// the argument.
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    /// <param name="removeditem">The value removed if any.</param>
+    /// <returns>True if the item was found (and removed).</returns>
+    bool Remove(T item, out T removeditem);
+
+
+    /// <summary>
+    /// Remove all items equivalent to a given value.
+    /// </summary>
+    /// <param name="item">The value to remove.</param>
+    void RemoveAllCopies(T item);
+
+
+    /// <summary>
+    /// Remove all items in another collection from this one. If this collection
+    /// has bag semantics, take multiplicities into account.
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to remove.</param>
+    void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T;
+
+    //void RemoveAll(Fun<T, bool> predicate);
+
+    /// <summary>
+    /// Remove all items from this collection.
+    /// </summary>
+    new void Clear();
+
+
+    /// <summary>
+    /// Remove all items not in some other collection from this one. If this collection
+    /// has bag semantics, take multiplicities into account.
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items">The items to retain.</param>
+    void RetainAll<U>(SCG.IEnumerable<U> items) where U : T;
+
+    //void RetainAll(Fun<T, bool> predicate);
+    //IDictionary<T> UniqueItems()
+  }
+
+
+
+  /// <summary>
+  /// An editable collection maintaining a definite sequence order of the items.
+  ///
+  /// <i>Implementations of this interface must compute the hash code and 
+  /// equality exactly as prescribed in the method definitions in order to
+  /// be consistent with other collection classes implementing this interface.</i>
+  /// <i>This interface is usually implemented by explicit interface implementation,
+  /// not as ordinary virtual methods.</i>
+  /// </summary>
+  public interface ISequenced<T> : ICollection<T>, IDirectedCollectionValue<T>
+  {
+    /// <summary>
+    /// The hashcode is defined as <code>h(...h(h(h(x1),x2),x3),...,xn)</code> for
+    /// <code>h(a,b)=CONSTANT*a+b</code> and the x's the hash codes of the items of 
+    /// this collection.
+    /// </summary>
+    /// <returns>The sequence order hashcode of this collection.</returns>
+    int GetSequencedHashCode();
+
+
+    /// <summary>
+    /// Compare this sequenced collection to another one in sequence order.
+    /// </summary>
+    /// <param name="otherCollection">The sequenced collection to compare to.</param>
+    /// <returns>True if this collection and that contains equal (according to
+    /// this collection's itemequalityComparer) in the same sequence order.</returns>
+    bool SequencedEquals(ISequenced<T> otherCollection);
+  }
+
+
+
+  /// <summary>
+  /// A sequenced collection, where indices of items in the order are maintained
+  /// </summary>
+  public interface IIndexed<T> : ISequenced<T>
+  {
+    /// <summary>
+    /// </summary>
+    /// <exception cref="IndexOutOfRangeException"> if <code>index</code> is negative or
+    /// &gt;= the size of the collection.</exception>
+    /// <value>The <code>index</code>'th item of this list.</value>
+    /// <param name="index">the index to lookup</param>
+    T this[int index] { get;}
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    Speed IndexingSpeed { get;}
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ArgumentOutOfRangeException"></exception>
+    /// <value>The directed collection of items in a specific index interval.</value>
+    /// <param name="start">The low index of the interval (inclusive).</param>
+    /// <param name="count">The size of the range.</param>
+    IDirectedCollectionValue<T> this[int start, int count] { get;}
+
+
+    /// <summary>
+    /// Searches for an item in the list going forwards from the start. 
+    /// </summary>
+    /// <param name="item">Item to search for.</param>
+    /// <returns>Index of item from start. A negative number if item not found, 
+    /// namely the one's complement of the index at which the Add operation would put the item.</returns>
+    int IndexOf(T item);
+
+
+    /// <summary>
+    /// Searches for an item in the list going backwards from the end.
+    /// </summary>
+    /// <param name="item">Item to search for.</param>
+    /// <returns>Index of of item from the end. A negative number if item not found, 
+    /// namely the two-complement of the index at which the Add operation would put the item.</returns>
+    int LastIndexOf(T item);
+
+    /// <summary>
+    /// Check if there exists an item  that satisfies a
+    /// specific predicate in this collection and return the index of the first one.
+    /// </summary>
+    /// <param name="predicate">A delegate 
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
+    /// <returns>the index, if found, a negative value else</returns>
+    int FindIndex(Fun<T, bool> predicate);
+
+    /// <summary>
+    /// Check if there exists an item  that satisfies a
+    /// specific predicate in this collection and return the index of the last one.
+    /// </summary>
+    /// <param name="predicate">A delegate 
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
+    /// <returns>the index, if found, a negative value else</returns>
+    int FindLastIndex(Fun<T, bool> predicate);
+
+
+    /// <summary>
+    /// Remove the item at a specific position of the list.
+    /// </summary>
+    /// <exception cref="IndexOutOfRangeException"> if <code>index</code> is negative or
+    /// &gt;= the size of the collection.</exception>
+    /// <param name="index">The index of the item to remove.</param>
+    /// <returns>The removed item.</returns>
+    T RemoveAt(int index);
+
+
+    /// <summary>
+    /// Remove all items in an index interval.
+    /// </summary>
+    /// <exception cref="ArgumentOutOfRangeException"> if start or count 
+    /// is negative or start+count &gt; the size of the collection.</exception>
+    /// <param name="start">The index of the first item to remove.</param>
+    /// <param name="count">The number of items to remove.</param>
+    void RemoveInterval(int start, int count);
+  }
+
+  //TODO: decide if this should extend ICollection
+  /// <summary>
+  /// The interface describing the operations of a LIFO stack data structure.
+  /// </summary>
+  /// <typeparam name="T">The item type</typeparam>
+  public interface IStack<T> : IDirectedCollectionValue<T>
+  {
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    bool AllowsDuplicates { get;}
+    /// <summary>
+    /// Get the <code>index</code>'th element of the stack.  The bottom of the stack has index 0.
+    /// </summary>
+    /// <param name="index"></param>
+    /// <returns></returns>
+    T this[int index] { get;}
+    /// <summary>
+    /// Push an item to the top of the stack.
+    /// </summary>
+    /// <param name="item">The item</param>
+    void Push(T item);
+    /// <summary>
+    /// Pop the item at the top of the stack from the stack.
+    /// </summary>
+    /// <returns>The popped item.</returns>
+    T Pop();
+  }
+
+  /// <summary>
+  /// The interface describing the operations of a FIFO queue data structure.
+  /// </summary>
+  /// <typeparam name="T">The item type</typeparam>
+  public interface IQueue<T> : IDirectedCollectionValue<T>
+  {
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    bool AllowsDuplicates { get;}
+    /// <summary>
+    /// Get the <code>index</code>'th element of the queue.  The front of the queue has index 0.
+    /// </summary>
+    /// <param name="index"></param>
+    /// <returns></returns>
+    T this[int index] { get;}
+    /// <summary>
+    /// Enqueue an item at the back of the queue. 
+    /// </summary>
+    /// <param name="item">The item</param>
+    void Enqueue(T item);
+    /// <summary>
+    /// Dequeue an item from the front of the queue.
+    /// </summary>
+    /// <returns>The item</returns>
+    T Dequeue();
+  }
+
+
+  /// <summary>
+  /// This is an indexed collection, where the item order is chosen by 
+  /// the user at insertion time.
+  ///
+  /// NBNBNB: we need a description of the view functionality here!
+  /// </summary>
+  public interface IList<T> : IIndexed<T>, IDisposable, SCG.IList<T>, System.Collections.IList
+  {
+    /// <summary>
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+    /// <value>The first item in this list.</value>
+    T First { get;}
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if this list is empty.</exception>
+    /// <value>The last item in this list.</value>
+    T Last { get;}
+
+    /// <summary>
+    /// Since <code>Add(T item)</code> always add at the end of the list,
+    /// this describes if list has FIFO or LIFO semantics.
+    /// </summary>
+    /// <value>True if the <code>Remove()</code> operation removes from the
+    /// start of the list, false if it removes from the end.</value>
+    bool FIFO { get; set;}
+
+    /// <summary>
+    /// 
+    /// </summary>
+    bool IsFixedSize { get; }
+
+    /// <summary>
+    /// On this list, this indexer is read/write.
+    /// </summary>
+    /// <exception cref="IndexOutOfRangeException"> if index is negative or
+    /// &gt;= the size of the collection.</exception>
+    /// <value>The index'th item of this list.</value>
+    /// <param name="index">The index of the item to fetch or store.</param>
+    new T this[int index] { get; set;}
+
+    #region Ambiguous calls when extending SCG.IList<T>
+
+    #region SCG.ICollection<T>
+    /// <summary>
+    /// 
+    /// </summary>
+    new int Count { get; }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    new bool IsReadOnly { get; }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    new bool Add(T item);
+
+    /// <summary>
+    /// 
+    /// </summary>
+    new void Clear();
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    new bool Contains(T item);
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="array"></param>
+    /// <param name="index"></param>
+    new void CopyTo(T[] array, int index);
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    new bool Remove(T item);
+
+    #endregion
+
+    #region SCG.IList<T> proper
+
+    /// <summary>
+    /// Searches for an item in the list going forwards from the start. 
+    /// </summary>
+    /// <param name="item">Item to search for.</param>
+    /// <returns>Index of item from start. A negative number if item not found, 
+    /// namely the one's complement of the index at which the Add operation would put the item.</returns>
+    new int IndexOf(T item);
+
+    /// <summary>
+    /// Remove the item at a specific position of the list.
+    /// </summary>
+    /// <exception cref="IndexOutOfRangeException"> if <code>index</code> is negative or
+    /// &gt;= the size of the collection.</exception>
+    /// <param name="index">The index of the item to remove.</param>
+    /// <returns>The removed item.</returns>
+    new T RemoveAt(int index);
+
+    #endregion
+
+    #endregion
+
+    /*/// <summary>
+    /// Insert an item at a specific index location in this list. 
+    /// </summary>
+    /// <exception cref="IndexOutOfRangeException"> if <code>index</code> is negative or
+    /// &gt; the size of the collection.</exception>
+    /// <exception cref="DuplicateNotAllowedException"> if the list has
+    /// <code>AllowsDuplicates==false</code> and the item is 
+    /// already in the list.</exception>
+    /// <param name="index">The index at which to insert.</param>
+    /// <param name="item">The item to insert.</param>
+    void Insert(int index, T item);*/
+
+    /// <summary>
+    /// Insert an item at the end of a compatible view, used as a pointer.
+    /// <para>The <code>pointer</code> must be a view on the same list as
+    /// <code>this</code> and the endpoitn of <code>pointer</code> must be
+    /// a valid insertion point of <code>this</code></para>
+    /// </summary>
+    /// <exception cref="IncompatibleViewException">If <code>pointer</code> 
+    /// is not a view on the same list as <code>this</code></exception>
+    /// <exception cref="IndexOutOfRangeException"><b>??????</b> if the endpoint of 
+    ///  <code>pointer</code> is not inside <code>this</code></exception>
+    /// <exception cref="DuplicateNotAllowedException"> if the list has
+    /// <code>AllowsDuplicates==false</code> and the item is 
+    /// already in the list.</exception>
+    /// <param name="pointer"></param>
+    /// <param name="item"></param>
+    void Insert(IList<T> pointer, T item);
+
+    /// <summary>
+    /// Insert an item at the front of this list.
+    /// <exception cref="DuplicateNotAllowedException"/> if the list has
+    /// <code>AllowsDuplicates==false</code> and the item is 
+    /// already in the list.
+    /// </summary>
+    /// <param name="item">The item to insert.</param>
+    void InsertFirst(T item);
+
+    /// <summary>
+    /// Insert an item at the back of this list.
+    /// <exception cref="DuplicateNotAllowedException"/> if the list has
+    /// <code>AllowsDuplicates==false</code> and the item is 
+    /// already in the list.
+    /// </summary>
+    /// <param name="item">The item to insert.</param>
+    void InsertLast(T item);
+
+    /// <summary>
+    /// Insert into this list all items from an enumerable collection starting 
+    /// at a particular index.
+    /// </summary>
+    /// <exception cref="IndexOutOfRangeException"> if <code>index</code> is negative or
+    /// &gt; the size of the collection.</exception>
+    /// <exception cref="DuplicateNotAllowedException"> if the list has 
+    /// <code>AllowsDuplicates==false</code> and one of the items to insert is
+    /// already in the list.</exception>
+    /// <param name="index">Index to start inserting at</param>
+    /// <param name="items">Items to insert</param>
+    /// <typeparam name="U"></typeparam>
+    void InsertAll<U>(int index, SCG.IEnumerable<U> items) where U : T;
+
+    /// <summary>
+    /// Create a new list consisting of the items of this list satisfying a 
+    /// certain predicate.
+    /// </summary>
+    /// <param name="filter">The filter delegate defining the predicate.</param>
+    /// <returns>The new list.</returns>
+    IList<T> FindAll(Fun<T, bool> filter);
+
+    /// <summary>
+    /// Create a new list consisting of the results of mapping all items of this
+    /// list. The new list will use the default equalityComparer for the item type V.
+    /// </summary>
+    /// <typeparam name="V">The type of items of the new list</typeparam>
+    /// <param name="mapper">The delegate defining the map.</param>
+    /// <returns>The new list.</returns>
+    IList<V> Map<V>(Fun<T, V> mapper);
+
+    /// <summary>
+    /// Create a new list consisting of the results of mapping all items of this
+    /// list. The new list will use a specified equalityComparer for the item type.
+    /// </summary>
+    /// <typeparam name="V">The type of items of the new list</typeparam>
+    /// <param name="mapper">The delegate defining the map.</param>
+    /// <param name="equalityComparer">The equalityComparer to use for the new list</param>
+    /// <returns>The new list.</returns>
+    IList<V> Map<V>(Fun<T, V> mapper, SCG.IEqualityComparer<V> equalityComparer);
+
+    /// <summary>
+    /// Remove one item from the list: from the front if <code>FIFO</code>
+    /// is true, else from the back.
+    /// <exception cref="NoSuchItemException"/> if this list is empty.
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    T Remove();
+
+    /// <summary>
+    /// Remove one item from the front of the list.
+    /// <exception cref="NoSuchItemException"/> if this list is empty.
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    T RemoveFirst();
+
+    /// <summary>
+    /// Remove one item from the back of the list.
+    /// <exception cref="NoSuchItemException"/> if this list is empty.
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    T RemoveLast();
+
+    /// <summary>
+    /// Create a list view on this list. 
+    /// <exception cref="ArgumentOutOfRangeException"/> if the view would not fit into
+    /// this list.
+    /// </summary>
+    /// <param name="start">The index in this list of the start of the view.</param>
+    /// <param name="count">The size of the view.</param>
+    /// <returns>The new list view.</returns>
+    IList<T> View(int start, int count);
+
+    /// <summary>
+    /// Create a list view on this list containing the (first) occurrence of a particular item. 
+    /// <exception cref="NoSuchItemException"/> if the item is not in this list.
+    /// </summary>
+    /// <param name="item">The item to find.</param>
+    /// <returns>The new list view.</returns>
+    IList<T> ViewOf(T item);
+
+    /// <summary>
+    /// Create a list view on this list containing the last occurrence of a particular item. 
+    /// <exception cref="NoSuchItemException"/> if the item is not in this list.
+    /// </summary>
+    /// <param name="item">The item to find.</param>
+    /// <returns>The new list view.</returns>
+    IList<T> LastViewOf(T item);
+
+    /// <summary>
+    /// Null if this list is not a view.
+    /// </summary>
+    /// <value>Underlying list for view.</value>
+    IList<T> Underlying { get;}
+
+    /// <summary>
+    /// </summary>
+    /// <value>Offset for this list view or 0 for an underlying list.</value>
+    int Offset { get;}
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    bool IsValid { get;}
+
+    /// <summary>
+    /// Slide this list view along the underlying list.
+    /// </summary>
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>
+    /// <exception cref="ArgumentOutOfRangeException"> if the operation
+    /// would bring either end of the view outside the underlying list.</exception>
+    /// <param name="offset">The signed amount to slide: positive to slide
+    /// towards the end.</param>
+    IList<T> Slide(int offset);
+
+    /// <summary>
+    /// Slide this list view along the underlying list, changing its size.
+    /// 
+    /// </summary>
+    /// <exception cref="NotAViewException"> if this list is not a view.</exception>
+    /// <exception cref="ArgumentOutOfRangeException"> if the operation
+    /// would bring either end of the view outside the underlying list.</exception>
+    /// <param name="offset">The signed amount to slide: positive to slide
+    /// towards the end.</param>
+    /// <param name="size">The new size of the view.</param>
+    IList<T> Slide(int offset, int size);
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="offset"></param>
+    /// <returns></returns>
+    bool TrySlide(int offset);
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="offset"></param>
+    /// <param name="size"></param>
+    /// <returns></returns>
+    bool TrySlide(int offset, int size);
+
+    /// <summary>
+    /// 
+    /// <para>Returns null if <code>otherView</code> is strictly to the left of this view</para>
+    /// </summary>
+    /// <param name="otherView"></param>
+    /// <exception cref="IncompatibleViewException">If otherView does not have the same underlying list as this</exception>
+    /// <exception cref="ArgumentOutOfRangeException">If <code>otherView</code> is strictly to the left of this view</exception>
+    /// <returns></returns>
+    IList<T> Span(IList<T> otherView);
+
+    /// <summary>
+    /// Reverse the list so the items are in the opposite sequence order.
+    /// </summary>
+    void Reverse();
+
+    /// <summary>
+    /// Check if this list is sorted according to the default sorting order
+    /// for the item type T, as defined by the <see cref="T:C5.Comparer`1"/> class 
+    /// </summary>
+    /// <exception cref="NotComparableException">if T is not comparable</exception>
+    /// <returns>True if the list is sorted, else false.</returns>
+    bool IsSorted();
+
+    /// <summary>
+    /// Check if this list is sorted according to a specific sorting order.
+    /// </summary>
+    /// <param name="comparer">The comparer defining the sorting order.</param>
+    /// <returns>True if the list is sorted, else false.</returns>
+    bool IsSorted(SCG.IComparer<T> comparer);
+
+    /// <summary>
+    /// Sort the items of the list according to the default sorting order
+    /// for the item type T, as defined by the <see cref="T:C5.Comparer`1"/> class 
+    /// </summary>
+    /// <exception cref="NotComparableException">if T is not comparable</exception>
+    void Sort();
+
+    /// <summary>
+    /// Sort the items of the list according to a specified sorting order.
+    /// <para>The sorting does not perform duplicate elimination or identify items
+    /// according to the comparer or itemequalityComparer. I.e. the list as an 
+    /// unsequenced collection with binary equality, will not change.
+    /// </para>
+    /// </summary>
+    /// <param name="comparer">The comparer defining the sorting order.</param>
+    void Sort(SCG.IComparer<T> comparer);
+
+
+    /// <summary>
+    /// Randomly shuffle the items of this list. 
+    /// </summary>
+    void Shuffle();
+
+
+    /// <summary>
+    /// Shuffle the items of this list according to a specific random source.
+    /// </summary>
+    /// <param name="rnd">The random source.</param>
+    void Shuffle(Random rnd);
+  }
+
+
+  /// <summary>
+  /// The base type of a priority queue handle
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  public interface IPriorityQueueHandle<T>
+  {
+    //TODO: make abstract and prepare for double dispatch:
+    //public virtual bool Delete(IPriorityQueue<T> q) { throw new InvalidFooException();}
+    //bool Replace(T item);
+  }
+
+
+  /// <summary>
+  /// A generic collection of items prioritized by a comparison (order) relation.
+  /// Supports adding items and reporting or removing extremal elements. 
+  /// <para>
+  /// 
+  /// </para>
+  /// When adding an item, the user may choose to have a handle allocated for this item in the queue. 
+  /// The resulting handle may be used for deleting the item even if not extremal, and for replacing the item.
+  /// A priority queue typically only holds numeric priorities associated with some objects
+  /// maintained separately in other collection objects.
+  /// </summary>
+  public interface IPriorityQueue<T> : IExtensible<T>
+  {
+    /// <summary>
+    /// Find the current least item of this priority queue.
+    /// </summary>
+    /// <returns>The least item.</returns>
+    T FindMin();
+
+
+    /// <summary>
+    /// Remove the least item from this  priority queue.
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    T DeleteMin();
+
+
+    /// <summary>
+    /// Find the current largest item of this priority queue.
+    /// </summary>
+    /// <returns>The largest item.</returns>
+    T FindMax();
+
+
+    /// <summary>
+    /// Remove the largest item from this priority queue.
+    /// </summary>
+    /// <returns>The removed item.</returns>
+    T DeleteMax();
+
+    /// <summary>
+    /// The comparer object supplied at creation time for this collection
+    /// </summary>
+    /// <value>The comparer</value>
+    SCG.IComparer<T> Comparer { get;}
+    /// <summary>
+    /// Get or set the item corresponding to a handle. Throws exceptions on 
+    /// invalid handles.
+    /// </summary>
+    /// <param name="handle"></param>
+    /// <returns></returns>
+    T this[IPriorityQueueHandle<T> handle] { get; set;}
+
+    /// <summary>
+    /// Check if the entry corresponding to a handle is in the priority queue.
+    /// </summary>
+    /// <param name="handle"></param>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    bool Find(IPriorityQueueHandle<T> handle, out T item);
+
+    /// <summary>
+    /// Add an item to the priority queue, receiving a 
+    /// handle for the item in the queue, 
+    /// or reusing an existing unused handle.
+    /// </summary>
+    /// <param name="handle">On output: a handle for the added item. 
+    /// On input: null for allocating a new handle, or a currently unused handle for reuse. 
+    /// A handle for reuse must be compatible with this priority queue, 
+    /// by being created by a priority queue of the same runtime type, but not 
+    /// necessarily the same priority queue object.</param>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    bool Add(ref IPriorityQueueHandle<T> handle, T item);
+
+    /// <summary>
+    /// Delete an item with a handle from a priority queue
+    /// </summary>
+    /// <param name="handle">The handle for the item. The handle will be invalidated, but reusable.</param>
+    /// <returns>The deleted item</returns>
+    T Delete(IPriorityQueueHandle<T> handle);
+
+    /// <summary>
+    /// Replace an item with a handle in a priority queue with a new item. 
+    /// Typically used for changing the priority of some queued object.
+    /// </summary>
+    /// <param name="handle">The handle for the old item</param>
+    /// <param name="item">The new item</param>
+    /// <returns>The old item</returns>
+    T Replace(IPriorityQueueHandle<T> handle, T item);
+
+    /// <summary>
+    /// Find the current least item of this priority queue.
+    /// </summary>
+    /// <param name="handle">On return: the handle of the item.</param>
+    /// <returns>The least item.</returns>
+    T FindMin(out IPriorityQueueHandle<T> handle);
+
+    /// <summary>
+    /// Find the current largest item of this priority queue.
+    /// </summary>
+    /// <param name="handle">On return: the handle of the item.</param>
+    /// <returns>The largest item.</returns>
+
+    T FindMax(out IPriorityQueueHandle<T> handle);
+
+    /// <summary>
+    /// Remove the least item from this  priority queue.
+    /// </summary>
+    /// <param name="handle">On return: the handle of the removed item.</param>
+    /// <returns>The removed item.</returns>
+
+    T DeleteMin(out IPriorityQueueHandle<T> handle);
+
+    /// <summary>
+    /// Remove the largest item from this  priority queue.
+    /// </summary>
+    /// <param name="handle">On return: the handle of the removed item.</param>
+    /// <returns>The removed item.</returns>
+    T DeleteMax(out IPriorityQueueHandle<T> handle);
+  }
+
+
+
+  /// <summary>
+  /// A sorted collection, i.e. a collection where items are maintained and can be searched for in sorted order.
+  /// Thus the sequence order is given as a sorting order.
+  /// 
+  /// <para>The sorting order is defined by a comparer, an object of type IComparer&lt;T&gt; 
+  /// (<see cref="T:C5.IComparer`1"/>). Implementors of this interface will normally let the user 
+  /// define the comparer as an argument to a constructor. 
+  /// Usually there will also be constructors without a comparer argument, in which case the 
+  /// comparer should be the defalt comparer for the item type, <see cref="P:C5.Comparer`1.Default"/>.</para>
+  /// 
+  /// <para>The comparer of the sorted collection is available as the <code>Comparer</code> property 
+  /// (<see cref="P:C5.ISorted`1.Comparer"/>).</para>
+  /// 
+  /// <para>The methods are grouped according to
+  /// <list>
+  /// <item>Extrema: report or report and delete an extremal item. This is reminiscent of simplified priority queues.</item>
+  /// <item>Nearest neighbor: report predecessor or successor in the collection of an item. Cut belongs to this group.</item>
+  /// <item>Range: report a view of a range of elements or remove all elements in a range.</item>
+  /// <item>AddSorted: add a collection of items known to be sorted in the same order (should be faster) (to be removed?)</item>
+  /// </list>
+  /// </para>
+  /// 
+  /// <para>Since this interface extends ISequenced&lt;T&gt;, sorted collections will also have an 
+  /// item equalityComparer (<see cref="P:C5.IExtensible`1.EqualityComparer"/>). This equalityComparer will not be used in connection with 
+  /// the inner workings of the sorted collection, but will be used if the sorted collection is used as 
+  /// an item in a collection of unsequenced or sequenced collections, 
+  /// (<see cref="T:C5.ICollection`1"/> and <see cref="T:C5.ISequenced`1"/>)</para>
+  /// 
+  /// <para>Note that code may check if two sorted collections has the same sorting order 
+  /// by checking if the Comparer properties are equal. This is done a few places in this library
+  /// for optimization purposes.</para>
+  /// </summary>
+  public interface ISorted<T> : ISequenced<T>
+  {
+    /// <summary>
+    /// Find the current least item of this sorted collection.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if the collection is empty.</exception>
+    /// <returns>The least item.</returns>
+    T FindMin();
+
+
+    /// <summary>
+    /// Remove the least item from this sorted collection.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if the collection is empty.</exception>
+    /// <returns>The removed item.</returns>
+    T DeleteMin();
+
+
+    /// <summary>
+    /// Find the current largest item of this sorted collection.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if the collection is empty.</exception>
+    /// <returns>The largest item.</returns>
+    T FindMax();
+
+
+    /// <summary>
+    /// Remove the largest item from this sorted collection.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if the collection is empty.</exception>
+    /// <returns>The removed item.</returns>
+    T DeleteMax();
+
+    /// <summary>
+    /// The comparer object supplied at creation time for this sorted collection.
+    /// </summary>
+    /// <value>The comparer</value>
+    SCG.IComparer<T> Comparer { get; }
+
+    /// <summary>
+    /// Find the strict predecessor of item in the sorted collection,
+    /// that is, the greatest item in the collection smaller than the item.
+    /// </summary>
+    /// <param name="item">The item to find the predecessor for.</param>
+    /// <param name="res">The predecessor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a predecessor; otherwise false.</returns>
+    bool TryPredecessor(T item, out T res);
+
+
+    /// <summary>
+    /// Find the strict successor of item in the sorted collection,
+    /// that is, the least item in the collection greater than the supplied value.
+    /// </summary>
+    /// <param name="item">The item to find the successor for.</param>
+    /// <param name="res">The successor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a successor; otherwise false.</returns>
+    bool TrySuccessor(T item, out T res);
+
+
+    /// <summary>
+    /// Find the weak predecessor of item in the sorted collection,
+    /// that is, the greatest item in the collection smaller than or equal to the item.
+    /// </summary>
+    /// <param name="item">The item to find the weak predecessor for.</param>
+    /// <param name="res">The weak predecessor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a weak predecessor; otherwise false.</returns>
+    bool TryWeakPredecessor(T item, out T res);
+
+
+    /// <summary>
+    /// Find the weak successor of item in the sorted collection,
+    /// that is, the least item in the collection greater than or equal to the supplied value.
+    /// </summary>
+    /// <param name="item">The item to find the weak successor for.</param>
+    /// <param name="res">The weak successor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a weak successor; otherwise false.</returns>
+    bool TryWeakSuccessor(T item, out T res);
+
+
+    /// <summary>
+    /// Find the strict predecessor in the sorted collection of a particular value,
+    /// that is, the largest item in the collection less than the supplied value.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such element exists (the
+    /// supplied  value is less than or equal to the minimum of this collection.)</exception>
+    /// <param name="item">The item to find the predecessor for.</param>
+    /// <returns>The predecessor.</returns>
+    T Predecessor(T item);
+
+
+    /// <summary>
+    /// Find the strict successor in the sorted collection of a particular value,
+    /// that is, the least item in the collection greater than the supplied value.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such element exists (the
+    /// supplied  value is greater than or equal to the maximum of this collection.)</exception>
+    /// <param name="item">The item to find the successor for.</param>
+    /// <returns>The successor.</returns>
+    T Successor(T item);
+
+
+    /// <summary>
+    /// Find the weak predecessor in the sorted collection of a particular value,
+    /// that is, the largest item in the collection less than or equal to the supplied value.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such element exists (the
+    /// supplied  value is less than the minimum of this collection.)</exception>
+    /// <param name="item">The item to find the weak predecessor for.</param>
+    /// <returns>The weak predecessor.</returns>
+    T WeakPredecessor(T item);
+
+
+    /// <summary>
+    /// Find the weak successor in the sorted collection of a particular value,
+    /// that is, the least item in the collection greater than or equal to the supplied value.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such element exists (the
+    /// supplied  value is greater than the maximum of this collection.)</exception>
+    ///<param name="item">The item to find the weak successor for.</param>
+    /// <returns>The weak successor.</returns>
+    T WeakSuccessor(T item);
+
+
+    /// <summary>
+    /// Given a "cut" function from the items of the sorted collection to <code>int</code>
+    /// whose only sign changes when going through items in increasing order
+    /// can be 
+    /// <list>
+    /// <item>from positive to zero</item>
+    /// <item>from positive to negative</item>
+    /// <item>from zero to negative</item>
+    /// </list>
+    /// The "cut" function is supplied as the <code>CompareTo</code> method 
+    /// of an object <code>c</code> implementing 
+    /// <code>IComparable&lt;T&gt;</code>. 
+    /// A typical example is the case where <code>T</code> is comparable and 
+    /// <code>cutFunction</code> is itself of type <code>T</code>.
+    /// <para>This method performs a search in the sorted collection for the ranges in which the
+    /// "cut" function is negative, zero respectively positive. If <code>T</code> is comparable
+    /// and <code>c</code> is of type <code>T</code>, this is a safe way (no exceptions thrown) 
+    /// to find predecessor and successor of <code>c</code>.
+    /// </para>
+    /// <para> If the supplied cut function does not satisfy the sign-change condition, 
+    /// the result of this call is undefined.
+    /// </para>
+    /// 
+    /// </summary>
+    /// <param name="cutFunction">The cut function <code>T</code> to <code>int</code>, given
+    /// by the <code>CompareTo</code> method of an object implementing 
+    /// <code>IComparable&lt;T&gt;</code>.</param>
+    /// <param name="low">Returns the largest item in the collection, where the
+    /// cut function is positive (if any).</param>
+    /// <param name="lowIsValid">Returns true if the cut function is positive somewhere
+    /// on this collection.</param>
+    /// <param name="high">Returns the least item in the collection, where the
+    /// cut function is negative (if any).</param>
+    /// <param name="highIsValid">Returns true if the cut function is negative somewhere
+    /// on this collection.</param>
+    /// <returns>True if the cut function is zero somewhere
+    /// on this collection.</returns>
+    bool Cut(IComparable<T> cutFunction, out T low, out bool lowIsValid, out T high, out bool highIsValid);
+
+
+    /// <summary>
+    /// Query this sorted collection for items greater than or equal to a supplied value.
+    /// <para>The returned collection is not a copy but a view into the collection.</para>
+    /// <para>The view is fragile in the sense that changes to the underlying collection will 
+    /// invalidate the view so that further operations on the view throws InvalidView exceptions.</para>
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive).</param>
+    /// <returns>The result directed collection.</returns>
+    IDirectedEnumerable<T> RangeFrom(T bot);
+
+
+    /// <summary>
+    /// Query this sorted collection for items between two supplied values.
+    /// <para>The returned collection is not a copy but a view into the collection.</para>
+    /// <para>The view is fragile in the sense that changes to the underlying collection will 
+    /// invalidate the view so that further operations on the view throws InvalidView exceptions.</para>
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive).</param>
+    /// <param name="top">The upper bound (exclusive).</param>
+    /// <returns>The result directed collection.</returns>
+    IDirectedEnumerable<T> RangeFromTo(T bot, T top);
+
+
+    /// <summary>
+    /// Query this sorted collection for items less than a supplied value.
+    /// <para>The returned collection is not a copy but a view into the collection.</para>
+    /// <para>The view is fragile in the sense that changes to the underlying collection will 
+    /// invalidate the view so that further operations on the view throws InvalidView exceptions.</para>
+    /// </summary>
+    /// <param name="top">The upper bound (exclusive).</param>
+    /// <returns>The result directed collection.</returns>
+    IDirectedEnumerable<T> RangeTo(T top);
+
+
+    /// <summary>
+    /// Create a directed collection with the same items as this collection.
+    /// <para>The returned collection is not a copy but a view into the collection.</para>
+    /// <para>The view is fragile in the sense that changes to the underlying collection will 
+    /// invalidate the view so that further operations on the view throws InvalidView exceptions.</para>
+    /// </summary>
+    /// <returns>The result directed collection.</returns>
+    IDirectedCollectionValue<T> RangeAll();
+
+
+    //TODO: remove now that we assume that we can check the sorting order?
+    /// <summary>
+    /// Add all the items from another collection with an enumeration order that 
+    /// is increasing in the items.
+    /// </summary>
+    /// <exception cref="ArgumentException"> if the enumerated items turns out
+    /// not to be in increasing order.</exception>
+    /// <param name="items">The collection to add.</param>
+    /// <typeparam name="U"></typeparam>
+    void AddSorted<U>(SCG.IEnumerable<U> items) where U : T;
+
+
+    /// <summary>
+    /// Remove all items of this collection above or at a supplied threshold.
+    /// </summary>
+    /// <param name="low">The lower threshold (inclusive).</param>
+    void RemoveRangeFrom(T low);
+
+
+    /// <summary>
+    /// Remove all items of this collection between two supplied thresholds.
+    /// </summary>
+    /// <param name="low">The lower threshold (inclusive).</param>
+    /// <param name="hi">The upper threshold (exclusive).</param>
+    void RemoveRangeFromTo(T low, T hi);
+
+
+    /// <summary>
+    /// Remove all items of this collection below a supplied threshold.
+    /// </summary>
+    /// <param name="hi">The upper threshold (exclusive).</param>
+    void RemoveRangeTo(T hi);
+  }
+
+
+
+  /// <summary>
+  /// A collection where items are maintained in sorted order together
+  /// with their indexes in that order.
+  /// </summary>
+  public interface IIndexedSorted<T> : ISorted<T>, IIndexed<T>
+  {
+    /// <summary>
+    /// Determine the number of items at or above a supplied threshold.
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive)</param>
+    /// <returns>The number of matcing items.</returns>
+    int CountFrom(T bot);
+
+
+    /// <summary>
+    /// Determine the number of items between two supplied thresholds.
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive)</param>
+    /// <param name="top">The upper bound (exclusive)</param>
+    /// <returns>The number of matcing items.</returns>
+    int CountFromTo(T bot, T top);
+
+
+    /// <summary>
+    /// Determine the number of items below a supplied threshold.
+    /// </summary>
+    /// <param name="top">The upper bound (exclusive)</param>
+    /// <returns>The number of matcing items.</returns>
+    int CountTo(T top);
+
+
+    /// <summary>
+    /// Query this sorted collection for items greater than or equal to a supplied value.
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive).</param>
+    /// <returns>The result directed collection.</returns>
+    new IDirectedCollectionValue<T> RangeFrom(T bot);
+
+
+    /// <summary>
+    /// Query this sorted collection for items between two supplied values.
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive).</param>
+    /// <param name="top">The upper bound (exclusive).</param>
+    /// <returns>The result directed collection.</returns>
+    new IDirectedCollectionValue<T> RangeFromTo(T bot, T top);
+
+
+    /// <summary>
+    /// Query this sorted collection for items less than a supplied value.
+    /// </summary>
+    /// <param name="top">The upper bound (exclusive).</param>
+    /// <returns>The result directed collection.</returns>
+    new IDirectedCollectionValue<T> RangeTo(T top);
+
+
+    /// <summary>
+    /// Create a new indexed sorted collection consisting of the items of this
+    /// indexed sorted collection satisfying a certain predicate.
+    /// </summary>
+    /// <param name="predicate">The filter delegate defining the predicate.</param>
+    /// <returns>The new indexed sorted collection.</returns>
+    IIndexedSorted<T> FindAll(Fun<T, bool> predicate);
+
+
+    /// <summary>
+    /// Create a new indexed sorted collection consisting of the results of
+    /// mapping all items of this list.
+    /// <exception cref="ArgumentException"/> if the map is not increasing over 
+    /// the items of this collection (with respect to the two given comparison 
+    /// relations).
+    /// </summary>
+    /// <param name="mapper">The delegate definging the map.</param>
+    /// <param name="comparer">The comparion relation to use for the result.</param>
+    /// <returns>The new sorted collection.</returns>
+    IIndexedSorted<V> Map<V>(Fun<T, V> mapper, SCG.IComparer<V> comparer);
+  }
+
+
+
+  /// <summary>
+  /// The type of a sorted collection with persistence
+  /// </summary>
+  public interface IPersistentSorted<T> : ISorted<T>, IDisposable
+  {
+    /// <summary>
+    /// Make a (read-only) snap shot of this collection.
+    /// </summary>
+    /// <returns>The snap shot.</returns>
+    ISorted<T> Snapshot();
+  }
+
+
+
+  /*************************************************************************/
+  /// <summary>
+  /// A dictionary with keys of type K and values of type V. Equivalent to a
+  /// finite partial map from K to V.
+  /// </summary>
+  public interface IDictionary<K, V> : ICollectionValue<KeyValuePair<K, V>>, ICloneable
+  {
+    /// <summary>
+    /// The key equalityComparer.
+    /// </summary>
+    /// <value></value>
+    SCG.IEqualityComparer<K> EqualityComparer { get;}
+
+    /// <summary>
+    /// Indexer for dictionary.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no entry is found. </exception>
+    /// <value>The value corresponding to the key</value>
+    V this[K key] { get; set;}
+
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>True if dictionary is read-only</value>
+    bool IsReadOnly { get;}
+
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>A collection containg the all the keys of the dictionary</value>
+    ICollectionValue<K> Keys { get;}
+
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>A collection containing all the values of the dictionary</value>
+    ICollectionValue<V> Values { get;}
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>A delegate of type <see cref="T:C5.Fun`2"/> defining the partial function from K to V give by the dictionary.</value>
+    Fun<K, V> Fun { get; }
+
+
+    //TODO: resolve inconsistency: Add thows exception if key already there, AddAll ignores keys already There?
+    /// <summary>
+    /// Add a new (key, value) pair (a mapping) to the dictionary.
+    /// </summary>
+    /// <exception cref="DuplicateNotAllowedException"> if there already is an entry with the same key. </exception>>
+    /// <param name="key">Key to add</param>
+    /// <param name="val">Value to add</param>
+    void Add(K key, V val);
+
+    /// <summary>
+    /// Add the entries from a collection of <see cref="T:C5.KeyValuePair`2"/> pairs to this dictionary.
+    /// </summary>
+    /// <exception cref="DuplicateNotAllowedException"> 
+    /// If the input contains duplicate keys or a key already present in this dictionary.</exception>
+    /// <param name="entries"></param>
+    void AddAll<U, W>(SCG.IEnumerable<KeyValuePair<U, W>> entries)
+        where U : K
+        where W : V
+      ;
+
+    /// <summary>
+    /// The value is symbolic indicating the type of asymptotic complexity
+    /// in terms of the size of this collection (worst-case or amortized as
+    /// relevant). 
+    /// <para>See <see cref="T:C5.Speed"/> for the set of symbols.</para>
+    /// </summary>
+    /// <value>A characterization of the speed of lookup operations
+    /// (<code>Contains()</code> etc.) of the implementation of this dictionary.</value>
+    Speed ContainsSpeed { get;}
+
+    /// <summary>
+    /// Check whether this collection contains all the values in another collection.
+    /// If this collection has bag semantics (<code>AllowsDuplicates==true</code>)
+    /// the check is made with respect to multiplicities, else multiplicities
+    /// are not taken into account.
+    /// </summary>
+    /// <param name="items">The </param>
+    /// <returns>True if all values in <code>items</code>is in this collection.</returns>
+      bool ContainsAll<H>(SCG.IEnumerable<H> items) where H : K;
+
+    /// <summary>
+    /// Remove an entry with a given key from the dictionary
+    /// </summary>
+    /// <param name="key">The key of the entry to remove</param>
+    /// <returns>True if an entry was found (and removed)</returns>
+    bool Remove(K key);
+
+
+    /// <summary>
+    /// Remove an entry with a given key from the dictionary and report its value.
+    /// </summary>
+    /// <param name="key">The key of the entry to remove</param>
+    /// <param name="val">On exit, the value of the removed entry</param>
+    /// <returns>True if an entry was found (and removed)</returns>
+    bool Remove(K key, out V val);
+
+
+    /// <summary>
+    /// Remove all entries from the dictionary
+    /// </summary>
+    void Clear();
+
+
+    /// <summary>
+    /// Check if there is an entry with a specified key
+    /// </summary>
+    /// <param name="key">The key to look for</param>
+    /// <returns>True if key was found</returns>
+    bool Contains(K key);
+
+
+    /// <summary>
+    /// Check if there is an entry with a specified key and report the corresponding
+    /// value if found. This can be seen as a safe form of "val = this[key]".
+    /// </summary>
+    /// <param name="key">The key to look for</param>
+    /// <param name="val">On exit, the value of the entry</param>
+    /// <returns>True if key was found</returns>
+    bool Find(K key, out V val);
+
+    /// <summary>
+    /// Check if there is an entry with a specified key and report the corresponding
+    /// value if found. This can be seen as a safe form of "val = this[key]".
+    /// </summary>
+    /// <param name="key">The key to look for</param>
+    /// <param name="val">On exit, the value of the entry</param>
+    /// <returns>True if key was found</returns>
+    bool Find(ref K key, out V val);
+
+
+    /// <summary>
+    /// Look for a specific key in the dictionary and if found replace the value with a new one.
+    /// This can be seen as a non-adding version of "this[key] = val".
+    /// </summary>
+    /// <param name="key">The key to look for</param>
+    /// <param name="val">The new value</param>
+    /// <returns>True if key was found</returns>
+    bool Update(K key, V val);          //no-adding				    	
+
+
+    /// <summary>
+    /// Look for a specific key in the dictionary and if found replace the value with a new one.
+    /// This can be seen as a non-adding version of "this[key] = val" reporting the old value.
+    /// </summary>
+    /// <param name="key">The key to look for</param>
+    /// <param name="val">The new value</param>
+    /// <param name="oldval">The old value if any</param>
+    /// <returns>True if key was found</returns>
+    bool Update(K key, V val, out V oldval);          //no-adding				    	
+
+    /// <summary>
+    /// Look for a specific key in the dictionary. If found, report the corresponding value,
+    /// else add an entry with the key and the supplied value.
+    /// </summary>
+    /// <param name="key">The key to look for</param>
+    /// <param name="val">On entry the value to add if the key is not found.
+    /// On exit the value found if any.</param>
+    /// <returns>True if key was found</returns>
+    bool FindOrAdd(K key, ref V val);   //mixture
+
+
+    /// <summary>
+    /// Update value in dictionary corresponding to key if found, else add new entry.
+    /// More general than "this[key] = val;" by reporting if key was found.
+    /// </summary>
+    /// <param name="key">The key to look for</param>
+    /// <param name="val">The value to add or replace with.</param>
+    /// <returns>True if key was found and value updated.</returns>
+    bool UpdateOrAdd(K key, V val);
+
+
+    /// <summary>
+    /// Update value in dictionary corresponding to key if found, else add new entry.
+    /// More general than "this[key] = val;" by reporting if key was found.
+    /// </summary>
+    /// <param name="key">The key to look for</param>
+    /// <param name="val">The value to add or replace with.</param>
+    /// <param name="oldval">The old value if any</param>
+    /// <returns>True if key was found and value updated.</returns>
+    bool UpdateOrAdd(K key, V val, out V oldval);
+
+
+    /// <summary>
+    /// Check the integrity of the internal data structures of this dictionary.
+    /// Only avaliable in DEBUG builds???
+    /// </summary>
+    /// <returns>True if check does not fail.</returns>
+    bool Check();
+  }
+
+
+
+  /// <summary>
+  /// A dictionary with sorted keys.
+  /// </summary>
+  public interface ISortedDictionary<K, V> : IDictionary<K, V>
+  {
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    new ISorted<K> Keys { get;}
+
+    /// <summary>
+    /// Find the current least item of this sorted collection.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if the collection is empty.</exception>
+    /// <returns>The least item.</returns>
+    KeyValuePair<K, V> FindMin();
+
+
+    /// <summary>
+    /// Remove the least item from this sorted collection.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if the collection is empty.</exception>
+    /// <returns>The removed item.</returns>
+    KeyValuePair<K, V> DeleteMin();
+
+
+    /// <summary>
+    /// Find the current largest item of this sorted collection.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if the collection is empty.</exception>
+    /// <returns>The largest item.</returns>
+    KeyValuePair<K, V> FindMax();
+
+
+    /// <summary>
+    /// Remove the largest item from this sorted collection.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if the collection is empty.</exception>
+    /// <returns>The removed item.</returns>
+    KeyValuePair<K, V> DeleteMax();
+
+    /// <summary>
+    /// The key comparer used by this dictionary.
+    /// </summary>
+    /// <value></value>
+    SCG.IComparer<K> Comparer { get;}
+
+    /// <summary>
+    /// Find the entry in the dictionary whose key is the
+    /// predecessor of the specified key.
+    /// </summary>
+    /// <param name="key">The key</param>
+    /// <param name="res">The predecessor, if any</param>
+    /// <returns>True if key has a predecessor</returns>
+    bool TryPredecessor(K key, out KeyValuePair<K, V> res);
+
+    /// <summary>
+    /// Find the entry in the dictionary whose key is the
+    /// successor of the specified key.
+    /// </summary>
+    /// <param name="key">The key</param>
+    /// <param name="res">The successor, if any</param>
+    /// <returns>True if the key has a successor</returns>
+    bool TrySuccessor(K key, out KeyValuePair<K, V> res);
+
+    /// <summary>
+    /// Find the entry in the dictionary whose key is the
+    /// weak predecessor of the specified key.
+    /// </summary>
+    /// <param name="key">The key</param>
+    /// <param name="res">The predecessor, if any</param>
+    /// <returns>True if key has a weak predecessor</returns>
+    bool TryWeakPredecessor(K key, out KeyValuePair<K, V> res);
+
+    /// <summary>
+    /// Find the entry in the dictionary whose key is the
+    /// weak successor of the specified key.
+    /// </summary>
+    /// <param name="key">The key</param>
+    /// <param name="res">The weak successor, if any</param>
+    /// <returns>True if the key has a weak successor</returns>
+    bool TryWeakSuccessor(K key, out KeyValuePair<K, V> res);
+
+    /// <summary>
+    /// Find the entry with the largest key less than a given key.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if there is no such entry. </exception>
+    /// <param name="key">The key to compare to</param>
+    /// <returns>The entry</returns>
+    KeyValuePair<K, V> Predecessor(K key);
+
+
+    /// <summary>
+    /// Find the entry with the least key greater than a given key.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if there is no such entry. </exception>
+    /// <param name="key">The key to compare to</param>
+    /// <returns>The entry</returns>
+    KeyValuePair<K, V> Successor(K key);
+
+
+    /// <summary>
+    /// Find the entry with the largest key less than or equal to a given key.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if there is no such entry. </exception>
+    /// <param name="key">The key to compare to</param>
+    /// <returns>The entry</returns>
+    KeyValuePair<K, V> WeakPredecessor(K key);
+
+
+    /// <summary>
+    /// Find the entry with the least key greater than or equal to a given key.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if there is no such entry. </exception>
+    /// <param name="key">The key to compare to</param>
+    /// <returns>The entry</returns>
+    KeyValuePair<K, V> WeakSuccessor(K key);
+
+    /// <summary>
+    /// Given a "cut" function from the items of the sorted collection to <code>int</code>
+    /// whose only sign changes when going through items in increasing order
+    /// can be 
+    /// <list>
+    /// <item>from positive to zero</item>
+    /// <item>from positive to negative</item>
+    /// <item>from zero to negative</item>
+    /// </list>
+    /// The "cut" function is supplied as the <code>CompareTo</code> method 
+    /// of an object <code>c</code> implementing 
+    /// <code>IComparable&lt;K&gt;</code>. 
+    /// A typical example is the case where <code>K</code> is comparable and 
+    /// <code>c</code> is itself of type <code>K</code>.
+    /// <para>This method performs a search in the sorted collection for the ranges in which the
+    /// "cut" function is negative, zero respectively positive. If <code>K</code> is comparable
+    /// and <code>c</code> is of type <code>K</code>, this is a safe way (no exceptions thrown) 
+    /// to find predecessor and successor of <code>c</code>.
+    /// </para>
+    /// <para> If the supplied cut function does not satisfy the sign-change condition, 
+    /// the result of this call is undefined.
+    /// </para>
+    /// 
+    /// </summary>
+    /// <param name="cutFunction">The cut function <code>K</code> to <code>int</code>, given
+    /// by the <code>CompareTo</code> method of an object implementing 
+    /// <code>IComparable&lt;K&gt;</code>.</param>
+    /// <param name="lowEntry">Returns the largest item in the collection, where the
+    /// cut function is positive (if any).</param>
+    /// <param name="lowIsValid">Returns true if the cut function is positive somewhere
+    /// on this collection.</param>
+    /// <param name="highEntry">Returns the least item in the collection, where the
+    /// cut function is negative (if any).</param>
+    /// <param name="highIsValid">Returns true if the cut function is negative somewhere
+    /// on this collection.</param>
+    /// <returns>True if the cut function is zero somewhere
+    /// on this collection.</returns>
+    bool Cut(IComparable<K> cutFunction, out KeyValuePair<K, V> lowEntry, out bool lowIsValid, out KeyValuePair<K, V> highEntry, out bool highIsValid);
+
+    /// <summary>
+    /// Query this sorted collection for items greater than or equal to a supplied value.
+    /// <para>The returned collection is not a copy but a view into the collection.</para>
+    /// <para>The view is fragile in the sense that changes to the underlying collection will 
+    /// invalidate the view so that further operations on the view throws InvalidView exceptions.</para>
+    /// </summary>
+    /// <param name="bot">The lower bound (inclusive).</param>
+    /// <returns>The result directed collection.</returns>
+    IDirectedEnumerable<KeyValuePair<K, V>> RangeFrom(K bot);
+
+
+    /// <summary>
+    /// Query this sorted collection for items between two supplied values.
+    /// <para>The returned collection is not a copy but a view into the collection.</para>
+    /// <para>The view is fragile in the sense that changes to the underlying collection will 
+    /// invalidate the view so that further operations on the view throws InvalidView exceptions.</para>
+    /// </summary>
+    /// <param name="lowerBound">The lower bound (inclusive).</param>
+    /// <param name="upperBound">The upper bound (exclusive).</param>
+    /// <returns>The result directed collection.</returns>
+    IDirectedEnumerable<KeyValuePair<K, V>> RangeFromTo(K lowerBound, K upperBound);
+
+
+    /// <summary>
+    /// Query this sorted collection for items less than a supplied value.
+    /// <para>The returned collection is not a copy but a view into the collection.</para>
+    /// <para>The view is fragile in the sense that changes to the underlying collection will 
+    /// invalidate the view so that further operations on the view throws InvalidView exceptions.</para>
+    /// </summary>
+    /// <param name="top">The upper bound (exclusive).</param>
+    /// <returns>The result directed collection.</returns>
+    IDirectedEnumerable<KeyValuePair<K, V>> RangeTo(K top);
+
+
+    /// <summary>
+    /// Create a directed collection with the same items as this collection.
+    /// <para>The returned collection is not a copy but a view into the collection.</para>
+    /// <para>The view is fragile in the sense that changes to the underlying collection will 
+    /// invalidate the view so that further operations on the view throws InvalidView exceptions.</para>
+    /// </summary>
+    /// <returns>The result directed collection.</returns>
+    IDirectedCollectionValue<KeyValuePair<K, V>> RangeAll();
+
+
+    //TODO: remove now that we assume that we can check the sorting order?
+    /// <summary>
+    /// Add all the items from another collection with an enumeration order that 
+    /// is increasing in the items.
+    /// </summary>
+    /// <exception cref="ArgumentException"> if the enumerated items turns out
+    /// not to be in increasing order.</exception>
+    /// <param name="items">The collection to add.</param>
+    void AddSorted(SCG.IEnumerable<KeyValuePair<K, V>> items);
+
+
+    /// <summary>
+    /// Remove all items of this collection above or at a supplied threshold.
+    /// </summary>
+    /// <param name="low">The lower threshold (inclusive).</param>
+    void RemoveRangeFrom(K low);
+
+
+    /// <summary>
+    /// Remove all items of this collection between two supplied thresholds.
+    /// </summary>
+    /// <param name="low">The lower threshold (inclusive).</param>
+    /// <param name="hi">The upper threshold (exclusive).</param>
+    void RemoveRangeFromTo(K low, K hi);
+
+
+    /// <summary>
+    /// Remove all items of this collection below a supplied threshold.
+    /// </summary>
+    /// <param name="hi">The upper threshold (exclusive).</param>
+    void RemoveRangeTo(K hi);
+  }
+
+
+
+  /*******************************************************************/
+  /*/// <summary>
+  /// The type of an item comparer
+  /// <i>Implementations of this interface must asure that the method is self-consistent
+  /// and defines a sorting order on items, or state precise conditions under which this is true.</i>
+  /// <i>Implementations <b>must</b> assure that repeated calls of
+  /// the method to the same (in reference or binary identity sense) arguments 
+  /// will return values with the same sign (-1, 0 or +1), or state precise conditions
+  /// under which the user 
+  /// can be assured repeated calls will return the same sign.</i>
+  /// <i>Implementations of this interface must always return values from the method
+  /// and never throw exceptions.</i>
+  /// <i>This interface is identical to System.Collections.Generic.IComparer&lt;T&gt;</i>
+  /// </summary>
+  public interface IComparer<T>
+  {
+    /// <summary>
+    /// Compare two items with respect to this item comparer
+    /// </summary>
+    /// <param name="item1">First item</param>
+    /// <param name="item2">Second item</param>
+    /// <returns>Positive if item1 is greater than item2, 0 if they are equal, negative if item1 is less than item2</returns>
+    int Compare(T item1, T item2);
+  }
+
+  /// <summary>
+  /// The type of an item equalityComparer. 
+  /// <i>Implementations of this interface <b>must</b> assure that the methods are 
+  /// consistent, that is, that whenever two items i1 and i2 satisfies that Equals(i1,i2)
+  /// returns true, then GetHashCode returns the same value for i1 and i2.</i>
+  /// <i>Implementations of this interface <b>must</b> assure that repeated calls of
+  /// the methods to the same (in reference or binary identity sense) arguments 
+  /// will return the same values, or state precise conditions under which the user 
+  /// can be assured repeated calls will return the same values.</i>
+  /// <i>Implementations of this interface must always return values from the methods
+  /// and never throw exceptions.</i>
+  /// <i>This interface is similar in function to System.IKeyComparer&lt;T&gt;</i>
+  /// </summary>
+  public interface SCG.IEqualityComparer<T>
+  {
+    /// <summary>
+    /// Get the hash code with respect to this item equalityComparer
+    /// </summary>
+    /// <param name="item">The item</param>
+    /// <returns>The hash code</returns>
+    int GetHashCode(T item);
+
+
+    /// <summary>
+    /// Check if two items are equal with respect to this item equalityComparer
+    /// </summary>
+    /// <param name="item1">first item</param>
+    /// <param name="item2">second item</param>
+    /// <returns>True if equal</returns>
+    bool Equals(T item1, T item2);
+  }*/
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/MappedEnumerators.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/MappedEnumerators.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/MappedEnumerators.cs	(revision 3)
@@ -0,0 +1,145 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+namespace C5
+{
+  abstract class MappedDirectedCollectionValue<T, V> : DirectedCollectionValueBase<V>, IDirectedCollectionValue<V>
+  {
+    IDirectedCollectionValue<T> directedcollectionvalue;
+
+    abstract public V Map(T item);
+
+    public MappedDirectedCollectionValue(IDirectedCollectionValue<T> directedcollectionvalue)
+    {
+      this.directedcollectionvalue = directedcollectionvalue;
+    }
+
+    public override V Choose() { return Map(directedcollectionvalue.Choose()); }
+
+    public override bool IsEmpty { get { return directedcollectionvalue.IsEmpty; } }
+
+    public override int Count { get { return directedcollectionvalue.Count; } }
+
+    public override Speed CountSpeed { get { return directedcollectionvalue.CountSpeed; } }
+
+    public override IDirectedCollectionValue<V> Backwards()
+    {
+      MappedDirectedCollectionValue<T, V> retval = (MappedDirectedCollectionValue<T, V>)MemberwiseClone();
+      retval.directedcollectionvalue = directedcollectionvalue.Backwards();
+      return retval;
+      //If we made this classs non-abstract we could do
+      //return new MappedDirectedCollectionValue<T,V>(directedcollectionvalue.Backwards());;
+    }
+
+
+    public override SCG.IEnumerator<V> GetEnumerator()
+    {
+      foreach (T item in directedcollectionvalue)
+        yield return Map(item);
+    }
+
+    public override EnumerationDirection Direction
+    {
+      get { return directedcollectionvalue.Direction; }
+    }
+
+    IDirectedEnumerable<V> IDirectedEnumerable<V>.Backwards()
+    {
+      return Backwards();
+    }
+
+
+  }
+
+  abstract class MappedCollectionValue<T, V> : CollectionValueBase<V>, ICollectionValue<V>
+  {
+    ICollectionValue<T> collectionvalue;
+
+    abstract public V Map(T item);
+
+    public MappedCollectionValue(ICollectionValue<T> collectionvalue)
+    {
+      this.collectionvalue = collectionvalue;
+    }
+
+    public override V Choose() { return Map(collectionvalue.Choose()); }
+
+    public override bool IsEmpty { get { return collectionvalue.IsEmpty; } }
+
+    public override int Count { get { return collectionvalue.Count; } }
+
+    public override Speed CountSpeed { get { return collectionvalue.CountSpeed; } }
+
+    public override SCG.IEnumerator<V> GetEnumerator()
+    {
+      foreach (T item in collectionvalue)
+        yield return Map(item);
+    }
+  }
+  
+  class MultiplicityOne<K> : MappedCollectionValue<K, KeyValuePair<K, int>>
+  {
+    public MultiplicityOne(ICollectionValue<K> coll):base(coll) { }
+    public override KeyValuePair<K, int> Map(K k) { return new KeyValuePair<K, int>(k, 1); }
+  }
+
+  class DropMultiplicity<K> : MappedCollectionValue<KeyValuePair<K, int>, K>
+  {
+    public DropMultiplicity(ICollectionValue<KeyValuePair<K, int>> coll):base(coll) { }
+    public override K Map(KeyValuePair<K, int> kvp) { return kvp.Key; }
+  }
+  
+  abstract class MappedDirectedEnumerable<T, V> : EnumerableBase<V>, IDirectedEnumerable<V>
+  {
+    IDirectedEnumerable<T> directedenumerable;
+
+    abstract public V Map(T item);
+
+    public MappedDirectedEnumerable(IDirectedEnumerable<T> directedenumerable)
+    {
+      this.directedenumerable = directedenumerable;
+    }
+
+    public IDirectedEnumerable<V> Backwards()
+    {
+      MappedDirectedEnumerable<T, V> retval = (MappedDirectedEnumerable<T, V>)MemberwiseClone();
+      retval.directedenumerable = directedenumerable.Backwards();
+      return retval;
+      //If we made this classs non-abstract we could do
+      //return new MappedDirectedCollectionValue<T,V>(directedcollectionvalue.Backwards());;
+    }
+
+
+    public override SCG.IEnumerator<V> GetEnumerator()
+    {
+      foreach (T item in directedenumerable)
+        yield return Map(item);
+    }
+
+    public EnumerationDirection Direction
+    {
+      get { return directedenumerable.Direction; }
+    }
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Random.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Random.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Random.cs	(revision 3)
@@ -0,0 +1,173 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+namespace C5
+{
+  /// <summary>
+  /// A modern random number generator based on G. Marsaglia: 
+  /// Seeds for Random Number Generators, Communications of the
+  /// ACM 46, 5 (May 2003) 90-93; and a posting by Marsaglia to 
+  /// comp.lang.c on 2003-04-03.
+  /// </summary>
+  public class C5Random : Random
+  {
+    private uint[] Q = new uint[16];
+
+    private uint c = 362436, i = 15;
+
+
+    private uint Cmwc()
+    {
+      ulong t, a = 487198574UL;
+      uint x, r = 0xfffffffe;
+
+      i = (i + 1) & 15;
+      t = a * Q[i] + c;
+      c = (uint)(t >> 32);
+      x = (uint)(t + c);
+      if (x < c)
+      {
+        x++;
+        c++;
+      }
+
+      return Q[i] = r - x;
+    }
+
+
+    /// <summary>
+    /// Get a new random System.Double value
+    /// </summary>
+    /// <returns>The random double</returns>
+    public override double NextDouble()
+    {
+      return Cmwc() / 4294967296.0;
+    }
+
+
+    /// <summary>
+    /// Get a new random System.Double value
+    /// </summary>
+    /// <returns>The random double</returns>
+    protected override double Sample()
+    {
+      return NextDouble();
+    }
+
+
+    /// <summary>
+    /// Get a new random System.Int32 value
+    /// </summary>
+    /// <returns>The random int</returns>
+    public override int Next()
+    {
+      return (int)Cmwc();
+    }
+
+
+    /// <summary>
+    /// Get a random non-negative integer less than a given upper bound
+    /// </summary>
+    /// <exception cref="ArgumentException">If max is negative</exception>
+    /// <param name="max">The upper bound (exclusive)</param>
+    /// <returns></returns>
+    public override int Next(int max)
+    {
+      if (max < 0)
+        throw new ArgumentException("max must be non-negative");
+
+      return (int)(Cmwc() / 4294967296.0 * max);
+    }
+
+
+    /// <summary>
+    /// Get a random integer between two given bounds
+    /// </summary>
+    /// <exception cref="ArgumentException">If max is less than min</exception>
+    /// <param name="min">The lower bound (inclusive)</param>
+    /// <param name="max">The upper bound (exclusive)</param>
+    /// <returns></returns>
+    public override int Next(int min, int max)
+    {
+      if (min > max)
+        throw new ArgumentException("min must be less than or equal to max");
+
+      return min + (int)(Cmwc() / 4294967296.0 * (max - min));
+    }
+
+    /// <summary>
+    /// Fill a array of byte with random bytes
+    /// </summary>
+    /// <param name="buffer">The array to fill</param>
+    public override void NextBytes(byte[] buffer)
+    {
+      for (int i = 0, length = buffer.Length; i < length; i++)
+        buffer[i] = (byte)Cmwc();
+    }
+
+
+    /// <summary>
+    /// Create a random number generator seed by system time.
+    /// </summary>
+    public C5Random() : this(DateTime.Now.Ticks)
+    {
+    }
+
+
+    /// <summary>
+    /// Create a random number generator with a given seed
+    /// </summary>
+    /// <exception cref="ArgumentException">If seed is zero</exception>
+    /// <param name="seed">The seed</param>
+    public C5Random(long seed)
+    {
+      if (seed == 0)
+        throw new ArgumentException("Seed must be non-zero");
+
+      uint j = (uint)(seed & 0xFFFFFFFF);
+
+      for (int i = 0; i < 16; i++)
+      {
+        j ^= j << 13;
+        j ^= j >> 17;
+        j ^= j << 5;
+        Q[i] = j;
+      }
+
+      Q[15] = (uint)(seed ^ (seed >> 32));
+    }
+
+    /// <summary>
+    /// Create a random number generator with a specified internal start state.
+    /// </summary>
+    /// <exception cref="ArgumentException">If Q is not of length exactly 16</exception>
+    /// <param name="Q">The start state. Must be a collection of random bits given by an array of exactly 16 uints.</param>
+    [CLSCompliant(false)]
+    public C5Random(uint[] Q)
+    {
+      if (Q.Length != 16)
+        throw new ArgumentException("Q must have length 16, was " + Q.Length);
+      Array.Copy(Q, this.Q, 16);
+    }
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Records.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Records.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Records.cs	(revision 3)
@@ -0,0 +1,510 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using C5;
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Diagnostics;
+
+namespace C5
+{
+  struct RecConst
+  {
+    public const int HASHFACTOR = 387281;
+  }
+  /// <summary>
+  /// A generic record type with two fields. 
+  /// <para>
+  /// Equality is defined field by field, using the <code>Equals</code> method 
+  /// inherited from <code>System.Object</code> (i.e. using <see cref="T:C5.NaturalEqualityComparer`1"/>).
+  /// </para>
+  /// <para>
+  /// This type is similar to <see cref="T:C5.KeyValuePair`2"/>, but the latter
+  /// uses <see cref="P:C5.EqualityComparer`1.Default"/> to define field equality instead of <see cref="T:C5.NaturalEqualityComparer`1"/>.
+  /// </para>
+  /// </summary>
+  /// <typeparam name="T1"></typeparam>
+  /// <typeparam name="T2"></typeparam>
+  public struct Rec<T1, T2> : IEquatable<Rec<T1, T2>>, IShowable
+  {
+    /// <summary>
+    /// 
+    /// </summary>
+    public readonly T1 X1;
+    /// <summary>
+    /// 
+    /// </summary>
+    public readonly T2 X2;
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="x1"></param>
+    /// <param name="x2"></param>
+    [Tested]
+    public Rec(T1 x1, T2 x2)
+    {
+      this.X1 = x1; this.X2 = x2;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="other"></param>
+    /// <returns></returns>
+    [Tested]
+    public bool Equals(Rec<T1, T2> other)
+    {
+      return
+        (X1 == null ? other.X1 == null : X1.Equals(other.X1)) &&
+        (X2 == null ? other.X2 == null : X2.Equals(other.X2))
+        ;
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="obj"></param>
+    /// <returns></returns>
+    [Tested]
+    public override bool Equals(object obj)
+    {
+      return obj is Rec<T1, T2> ? Equals((Rec<T1, T2>)obj) : false;
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="record1"></param>
+    /// <param name="record2"></param>
+    /// <returns></returns>
+    [Tested]
+    public static bool operator ==(Rec<T1, T2> record1, Rec<T1, T2> record2)
+    {
+      return record1.Equals(record2);
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="record1"></param>
+    /// <param name="record2"></param>
+    /// <returns></returns>
+    [Tested]
+    public static bool operator !=(Rec<T1, T2> record1, Rec<T1, T2> record2)
+    {
+      return !record1.Equals(record2);
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    [Tested]
+    public override int GetHashCode()
+    {
+      //TODO: don't use 0 as hashcode for null, but something else!
+      int hashcode = X1 == null ? 0 : X1.GetHashCode();
+      hashcode = hashcode * RecConst.HASHFACTOR + (X2 == null ? 0 : X2.GetHashCode());
+      return hashcode;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override string ToString()
+    {
+      return String.Format("({0}, {1})", X1, X2);
+    }
+
+    #region IShowable Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="stringbuilder"></param>
+    /// <param name="rest"></param>
+    /// <param name="formatProvider"></param>
+    /// <returns></returns>
+    public bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
+    {
+      bool incomplete = true;
+      stringbuilder.Append("(");
+      rest -= 2;
+      try
+      {
+        if (incomplete = !Showing.Show(X1, stringbuilder, ref rest, formatProvider))
+          return false;
+        stringbuilder.Append(", ");
+        rest -= 2;
+        if (incomplete = !Showing.Show(X2, stringbuilder, ref rest, formatProvider))
+          return false;
+      }
+      finally
+      {
+        if (incomplete)
+        {
+          stringbuilder.Append("...");
+          rest -= 3;
+        }
+        stringbuilder.Append(")");
+      }
+      return true;
+    }
+    #endregion
+
+    #region IFormattable Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="format"></param>
+    /// <param name="formatProvider"></param>
+    /// <returns></returns>
+    public string ToString(string format, IFormatProvider formatProvider)
+    {
+      return Showing.ShowString(this, format, formatProvider);
+    }
+
+    #endregion
+  }
+  /// <summary>
+  /// 
+  /// </summary>
+  /// <typeparam name="T1"></typeparam>
+  /// <typeparam name="T2"></typeparam>
+  /// <typeparam name="T3"></typeparam>
+  public struct Rec<T1, T2, T3> : IEquatable<Rec<T1, T2, T3>>, IShowable
+  {
+    /// <summary>
+    /// 
+    /// </summary>
+    public readonly T1 X1;
+    /// <summary>
+    /// 
+    /// </summary>
+    public readonly T2 X2;
+    /// <summary>
+    /// 
+    /// </summary>
+    public readonly T3 X3;
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="x1"></param>
+    /// <param name="x2"></param>
+    /// <param name="x3"></param>
+    [Tested]
+    public Rec(T1 x1, T2 x2, T3 x3)
+    {
+      this.X1 = x1; this.X2 = x2; this.X3 = x3;
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="other"></param>
+    /// <returns></returns>
+    [Tested]
+    public bool Equals(Rec<T1, T2, T3> other)
+    {
+      return
+        (X1 == null ? other.X1 == null : X1.Equals(other.X1)) &&
+        (X2 == null ? other.X2 == null : X2.Equals(other.X2)) &&
+        (X3 == null ? other.X3 == null : X3.Equals(other.X3))
+        ;
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="obj"></param>
+    /// <returns></returns>
+    [Tested]
+    public override bool Equals(object obj)
+    {
+      return obj is Rec<T1, T2, T3> ? Equals((Rec<T1, T2, T3>)obj) : false;
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="record1"></param>
+    /// <param name="record2"></param>
+    /// <returns></returns>
+    [Tested]
+    public static bool operator ==(Rec<T1, T2, T3> record1, Rec<T1, T2, T3> record2)
+    {
+      return record1.Equals(record2);
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="record1"></param>
+    /// <param name="record2"></param>
+    /// <returns></returns>
+    [Tested]
+    public static bool operator !=(Rec<T1, T2, T3> record1, Rec<T1, T2, T3> record2)
+    {
+      return !record1.Equals(record2);
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    [Tested]
+    public override int GetHashCode()
+    {
+      //TODO: don't use 0 as hashcode for null, but something else!
+      int hashcode = X1 == null ? 0 : X1.GetHashCode();
+      hashcode = hashcode * RecConst.HASHFACTOR + (X2 == null ? 0 : X2.GetHashCode());
+      hashcode = hashcode * RecConst.HASHFACTOR + (X3 == null ? 0 : X3.GetHashCode());
+      return hashcode;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override string ToString()
+    {
+      return String.Format("({0}, {1}, {2})", X1, X2, X3);
+    }
+    #region IShowable Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="stringbuilder"></param>
+    /// <param name="rest"></param>
+    /// <param name="formatProvider"></param>
+    /// <returns></returns>
+    public bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
+    {
+      bool incomplete = true;
+      stringbuilder.Append("(");
+      rest -= 2;
+      try
+      {
+        if (incomplete = !Showing.Show(X1, stringbuilder, ref rest, formatProvider))
+          return false;
+        stringbuilder.Append(", ");
+        rest -= 2;
+        if (incomplete = !Showing.Show(X2, stringbuilder, ref rest, formatProvider))
+          return false;
+        stringbuilder.Append(", ");
+        rest -= 2;
+        if (incomplete = !Showing.Show(X3, stringbuilder, ref rest, formatProvider))
+          return false;
+      }
+      finally
+      {
+        if (incomplete)
+        {
+          stringbuilder.Append("...");
+          rest -= 3;
+        }
+        stringbuilder.Append(")");
+      }
+      return true;
+    }
+    #endregion
+
+    #region IFormattable Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="format"></param>
+    /// <param name="formatProvider"></param>
+    /// <returns></returns>
+    public string ToString(string format, IFormatProvider formatProvider)
+    {
+      return Showing.ShowString(this, format, formatProvider);
+    }
+
+    #endregion
+  }
+
+  /// <summary>
+  /// 
+  /// </summary>
+  /// <typeparam name="T1"></typeparam>
+  /// <typeparam name="T2"></typeparam>
+  /// <typeparam name="T3"></typeparam>
+  /// <typeparam name="T4"></typeparam>
+  public struct Rec<T1, T2, T3, T4> : IEquatable<Rec<T1, T2, T3, T4>>, IShowable
+  {
+    /// <summary>
+    /// 
+    /// </summary>
+    public readonly T1 X1;
+    /// <summary>
+    /// 
+    /// </summary>
+    public readonly T2 X2;
+    /// <summary>
+    /// 
+    /// </summary>
+    public readonly T3 X3;
+    /// <summary>
+    /// 
+    /// </summary>
+    public readonly T4 X4;
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="x1"></param>
+    /// <param name="x2"></param>
+    /// <param name="x3"></param>
+    /// <param name="x4"></param>
+    [Tested]
+    public Rec(T1 x1, T2 x2, T3 x3, T4 x4)
+    {
+      this.X1 = x1; this.X2 = x2; this.X3 = x3; this.X4 = x4;
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="other"></param>
+    /// <returns></returns>
+    [Tested]
+    public bool Equals(Rec<T1, T2, T3, T4> other)
+    {
+      return
+        (X1 == null ? other.X1 == null : X1.Equals(other.X1)) &&
+        (X2 == null ? other.X2 == null : X2.Equals(other.X2)) &&
+        (X3 == null ? other.X3 == null : X3.Equals(other.X3)) &&
+        (X4 == null ? other.X4 == null : X4.Equals(other.X4))
+        ;
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="obj"></param>
+    /// <returns></returns>
+    [Tested]
+    public override bool Equals(object obj)
+    {
+      return obj is Rec<T1, T2, T3, T4> ? Equals((Rec<T1, T2, T3, T4>)obj) : false;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="record1"></param>
+    /// <param name="record2"></param>
+    /// <returns></returns>
+    [Tested]
+    public static bool operator ==(Rec<T1, T2, T3, T4> record1, Rec<T1, T2, T3, T4> record2)
+    {
+      return record1.Equals(record2);
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="record1"></param>
+    /// <param name="record2"></param>
+    /// <returns></returns>
+    [Tested]
+    public static bool operator !=(Rec<T1, T2, T3, T4> record1, Rec<T1, T2, T3, T4> record2)
+    {
+      return !record1.Equals(record2);
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    [Tested]
+    public override int GetHashCode()
+    {
+      //TODO: don't use 0 as hashcode for null, but something else!
+      int hashcode = X1 == null ? 0 : X1.GetHashCode();
+      hashcode = hashcode * RecConst.HASHFACTOR + (X2 == null ? 0 : X2.GetHashCode());
+      hashcode = hashcode * RecConst.HASHFACTOR + (X3 == null ? 0 : X3.GetHashCode());
+      hashcode = hashcode * RecConst.HASHFACTOR + (X4 == null ? 0 : X4.GetHashCode());
+      return hashcode;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override string ToString()
+    {
+      return String.Format("({0}, {1}, {2}, {3})", X1, X2, X3, X4);
+    }
+    #region IShowable Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="stringbuilder"></param>
+    /// <param name="rest"></param>
+    /// <param name="formatProvider"></param>
+    /// <returns></returns>
+    public bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
+    {
+      bool incomplete = true;
+      stringbuilder.Append("(");
+      rest -= 2;
+      try
+      {
+        if (incomplete = !Showing.Show(X1, stringbuilder, ref rest, formatProvider))
+          return false;
+        stringbuilder.Append(", ");
+        rest -= 2;
+        if (incomplete = !Showing.Show(X2, stringbuilder, ref rest, formatProvider))
+          return false;
+        stringbuilder.Append(", ");
+        rest -= 2;
+        if (incomplete = !Showing.Show(X3, stringbuilder, ref rest, formatProvider))
+          return false;
+        stringbuilder.Append(", ");
+        rest -= 2;
+        if (incomplete = !Showing.Show(X4, stringbuilder, ref rest, formatProvider))
+          return false;
+      }
+      finally
+      {
+        if (incomplete)
+        {
+          stringbuilder.Append("...");
+          rest -= 3;
+        }
+        stringbuilder.Append(")");
+      }
+      return true;
+    }
+    #endregion
+
+    #region IFormattable Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="format"></param>
+    /// <param name="formatProvider"></param>
+    /// <returns></returns>
+    public string ToString(string format, IFormatProvider formatProvider)
+    {
+      return Showing.ShowString(this, format, formatProvider);
+    }
+
+    #endregion
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Sorting.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Sorting.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Sorting.cs	(revision 3)
@@ -0,0 +1,239 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+namespace C5
+{
+  /// <summary>
+  /// A utility class with functions for sorting arrays with respect to an IComparer&lt;T&gt;
+  /// </summary>
+  public class Sorting
+  {
+    Sorting() { }
+
+    /// <summary>
+    /// Sort part of array in place using IntroSort
+    /// </summary>
+    /// <exception cref="ArgumentOutOfRangeException">If the <code>start</code>
+    /// and <code>count</code> arguments does not describe a valid range.</exception>
+    /// <param name="array">Array to sort</param>
+    /// <param name="start">Index of first position to sort</param>
+    /// <param name="count">Number of elements to sort</param>
+    /// <param name="comparer">IComparer&lt;T&gt; to sort by</param>
+    [Tested]
+    public static void IntroSort<T>(T[] array, int start, int count, SCG.IComparer<T> comparer)
+    {
+      if (start < 0 || count < 0 || start + count > array.Length)
+        throw new ArgumentOutOfRangeException();
+      new Sorter<T>(array, comparer).IntroSort(start, start + count);
+    }
+
+    /// <summary>
+    /// Sort an array in place using IntroSort and default comparer
+    /// </summary>
+    /// <exception cref="NotComparableException">If T is not comparable</exception>
+    /// <param name="array">Array to sort</param>
+    [Tested]
+    public static void IntroSort<T>(T[] array)
+    {
+      new Sorter<T>(array, Comparer<T>.Default).IntroSort(0, array.Length);
+    }
+
+
+    /// <summary>
+    /// Sort part of array in place using Insertion Sort
+    /// </summary>
+    /// <exception cref="ArgumentOutOfRangeException">If the <code>start</code>
+    /// and <code>count</code> arguments does not describe a valid range.</exception>
+    /// <param name="array">Array to sort</param>
+    /// <param name="start">Index of first position to sort</param>
+    /// <param name="count">Number of elements to sort</param>
+    /// <param name="comparer">IComparer&lt;T&gt; to sort by</param>
+    [Tested]
+    public static void InsertionSort<T>(T[] array, int start, int count, SCG.IComparer<T> comparer)
+    {
+      if (start < 0 || count < 0 || start + count > array.Length)
+        throw new ArgumentOutOfRangeException();
+      new Sorter<T>(array, comparer).InsertionSort(start, start + count);
+    }
+
+
+    /// <summary>
+    /// Sort part of array in place using Heap Sort
+    /// </summary>
+    /// <exception cref="ArgumentOutOfRangeException">If the <code>start</code>
+    /// and <code>count</code> arguments does not describe a valid range.</exception>
+    /// <param name="array">Array to sort</param>
+    /// <param name="start">Index of first position to sort</param>
+    /// <param name="count">Number of elements to sort</param>
+    /// <param name="comparer">IComparer&lt;T&gt; to sort by</param>
+    [Tested]
+    public static void HeapSort<T>(T[] array, int start, int count, SCG.IComparer<T> comparer)
+    {
+      if (start < 0 || count < 0 || start + count > array.Length)
+        throw new ArgumentOutOfRangeException();
+      new Sorter<T>(array, comparer).HeapSort(start, start + count);
+    }
+
+
+    class Sorter<T>
+    {
+      T[] a;
+
+      SCG.IComparer<T> c;
+
+
+      internal Sorter(T[] a, SCG.IComparer<T> c) { this.a = a; this.c = c; }
+
+
+      internal void IntroSort(int f, int b)
+      {
+        if (b - f > 31)
+        {
+          int depth_limit = (int)Math.Floor(2.5 * Math.Log(b - f, 2));
+
+          introSort(f, b, depth_limit);
+        }
+        else
+          InsertionSort(f, b);
+      }
+
+
+      private void introSort(int f, int b, int depth_limit)
+      {
+        const int size_threshold = 14;//24;
+
+        if (depth_limit-- == 0)
+          HeapSort(f, b);
+        else if (b - f <= size_threshold)
+          InsertionSort(f, b);
+        else
+        {
+          int p = partition(f, b);
+
+          introSort(f, p, depth_limit);
+          introSort(p, b, depth_limit);
+        }
+      }
+
+
+      private int compare(T i1, T i2) { return c.Compare(i1, i2); }
+
+
+      private int partition(int f, int b)
+      {
+        int bot = f, mid = (b + f) / 2, top = b - 1;
+        T abot = a[bot], amid = a[mid], atop = a[top];
+
+        if (compare(abot, amid) < 0)
+        {
+          if (compare(atop, abot) < 0)//atop<abot<amid
+          { a[top] = amid; amid = a[mid] = abot; a[bot] = atop; }
+          else if (compare(atop, amid) < 0) //abot<=atop<amid
+          { a[top] = amid; amid = a[mid] = atop; }
+          //else abot<amid<=atop
+        }
+        else
+        {
+          if (compare(amid, atop) > 0) //atop<amid<=abot
+          { a[bot] = atop; a[top] = abot; }
+          else if (compare(abot, atop) > 0) //amid<=atop<abot
+          { a[bot] = amid; amid = a[mid] = atop; a[top] = abot; }
+          else //amid<=abot<=atop
+          { a[bot] = amid; amid = a[mid] = abot; }
+        }
+
+        int i = bot, j = top;
+
+        while (true)
+        {
+          while (compare(a[++i], amid) < 0) ;
+
+          while (compare(amid, a[--j]) < 0) ;
+
+          if (i < j)
+          {
+            T tmp = a[i]; a[i] = a[j]; a[j] = tmp;
+          }
+          else
+            return i;
+        }
+      }
+
+
+      internal void InsertionSort(int f, int b)
+      {
+        for (int j = f + 1; j < b; j++)
+        {
+          T key = a[j], other;
+          int i = j - 1;
+
+          if (c.Compare(other = a[i], key) > 0)
+          {
+            a[j] = other;
+            while (i > f && c.Compare(other = a[i - 1], key) > 0) { a[i--] = other; }
+
+            a[i] = key;
+          }
+        }
+      }
+
+
+      internal void HeapSort(int f, int b)
+      {
+        for (int i = (b + f) / 2; i >= f; i--) heapify(f, b, i);
+
+        for (int i = b - 1; i > f; i--)
+        {
+          T tmp = a[f]; a[f] = a[i]; a[i] = tmp;
+          heapify(f, i, f);
+        }
+      }
+
+
+      private void heapify(int f, int b, int i)
+      {
+        T pv = a[i], lv, rv, max = pv;
+        int j = i, maxpt = j;
+
+        while (true)
+        {
+          int l = 2 * j - f + 1, r = l + 1;
+
+          if (l < b && compare(lv = a[l], max) > 0) { maxpt = l; max = lv; }
+
+          if (r < b && compare(rv = a[r], max) > 0) { maxpt = r; max = rv; }
+
+          if (maxpt == j)
+            break;
+
+          a[j] = max;
+          max = pv;
+          j = maxpt;
+        }
+
+        if (j > i)
+          a[j] = pv;
+      }
+    }
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/ViewSupport.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/ViewSupport.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/ViewSupport.cs	(revision 3)
@@ -0,0 +1,101 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+
+namespace C5
+{
+  /// <summary>
+  /// Characterize the mutual position of some view B (other) relative to view A (this)
+  /// </summary>
+  enum MutualViewPosition
+  {
+    /// <summary>
+    /// B contains A(this)
+    /// </summary>
+    Contains,
+    /// <summary>
+    /// B is containd in A(this), but not vice versa
+    /// </summary>
+    ContainedIn,
+    /// <summary>
+    /// A and B does not overlap
+    /// </summary>
+    NonOverlapping,
+    /// <summary>
+    /// A and B overlap, but neither is contained in the other
+    /// </summary>
+    Overlapping
+  }
+
+  #region View List Nested class
+  /// <summary>
+  /// This class is shared between the linked list and array list implementations.
+  /// </summary>
+  /// <typeparam name="V"></typeparam>
+  [Serializable]
+  class WeakViewList<V> where V : class
+  {
+    Node start;
+    [Serializable]
+    internal class Node
+    {
+      internal WeakReference weakview; internal Node prev, next;
+      internal Node(V view) { weakview = new WeakReference(view); }
+    }
+    internal Node Add(V view)
+    {
+      Node newNode = new Node(view);
+      if (start != null) { start.prev = newNode; newNode.next = start; }
+      start = newNode;
+      return newNode;
+    }
+    internal void Remove(Node n)
+    {
+      if (n == start) { start = start.next; if (start != null) start.prev = null; }
+      else { n.prev.next = n.next; if (n.next != null) n.next.prev = n.prev; }
+    }
+    /// <summary>
+    /// Note that it is safe to call views.Remove(view.myWeakReference) if view
+    /// is the currently yielded object
+    /// </summary>
+    /// <returns></returns>
+    public SCG.IEnumerator<V> GetEnumerator()
+    {
+      Node n = start;
+      while (n != null)
+      {
+        //V view = n.weakview.Target as V; //This provokes a bug in the beta1 verifyer
+        object o = n.weakview.Target;
+        V view = o is V ? (V)o : null;
+        if (view == null)
+          Remove(n);
+        else
+          yield return view;
+        n = n.next;
+      }
+    }
+  }
+
+  #endregion
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/WrappedArray.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/WrappedArray.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/WrappedArray.cs	(revision 3)
@@ -0,0 +1,944 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Text;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+namespace C5
+{
+  /// <summary>
+  /// An advanced interface to operations on an array. The array is viewed as an 
+  /// <see cref="T:C5.IList`1"/> of fixed size, and so all operations that would change the
+  /// size of the array will be invalid (and throw <see cref="T:C5.FixedSizeCollectionException"/>
+  /// </summary>
+  /// <typeparam name="T"></typeparam>
+  public class WrappedArray<T> : IList<T>, SCG.IList<T>
+  {
+    class InnerList : ArrayList<T>
+    {
+      internal InnerList(T[] array) { this.array = array; size = array.Length; }
+    }
+    ArrayList<T> innerlist;
+    //TODO: remember a ref to the wrapped array in WrappedArray to save a little on indexing?
+    WrappedArray<T> underlying;
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="wrappedarray"></param>
+    public WrappedArray(T[] wrappedarray) { innerlist = new InnerList(wrappedarray); }
+
+    //for views
+    WrappedArray(ArrayList<T> arraylist, WrappedArray<T> underlying) { innerlist = arraylist; this.underlying = underlying; }
+
+    #region IList<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public T First { get { return innerlist.First; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public T Last { get { return innerlist.Last; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="index"></param>
+    /// <returns></returns>
+    public T this[int index]
+    {
+      get { return innerlist[index]; }
+      set { innerlist[index] = value; }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="filter"></param>
+    /// <returns></returns>
+    public IList<T> FindAll(Fun<T, bool> filter) { return innerlist.FindAll(filter); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <typeparam name="V"></typeparam>
+    /// <param name="mapper"></param>
+    /// <returns></returns>
+    public IList<V> Map<V>(Fun<T, V> mapper) { return innerlist.Map<V>(mapper); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <typeparam name="V"></typeparam>
+    /// <param name="mapper"></param>
+    /// <param name="equalityComparer"></param>
+    /// <returns></returns>
+    public IList<V> Map<V>(Fun<T, V> mapper, SCG.IEqualityComparer<V> equalityComparer) { return innerlist.Map<V>(mapper, equalityComparer); }
+
+    /// <summary>
+    /// ???? should we throw NotRelevantException
+    /// </summary>
+    /// <value></value>
+    public bool FIFO
+    {
+      get { throw new FixedSizeCollectionException(); }
+      set { throw new FixedSizeCollectionException(); }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public virtual bool IsFixedSize
+    {
+      get { return true; }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="index"></param>
+    /// <param name="item"></param>
+    public void Insert(int index, T item)
+    {
+      throw new FixedSizeCollectionException();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="pointer"></param>
+    /// <param name="item"></param>
+    public void Insert(IList<T> pointer, T item)
+    {
+      throw new FixedSizeCollectionException();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    public void InsertFirst(T item)
+    {
+      throw new FixedSizeCollectionException();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    public void InsertLast(T item)
+    {
+      throw new FixedSizeCollectionException();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="i"></param>
+    /// <param name="items"></param>
+    public void InsertAll<U>(int i, System.Collections.Generic.IEnumerable<U> items) where U : T
+    {
+      throw new FixedSizeCollectionException();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public T Remove()
+    {
+      throw new FixedSizeCollectionException();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public T RemoveFirst()
+    {
+      throw new FixedSizeCollectionException();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public T RemoveLast()
+    {
+      throw new FixedSizeCollectionException();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="start"></param>
+    /// <param name="count"></param>
+    /// <returns></returns>
+    public IList<T> View(int start, int count)
+    {
+      return new WrappedArray<T>((ArrayList<T>)innerlist.View(start, count), underlying ?? this);
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public IList<T> ViewOf(T item)
+    {
+      return new WrappedArray<T>((ArrayList<T>)innerlist.ViewOf(item), underlying ?? this);
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public IList<T> LastViewOf(T item)
+    {
+      return new WrappedArray<T>((ArrayList<T>)innerlist.LastViewOf(item), underlying ?? this);
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public IList<T> Underlying { get { return underlying; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public int Offset { get { return innerlist.Offset; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public bool IsValid { get { return innerlist.IsValid; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="offset"></param>
+    /// <returns></returns>
+    public IList<T> Slide(int offset) { return innerlist.Slide(offset); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="offset"></param>
+    /// <param name="size"></param>
+    /// <returns></returns>
+    public IList<T> Slide(int offset, int size) { return innerlist.Slide(offset, size); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="offset"></param>
+    /// <returns></returns>
+    public bool TrySlide(int offset) { return innerlist.TrySlide(offset); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="offset"></param>
+    /// <param name="size"></param>
+    /// <returns></returns>
+    public bool TrySlide(int offset, int size) { return innerlist.TrySlide(offset, size); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="otherView"></param>
+    /// <returns></returns>
+    public IList<T> Span(IList<T> otherView) { return innerlist.Span(((WrappedArray<T>)otherView).innerlist); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public void Reverse() { innerlist.Reverse(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public bool IsSorted() { return innerlist.IsSorted(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="comparer"></param>
+    /// <returns></returns>
+    public bool IsSorted(SCG.IComparer<T> comparer) { return innerlist.IsSorted(comparer); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public void Sort() { innerlist.Sort(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="comparer"></param>
+    public void Sort(SCG.IComparer<T> comparer) { innerlist.Sort(comparer); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public void Shuffle() { innerlist.Shuffle(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="rnd"></param>
+    public void Shuffle(Random rnd) { innerlist.Shuffle(rnd); }
+
+    #endregion
+
+    #region IIndexed<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public Speed IndexingSpeed { get { return Speed.Constant; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="start"></param>
+    /// <param name="count"></param>
+    /// <returns></returns>
+    public IDirectedCollectionValue<T> this[int start, int count] { get { return innerlist[start, count]; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public int IndexOf(T item) { return innerlist.IndexOf(item); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public int LastIndexOf(T item) { return innerlist.LastIndexOf(item); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="predicate"></param>
+    /// <returns></returns>
+    public int FindIndex(Fun<T, bool> predicate) { return innerlist.FindIndex(predicate); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="predicate"></param>
+    /// <returns></returns>
+    public int FindLastIndex(Fun<T, bool> predicate) { return innerlist.FindLastIndex(predicate); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="i"></param>
+    /// <returns></returns>
+    public T RemoveAt(int i) { throw new FixedSizeCollectionException(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="start"></param>
+    /// <param name="count"></param>
+    public void RemoveInterval(int start, int count) { throw new FixedSizeCollectionException(); }
+
+    #endregion
+
+    #region ISequenced<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public int GetSequencedHashCode() { return innerlist.GetSequencedHashCode(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="that"></param>
+    /// <returns></returns>
+    public bool SequencedEquals(ISequenced<T> that) { return innerlist.SequencedEquals(that); }
+
+    #endregion
+
+    #region ICollection<T> Members
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public Speed ContainsSpeed { get { return Speed.Linear; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public int GetUnsequencedHashCode() { return innerlist.GetUnsequencedHashCode(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="that"></param>
+    /// <returns></returns>
+    public bool UnsequencedEquals(ICollection<T> that) { return innerlist.UnsequencedEquals(that); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public bool Contains(T item) { return innerlist.Contains(item); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public int ContainsCount(T item) { return innerlist.ContainsCount(item); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public ICollectionValue<T> UniqueItems() { return innerlist.UniqueItems(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities() { return innerlist.ItemMultiplicities(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items"></param>
+    /// <returns></returns>
+    public bool ContainsAll<U>(System.Collections.Generic.IEnumerable<U> items) where U : T
+    { return innerlist.ContainsAll(items); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public bool Find(ref T item) { return innerlist.Find(ref item); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public bool FindOrAdd(ref T item) { throw new FixedSizeCollectionException(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public bool Update(T item) { throw new FixedSizeCollectionException(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public bool Update(T item, out T olditem) { throw new FixedSizeCollectionException(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public bool UpdateOrAdd(T item) { throw new FixedSizeCollectionException(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public bool UpdateOrAdd(T item, out T olditem) { throw new FixedSizeCollectionException(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public bool Remove(T item) { throw new FixedSizeCollectionException(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <param name="removeditem"></param>
+    /// <returns></returns>
+    public bool Remove(T item, out T removeditem) { throw new FixedSizeCollectionException(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    public void RemoveAllCopies(T item) { throw new FixedSizeCollectionException(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items"></param>
+    public void RemoveAll<U>(System.Collections.Generic.IEnumerable<U> items) where U : T { throw new FixedSizeCollectionException(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public void Clear() { throw new FixedSizeCollectionException(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items"></param>
+    public void RetainAll<U>(System.Collections.Generic.IEnumerable<U> items) where U : T { throw new FixedSizeCollectionException(); }
+
+    #endregion
+
+    #region IExtensible<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public bool IsReadOnly { get { return true; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public bool AllowsDuplicates
+    {
+      get { return true; }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public SCG.IEqualityComparer<T> EqualityComparer { get { return innerlist.EqualityComparer; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public bool DuplicatesByCounting
+    {
+      get { return false; }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public bool Add(T item)
+    {
+      throw new FixedSizeCollectionException();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items"></param>
+    public void AddAll<U>(System.Collections.Generic.IEnumerable<U> items) where U : T
+    {
+      throw new FixedSizeCollectionException();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public bool Check()
+    {
+      return innerlist.Check() && (underlying == null || underlying.innerlist == innerlist.Underlying);
+    }
+
+    #endregion
+
+    #region ICollectionValue<T> Members
+    /// <summary>
+    /// No listeners may be installed
+    /// </summary>
+    /// <value>0</value>
+    public virtual EventTypeEnum ListenableEvents { get { return 0; } }
+
+    /// <summary>
+    /// No listeners ever installed
+    /// </summary>
+    /// <value>0</value>
+    public virtual EventTypeEnum ActiveEvents { get { return 0; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public event CollectionChangedHandler<T> CollectionChanged
+    {
+      add { throw new UnlistenableEventException(); }
+      remove { throw new UnlistenableEventException(); }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public event CollectionClearedHandler<T> CollectionCleared
+    {
+      add { throw new UnlistenableEventException(); }
+      remove { throw new UnlistenableEventException(); }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public event ItemsAddedHandler<T> ItemsAdded
+    {
+      add { throw new UnlistenableEventException(); }
+      remove { throw new UnlistenableEventException(); }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public event ItemInsertedHandler<T> ItemInserted
+    {
+      add { throw new UnlistenableEventException(); }
+      remove { throw new UnlistenableEventException(); }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public event ItemsRemovedHandler<T> ItemsRemoved
+    {
+      add { throw new UnlistenableEventException(); }
+      remove { throw new UnlistenableEventException(); }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public event ItemRemovedAtHandler<T> ItemRemovedAt
+    {
+      add { throw new UnlistenableEventException(); }
+      remove { throw new UnlistenableEventException(); }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public bool IsEmpty { get { return innerlist.IsEmpty; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public int Count { get { return innerlist.Count; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public Speed CountSpeed { get { return innerlist.CountSpeed; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="array"></param>
+    /// <param name="index"></param>
+    public void CopyTo(T[] array, int index) { innerlist.CopyTo(array, index); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public T[] ToArray() { return innerlist.ToArray(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="action"></param>
+    public void Apply(Act<T> action) { innerlist.Apply(action); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="predicate"></param>
+    /// <returns></returns>
+    public bool Exists(Fun<T, bool> predicate) { return innerlist.Exists(predicate); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="predicate"></param>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public bool Find(Fun<T, bool> predicate, out T item) { return innerlist.Find(predicate, out item); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="predicate"></param>
+    /// <returns></returns>
+    public bool All(Fun<T, bool> predicate) { return innerlist.All(predicate); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public T Choose() { return innerlist.Choose(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="filter"></param>
+    /// <returns></returns>
+    public SCG.IEnumerable<T> Filter(Fun<T, bool> filter) { return innerlist.Filter(filter); }
+
+    #endregion
+
+    #region IEnumerable<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public SCG.IEnumerator<T> GetEnumerator() { return innerlist.GetEnumerator(); }
+    #endregion
+
+    #region IShowable Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="stringbuilder"></param>
+    /// <param name="rest"></param>
+    /// <param name="formatProvider"></param>
+    /// <returns></returns>
+    public bool Show(StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
+    { return innerlist.Show(stringbuilder, ref  rest, formatProvider); }
+
+    #endregion
+
+    #region IFormattable Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override string ToString() { return innerlist.ToString(); }
+
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="format"></param>
+    /// <param name="formatProvider"></param>
+    /// <returns></returns>
+    public virtual string ToString(string format, IFormatProvider formatProvider) { return innerlist.ToString(format, formatProvider); }
+
+    #endregion
+
+    #region IDirectedCollectionValue<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public IDirectedCollectionValue<T> Backwards() { return innerlist.Backwards(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="predicate"></param>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public bool FindLast(Fun<T, bool> predicate, out T item) { return innerlist.FindLast(predicate, out item); }
+
+    #endregion
+
+    #region IDirectedEnumerable<T> Members
+
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards() { return Backwards(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public EnumerationDirection Direction { get { return EnumerationDirection.Forwards; } }
+
+    #endregion
+
+    #region IDisposable Members
+
+    /// <summary>
+    /// Dispose this if a view else operation is illegal 
+    /// </summary>
+    /// <exception cref="FixedSizeCollectionException">If not a view</exception>
+    public void Dispose()
+    {
+      if (underlying == null)
+        throw new FixedSizeCollectionException();
+      else
+        innerlist.Dispose();
+    }
+
+    #endregion
+
+    #region ICloneable Members
+
+    /// <summary>
+    /// Make a shallow copy of this WrappedArray.
+    /// 
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual object Clone()
+    {
+      return new WrappedArray<T>(innerlist.ToArray());
+    }
+
+    #endregion
+
+    #region System.Collections.Generic.IList<T> Members
+
+    void System.Collections.Generic.IList<T>.RemoveAt(int index)
+    {
+      throw new FixedSizeCollectionException();
+    }
+
+    void System.Collections.Generic.ICollection<T>.Add(T item)
+    {
+      throw new FixedSizeCollectionException();
+    }
+
+    #endregion
+
+    #region System.Collections.ICollection Members
+
+    bool System.Collections.ICollection.IsSynchronized
+    {
+      get { return false; }
+    }
+
+    [Obsolete]
+    Object System.Collections.ICollection.SyncRoot
+    {
+      get { return ((System.Collections.IList)innerlist).SyncRoot; }
+    }
+
+    void System.Collections.ICollection.CopyTo(Array arr, int index)
+    {
+      if (index < 0 || index + Count > arr.Length)
+        throw new ArgumentOutOfRangeException();
+
+      foreach (T item in this)
+        arr.SetValue(item, index++);
+    }
+    
+    #endregion
+
+    #region System.Collections.IList Members
+
+    Object System.Collections.IList.this[int index]
+    {
+      get { return this[index]; }
+      set { this[index] = (T)value; }
+    }
+
+    int System.Collections.IList.Add(Object o)
+    {
+      bool added = Add((T)o);
+      // What position to report if item not added? SC.IList.Add doesn't say
+      return added ? Count - 1 : -1;
+    }
+
+    bool System.Collections.IList.Contains(Object o)
+    {
+      return Contains((T)o);
+    }
+
+    int System.Collections.IList.IndexOf(Object o)
+    {
+      return Math.Max(-1, IndexOf((T)o));
+    }
+
+    void System.Collections.IList.Insert(int index, Object o)
+    {
+      Insert(index, (T)o);
+    }
+
+    void System.Collections.IList.Remove(Object o)
+    {
+      Remove((T)o);
+    }
+
+    void System.Collections.IList.RemoveAt(int index)
+    {
+      RemoveAt(index);
+    }
+
+    #endregion
+    
+    #region IEnumerable Members
+
+    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+    {
+      throw new Exception("The method or operation is not implemented.");
+    }
+
+    #endregion
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Wrappers.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Wrappers.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5/Wrappers.cs	(revision 3)
@@ -0,0 +1,2405 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Diagnostics;
+using SCG = System.Collections.Generic;
+namespace C5
+{
+  /// <summary>
+  /// A read-only wrapper class for a generic enumerator
+  /// </summary>
+  public class GuardedEnumerator<T> : SCG.IEnumerator<T>
+  {
+    #region Fields
+
+    SCG.IEnumerator<T> enumerator;
+
+    #endregion
+
+    #region Constructor
+
+    /// <summary>
+    /// Create a wrapper around a generic enumerator
+    /// </summary>
+    /// <param name="enumerator">The enumerator to wrap</param>
+    public GuardedEnumerator(SCG.IEnumerator<T> enumerator)
+    { this.enumerator = enumerator; }
+
+    #endregion
+
+    #region IEnumerator<T> Members
+
+    /// <summary>
+    /// Move wrapped enumerator to next item, or the first item if
+    /// this is the first call to MoveNext. 
+    /// </summary>
+    /// <returns>True if enumerator is valid now</returns>
+    public bool MoveNext() { return enumerator.MoveNext(); }
+
+
+    /// <summary>
+    /// Undefined if enumerator is not valid (MoveNext hash been called returning true)
+    /// </summary>
+    /// <value>The current item of the wrapped enumerator.</value>
+    public T Current { get { return enumerator.Current; } }
+
+    #endregion
+
+    #region IDisposable Members
+
+    //TODO: consider possible danger of calling through to Dispose. 
+    /// <summary>
+    /// Dispose wrapped enumerator.
+    /// </summary>
+    public void Dispose() { enumerator.Dispose(); }
+
+    #endregion
+
+
+    #region IEnumerator Members
+
+    object System.Collections.IEnumerator.Current
+    {
+      get { return enumerator.Current; }
+    }
+
+    void System.Collections.IEnumerator.Reset()
+    {
+      enumerator.Reset();
+    }
+
+    #endregion
+  }
+
+
+
+  /// <summary>
+  /// A read-only wrapper class for a generic enumerable
+  ///
+  /// <i>This is mainly interesting as a base of other guard classes</i>
+  /// </summary>
+  public class GuardedEnumerable<T> : SCG.IEnumerable<T>
+  {
+    #region Fields
+
+    SCG.IEnumerable<T> enumerable;
+
+    #endregion
+
+    #region Constructor
+
+    /// <summary>
+    /// Wrap an enumerable in a read-only wrapper
+    /// </summary>
+    /// <param name="enumerable">The enumerable to wrap</param>
+    public GuardedEnumerable(SCG.IEnumerable<T> enumerable)
+    { this.enumerable = enumerable; }
+
+    #endregion
+
+    #region SCG.IEnumerable<T> Members
+
+    /// <summary>
+    /// Get an enumerator from the wrapped enumerable
+    /// </summary>
+    /// <returns>The enumerator (itself wrapped)</returns>
+    public SCG.IEnumerator<T> GetEnumerator()
+    { return new GuardedEnumerator<T>(enumerable.GetEnumerator()); }
+
+    #endregion
+
+    #region IEnumerable Members
+
+    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+    {
+      return GetEnumerator();
+    }
+
+    #endregion
+
+  }
+
+
+
+  /// <summary>
+  /// A read-only wrapper for a generic directed enumerable
+  ///
+  /// <i>This is mainly interesting as a base of other guard classes</i>
+  /// </summary>
+  public class GuardedDirectedEnumerable<T> : GuardedEnumerable<T>, IDirectedEnumerable<T>
+  {
+    #region Fields
+
+    IDirectedEnumerable<T> directedenumerable;
+
+    #endregion
+
+    #region Constructor
+
+    /// <summary>
+    /// Wrap a directed enumerable in a read-only wrapper
+    /// </summary>
+    /// <param name="directedenumerable">the collection to wrap</param>
+    public GuardedDirectedEnumerable(IDirectedEnumerable<T> directedenumerable)
+      : base(directedenumerable)
+    { this.directedenumerable = directedenumerable; }
+
+    #endregion
+
+    #region IDirectedEnumerable<T> Members
+
+    /// <summary>
+    /// Get a enumerable that enumerates the wrapped collection in the opposite direction
+    /// </summary>
+    /// <returns>The mirrored enumerable</returns>
+    public IDirectedEnumerable<T> Backwards()
+    { return new GuardedDirectedEnumerable<T>(directedenumerable.Backwards()); }
+
+
+    /// <summary>
+    /// <code>Forwards</code> if same, else <code>Backwards</code>
+    /// </summary>
+    /// <value>The enumeration direction relative to the original collection.</value>
+    public EnumerationDirection Direction
+    { get { return directedenumerable.Direction; } }
+
+    #endregion
+  }
+
+
+
+  /// <summary>
+  /// A read-only wrapper for an ICollectionValue&lt;T&gt;
+  ///
+  /// <i>This is mainly interesting as a base of other guard classes</i>
+  /// </summary>
+  public class GuardedCollectionValue<T> : GuardedEnumerable<T>, ICollectionValue<T>
+  {
+    #region Events
+    /// <summary>
+    /// The ListenableEvents value of the wrapped collection
+    /// </summary>
+    /// <value></value>
+    public virtual EventTypeEnum ListenableEvents { get { return collectionvalue.ListenableEvents; } }
+
+    /// <summary>
+    /// The ActiveEvents value of the wrapped collection
+    /// </summary>
+    /// <value></value>
+    public virtual EventTypeEnum ActiveEvents { get { return collectionvalue.ActiveEvents; } }
+
+    ProxyEventBlock<T> eventBlock;
+    /// <summary>
+    /// The change event. Will be raised for every change operation on the collection.
+    /// </summary>
+    public event CollectionChangedHandler<T> CollectionChanged
+    {
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).CollectionChanged += value; }
+      remove { if (eventBlock != null) eventBlock.CollectionChanged -= value; }
+    }
+
+    /// <summary>
+    /// The change event. Will be raised for every change operation on the collection.
+    /// </summary>
+    public event CollectionClearedHandler<T> CollectionCleared
+    {
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).CollectionCleared += value; }
+      remove { if (eventBlock != null) eventBlock.CollectionCleared -= value; }
+    }
+
+    /// <summary>
+    /// The item added  event. Will be raised for every individual addition to the collection.
+    /// </summary>
+    public event ItemsAddedHandler<T> ItemsAdded
+    {
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemsAdded += value; }
+      remove { if (eventBlock != null) eventBlock.ItemsAdded -= value; }
+    }
+
+    /// <summary>
+    /// The item added  event. Will be raised for every individual addition to the collection.
+    /// </summary>
+    public event ItemInsertedHandler<T> ItemInserted
+    {
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemInserted += value; }
+      remove { if (eventBlock != null) eventBlock.ItemInserted -= value; }
+    }
+
+    /// <summary>
+    /// The item removed event. Will be raised for every individual removal from the collection.
+    /// </summary>
+    public event ItemsRemovedHandler<T> ItemsRemoved
+    {
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemsRemoved += value; }
+      remove { if (eventBlock != null) eventBlock.ItemsRemoved -= value; }
+    }
+
+    /// <summary>
+    /// The item removed event. Will be raised for every individual removal from the collection.
+    /// </summary>
+    public event ItemRemovedAtHandler<T> ItemRemovedAt
+    {
+      add { (eventBlock ?? (eventBlock = new ProxyEventBlock<T>(this, collectionvalue))).ItemRemovedAt += value; }
+      remove { if (eventBlock != null) eventBlock.ItemRemovedAt -= value; }
+    }
+    #endregion
+
+    #region Fields
+
+    ICollectionValue<T> collectionvalue;
+
+    #endregion
+
+    #region Constructor
+
+    /// <summary>
+    /// Wrap a ICollectionValue&lt;T&gt; in a read-only wrapper
+    /// </summary>
+    /// <param name="collectionvalue">the collection to wrap</param>
+    public GuardedCollectionValue(ICollectionValue<T> collectionvalue)
+      : base(collectionvalue)
+    { this.collectionvalue = collectionvalue; }
+
+    #endregion
+
+    #region ICollection<T> Members
+
+    /// <summary>
+    /// Get the size of the wrapped collection
+    /// </summary>
+    /// <value>The size</value>
+    public virtual bool IsEmpty { get { return collectionvalue.IsEmpty; } }
+
+    /// <summary>
+    /// Get the size of the wrapped collection
+    /// </summary>
+    /// <value>The size</value>
+    public virtual int Count { get { return collectionvalue.Count; } }
+
+    /// <summary>
+    /// The value is symbolic indicating the type of asymptotic complexity
+    /// in terms of the size of this collection (worst-case or amortized as
+    /// relevant).
+    /// </summary>
+    /// <value>A characterization of the speed of the 
+    /// <code>Count</code> property in this collection.</value>
+    public virtual Speed CountSpeed { get { return collectionvalue.CountSpeed; } }
+
+    /// <summary>
+    /// Copy the items of the wrapped collection to an array
+    /// </summary>
+    /// <param name="a">The array</param>
+    /// <param name="i">Starting offset</param>
+    public virtual void CopyTo(T[] a, int i) { collectionvalue.CopyTo(a, i); }
+
+    /// <summary>
+    /// Create an array from the items of the wrapped collection
+    /// </summary>
+    /// <returns>The array</returns>
+    public virtual T[] ToArray() { return collectionvalue.ToArray(); }
+
+    /// <summary>
+    /// Apply a delegate to all items of the wrapped enumerable.
+    /// </summary>
+    /// <param name="a">The delegate to apply</param>
+    //TODO: change this to throw an exception?
+    public virtual void Apply(Act<T> a) { collectionvalue.Apply(a); }
+
+
+    /// <summary>
+    /// Check if there exists an item  that satisfies a
+    /// specific predicate in the wrapped enumerable.
+    /// </summary>
+    /// <param name="filter">A filter delegate 
+    /// (<see cref="T:C5.Filter`1"/>) defining the predicate</param>
+    /// <returns>True is such an item exists</returns>
+    public virtual bool Exists(Fun<T, bool> filter) { return collectionvalue.Exists(filter); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="filter"></param>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public virtual bool Find(Fun<T, bool> filter, out T item) { return collectionvalue.Find(filter, out item); }
+
+    /// <summary>
+    /// Check if all items in the wrapped enumerable satisfies a specific predicate.
+    /// </summary>
+    /// <param name="filter">A filter delegate 
+    /// (<see cref="T:C5.Filter`1"/>) defining the predicate</param>
+    /// <returns>True if all items satisfies the predicate</returns>
+    public virtual bool All(Fun<T, bool> filter) { return collectionvalue.All(filter); }
+
+    /// <summary>
+    /// Create an enumerable, enumerating the items of this collection that satisfies 
+    /// a certain condition.
+    /// </summary>
+    /// <param name="filter">The T->bool filter delegate defining the condition</param>
+    /// <returns>The filtered enumerable</returns>
+    public virtual SCG.IEnumerable<T> Filter(Fun<T, bool> filter) { return collectionvalue.Filter(filter); }
+
+    /// <summary>
+    /// Choose some item of this collection. 
+    /// </summary>
+    /// <exception cref="NoSuchItemException">if collection is empty.</exception>
+    /// <returns></returns>
+    public virtual T Choose() { return collectionvalue.Choose(); }
+
+    #endregion
+
+    #region IShowable Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="stringbuilder"></param>
+    /// <param name="formatProvider"></param>
+    /// <param name="rest"></param>
+    /// <returns></returns>
+    public bool Show(System.Text.StringBuilder stringbuilder, ref int rest, IFormatProvider formatProvider)
+    {
+      return collectionvalue.Show(stringbuilder, ref rest, formatProvider);
+    }
+    #endregion
+
+    #region IFormattable Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="format"></param>
+    /// <param name="formatProvider"></param>
+    /// <returns></returns>
+    public string ToString(string format, IFormatProvider formatProvider)
+    {
+      return collectionvalue.ToString(format, formatProvider);
+    }
+
+    #endregion
+  }
+
+
+
+  /// <summary>
+  /// A read-only wrapper for a directed collection
+  ///
+  /// <i>This is mainly interesting as a base of other guard classes</i>
+  /// </summary>
+  public class GuardedDirectedCollectionValue<T> : GuardedCollectionValue<T>, IDirectedCollectionValue<T>
+  {
+    #region Fields
+
+    IDirectedCollectionValue<T> directedcollection;
+
+    #endregion
+
+    #region Constructor
+
+    /// <summary>
+    /// Wrap a directed collection in a read-only wrapper
+    /// </summary>
+    /// <param name="directedcollection">the collection to wrap</param>
+    public GuardedDirectedCollectionValue(IDirectedCollectionValue<T> directedcollection)
+      :
+      base(directedcollection)
+    { this.directedcollection = directedcollection; }
+
+    #endregion
+
+    #region IDirectedCollection<T> Members
+
+    /// <summary>
+    /// Get a collection that enumerates the wrapped collection in the opposite direction
+    /// </summary>
+    /// <returns>The mirrored collection</returns>
+    public virtual IDirectedCollectionValue<T> Backwards()
+    { return new GuardedDirectedCollectionValue<T>(directedcollection.Backwards()); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="predicate"></param>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public virtual bool FindLast(Fun<T, bool> predicate, out T item) { return directedcollection.FindLast(predicate, out item); }
+
+    #endregion
+
+    #region IDirectedEnumerable<T> Members
+
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
+    { return Backwards(); }
+
+
+    /// <summary>
+    /// <code>Forwards</code> if same, else <code>Backwards</code>
+    /// </summary>
+    /// <value>The enumeration direction relative to the original collection.</value>
+    public EnumerationDirection Direction
+    { get { return directedcollection.Direction; } }
+
+    #endregion
+  }
+
+
+
+  /// <summary>
+  /// A read-only wrapper for an <see cref="T:C5.ICollection`1"/>,
+  /// <para>
+  /// <i>Suitable for wrapping hash tables, <see cref="T:C5.HashSet`1"/>
+  /// and <see cref="T:C5.HashBag`1"/>  </i></para>
+  /// </summary>
+  public class GuardedCollection<T> : GuardedCollectionValue<T>, ICollection<T>
+  {
+    #region Fields
+
+    ICollection<T> collection;
+
+    #endregion
+
+    #region Constructor
+
+    /// <summary>
+    /// Wrap an ICollection&lt;T&gt; in a read-only wrapper
+    /// </summary>
+    /// <param name="collection">the collection to wrap</param>
+    public GuardedCollection(ICollection<T> collection)
+      : base(collection)
+    {
+      this.collection = collection;
+    }
+
+    #endregion
+
+    #region ICollection<T> Members
+
+    /// <summary>
+    /// (This is a read-only wrapper)
+    /// </summary>
+    /// <value>True</value>
+    public virtual bool IsReadOnly { get { return true; } }
+
+
+    /// <summary> </summary>
+    /// <value>Speed of wrapped collection</value>
+    public virtual Speed ContainsSpeed { get { return collection.ContainsSpeed; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual int GetUnsequencedHashCode()
+    { return collection.GetUnsequencedHashCode(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="that"></param>
+    /// <returns></returns>
+    public virtual bool UnsequencedEquals(ICollection<T> that)
+    { return collection.UnsequencedEquals(that); }
+
+
+    /// <summary>
+    /// Check if an item is in the wrapped collection
+    /// </summary>
+    /// <param name="item">The item</param>
+    /// <returns>True if found</returns>
+    public virtual bool Contains(T item) { return collection.Contains(item); }
+
+
+    /// <summary>
+    /// Count the number of times an item appears in the wrapped collection
+    /// </summary>
+    /// <param name="item">The item</param>
+    /// <returns>The number of copies</returns>
+    public virtual int ContainsCount(T item) { return collection.ContainsCount(item); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<T> UniqueItems() { return new GuardedCollectionValue<T>(collection.UniqueItems()); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual ICollectionValue<KeyValuePair<T, int>> ItemMultiplicities() { return new GuardedCollectionValue<KeyValuePair<T, int>>(collection.ItemMultiplicities()); }
+
+    /// <summary>
+    /// Check if all items in the argument is in the wrapped collection
+    /// </summary>
+    /// <param name="items">The items</param>
+    /// <typeparam name="U"></typeparam>
+    /// <returns>True if so</returns>
+    public virtual bool ContainsAll<U>(SCG.IEnumerable<U> items) where U : T { return collection.ContainsAll(items); }
+
+    /// <summary> 
+    /// Search for an item in the wrapped collection
+    /// </summary>
+    /// <param name="item">On entry the item to look for, on exit the equivalent item found (if any)</param>
+    /// <returns></returns>
+    public virtual bool Find(ref T item) { return collection.Find(ref item); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public virtual bool FindOrAdd(ref T item)
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public virtual bool Update(T item)
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public virtual bool Update(T item, out T olditem)
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public virtual bool UpdateOrAdd(T item)
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="item"></param>
+    /// <param name="olditem"></param>
+    /// <returns></returns>
+    public virtual bool UpdateOrAdd(T item, out T olditem)
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public virtual bool Remove(T item)
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="item">The value to remove.</param>
+    /// <param name="removeditem">The removed value.</param>
+    /// <returns></returns>
+    public virtual bool Remove(T item, out T removeditem)
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="item"></param>
+    public virtual void RemoveAllCopies(T item)
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items"></param>
+    public virtual void RemoveAll<U>(SCG.IEnumerable<U> items) where U : T
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    public virtual void Clear()
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items"></param>
+    public virtual void RetainAll<U>(SCG.IEnumerable<U> items) where U : T
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+    /// <summary>
+    /// Check  wrapped collection for internal consistency
+    /// </summary>
+    /// <returns>True if check passed</returns>
+    public virtual bool Check() { return collection.Check(); }
+
+    #endregion
+
+    #region IExtensible<T> Members
+
+    /// <summary> </summary>
+    /// <value>False if wrapped collection has set semantics</value>
+    public virtual bool AllowsDuplicates { get { return collection.AllowsDuplicates; } }
+
+    //TODO: the equalityComparer should be guarded
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual SCG.IEqualityComparer<T> EqualityComparer { get { return collection.EqualityComparer; } }
+
+    /// <summary>
+    /// By convention this is true for any collection with set semantics.
+    /// </summary>
+    /// <value>True if only one representative of a group of equal items 
+    /// is kept in the collection together with the total count.</value>
+    public virtual bool DuplicatesByCounting { get { return collection.DuplicatesByCounting; } }
+
+
+    /// <summary> </summary>
+    /// <value>True if wrapped collection is empty</value>
+    public override bool IsEmpty { get { return collection.IsEmpty; } }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public virtual bool Add(T item)
+    { throw new ReadOnlyCollectionException(); }
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="item"></param>
+    void SCG.ICollection<T>.Add(T item)
+    { throw new ReadOnlyCollectionException(); }
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <typeparam name="U"></typeparam>
+    /// <param name="items"></param>
+    public virtual void AddAll<U>(SCG.IEnumerable<U> items) where U : T
+    { throw new ReadOnlyCollectionException(); }
+
+    #endregion
+
+    #region ICloneable Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual object Clone()
+    {
+      return new GuardedCollection<T>((ICollection<T>)(collection.Clone()));
+    }
+
+    #endregion
+
+  }
+
+
+  /// <summary>
+  /// A read-only wrapper for a sequenced collection
+  ///
+  /// <i>This is mainly interesting as a base of other guard classes</i>
+  /// </summary>
+  public class GuardedSequenced<T> : GuardedCollection<T>, ISequenced<T>
+  {
+    #region Fields
+
+    ISequenced<T> sequenced;
+
+    #endregion
+
+    #region Constructor
+
+    /// <summary>
+    /// Wrap a sequenced collection in a read-only wrapper
+    /// </summary>
+    /// <param name="sorted"></param>
+    public GuardedSequenced(ISequenced<T> sorted) : base(sorted) { this.sequenced = sorted; }
+
+    #endregion
+
+    /// <summary>
+    /// Check if there exists an item  that satisfies a
+    /// specific predicate in this collection and return the index of the first one.
+    /// </summary>
+    /// <param name="predicate">A delegate 
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
+    /// <returns>the index, if found, a negative value else</returns>
+    public int FindIndex(Fun<T, bool> predicate)
+    {
+      IIndexed<T> indexed = sequenced as IIndexed<T>;
+      if (indexed != null)
+        return indexed.FindIndex(predicate);
+      int index = 0;
+      foreach (T item in this)
+      {
+        if (predicate(item))
+          return index;
+        index++;
+      }
+      return -1;
+    }
+
+    /// <summary>
+    /// Check if there exists an item  that satisfies a
+    /// specific predicate in this collection and return the index of the last one.
+    /// </summary>
+    /// <param name="predicate">A delegate 
+    /// (<see cref="T:C5.Fun`2"/> with <code>R == bool</code>) defining the predicate</param>
+    /// <returns>the index, if found, a negative value else</returns>
+    public int FindLastIndex(Fun<T, bool> predicate)
+    {
+      IIndexed<T> indexed = sequenced as IIndexed<T>;
+      if (indexed != null)
+        return indexed.FindLastIndex(predicate);
+      int index = Count - 1;
+      foreach (T item in Backwards())
+      {
+        if (predicate(item))
+          return index;
+        index--;
+      }
+      return -1;
+    }
+
+
+
+    #region ISequenced<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public int GetSequencedHashCode()
+    { return sequenced.GetSequencedHashCode(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="that"></param>
+    /// <returns></returns>
+    public bool SequencedEquals(ISequenced<T> that)
+    { return sequenced.SequencedEquals(that); }
+
+    #endregion
+
+    #region IDirectedCollection<T> Members
+
+    /// <summary>
+    /// Get a collection that enumerates the wrapped collection in the opposite direction
+    /// </summary>
+    /// <returns>The mirrored collection</returns>
+    public virtual IDirectedCollectionValue<T> Backwards()
+    { return new GuardedDirectedCollectionValue<T>(sequenced.Backwards()); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="predicate"></param>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public virtual bool FindLast(Fun<T, bool> predicate, out T item) { return sequenced.FindLast(predicate, out item); }
+
+    #endregion
+
+    #region IDirectedEnumerable<T> Members
+
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
+    { return Backwards(); }
+
+
+
+    /// <summary>
+    /// <code>Forwards</code> if same, else <code>Backwards</code>
+    /// </summary>
+    /// <value>The enumeration direction relative to the original collection.</value>
+    public EnumerationDirection Direction
+    { get { return EnumerationDirection.Forwards; } }
+
+    #endregion
+
+    #region ICloneable Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override object Clone()
+    {
+      return new GuardedCollection<T>((ISequenced<T>)(sequenced.Clone()));
+    }
+
+    #endregion
+
+  }
+
+
+  /// <summary>
+  /// A read-only wrapper for a sorted collection
+  ///
+  /// <i>This is mainly interesting as a base of other guard classes</i>
+  /// </summary>
+  public class GuardedSorted<T> : GuardedSequenced<T>, ISorted<T>
+  {
+    #region Fields
+
+    ISorted<T> sorted;
+
+    #endregion
+
+    #region Constructor
+
+    /// <summary>
+    /// Wrap a sorted collection in a read-only wrapper
+    /// </summary>
+    /// <param name="sorted"></param>
+    public GuardedSorted(ISorted<T> sorted) : base(sorted) { this.sorted = sorted; }
+
+    #endregion
+
+    #region ISorted<T> Members
+
+    /// <summary>
+    /// Find the strict predecessor of item in the guarded sorted collection,
+    /// that is, the greatest item in the collection smaller than the item.
+    /// </summary>
+    /// <param name="item">The item to find the predecessor for.</param>
+    /// <param name="res">The predecessor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a predecessor; otherwise false.</returns>
+    public bool TryPredecessor(T item, out T res) { return sorted.TryPredecessor(item, out res); }
+
+
+    /// <summary>
+    /// Find the strict successor of item in the guarded sorted collection,
+    /// that is, the least item in the collection greater than the supplied value.
+    /// </summary>
+    /// <param name="item">The item to find the successor for.</param>
+    /// <param name="res">The successor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a successor; otherwise false.</returns>
+    public bool TrySuccessor(T item, out T res) { return sorted.TrySuccessor(item, out res); }
+
+
+    /// <summary>
+    /// Find the weak predecessor of item in the guarded sorted collection,
+    /// that is, the greatest item in the collection smaller than or equal to the item.
+    /// </summary>
+    /// <param name="item">The item to find the weak predecessor for.</param>
+    /// <param name="res">The weak predecessor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a weak predecessor; otherwise false.</returns>
+    public bool TryWeakPredecessor(T item, out T res) { return sorted.TryWeakPredecessor(item, out res); }
+
+
+    /// <summary>
+    /// Find the weak successor of item in the sorted collection,
+    /// that is, the least item in the collection greater than or equal to the supplied value.
+    /// </summary>
+    /// <param name="item">The item to find the weak successor for.</param>
+    /// <param name="res">The weak successor, if any; otherwise the default value for T.</param>
+    /// <returns>True if item has a weak successor; otherwise false.</returns>
+    public bool TryWeakSuccessor(T item, out T res) { return sorted.TryWeakSuccessor(item, out res); }
+
+
+    /// <summary>
+    /// Find the predecessor of the item in the wrapped sorted collection
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such element exists </exception>    
+    /// <param name="item">The item</param>
+    /// <returns>The predecessor</returns>
+    public T Predecessor(T item) { return sorted.Predecessor(item); }
+
+
+    /// <summary>
+    /// Find the Successor of the item in the wrapped sorted collection
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such element exists </exception>    
+    /// <param name="item">The item</param>
+    /// <returns>The Successor</returns>
+    public T Successor(T item) { return sorted.Successor(item); }
+
+
+    /// <summary>
+    /// Find the weak predecessor of the item in the wrapped sorted collection
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such element exists </exception>    
+    /// <param name="item">The item</param>
+    /// <returns>The weak predecessor</returns>
+    public T WeakPredecessor(T item) { return sorted.WeakPredecessor(item); }
+
+
+    /// <summary>
+    /// Find the weak Successor of the item in the wrapped sorted collection
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such element exists </exception>    
+    /// <param name="item">The item</param>
+    /// <returns>The weak Successor</returns>
+    public T WeakSuccessor(T item) { return sorted.WeakSuccessor(item); }
+
+
+    /// <summary>
+    /// Run Cut on the wrapped sorted collection
+    /// </summary>
+    /// <param name="c"></param>
+    /// <param name="low"></param>
+    /// <param name="lval"></param>
+    /// <param name="high"></param>
+    /// <param name="hval"></param>
+    /// <returns></returns>
+    public bool Cut(IComparable<T> c, out T low, out bool lval, out T high, out bool hval)
+    { return sorted.Cut(c, out low, out lval, out high, out hval); }
+
+
+    /// <summary>
+    /// Get the specified range from the wrapped collection. 
+    /// (The current implementation erroneously does not wrap the result.)
+    /// </summary>
+    /// <param name="bot"></param>
+    /// <returns></returns>
+    public IDirectedEnumerable<T> RangeFrom(T bot) { return sorted.RangeFrom(bot); }
+
+
+    /// <summary>
+    /// Get the specified range from the wrapped collection. 
+    /// (The current implementation erroneously does not wrap the result.)
+    /// </summary>
+    /// <param name="bot"></param>
+    /// <param name="top"></param>
+    /// <returns></returns>
+    public IDirectedEnumerable<T> RangeFromTo(T bot, T top)
+    { return sorted.RangeFromTo(bot, top); }
+
+
+    /// <summary>
+    /// Get the specified range from the wrapped collection. 
+    /// (The current implementation erroneously does not wrap the result.)
+    /// </summary>
+    /// <param name="top"></param>
+    /// <returns></returns>
+    public IDirectedEnumerable<T> RangeTo(T top) { return sorted.RangeTo(top); }
+
+
+    /// <summary>
+    /// Get the specified range from the wrapped collection. 
+    /// (The current implementation erroneously does not wrap the result.)
+    /// </summary>
+    /// <returns></returns>
+    public IDirectedCollectionValue<T> RangeAll() { return sorted.RangeAll(); }
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="items"></param>
+    /// <typeparam name="U"></typeparam>
+    public void AddSorted<U>(SCG.IEnumerable<U> items) where U : T
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="low"></param>
+    public void RemoveRangeFrom(T low)
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="low"></param>
+    /// <param name="hi"></param>
+    public void RemoveRangeFromTo(T low, T hi)
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="hi"></param>
+    public void RemoveRangeTo(T hi)
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+    #endregion
+
+    #region IPriorityQueue<T> Members
+
+    /// <summary>
+    /// Find the minimum of the wrapped collection
+    /// </summary>
+    /// <returns>The minimum</returns>
+    public T FindMin() { return sorted.FindMin(); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <returns></returns>
+    public T DeleteMin()
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+    /// <summary>
+    /// Find the maximum of the wrapped collection
+    /// </summary>
+    /// <returns>The maximum</returns>
+    public T FindMax() { return sorted.FindMax(); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <returns></returns>
+    public T DeleteMax()
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+    //TODO: we should guard the comparer!
+    /// <summary>
+    /// The comparer object supplied at creation time for the underlying collection
+    /// </summary>
+    /// <value>The comparer</value>
+    public SCG.IComparer<T> Comparer { get { return sorted.Comparer; } }
+    #endregion
+
+    #region IDirectedEnumerable<T> Members
+
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
+    { return Backwards(); }
+
+    #endregion
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override object Clone()
+    {
+      return new GuardedSorted<T>((ISorted<T>)(sorted.Clone()));
+    }
+
+  }
+
+
+
+  /// <summary>
+  /// Read-only wrapper for indexed sorted collections
+  ///
+  /// <i>Suitable for wrapping TreeSet, TreeBag and SortedArray</i>
+  /// </summary>
+  public class GuardedIndexedSorted<T> : GuardedSorted<T>, IIndexedSorted<T>
+  {
+    #region Fields
+
+    IIndexedSorted<T> indexedsorted;
+
+    #endregion
+
+    #region Constructor
+
+    /// <summary>
+    /// Wrap an indexed sorted collection in a read-only wrapper
+    /// </summary>
+    /// <param name="list">the indexed sorted collection</param>
+    public GuardedIndexedSorted(IIndexedSorted<T> list)
+      : base(list)
+    { this.indexedsorted = list; }
+
+    #endregion
+
+    #region IIndexedSorted<T> Members
+
+    /// <summary>
+    /// Get the specified range from the wrapped collection. 
+    /// (The current implementation erroneously does not wrap the result.)
+    /// </summary>
+    /// <param name="bot"></param>
+    /// <returns></returns>
+    public new IDirectedCollectionValue<T> RangeFrom(T bot)
+    { return indexedsorted.RangeFrom(bot); }
+
+
+    /// <summary>
+    /// Get the specified range from the wrapped collection. 
+    /// (The current implementation erroneously does not wrap the result.)
+    /// </summary>
+    /// <param name="bot"></param>
+    /// <param name="top"></param>
+    /// <returns></returns>
+    public new IDirectedCollectionValue<T> RangeFromTo(T bot, T top)
+    { return indexedsorted.RangeFromTo(bot, top); }
+
+
+    /// <summary>
+    /// Get the specified range from the wrapped collection. 
+    /// (The current implementation erroneously does not wrap the result.)
+    /// </summary>
+    /// <param name="top"></param>
+    /// <returns></returns>
+    public new IDirectedCollectionValue<T> RangeTo(T top)
+    { return indexedsorted.RangeTo(top); }
+
+
+    /// <summary>
+    /// Report the number of items in the specified range of the wrapped collection
+    /// </summary>
+    /// <param name="bot"></param>
+    /// <returns></returns>
+    public int CountFrom(T bot) { return indexedsorted.CountFrom(bot); }
+
+
+    /// <summary>
+    /// Report the number of items in the specified range of the wrapped collection
+    /// </summary>
+    /// <param name="bot"></param>
+    /// <param name="top"></param>
+    /// <returns></returns>
+    public int CountFromTo(T bot, T top) { return indexedsorted.CountFromTo(bot, top); }
+
+
+    /// <summary>
+    /// Report the number of items in the specified range of the wrapped collection
+    /// </summary>
+    /// <param name="top"></param>
+    /// <returns></returns>
+    public int CountTo(T top) { return indexedsorted.CountTo(top); }
+
+
+    /// <summary>
+    /// Run FindAll on the wrapped collection with the indicated filter.
+    /// The result will <b>not</b> be read-only.
+    /// </summary>
+    /// <param name="f"></param>
+    /// <returns></returns>
+    public IIndexedSorted<T> FindAll(Fun<T, bool> f)
+    { return indexedsorted.FindAll(f); }
+
+
+    /// <summary>
+    /// Run Map on the wrapped collection with the indicated mapper.
+    /// The result will <b>not</b> be read-only.
+    /// </summary>
+    /// <param name="m"></param>
+    /// <param name="c">The comparer to use in the result</param>
+    /// <returns></returns>
+    public IIndexedSorted<V> Map<V>(Fun<T, V> m, SCG.IComparer<V> c)
+    { return indexedsorted.Map(m, c); }
+
+    #endregion
+
+    #region IIndexed<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>The i'th item of the wrapped sorted collection</value>
+    public T this[int i] { get { return indexedsorted[i]; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual Speed IndexingSpeed { get { return indexedsorted.IndexingSpeed; } }
+
+    /// <summary> </summary>
+    /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>
+    public IDirectedCollectionValue<T> this[int start, int end]
+    { get { return new GuardedDirectedCollectionValue<T>(indexedsorted[start, end]); } }
+
+
+    /// <summary>
+    /// Find the (first) index of an item in the wrapped collection
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public int IndexOf(T item) { return indexedsorted.IndexOf(item); }
+
+
+    /// <summary>
+    /// Find the last index of an item in the wrapped collection
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public int LastIndexOf(T item) { return indexedsorted.LastIndexOf(item); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="i"></param>
+    /// <returns></returns>
+    public T RemoveAt(int i)
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="start"></param>
+    /// <param name="count"></param>
+    public void RemoveInterval(int start, int count)
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+    #endregion
+
+    #region IDirectedEnumerable<T> Members
+
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
+    { return Backwards(); }
+
+    #endregion
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override object Clone()
+    {
+      return new GuardedIndexedSorted<T>((IIndexedSorted<T>)(indexedsorted.Clone()));
+    }
+
+  }
+
+
+
+  /// <summary>
+  /// A read-only wrapper for a generic list collection
+  /// <i>Suitable as a wrapper for LinkedList, HashedLinkedList, ArrayList and HashedArray.
+  /// <see cref="T:C5.LinkedList`1"/>, 
+  /// <see cref="T:C5.HashedLinkedList`1"/>, 
+  /// <see cref="T:C5.ArrayList`1"/> or
+  /// <see cref="T:C5.HashedArray`1"/>.
+  /// </i>
+  /// </summary>
+  public class GuardedList<T> : GuardedSequenced<T>, IList<T>, SCG.IList<T>
+  {
+    #region Fields
+
+    IList<T> innerlist;
+    GuardedList<T> underlying;
+    bool slidableView = false;
+
+    #endregion
+
+    #region Constructor
+
+    /// <summary>
+    /// Wrap a list in a read-only wrapper.  A list gets wrapped as read-only,
+    /// a list view gets wrapped as read-only and non-slidable.
+    /// </summary>
+    /// <param name="list">The list</param>
+    public GuardedList(IList<T> list)
+      : base(list)
+    {
+      this.innerlist = list;
+      // If wrapping a list view, make innerlist = the view, and make 
+      // underlying = a guarded version of the view's underlying list
+      if (list.Underlying != null)
+        underlying = new GuardedList<T>(list.Underlying, null, false);
+    }
+
+    GuardedList(IList<T> list, GuardedList<T> underlying, bool slidableView)
+      : base(list)
+    {
+      this.innerlist = list; this.underlying = underlying; this.slidableView = slidableView;
+    }
+    #endregion
+
+    #region IList<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>The first item of the wrapped list</value>
+    public T First { get { return innerlist.First; } }
+
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>The last item of the wrapped list</value>
+    public T Last { get { return innerlist.Last; } }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> if used as setter</exception>
+    /// <value>True if wrapped list has FIFO semantics for the Add(T item) and Remove() methods</value>
+    public bool FIFO
+    {
+      get { return innerlist.FIFO; }
+      set { throw new ReadOnlyCollectionException("List is read only"); }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public virtual bool IsFixedSize
+    {
+      get { return true; }
+    }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> if used as setter</exception>
+    /// <value>The i'th item of the wrapped list</value>
+    public T this[int i]
+    {
+      get { return innerlist[i]; }
+      set { throw new ReadOnlyCollectionException("List is read only"); }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual Speed IndexingSpeed { get { return innerlist.IndexingSpeed; } }
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="index"></param>
+    /// <param name="item"></param>
+    public void Insert(int index, T item)
+    { throw new ReadOnlyCollectionException(); }
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="pointer"></param>
+    /// <param name="item"></param>
+    public void Insert(IList<T> pointer, T item)
+    { throw new ReadOnlyCollectionException(); }
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="item"></param>
+    public void InsertFirst(T item)
+    { throw new ReadOnlyCollectionException("List is read only"); }
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="item"></param>
+    public void InsertLast(T item)
+    { throw new ReadOnlyCollectionException("List is read only"); }
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="item"></param>
+    /// <param name="target"></param>
+    public void InsertBefore(T item, T target)
+    { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="item"></param>
+    /// <param name="target"></param>
+    public void InsertAfter(T item, T target)
+    { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="i"></param>
+    /// <param name="items"></param>
+    public void InsertAll<U>(int i, SCG.IEnumerable<U> items) where U : T
+    { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+    /// <summary>
+    /// Perform FindAll on the wrapped list. The result is <b>not</b> necessarily read-only.
+    /// </summary>
+    /// <param name="filter">The filter to use</param>
+    /// <returns></returns>
+    public IList<T> FindAll(Fun<T, bool> filter) { return innerlist.FindAll(filter); }
+
+
+    /// <summary>
+    /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
+    /// </summary>
+    /// <typeparam name="V">The type of items of the new list</typeparam>
+    /// <param name="mapper">The mapper to use.</param>
+    /// <returns>The mapped list</returns>
+    public IList<V> Map<V>(Fun<T, V> mapper) { return innerlist.Map(mapper); }
+
+    /// <summary>
+    /// Perform Map on the wrapped list. The result is <b>not</b> necessarily read-only.
+    /// </summary>
+    /// <typeparam name="V">The type of items of the new list</typeparam>
+    /// <param name="mapper">The delegate defining the map.</param>
+    /// <param name="itemequalityComparer">The itemequalityComparer to use for the new list</param>
+    /// <returns>The new list.</returns>
+    public IList<V> Map<V>(Fun<T, V> mapper, SCG.IEqualityComparer<V> itemequalityComparer) { return innerlist.Map(mapper, itemequalityComparer); }
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <returns></returns>
+    public T Remove() { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <returns></returns>
+    public T RemoveFirst() { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <returns></returns>
+    public T RemoveLast() { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+    /// <summary>
+    /// Create the indicated view on the wrapped list and wrap it read-only.
+    /// </summary>
+    /// <param name="start"></param>
+    /// <param name="count"></param>
+    /// <returns></returns>
+    public IList<T> View(int start, int count)
+    {
+      IList<T> view = innerlist.View(start, count);
+      return view == null ? null : new GuardedList<T>(view, underlying ?? this, true);
+    }
+
+    /// <summary>
+    /// Create the indicated view on the wrapped list and wrap it read-only.
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public IList<T> ViewOf(T item)
+    {
+      IList<T> view = innerlist.ViewOf(item);
+      return view == null ? null : new GuardedList<T>(view, underlying ?? this, true);
+    }
+
+    /// <summary>
+    /// Create the indicated view on the wrapped list and wrap it read-only.
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public IList<T> LastViewOf(T item)
+    {
+      IList<T> view = innerlist.LastViewOf(item);
+      return view == null ? null : new GuardedList<T>(view, underlying ?? this, true);
+    }
+
+
+    /// <summary>
+    /// </summary>
+    /// <value>The wrapped underlying list of the wrapped view </value>
+    public IList<T> Underlying { get { return underlying; } }
+
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>The offset of the wrapped list as a view.</value>
+    public int Offset { get { return innerlist.Offset; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public virtual bool IsValid { get { return innerlist.IsValid; } }
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> if this is a wrapped view and not a view that was made on a wrapper</exception>
+    /// <param name="offset"></param>
+    public IList<T> Slide(int offset)
+    {
+      if (slidableView)
+      {
+        innerlist.Slide(offset);
+        return this;
+      }
+      else
+        throw new ReadOnlyCollectionException("List is read only");
+    }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="offset"></param>
+    /// <param name="size"></param>
+    public IList<T> Slide(int offset, int size)
+    {
+      if (slidableView)
+      {
+        innerlist.Slide(offset, size);
+        return this;
+      }
+      else
+        throw new ReadOnlyCollectionException("List is read only");
+    }
+
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="offset"></param>
+    /// <returns></returns>
+    public bool TrySlide(int offset)
+    {
+      if (slidableView)
+        return innerlist.TrySlide(offset);
+      else
+        throw new ReadOnlyCollectionException("List is read only");
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="offset"></param>
+    /// <param name="size"></param>
+    /// <returns></returns>
+    public bool TrySlide(int offset, int size)
+    {
+      if (slidableView)
+        return innerlist.TrySlide(offset, size);
+      else
+        throw new ReadOnlyCollectionException("List is read only");
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="otherView"></param>
+    /// <returns></returns>
+    public IList<T> Span(IList<T> otherView)
+    {
+      GuardedList<T> otherGuardedList = otherView as GuardedList<T>;
+      if (otherGuardedList == null)
+        throw new IncompatibleViewException();
+      IList<T> span = innerlist.Span(otherGuardedList.innerlist);
+      if (span == null)
+        return null;
+      return new GuardedList<T>(span, underlying ?? otherGuardedList.underlying ?? this, true);
+    }
+
+    /// <summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// </summary>
+    public void Reverse() { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="start"></param>
+    /// <param name="count"></param>
+    public void Reverse(int start, int count)
+    { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+    /// <summary>
+    /// Check if wrapped list is sorted according to the default sorting order
+    /// for the item type T, as defined by the <see cref="T:C5.Comparer`1"/> class 
+    /// </summary>
+    /// <exception cref="NotComparableException">if T is not comparable</exception>
+    /// <returns>True if the list is sorted, else false.</returns>
+    public bool IsSorted() { return innerlist.IsSorted(Comparer<T>.Default); }
+
+    /// <summary>
+    /// Check if wrapped list is sorted
+    /// </summary>
+    /// <param name="c">The sorting order to use</param>
+    /// <returns>True if sorted</returns>
+    public bool IsSorted(SCG.IComparer<T> c) { return innerlist.IsSorted(c); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    public void Sort()
+    { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="c"></param>
+    public void Sort(SCG.IComparer<T> c)
+    { throw new ReadOnlyCollectionException("List is read only"); }
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    public void Shuffle()
+    { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="rnd"></param>
+    public void Shuffle(Random rnd)
+    { throw new ReadOnlyCollectionException("List is read only"); }
+
+    #endregion
+
+    #region IIndexed<T> Members
+
+    /// <summary> </summary>
+    /// <value>A directed collection of the items in the indicated interval of the wrapped collection</value>
+    public IDirectedCollectionValue<T> this[int start, int end]
+    { get { return new GuardedDirectedCollectionValue<T>(innerlist[start, end]); } }
+
+
+    /// <summary>
+    /// Find the (first) index of an item in the wrapped collection
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public int IndexOf(T item) { return innerlist.IndexOf(item); }
+
+
+    /// <summary>
+    /// Find the last index of an item in the wrapped collection
+    /// </summary>
+    /// <param name="item"></param>
+    /// <returns></returns>
+    public int LastIndexOf(T item) { return innerlist.LastIndexOf(item); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="i"></param>
+    /// <returns></returns>
+    public T RemoveAt(int i)
+    { throw new ReadOnlyCollectionException("List is read only"); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="start"></param>
+    /// <param name="count"></param>
+    public void RemoveInterval(int start, int count)
+    { throw new ReadOnlyCollectionException("List is read only"); }
+
+    #endregion
+
+    #region IDirectedEnumerable<T> Members
+
+    IDirectedEnumerable<T> IDirectedEnumerable<T>.Backwards()
+    { return Backwards(); }
+
+    #endregion
+
+    #region IStack<T> Members
+
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <returns>-</returns>
+    public void Push(T item)
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <returns>-</returns>
+    public T Pop()
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+    #endregion
+
+    #region IQueue<T> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <returns>-</returns>
+    public void Enqueue(T item)
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <returns>-</returns>
+    public T Dequeue()
+    { throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object"); }
+
+    #endregion
+
+    #region IDisposable Members
+
+    /// <summary>
+    /// Ignore: this may be called by a foreach or using statement.
+    /// </summary>
+    public void Dispose() { }
+
+    #endregion
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override object Clone()
+    {
+      return new GuardedList<T>((IList<T>)(innerlist.Clone()));
+    }
+
+    #region System.Collections.Generic.IList<T> Members
+
+    void System.Collections.Generic.IList<T>.RemoveAt(int index)
+    {
+      throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
+    }
+
+    void System.Collections.Generic.ICollection<T>.Add(T item)
+    {
+      throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
+    }
+
+    #endregion
+
+    #region System.Collections.ICollection Members
+
+    bool System.Collections.ICollection.IsSynchronized
+    {
+      get { return false; }
+    }
+
+    [Obsolete]
+    Object System.Collections.ICollection.SyncRoot
+    {
+      get { return innerlist.SyncRoot; }
+    }
+
+    void System.Collections.ICollection.CopyTo(Array arr, int index)
+    {
+      if (index < 0 || index + Count > arr.Length)
+        throw new ArgumentOutOfRangeException();
+
+      foreach (T item in this)
+        arr.SetValue(item, index++);
+    }
+
+    #endregion
+
+    #region System.Collections.IList Members
+    
+    Object System.Collections.IList.this[int index]
+    {
+      get { return this[index]; }
+      set
+      {
+        throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
+      }
+    }
+
+    int System.Collections.IList.Add(Object o)
+    {
+      throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
+    }
+
+    bool System.Collections.IList.Contains(Object o)
+    {
+      return Contains((T)o);
+    }
+
+    int System.Collections.IList.IndexOf(Object o)
+    {
+      return Math.Max(-1, IndexOf((T)o));
+    }
+
+    void System.Collections.IList.Insert(int index, Object o)
+    {
+      throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
+    }
+
+    void System.Collections.IList.Remove(Object o)
+    {
+      throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
+    }
+
+    void System.Collections.IList.RemoveAt(int index)
+    {
+      throw new ReadOnlyCollectionException("Collection cannot be modified through this guard object");
+    }
+
+    #endregion
+  }
+
+  /// <summary>
+  /// A read-only wrapper for a generic indexable queue (allows indexing).
+  /// 
+  /// <para>Suitable for wrapping a <see cref="T:C5.CircularQueue`1"/></para>
+  /// </summary>
+  /// <typeparam name="T">The item type.</typeparam>
+  public class GuardedQueue<T> : GuardedDirectedCollectionValue<T>, IQueue<T>
+  {
+    #region Fields
+
+    IQueue<T> queue;
+
+    #endregion
+
+    #region Constructor
+
+    /// <summary>
+    /// Wrap a queue in a read-only wrapper
+    /// </summary>
+    /// <param name="queue">The queue</param>
+    public GuardedQueue(IQueue<T> queue) : base(queue) { this.queue = queue; }
+
+    #endregion
+
+    #region IQueue<T> Members
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public bool AllowsDuplicates { get { return queue.AllowsDuplicates; } }
+
+    /// <summary>
+    /// Index into the wrapped queue
+    /// </summary>
+    /// <param name="i"></param>
+    /// <returns></returns>
+    public T this[int i] { get { return queue[i]; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <returns>-</returns>
+    public void Enqueue(T item)
+    { throw new ReadOnlyCollectionException("Queue cannot be modified through this guard object"); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <returns>-</returns>
+    public T Dequeue()
+    { throw new ReadOnlyCollectionException("Queue cannot be modified through this guard object"); }
+
+    #endregion
+  }
+
+  /// <summary>
+  /// A read-only wrapper for a dictionary.
+  ///
+  /// <i>Suitable for wrapping a HashDictionary. <see cref="T:C5.HashDictionary`2"/></i>
+  /// </summary>
+  public class GuardedDictionary<K, V> : GuardedCollectionValue<KeyValuePair<K, V>>, IDictionary<K, V>
+  {
+    #region Fields
+
+    IDictionary<K, V> dict;
+
+    #endregion
+
+    #region Constructor
+
+    /// <summary>
+    /// Wrap a dictionary in a read-only wrapper
+    /// </summary>
+    /// <param name="dict">the dictionary</param>
+    public GuardedDictionary(IDictionary<K, V> dict) : base(dict) { this.dict = dict; }
+
+    #endregion
+
+    #region IDictionary<K,V> Members
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public SCG.IEqualityComparer<K> EqualityComparer { get { return dict.EqualityComparer; } }
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a
+    /// read-only wrappper if used as a setter</exception>
+    /// <value>Get the value corresponding to a key in the wrapped dictionary</value>
+    public V this[K key]
+    {
+      get { return dict[key]; }
+      set { throw new ReadOnlyCollectionException(); }
+    }
+
+    /// <summary>
+    /// (This is a read-only wrapper)
+    /// </summary>
+    /// <value>True</value>
+    public bool IsReadOnly { get { return true; } }
+
+
+    //TODO: guard with a read-only wrapper? Probably so!
+    /// <summary> </summary>
+    /// <value>The collection of keys of the wrapped dictionary</value>
+    public ICollectionValue<K> Keys
+    { get { return dict.Keys; } }
+
+
+    /// <summary> </summary>
+    /// <value>The collection of values of the wrapped dictionary</value>
+    public ICollectionValue<V> Values { get { return dict.Values; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public virtual Fun<K, V> Fun { get { return delegate(K k) { return this[k]; }; } }
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="key"></param>
+    /// <param name="val"></param>
+    public void Add(K key, V val)
+    { throw new ReadOnlyCollectionException(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="items"></param>
+    public void AddAll<L, W>(SCG.IEnumerable<KeyValuePair<L, W>> items)
+      where L : K
+      where W : V
+    { throw new ReadOnlyCollectionException(); }
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="key"></param>
+    /// <returns></returns>
+    public bool Remove(K key)
+    { throw new ReadOnlyCollectionException(); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="key"></param>
+    /// <param name="val"></param>
+    /// <returns></returns>
+    public bool Remove(K key, out V val)
+    { throw new ReadOnlyCollectionException(); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    public void Clear()
+    { throw new ReadOnlyCollectionException(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public Speed ContainsSpeed { get { return dict.ContainsSpeed; } }
+
+    /// <summary>
+    /// Check if the wrapped dictionary contains a specific key
+    /// </summary>
+    /// <param name="key">The key</param>
+    /// <returns>True if it does</returns>
+    public bool Contains(K key) { return dict.Contains(key); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="keys"></param>
+    /// <returns></returns>
+    public bool ContainsAll<H>(SCG.IEnumerable<H> keys) where H : K { return dict.ContainsAll(keys); }
+
+    /// <summary>
+    /// Search for a key in the wrapped dictionary, reporting the value if found
+    /// </summary>
+    /// <param name="key">The key</param>
+    /// <param name="val">On exit: the value if found</param>
+    /// <returns>True if found</returns>
+    public bool Find(K key, out V val) { return dict.Find(key, out val); }
+
+    /// <summary>
+    /// Search for a key in the wrapped dictionary, reporting the value if found
+    /// </summary>
+    /// <param name="key">The key</param>
+    /// <param name="val">On exit: the value if found</param>
+    /// <returns>True if found</returns>
+    public bool Find(ref K key, out V val) { return dict.Find(ref key, out val); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="key"></param>
+    /// <param name="val"></param>
+    /// <returns></returns>
+    public bool Update(K key, V val)
+    { throw new ReadOnlyCollectionException(); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="key"></param>
+    /// <param name="val"></param>
+    /// <param name="oldval"></param>
+    /// <returns></returns>
+    public bool Update(K key, V val, out V oldval)
+    { throw new ReadOnlyCollectionException(); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="key"></param>
+    /// <param name="val"></param>
+    /// <returns></returns>
+    public bool FindOrAdd(K key, ref V val)
+    { throw new ReadOnlyCollectionException(); }
+
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="key"></param>
+    /// <param name="val"></param>
+    /// <returns></returns>
+    public bool UpdateOrAdd(K key, V val)
+    { throw new ReadOnlyCollectionException(); }
+
+    /// <summary>
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="key"></param>
+    /// <param name="val"></param>
+    /// <param name="oldval"></param>
+    /// <returns></returns>
+    public bool UpdateOrAdd(K key, V val, out V oldval)
+    { throw new ReadOnlyCollectionException(); }
+
+
+    /// <summary>
+    /// Check the internal consistency of the wrapped dictionary
+    /// </summary>
+    /// <returns>True if check passed</returns>
+    public bool Check() { return dict.Check(); }
+
+    #endregion
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public virtual object Clone()
+    {
+      return new GuardedDictionary<K, V>((IDictionary<K, V>)(dict.Clone()));
+    }
+  }
+
+
+
+  /// <summary>
+  /// A read-only wrapper for a sorted dictionary.
+  ///
+  /// <i>Suitable for wrapping a Dictionary. <see cref="T:C5.Dictionary`2"/></i>
+  /// </summary>
+  public class GuardedSortedDictionary<K, V> : GuardedDictionary<K, V>, ISortedDictionary<K, V>
+  {
+    #region Fields
+
+    ISortedDictionary<K, V> sorteddict;
+
+    #endregion
+
+    #region Constructor
+
+    /// <summary>
+    /// Wrap a sorted dictionary in a read-only wrapper
+    /// </summary>
+    /// <param name="sorteddict">the dictionary</param>
+    public GuardedSortedDictionary(ISortedDictionary<K, V> sorteddict)
+      : base(sorteddict)
+    { this.sorteddict = sorteddict; }
+
+    #endregion
+
+    #region ISortedDictionary<K,V> Members
+
+    /// <summary>
+    /// The key comparer used by this dictionary.
+    /// </summary>
+    /// <value></value>
+    public SCG.IComparer<K> Comparer { get { return sorteddict.Comparer; } }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value></value>
+    public new ISorted<K> Keys { get { return null; } }
+
+    /// <summary>
+    /// Find the entry in the dictionary whose key is the
+    /// predecessor of the specified key.
+    /// </summary>
+    /// <param name="key">The key</param>
+    /// <param name="res">The predecessor, if any</param>
+    /// <returns>True if key has a predecessor</returns>
+    public bool TryPredecessor(K key, out KeyValuePair<K, V> res)
+    {
+      return sorteddict.TryPredecessor(key, out res);
+    }
+
+    /// <summary>
+    /// Find the entry in the dictionary whose key is the
+    /// successor of the specified key.
+    /// </summary>
+    /// <param name="key">The key</param>
+    /// <param name="res">The successor, if any</param>
+    /// <returns>True if the key has a successor</returns>
+    public bool TrySuccessor(K key, out KeyValuePair<K, V> res)
+    {
+      return sorteddict.TrySuccessor(key, out res);
+    }
+
+    /// <summary>
+    /// Find the entry in the dictionary whose key is the
+    /// weak predecessor of the specified key.
+    /// </summary>
+    /// <param name="key">The key</param>
+    /// <param name="res">The predecessor, if any</param>
+    /// <returns>True if key has a weak predecessor</returns>
+    public bool TryWeakPredecessor(K key, out KeyValuePair<K, V> res)
+    {
+      return sorteddict.TryWeakPredecessor(key, out res);
+    }
+
+    /// <summary>
+    /// Find the entry in the dictionary whose key is the
+    /// weak successor of the specified key.
+    /// </summary>
+    /// <param name="key">The key</param>
+    /// <param name="res">The weak successor, if any</param>
+    /// <returns>True if the key has a weak successor</returns>
+    public bool TryWeakSuccessor(K key, out KeyValuePair<K, V> res)
+    {
+      return sorteddict.TryWeakSuccessor(key, out res);
+    }
+
+    /// <summary>
+    /// Get the entry in the wrapped dictionary whose key is the
+    /// predecessor of a specified key.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such entry exists </exception>    
+    /// <param name="key">The key</param>
+    /// <returns>The entry</returns>
+    public KeyValuePair<K, V> Predecessor(K key)
+    { return sorteddict.Predecessor(key); }
+
+    /// <summary>
+    /// Get the entry in the wrapped dictionary whose key is the
+    /// successor of a specified key.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such entry exists </exception>    
+    /// <param name="key">The key</param>
+    /// <returns>The entry</returns>
+    public KeyValuePair<K, V> Successor(K key)
+    { return sorteddict.Successor(key); }
+
+
+    /// <summary>
+    /// Get the entry in the wrapped dictionary whose key is the
+    /// weak predecessor of a specified key.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such entry exists </exception>    
+    /// <param name="key">The key</param>
+    /// <returns>The entry</returns>
+    public KeyValuePair<K, V> WeakPredecessor(K key)
+    { return sorteddict.WeakPredecessor(key); }
+
+
+    /// <summary>
+    /// Get the entry in the wrapped dictionary whose key is the
+    /// weak successor of a specified key.
+    /// </summary>
+    /// <exception cref="NoSuchItemException"> if no such entry exists </exception>    
+    /// <param name="key">The key</param>
+    /// <returns>The entry</returns>
+    public KeyValuePair<K, V> WeakSuccessor(K key)
+    { return sorteddict.WeakSuccessor(key); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public KeyValuePair<K, V> FindMin()
+    {
+      return sorteddict.FindMin();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <returns></returns>
+    public KeyValuePair<K, V> DeleteMin()
+    { throw new ReadOnlyCollectionException(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public KeyValuePair<K, V> FindMax()
+    {
+      return sorteddict.FindMax();
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <returns></returns>
+    public KeyValuePair<K, V> DeleteMax()
+    { throw new ReadOnlyCollectionException(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="c"></param>
+    /// <param name="lowEntry"></param>
+    /// <param name="lowIsValid"></param>
+    /// <param name="highEntry"></param>
+    /// <param name="highIsValid"></param>
+    /// <returns></returns>
+    public bool Cut(IComparable<K> c, out KeyValuePair<K, V> lowEntry, out bool lowIsValid, out KeyValuePair<K, V> highEntry, out bool highIsValid)
+    {
+      return sorteddict.Cut(c, out lowEntry, out lowIsValid, out highEntry, out highIsValid); ;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="bot"></param>
+    /// <returns></returns>
+    public IDirectedEnumerable<KeyValuePair<K, V>> RangeFrom(K bot)
+    {
+      return new GuardedDirectedEnumerable<KeyValuePair<K, V>>(sorteddict.RangeFrom(bot));
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="bot"></param>
+    /// <param name="top"></param>
+    /// <returns></returns>
+    public IDirectedEnumerable<KeyValuePair<K, V>> RangeFromTo(K bot, K top)
+    {
+      return new GuardedDirectedEnumerable<KeyValuePair<K, V>>(sorteddict.RangeFromTo(bot, top));
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <param name="top"></param>
+    /// <returns></returns>
+    public IDirectedEnumerable<KeyValuePair<K, V>> RangeTo(K top)
+    {
+      return new GuardedDirectedEnumerable<KeyValuePair<K, V>>(sorteddict.RangeTo(top));
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public IDirectedCollectionValue<KeyValuePair<K, V>> RangeAll()
+    {
+      return new GuardedDirectedCollectionValue<KeyValuePair<K, V>>(sorteddict.RangeAll());
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="items"></param>
+    public void AddSorted(System.Collections.Generic.IEnumerable<KeyValuePair<K, V>> items)
+    { throw new ReadOnlyCollectionException(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="low"></param>
+    public void RemoveRangeFrom(K low)
+    { throw new ReadOnlyCollectionException(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="low"></param>
+    /// <param name="hi"></param>
+    public void RemoveRangeFromTo(K low, K hi)
+    { throw new ReadOnlyCollectionException(); }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <exception cref="ReadOnlyCollectionException"> since this is a read-only wrappper</exception>
+    /// <param name="hi"></param>
+    public void RemoveRangeTo(K hi)
+    { throw new ReadOnlyCollectionException(); }
+
+    #endregion
+  }
+
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/PreProcess/PreProcess.csproj
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/PreProcess/PreProcess.csproj	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/PreProcess/PreProcess.csproj	(revision 3)
@@ -0,0 +1,48 @@
+﻿<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <RootNamespace>PreProcess</RootNamespace>
+    <AssemblyName>PreProcess</AssemblyName>
+    <WarningLevel>4</WarningLevel>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <UpgradeBackupLocation>
+    </UpgradeBackupLocation>
+    <OldToolsVersion>2.0</OldToolsVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>.\bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugSymbols>false</DebugSymbols>
+    <Optimize>true</Optimize>
+    <OutputPath>.\bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugSnk|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\DebugSnk\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSnk|AnyCPU' ">
+    <OutputPath>bin\ReleaseSnk\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="Program.cs" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
+</Project>
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/PreProcess/Program.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/PreProcess/Program.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/PreProcess/Program.cs	(revision 3)
@@ -0,0 +1,72 @@
+﻿/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Text;
+using System.IO;
+
+namespace PreProcess
+{
+  class Program
+  {
+    static void preprocess(string dir, string filein, string fileout, string symbol, string classin, string classout)
+    {
+      fileout = Path.Combine(dir, fileout);
+      string[] contents = File.ReadAllLines(Path.Combine(dir, filein));
+      string symboldef = "#define " + symbol + "not";
+      bool equal = File.Exists(fileout);
+      TextReader oldversion = equal ? new StreamReader(fileout) : null;
+      for (int lineno = 0; lineno < contents.Length; lineno++)
+      {
+        if (contents[lineno].StartsWith(symboldef))
+          contents[lineno] = "#define " + symbol;
+        else
+          contents[lineno] = contents[lineno].Replace(classin, classout);
+        if (equal)
+          equal = contents[lineno] == oldversion.ReadLine();
+      }
+      if (equal && oldversion.ReadLine() == null)
+      {
+        Console.Error.WriteLine("File {0} is up-to-date", fileout);
+        return;
+      }
+      File.WriteAllLines(fileout + "-new", contents);
+      if (oldversion != null)
+      {
+        oldversion.Close();
+        File.Replace(fileout + "-new", fileout, fileout + ".bak");
+        Console.Error.WriteLine("Updated {0}", fileout);
+      }
+      else
+      {
+        File.Move(fileout + "-new", fileout);
+        Console.Error.WriteLine("Created {0}", fileout);
+      }
+    }
+    static void Main(string[] args)
+    {
+      System.Environment.CurrentDirectory = @"..\..\..\C5";
+      preprocess("trees", "RedBlackTreeSet.cs", "RedBlackTreeBag.cs", "BAG", "TreeSet", "TreeBag");
+      preprocess("arrays", "ArrayList.cs", "HashedArrayList.cs", "HASHINDEX", "ArrayList", "HashedArrayList");
+      preprocess("linkedlists", "LinkedList.cs", "HashedLinkedList.cs", "HASHINDEX", "LinkedList", "HashedLinkedList");
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/AnagramHashBag.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/AnagramHashBag.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/AnagramHashBag.cs	(revision 3)
@@ -0,0 +1,158 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: anagrams 2004-08-08, 2004-11-16
+
+// Compile with 
+//   csc /r:C5.dll AnagramHashBag.cs 
+
+using System;
+using System.IO;                        // StreamReader, TextReader
+using System.Text;                      // Encoding
+using System.Text.RegularExpressions;   // Regex
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace AnagramHashBag
+{
+  class MyTest
+  {
+    public static void Main(String[] args)
+    {
+      Console.OutputEncoding = Encoding.GetEncoding("iso-8859-1");
+      SCG.IEnumerable<String> ss;
+      if (args.Length == 2)
+        ss = ReadFileWords(args[0], int.Parse(args[1]));
+      else
+        ss = args;
+      // foreach (String s in FirstAnagramOnly(ss)) 
+      //   Console.WriteLine(s);
+      //   Console.WriteLine("===");
+      Timer t = new Timer();
+      SCG.IEnumerable<SCG.IEnumerable<String>> classes = AnagramClasses(ss);
+      int count = 0;
+      foreach (SCG.IEnumerable<String> anagramClass in classes)
+      {
+        count++;
+        foreach (String s in anagramClass) 
+           Console.Write(s + " ");
+         Console.WriteLine();
+      }
+      Console.WriteLine("{0} non-trivial anagram classes", count);
+      Console.WriteLine(t.Check());
+    }
+
+    // Read words at most n words from a file
+
+    public static SCG.IEnumerable<String> ReadFileWords(String filename, int n)
+    {
+      Regex delim = new Regex("[^a-z���A-Z���0-9-]+");
+      Encoding enc = Encoding.GetEncoding("iso-8859-1");
+      using (TextReader rd = new StreamReader(filename, enc))
+      {
+        for (String line = rd.ReadLine(); line != null; line = rd.ReadLine()) {
+          foreach (String s in delim.Split(line))
+            if (s != "")
+              yield return s.ToLower();
+          if (--n == 0)
+            yield break;
+        }
+      }
+    }
+
+    // From an anagram point of view, a word is just a bag of
+    // characters.  So an anagram class is represented as HashBag<char>
+    // which permits fast equality comparison -- we shall use them as
+    // elements of hash sets or keys in hash maps.
+
+    public static HashBag<char> AnagramClass(String s) {
+      HashBag<char> anagram = new HashBag<char>();
+      foreach (char c in s)
+        anagram.Add(c);
+      return anagram;
+    }
+
+    // Given a sequence of strings, return only the first member of each
+    // anagram class.
+
+    public static SCG.IEnumerable<String> FirstAnagramOnly(SCG.IEnumerable<String> ss)
+    {
+      HashSet<HashBag<char>> anagrams = new HashSet<HashBag<char>>();
+      foreach (String s in ss) {
+        HashBag<char> anagram = AnagramClass(s);
+        if (!anagrams.Contains(anagram)) {
+          anagrams.Add(anagram);
+          yield return s;
+        }
+      }
+    }
+
+    // Given a sequence of strings, return all non-trivial anagram
+    // classes.  
+
+    // Using HashBag<char> and an unsequenced equalityComparer, this performs as
+    // follows on 1600 MHz Mobile P4 and .Net 2.0 beta 1 (wall-clock
+    // time):
+    //  50 000 words  2 822 classes   2.0 sec
+    // 100 000 words  5 593 classes   4.3 sec
+    // 200 000 words 11 705 classes   8.8 sec
+    // 300 000 words 20 396 classes  52.0 sec includes swapping
+    // 347 165 words 24 428 classes 146.0 sec includes swapping
+
+    // The maximal memory consumption is less than 180 MB.
+
+    public static SCG.IEnumerable<SCG.IEnumerable<String>>
+      AnagramClasses(SCG.IEnumerable<String> ss)
+    {
+      IDictionary<HashBag<char>, TreeSet<String>> classes
+        = new HashDictionary<HashBag<char>, TreeSet<String>>();
+      foreach (String s in ss) {
+        HashBag<char> anagram = AnagramClass(s);
+        TreeSet<String> anagramClass;
+        if (!classes.Find(anagram, out anagramClass))
+          classes[anagram] = anagramClass = new TreeSet<String>();
+        anagramClass.Add(s);
+      }
+      foreach (TreeSet<String> anagramClass in classes.Values)
+        if (anagramClass.Count > 1)
+          yield return anagramClass;
+    }
+  }
+
+// Crude timing utility ----------------------------------------
+
+  public class Timer
+  {
+    private DateTime start;
+
+    public Timer()
+    {
+      start = DateTime.Now;
+    }
+
+    public double Check()
+    {
+      TimeSpan dur = DateTime.Now - start;
+      return dur.TotalSeconds;
+    }
+  }
+
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/AnagramStrings.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/AnagramStrings.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/AnagramStrings.cs	(revision 3)
@@ -0,0 +1,159 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: anagrams represented as sorted strings 2004-08-26
+
+// To represent an anagram class, use a string containing the sorted
+// characters of a word.  
+
+// This is faster than a TreeBag<char> because the words and hence
+// bags are small.  Takes 15 CPU seconds and 138 MB RAM to find the
+// 26,058 anagram classes among 347,000 distinct words.
+
+// Compile with 
+//   csc /r:C5.dll Anagrams.cs 
+
+using System;
+using System.IO;                        // StreamReader, TextReader
+using System.Text;			// Encoding
+using System.Text.RegularExpressions;   // Regex
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace AnagramStrings
+{
+  class MyTest
+  {
+    public static void Main(String[] args)
+    {
+      Console.OutputEncoding = Encoding.GetEncoding("iso-8859-1");
+      SCG.IEnumerable<String> ss;
+      if (args.Length == 1)
+        ss = ReadFileWords(args[0]);
+      else
+        ss = args;
+
+      Timer t = new Timer();
+      SCG.IEnumerable<SCG.IEnumerable<String>> classes = AnagramClasses(ss);
+      int count = 0;
+      foreach (SCG.IEnumerable<String> anagramClass in classes)
+      {
+        count++;
+        // foreach (String s in anagramClass) 
+        //   Console.Write(s + " ");
+        // Console.WriteLine();
+      }
+      Console.WriteLine("{0} anagram classes", count);
+      Console.WriteLine(t.Check());
+    }
+
+    // Read words from a file
+
+    public static SCG.IEnumerable<String> ReadFileWords(String filename)
+    {
+      Regex delim = new Regex("[^a-z���A-Z���0-9-]+");
+      using (TextReader rd = new StreamReader(filename, Encoding.GetEncoding("iso-8859-1")))
+      {
+        for (String line = rd.ReadLine(); line != null; line = rd.ReadLine())
+          foreach (String s in delim.Split(line))
+            if (s != "")
+              yield return s.ToLower();
+      }
+    }
+
+    // From an anagram point of view, a word is just a bag of characters.
+
+    public static CharBag AnagramClass(String s)
+    {
+      return new CharBag(s);
+    }
+
+    // Given a sequence of strings, return all non-trivial anagram classes   
+
+    public static SCG.IEnumerable<SCG.IEnumerable<String>> AnagramClasses(SCG.IEnumerable<String> ss)
+    {
+      IDictionary<CharBag, HashSet<String>> classes
+        = new TreeDictionary<CharBag, HashSet<String>>();
+      foreach (String s in ss)
+      {
+        CharBag anagram = AnagramClass(s);
+        HashSet<String> anagramClass;
+        if (!classes.Find(anagram, out anagramClass))
+          classes[anagram] = anagramClass = new HashSet<String>();
+        anagramClass.Add(s);
+      }
+      foreach (HashSet<String> anagramClass in classes.Values)
+        if (anagramClass.Count > 1
+      ) // && anagramClass.Exists(delegate(String s) { return !s.EndsWith("s"); }))
+          yield return anagramClass;
+    }
+  }
+
+// A bag of characters is represented as a sorted string of the
+// characters, with multiplicity.  Since natural language words are
+// short, the bags are small, so this is vastly better than
+// representing character bags using HashBag<char> or TreeBag<char>
+
+  class CharBag : IComparable<CharBag>
+  {
+    private readonly String contents; // The bag's characters, sorted, with multiplicity
+
+    public CharBag(String s)
+    {
+      char[] chars = s.ToCharArray();
+      Array.Sort(chars);
+      this.contents = new String(chars);
+    }
+
+    public override int GetHashCode()
+    {
+      return contents.GetHashCode();
+    }
+
+    public bool Equals(CharBag that)
+    {
+      return this.contents.Equals(that.contents);
+    }
+
+    public int CompareTo(CharBag that)
+    {
+      return this.contents.CompareTo(that.contents);
+    }
+  }
+
+// Crude timing utility ----------------------------------------
+
+  public class Timer
+  {
+    private DateTime start;
+
+    public Timer()
+    {
+      start = DateTime.Now;
+    }
+
+    public double Check()
+    {
+      TimeSpan dur = DateTime.Now - start;
+      return dur.TotalSeconds;
+    }
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/AnagramTreeBag.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/AnagramTreeBag.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/AnagramTreeBag.cs	(revision 3)
@@ -0,0 +1,163 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: anagrams 2004-08-08, 2004-11-16
+
+// Compile with 
+//   csc /r:C5.dll AnagramTreeBag.cs 
+
+using System;
+using System.IO;                        // StreamReader, TextReader
+using System.Text;			// Encoding
+using System.Text.RegularExpressions;   // Regex
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace AnagramTreeBag
+{
+  class MyTest
+  {
+    public static void Main(String[] args)
+    {
+      Console.OutputEncoding = Encoding.GetEncoding("iso-8859-1");
+      SCG.IEnumerable<String> ss;
+      if (args.Length == 2)
+        ss = ReadFileWords(args[0], int.Parse(args[1]));
+      else
+        ss = args;
+      // foreach (String s in FirstAnagramOnly(ss)) 
+      //   Console.WriteLine(s);
+      //   Console.WriteLine("===");
+      Timer t = new Timer();
+      SCG.IEnumerable<SCG.IEnumerable<String>> classes = AnagramClasses(ss);
+      int count = 0;
+      foreach (SCG.IEnumerable<String> anagramClass in classes)
+      {
+        count++;
+	// foreach (String s in anagramClass)
+	//   Console.Write(s + " ");
+	// Console.WriteLine();
+      }
+      Console.WriteLine("{0} non-trivial anagram classes", count);
+      Console.WriteLine(t.Check());
+    }
+
+    // Read words at most n words from a file
+
+    public static SCG.IEnumerable<String> ReadFileWords(String filename, int n)
+    {
+      Regex delim = new Regex("[^a-z���A-Z���0-9-]+");
+      Encoding enc = Encoding.GetEncoding("iso-8859-1");
+      using (TextReader rd = new StreamReader(filename, enc))
+      {
+        for (String line = rd.ReadLine(); line != null; line = rd.ReadLine())
+        {
+          foreach (String s in delim.Split(line))
+            if (s != "")
+              yield return s.ToLower();
+          if (--n == 0)
+            yield break;
+        }
+      }
+    }
+
+    // From an anagram point of view, a word is just a bag of
+    // characters.  So an anagram class is represented as TreeBag<char>
+    // which permits fast equality comparison -- we shall use them as
+    // elements of hash sets or keys in hash maps.
+
+    public static TreeBag<char> AnagramClass(String s)
+    {
+      TreeBag<char> anagram = new TreeBag<char>(Comparer<char>.Default, EqualityComparer<char>.Default);
+      foreach (char c in s)
+        anagram.Add(c);
+      return anagram;
+    }
+
+    // Given a sequence of strings, return only the first member of each
+    // anagram class.
+
+    public static SCG.IEnumerable<String> FirstAnagramOnly(SCG.IEnumerable<String> ss)
+    {
+      HashSet<TreeBag<char>> anagrams = new HashSet<TreeBag<char>>();
+      foreach (String s in ss)
+      {
+        TreeBag<char> anagram = AnagramClass(s);
+        if (!anagrams.Contains(anagram))
+        {
+          anagrams.Add(anagram);
+          yield return s;
+        }
+      }
+    }
+
+    // Given a sequence of strings, return all non-trivial anagram
+    // classes.  
+
+    // Using TreeBag<char> and an unsequenced equalityComparer, this performs as
+    // follows on 1600 MHz Mobile P4 and .Net 2.0 beta 1 (wall-clock
+    // time; number of distinct words):
+
+    //  50 000 words  2 822 classes   2.4 sec
+    // 100 000 words  5 593 classes   4.6 sec
+    // 200 000 words 11 705 classes   9.6 sec
+    // 300 000 words 20 396 classes  88.2 sec (includes swapping)
+    // 347 165 words 24 428 classes 121.3 sec (includes swapping)
+
+    // The maximal memory consumption is around 180 MB.
+
+    public static SCG.IEnumerable<SCG.IEnumerable<String>>
+      AnagramClasses(SCG.IEnumerable<String> ss)
+    {
+      IDictionary<TreeBag<char>, TreeSet<String>> classes;
+      classes = new HashDictionary<TreeBag<char>, TreeSet<String>>();
+      foreach (String s in ss)
+      {
+        TreeBag<char> anagram = AnagramClass(s);
+        TreeSet<String> anagramClass;
+        if (!classes.Find(anagram, out anagramClass))
+          classes[anagram] = anagramClass = new TreeSet<String>();
+        anagramClass.Add(s);
+      }
+      foreach (TreeSet<String> anagramClass in classes.Values)
+        if (anagramClass.Count > 1)
+          yield return anagramClass;
+    }
+  }
+
+// Crude timing utility ----------------------------------------
+
+  public class Timer
+  {
+    private DateTime start;
+
+    public Timer()
+    {
+      start = DateTime.Now;
+    }
+
+    public double Check()
+    {
+      TimeSpan dur = DateTime.Now - start;
+      return dur.TotalSeconds;
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Anagrams.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Anagrams.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Anagrams.cs	(revision 3)
@@ -0,0 +1,177 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: anagrams 2004-08-08, 2004-11-16
+
+// Compile with 
+//   csc /r:C5.dll Anagrams.cs 
+
+using System;
+using System.IO;                        // StreamReader, TextReader
+using System.Text;			// Encoding
+using System.Text.RegularExpressions;   // Regex
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace Anagrams
+{
+  class MyTest
+  {
+    public static void Main(String[] args)
+    {
+      Console.OutputEncoding = Encoding.GetEncoding("iso-8859-1");
+      SCG.IEnumerable<String> ss;
+      if (args.Length == 2)
+        ss = ReadFileWords(args[0], int.Parse(args[1]));
+      else
+        ss = args;
+      // foreach (String s in FirstAnagramOnly(ss)) 
+      //   Console.WriteLine(s);
+      //   Console.WriteLine("===");
+      Timer t = new Timer();
+      SCG.IEnumerable<SCG.IEnumerable<String>> classes = AnagramClasses(ss);
+      int count = 0;
+      foreach (SCG.IEnumerable<String> anagramClass in classes)
+      {
+        count++;
+        // foreach (String s in anagramClass) 
+        //   Console.Write(s + " ");
+        // Console.WriteLine();
+      }
+      Console.WriteLine("{0} non-trivial anagram classes", count);
+      Console.WriteLine(t.Check());
+    }
+
+    // Read words at most n words from a file
+
+    public static SCG.IEnumerable<String> ReadFileWords(String filename, int n)
+    {
+      Regex delim = new Regex("[^a-z���A-Z���0-9-]+");
+      Encoding enc = Encoding.GetEncoding("iso-8859-1");
+      using (TextReader rd = new StreamReader(filename, enc))
+      {
+        for (String line = rd.ReadLine(); line != null; line = rd.ReadLine())
+        {
+          foreach (String s in delim.Split(line))
+            if (s != "")
+              yield return s.ToLower();
+          if (--n == 0)
+            yield break;
+        }
+      }
+    }
+
+    // From an anagram point of view, a word is just a bag of
+    // characters.  So an anagram class is represented as TreeBag<char>
+    // which permits fast equality comparison -- we shall use them as
+    // elements of hash sets or keys in hash maps.
+
+    public static TreeBag<char> AnagramClass(String s)
+    {
+      TreeBag<char> anagram = new TreeBag<char>(Comparer<char>.Default, EqualityComparer<char>.Default);
+      foreach (char c in s)
+        anagram.Add(c);
+      return anagram;
+    }
+
+    // Given a sequence of strings, return only the first member of each
+    // anagram class.
+
+    public static SCG.IEnumerable<String> FirstAnagramOnly(SCG.IEnumerable<String> ss)
+    {
+      SCG.IEqualityComparer<TreeBag<char>> tbh
+        = UnsequencedCollectionEqualityComparer<TreeBag<char>, char>.Default;
+      HashSet<TreeBag<char>> anagrams = new HashSet<TreeBag<char>>(tbh);
+      foreach (String s in ss)
+      {
+        TreeBag<char> anagram = AnagramClass(s);
+        if (!anagrams.Contains(anagram))
+        {
+          anagrams.Add(anagram);
+          yield return s;
+        }
+      }
+    }
+
+    // Given a sequence of strings, return all non-trivial anagram
+    // classes.  Should use a *sequenced* equalityComparer on a TreeBag<char>,
+    // obviously: after all, characters can be sorted by ASCII code.  On
+    // 347 000 distinct Danish words this takes 70 cpu seconds, 180 MB
+    // memory, and 263 wall-clock seconds (due to swapping).
+
+    // Using a TreeBag<char> and a sequenced equalityComparer takes 82 cpu seconds
+    // and 180 MB RAM to find the 26,058 anagram classes among 347,000
+    // distinct words.
+
+    // Using an unsequenced equalityComparer on TreeBag<char> or HashBag<char>
+    // makes it criminally slow: at least 1200 cpu seconds.  This must
+    // be because many bags get the same hash code, so that there are
+    // many collisions.  But exactly how the unsequenced equalityComparer works is
+    // not clear ... or is it because unsequenced equality is slow?
+
+    public static SCG.IEnumerable<SCG.IEnumerable<String>> AnagramClasses(SCG.IEnumerable<String> ss)
+    {
+      bool unseq = true;
+      IDictionary<TreeBag<char>, TreeSet<String>> classes;
+      if (unseq)
+      {
+        SCG.IEqualityComparer<TreeBag<char>> unsequencedTreeBagEqualityComparer
+    = UnsequencedCollectionEqualityComparer<TreeBag<char>, char>.Default;
+        classes = new HashDictionary<TreeBag<char>, TreeSet<String>>(unsequencedTreeBagEqualityComparer);
+      }
+      else
+      {
+        SCG.IEqualityComparer<TreeBag<char>> sequencedTreeBagEqualityComparer
+    = SequencedCollectionEqualityComparer<TreeBag<char>, char>.Default;
+        classes = new HashDictionary<TreeBag<char>, TreeSet<String>>(sequencedTreeBagEqualityComparer);
+      }
+      foreach (String s in ss)
+      {
+        TreeBag<char> anagram = AnagramClass(s);
+        TreeSet<String> anagramClass;
+        if (!classes.Find(anagram, out anagramClass))
+          classes[anagram] = anagramClass = new TreeSet<String>();
+        anagramClass.Add(s);
+      }
+      foreach (TreeSet<String> anagramClass in classes.Values)
+        if (anagramClass.Count > 1)
+          yield return anagramClass;
+    }
+  }
+
+// Crude timing utility ----------------------------------------
+
+  public class Timer
+  {
+    private DateTime start;
+
+    public Timer()
+    {
+      start = DateTime.Now;
+    }
+
+    public double Check()
+    {
+      TimeSpan dur = DateTime.Now - start;
+      return dur.TotalSeconds;
+    }
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Antipatterns.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Antipatterns.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Antipatterns.cs	(revision 3)
@@ -0,0 +1,103 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: Antipatterns 2004-12-29
+
+// Compile with 
+//   csc /r:C5.dll Antipatterns.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace Antipatterns {
+  class Antipatterns {
+    public static void Main(String[] args) {
+      ModifyInner();
+      DontModifyInner();
+    }
+
+    // Anti-pattern: modifying an inner collection while it is a
+    // member of an outer one may cause it to be lost from the outer
+    // collection.
+    
+    private static void ModifyInner() {
+      Console.WriteLine("\nAnti-pattern: Add to outer, modify, lose");
+      ICollection<ISequenced<int>> outer = new HashSet<ISequenced<int>>();
+      for (int i=0; i<100; i++) {
+        ISequenced<int> inner = new TreeSet<int>();
+        inner.Add(i); inner.Add(i+1);
+        outer.Add(inner);
+      }
+      ISequenced<int> 
+        inner1 = new TreeSet<int>(), 
+        inner2 = new TreeSet<int>(),
+        inner3 = new TreeSet<int>();    
+      inner1.AddAll<int>(new int[] { 2, 3, 5, 7, 11 });
+      inner2.AddAll(inner1); inner2.Add(13);
+      inner3.AddAll(inner1); 
+      outer.Add(inner1);
+      Console.WriteLine("inner1 in outer: {0}", outer.Contains(inner1));
+      Console.WriteLine("inner2 in outer: {0}", outer.Contains(inner2));
+      Console.WriteLine("inner3 in outer: {0}", outer.Contains(inner3));
+      inner1.Add(13);
+      Console.WriteLine("inner1 equals inner2: {0}", 
+                        outer.EqualityComparer.Equals(inner1, inner2));
+      Console.WriteLine("inner1 equals inner3: {0}", 
+                        outer.EqualityComparer.Equals(inner1, inner3));
+      Console.WriteLine("inner1 in outer: {0}", outer.Contains(inner1));
+      Console.WriteLine("inner2 in outer: {0}", outer.Contains(inner2));
+      Console.WriteLine("inner3 in outer: {0}", outer.Contains(inner3));
+      Console.WriteLine("outer.Count: {0}", outer.Count);
+    }
+
+    private static void DontModifyInner() {
+      Console.WriteLine("\nMake a snapshot and add it to outer");
+      ICollection<ISequenced<int>> outer = new HashSet<ISequenced<int>>();
+      for (int i=0; i<100; i++) {
+        ISequenced<int> inner = new TreeSet<int>();
+        inner.Add(i); inner.Add(i+1);
+        outer.Add(inner);
+      }
+      IPersistentSorted<int> 
+        inner1 = new TreeSet<int>(), 
+        inner2 = new TreeSet<int>(),
+        inner3 = new TreeSet<int>();    
+      inner1.AddAll<int>(new int[] { 2, 3, 5, 7, 11 });
+      inner2.AddAll(inner1); inner2.Add(13);
+      inner3.AddAll(inner1); 
+      // Take a snapshot and add it to outer:
+      outer.Add(inner1.Snapshot());
+      Console.WriteLine("inner1 in outer: {0}", outer.Contains(inner1));
+      Console.WriteLine("inner2 in outer: {0}", outer.Contains(inner2));
+      Console.WriteLine("inner3 in outer: {0}", outer.Contains(inner3));
+      inner1.Add(13);
+      Console.WriteLine("inner1 equals inner2: {0}", 
+                        outer.EqualityComparer.Equals(inner1, inner2));
+      Console.WriteLine("inner1 equals inner3: {0}", 
+                        outer.EqualityComparer.Equals(inner1, inner3));
+      Console.WriteLine("inner1 in outer: {0}", outer.Contains(inner1));
+      Console.WriteLine("inner2 in outer: {0}", outer.Contains(inner2));
+      Console.WriteLine("inner3 in outer: {0}", outer.Contains(inner3));
+      Console.WriteLine("outer.Count: {0}", outer.Count);
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/BipartiteMatching.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/BipartiteMatching.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/BipartiteMatching.cs	(revision 3)
@@ -0,0 +1,231 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: bipartite matching 2006-02-04
+
+// Compile with 
+//   csc /r:C5.dll BipartiteMatching.cs 
+
+using System;
+using System.IO;                        // StreamReader, TextReader
+using System.Text;			// Encoding
+using System.Text.RegularExpressions;   // Regex
+using C5;
+using SCG = System.Collections.Generic;
+using System.Diagnostics;
+
+namespace BipartiteMatching
+{
+  class MyTest
+  {
+    public static void Main(String[] args)
+    {
+      BipartiteMatching<int, char> bmi = new BipartiteMatching<int, char>(generateGraph(args));
+      HashDictionary<int, char> res = new HashDictionary<int, char>();
+      foreach (Rec<int,char> rec in bmi.Result)
+      {
+        res.Add(rec.X1, rec.X2);
+      }
+      for (int i = 0; i < args.Length; i++)
+      {
+        char c;
+        if (!res.Find(i,out c))
+          c='-';
+        Console.WriteLine(@"""{0}"" -> '{1}'", args[i], c);
+      }
+    }
+
+    static SCG.IEnumerable<Rec<int, char>> generateGraph(string[] words)
+    {
+      int i = 0;
+      foreach (string s in words)
+      {
+        foreach (char c in s)
+        {
+          yield return new Rec<int, char>(i, c);
+        }
+        i++;
+      }
+    }
+
+    /// <summary>
+    /// Implements Hopcroft and Karps algorithm for Maximum bipartite matching.
+    /// 
+    /// Input (to the constructor): the edges of the graph as a collection of pairs 
+    ///                             of labels of left and right nodes.
+    /// 
+    /// Output (from Result property): a maximum matching as a collection of pairs 
+    ///                             of labels of left and right nodes.
+    /// 
+    /// The algorithm uses natural equality on the label types to identify nodes.
+    /// 
+    /// </summary>
+    /// <typeparam name="TLeftLabel"></typeparam>
+    /// <typeparam name="TRightLabel"></typeparam>
+    public class BipartiteMatching<TLeftLabel, TRightLabel>
+    {
+      LeftNode[] leftNodes;
+      RightNode[] rightNodes;
+
+      class LeftNode
+      {
+        public TLeftLabel label;
+        public RightNode match;
+        public RightNode[] edges;
+        public LeftNode(TLeftLabel label, params RightNode[] edges)
+        {
+          this.label = label;
+          this.edges = (RightNode[])edges.Clone();
+        }
+        public override string ToString()
+        {
+          return String.Format(@"""{0}"" -> '{1}'", label, match);
+        }
+      }
+      class RightNode
+      {
+        public TRightLabel label;
+        public LeftNode match;
+        public LeftNode backref;
+        public LeftNode origin;
+        public RightNode(TRightLabel label)
+        {
+          this.label = label;
+        }
+        public override string ToString()
+        {
+          return String.Format(@"'{0}'", label);
+        }
+      }
+      public BipartiteMatching(SCG.IEnumerable<Rec<TLeftLabel, TRightLabel>> graph)
+      {
+        HashDictionary<TRightLabel, RightNode> rdict = new HashDictionary<TRightLabel, RightNode>();
+        HashDictionary<TLeftLabel, HashSet<RightNode>> edges = new HashDictionary<TLeftLabel, HashSet<RightNode>>();
+        HashSet<RightNode> newrnodes = new HashSet<RightNode>();
+        foreach (Rec<TLeftLabel, TRightLabel> edge in graph)
+        {
+          RightNode rnode;
+          if (!rdict.Find(edge.X2, out rnode))
+            rdict.Add(edge.X2, rnode = new RightNode(edge.X2));
+
+          HashSet<RightNode> ledges = newrnodes;
+          if (!edges.FindOrAdd(edge.X1, ref ledges))
+            newrnodes = new HashSet<RightNode>();
+          ledges.Add(rnode);
+        }
+
+        rightNodes = rdict.Values.ToArray();
+
+        leftNodes = new LeftNode[edges.Count];
+        int li = 0;
+        foreach (KeyValuePair<TLeftLabel, HashSet<RightNode>> les in edges)
+        {
+          leftNodes[li++] = new LeftNode(les.Key, les.Value.ToArray());
+        }
+
+        Compute();
+      }
+
+      public SCG.IEnumerable<Rec<TLeftLabel, TRightLabel>> Result
+      {
+        get
+        {
+          foreach (LeftNode l in leftNodes)
+          {
+            if (l.match != null)
+            {
+              yield return new Rec<TLeftLabel, TRightLabel>(l.label, l.match.label);
+            }
+          }
+        }
+      }
+
+      HashSet<RightNode> endPoints;
+      bool foundAugmentingPath;
+
+      void Compute()
+      {
+        HashSet<LeftNode> unmatchedLeftNodes = new HashSet<LeftNode>();
+        unmatchedLeftNodes.AddAll(leftNodes);
+        foundAugmentingPath = true;
+        Debug.Print("Compute start");
+        while (foundAugmentingPath)
+        {
+          Debug.Print("Start outer");
+          foundAugmentingPath = false;
+          endPoints = new HashSet<RightNode>();
+          foreach (RightNode rightNode in rightNodes)
+            rightNode.backref = null;
+          foreach (LeftNode l in unmatchedLeftNodes)
+          {
+            Debug.Print("Unmatched: {0}", l);
+            search(l, l);
+          }
+          while (!foundAugmentingPath && endPoints.Count > 0)
+          {
+            HashSet<RightNode> oldLayer = endPoints;
+            endPoints = new HashSet<RightNode>();
+            foreach (RightNode rb in oldLayer)
+              search(rb.match, rb.origin);
+          }
+          if (endPoints.Count == 0)
+            return;
+          //Flip
+          Debug.Print("Flip");
+          foreach (RightNode r in endPoints)
+          {
+            if (r.match == null && unmatchedLeftNodes.Contains(r.origin))
+            {
+              RightNode nextR = r;
+              LeftNode nextL = null;
+              while (nextR != null)
+              {
+                nextL = nextR.match = nextR.backref;
+                RightNode rSwap = nextL.match;
+                nextL.match = nextR;
+                nextR = rSwap;
+              }
+              unmatchedLeftNodes.Remove(nextL);
+            }
+          }
+        }
+      }
+
+      void search(LeftNode l, LeftNode origin)
+      {
+        foreach (RightNode r in l.edges)
+        {
+          if (r.backref == null)
+          {
+            r.backref = l;
+            r.origin = origin;
+            endPoints.Add(r);
+            if (r.match == null)
+              foundAugmentingPath = true;
+            //First round should be greedy
+            if (l == origin)
+              return;
+          }
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/BugHashedArray.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/BugHashedArray.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/BugHashedArray.cs	(revision 3)
@@ -0,0 +1,34 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+*/
+
+// C5 bugs 2007-09-16
+
+// Compile with 
+//   csc /r:C5.dll BugHashArray.cs 
+
+using System;
+using C5;
+
+namespace Anagrams {
+  class MyTest {
+    public static void Main(String[] args) {
+      HashedLinkedList<int> test = new HashedLinkedList<int>();
+      for (int i = 0; i < 33; i++) {
+        test.Add(i);
+      } // for
+
+      // Fails after 7 removals
+      for (int i = 0; i < 33; i++) {
+        Console.WriteLine(i);
+        test.Remove(i);
+      } // for
+
+      // Fails after 23 removals
+//        for (int i = 32; i >= 0; i--) {
+//          Console.WriteLine(i);
+//          test.Remove(i);
+//        } // for
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/CharBags.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/CharBags.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/CharBags.cs	(revision 3)
@@ -0,0 +1,47 @@
+// C5 example
+// 2004-09-01
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+class MyTest {
+  static readonly IHasher<TreeBag<char>> sequencedTreeBagHasher
+    = new C5.HasherBuilder.SequencedHasher<TreeBag<char>,char>();
+  static readonly IHasher<TreeBag<char>> unsequencedTreeBagHasher
+    = new C5.HasherBuilder.UnsequencedHasher<TreeBag<char>,char>();
+
+  static readonly IHasher<HashBag<char>> unsequencedHashBagHasher
+    = new C5.HasherBuilder.UnsequencedHasher<HashBag<char>,char>();
+
+  public static void Main(String[] args) {
+  }
+
+  public static void FindCollisions(SCG.IEnumerable<String> ss) {
+    HashBag<int> occurrences = new HashBag<int>();
+    foreach (String s in ss) {
+      TreeBag<char> tb = TreeBag(s);
+      // HashBag<char> hb = HashBag(s);
+      occurrences.Add(sequencedTreeBagHasher.GetHashCode(tb));
+      // unsequencedTreeBagHasher.GetHashCode(tb);
+      // unsequencedHashBagHasher.GetHashCode(hb);
+    }
+    
+  }
+  
+  public static TreeBag<char> TreeBag(String s) { 
+    TreeBag<char> anagram = new TreeBag<char>();
+    foreach (char c in s) 
+      anagram.Add(c);
+    return anagram;
+  }
+
+  public static HashBag<char> HashBag(String s) { 
+    HashBag<char> anagram = new HashBag<char>();
+    foreach (char c in s) 
+      anagram.Add(c);
+    return anagram;
+  }
+}
+
+
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Cloning.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Cloning.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Cloning.cs	(revision 3)
@@ -0,0 +1,45 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: anagrams 2004-12-
+
+// Compile with 
+//   csc /r:C5.dll Cloning.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace MyCloningTest {
+  class MyTest {
+    public static void Main(String[] args) {
+      IList<int> lst = new ArrayList<int>();
+      lst.AddAll(new int[] { 2, 3, 5, 7, 11, 13 });
+      Console.WriteLine(lst);
+      IList<int> v1 = lst.ViewOf(7);
+      Console.WriteLine(v1);
+      IList<int> v2 = (IList<int>)v1.Clone();
+      v2.Slide(1);
+      Console.WriteLine(v1);
+      Console.WriteLine(v2);
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/CollectionCollection.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/CollectionCollection.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/CollectionCollection.cs	(revision 3)
@@ -0,0 +1,125 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: collections of collections 2004-11-16
+
+// Compile with 
+//   csc /r:C5.dll CollectionCollection.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace CollectionCollection
+{
+  class MyTest
+  {
+    private static IList<int> col1 = new LinkedList<int>(),
+      col2 = new LinkedList<int>(), col3 = new LinkedList<int>();
+
+    public static void Main(String[] args) {
+      ListEqualityComparers();
+      IntSetSet();
+      CharBagSet();
+    }
+      
+    public static void ListEqualityComparers() {
+      col1.AddAll<int>(new int[] { 7, 9, 13 });
+      col2.AddAll<int>(new int[] { 7, 9, 13 });
+      col3.AddAll<int>(new int[] { 9, 7, 13 });
+
+      // Default equality and hasher == sequenced equality and hasher
+      HashSet<IList<int>> hs1 = new HashSet<IList<int>>();
+      Equalities("Default equality (sequenced equality)", hs1.EqualityComparer);
+      hs1.Add(col1); hs1.Add(col2); hs1.Add(col3);
+      Console.WriteLine("hs1.Count = {0}", hs1.Count);
+
+      // Sequenced equality and hasher 
+      SCG.IEqualityComparer<IList<int>> seqEqualityComparer
+        = SequencedCollectionEqualityComparer<IList<int>, int>.Default;
+      HashSet<IList<int>> hs2 = new HashSet<IList<int>>(seqEqualityComparer);
+      Equalities("Sequenced equality", hs2.EqualityComparer);
+      hs2.Add(col1); hs2.Add(col2); hs2.Add(col3);
+      Console.WriteLine("hs2.Count = {0}", hs2.Count);
+
+      // Unsequenced equality and hasher
+      SCG.IEqualityComparer<IList<int>> unseqEqualityComparer
+        = UnsequencedCollectionEqualityComparer<IList<int>, int>.Default;
+      HashSet<IList<int>> hs3 = new HashSet<IList<int>>(unseqEqualityComparer);
+      Equalities("Unsequenced equality", hs3.EqualityComparer);
+      hs3.Add(col1); hs3.Add(col2); hs3.Add(col3);
+      Console.WriteLine("hs3.Count = {0}", hs3.Count);
+
+      // Reference equality and hasher
+      SCG.IEqualityComparer<IList<int>> refEqEqualityComparer 
+        = ReferenceEqualityComparer<IList<int>>.Default;
+      HashSet<IList<int>> hs4 = new HashSet<IList<int>>(refEqEqualityComparer);
+      Equalities("Reference equality", hs4.EqualityComparer);
+      hs4.Add(col1); hs4.Add(col2); hs4.Add(col3);
+      Console.WriteLine("hs4.Count = {0}", hs4.Count);
+    }
+
+    public static void Equalities(String msg, SCG.IEqualityComparer<IList<int>> equalityComparer)
+    {
+      Console.WriteLine("\n{0}:", msg);
+      Console.Write("Equals(col1,col2)={0,-5}; ", equalityComparer.Equals(col1, col2));
+      Console.Write("Equals(col1,col3)={0,-5}; ", equalityComparer.Equals(col1, col3));
+      Console.WriteLine("Equals(col2,col3)={0,-5}", equalityComparer.Equals(col2, col3));
+    }
+
+    public static void IntSetSet() {
+      ICollection<ISequenced<int>> outer = new HashSet<ISequenced<int>>();
+      int[] ss = { 2, 3, 5, 7 };
+      TreeSet<int> inner = new TreeSet<int>();
+      outer.Add(inner.Snapshot());
+      foreach (int i in ss) { 
+        inner.Add(i);
+        outer.Add(inner.Snapshot());
+      }
+      foreach (ISequenced<int> s in outer) {
+        int sum = 0;
+        s.Apply(delegate(int x) { sum += x; });
+        Console.WriteLine("Set has {0} elements and sum {1}", s.Count, sum);
+      }
+    }
+
+    public static void CharBagSet() { 
+      String text = 
+        @"three sorted streams aligned by leading masters are stored 
+          there; an integral triangle ends, and stable tables keep;
+          being alert, they later reread the logarithm, peek at the
+          recent center, then begin to send their reader algorithm.";
+      String[] words = text.Split(' ', '\n', '\r', ';', ',', '.');
+      ICollection<ICollection<char>> anagrams 
+        = new HashSet<ICollection<char>>();
+      int count = 0;
+      foreach (String word in words) {
+        if (word != "") {
+          count++;
+          HashBag<char> anagram = new HashBag<char>();
+          anagram.AddAll<char>(word.ToCharArray());
+          anagrams.Add(anagram);
+        }
+      }
+      Console.WriteLine("Found {0} anagrams", count - anagrams.Count);
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/CollectionSanity.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/CollectionSanity.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/CollectionSanity.cs	(revision 3)
@@ -0,0 +1,65 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: anagrams 2004-12-08
+
+// Compile with 
+//   csc /r:C5.dll CollectionSanity.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace CollectionSanity {
+  class CollectionSanity {
+    public static void Main(String[] args) {
+      IList<int> col1 = new LinkedList<int>(),
+        col2 = new LinkedList<int>(), col3 = new LinkedList<int>();
+      col1.AddAll<int>(new int[] { 7, 9, 13 });
+      col2.AddAll<int>(new int[] { 7, 9, 13 });
+      col3.AddAll<int>(new int[] { 9, 7, 13 });
+
+      HashSet<IList<int>> hs1 = new HashSet<IList<int>>();
+      hs1.Add(col1); hs1.Add(col2); hs1.Add(col3);
+      Console.WriteLine("hs1 is sane: {0}", EqualityComparerSanity<int,IList<int>>(hs1));
+    }
+    
+    // When colls is a collection of collections, this method checks
+    // that all `inner' collections use the exact same equalityComparer.  Note
+    // that two equalityComparer objects may be functionally (extensionally)
+    // identical, yet be distinct objects.  However, if the equalityComparers
+    // were obtained from EqualityComparer<T>.Default, there will be at most one
+    // equalityComparer for each type T.
+
+    public static bool EqualityComparerSanity<T,U>(ICollectionValue<U> colls) 
+      where U : IExtensible<T>
+    {
+      SCG.IEqualityComparer<T> equalityComparer = null;
+      foreach (IExtensible<T> coll in colls) {
+        if (equalityComparer == null) 
+          equalityComparer = coll.EqualityComparer;
+        if (equalityComparer != coll.EqualityComparer) 
+          return false;
+      }
+      return true;
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Commonwords.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Commonwords.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Commonwords.cs	(revision 3)
@@ -0,0 +1,80 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: Find and print the most common words in a text file. 
+// Programming pearl by D.E. Knuth in CACM 29 (June 1986) 471-483.
+
+// Compile with 
+//   csc /r:C5.dll Commonwords.cs 
+
+using System;                           // Console
+using System.IO;                        // StreamReader, TextReader
+using System.Text.RegularExpressions;   // Regex
+using C5;                               // IDictionary, TreeDictionary, TreeSet
+using SCG = System.Collections.Generic; // IComparer
+
+namespace Commonwords {
+  class Commonwords {
+    static void Main(String[] args) {
+      if (args.Length != 2)
+        Console.WriteLine("Usage: Commonwords <maxwords> <filename>\n");
+      else 
+        PrintMostCommon(int.Parse(args[0]), args[1]);
+    }
+
+    static void PrintMostCommon(int maxWords, String filename) {
+      ICollection<String> wordbag = new HashBag<String>();
+      Regex delim = new Regex("[^a-zA-Z0-9]+");
+      using (TextReader rd = new StreamReader(filename)) {
+        for (String line = rd.ReadLine(); line != null; line = rd.ReadLine()) 
+          foreach (String s in delim.Split(line)) 
+            if (s != "")
+              wordbag.Add(s);
+      }
+      KeyValuePair<String,int>[] frequency 
+        = wordbag.ItemMultiplicities().ToArray();
+      // Sorting.IntroSort(frequency, 0, frequency.Length, new FreqOrder());
+      Sorting.IntroSort(frequency, 0, frequency.Length, 
+          new DelegateComparer<KeyValuePair<String,int>>
+                        (delegate(KeyValuePair<String,int> p1, 
+                                  KeyValuePair<String,int> p2)
+                        { 
+                          int major = p2.Value.CompareTo(p1.Value);
+                          return major != 0 ? major : p1.Key.CompareTo(p2.Key);
+                        }));
+      int stop = Math.Min(frequency.Length, maxWords);
+      for (int i=0; i<stop; i++) {
+        KeyValuePair<String,int> p = frequency[i];
+        Console.WriteLine("{0,4} occurrences of {1}", p.Value, p.Key);
+      }
+    }
+
+    // Lexicographic ordering: decreasing frequency, then increasing string
+    
+    class FreqOrder : SCG.IComparer<KeyValuePair<String,int>> { 
+      public int Compare(KeyValuePair<String,int> p1, 
+                         KeyValuePair<String,int> p2) {
+        int major = p2.Value.CompareTo(p1.Value);
+        return major != 0 ? major : p1.Key.CompareTo(p2.Key);
+      }
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/ComparerPatterns.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/ComparerPatterns.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/ComparerPatterns.cs	(revision 3)
@@ -0,0 +1,76 @@
+/*
+ Copyright (c) 2003-2008 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: Comparer patterns
+
+// Compile with 
+//   csc /r:C5.dll ComparerPatterns.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+class MyTest {
+  public static void Main(String[] args) {
+    SCG.IComparer<Rec<string,int>> lexico1 = new Lexico();
+    SCG.IComparer<Rec<string,int>> lexico2 =
+      new DelegateComparer<Rec<string,int>>(
+          delegate(Rec<string,int> item1, Rec<string,int> item2) { 
+            int major = item1.X1.CompareTo(item2.X1);
+            return major != 0 ? major : item1.X2.CompareTo(item2.X2);
+          });
+    Rec<String,int> r1 = new Rec<String,int>("Carsten", 1962);
+    Rec<String,int> r2 = new Rec<String,int>("Carsten", 1964);
+    Rec<String,int> r3 = new Rec<String,int>("Christian", 1932);
+    Console.WriteLine(lexico1.Compare(r1, r1) == 0);
+    Console.WriteLine(lexico1.Compare(r1, r2) < 0);
+    Console.WriteLine(lexico1.Compare(r2, r3) < 0);
+    Console.WriteLine(lexico2.Compare(r1, r1) == 0);
+    Console.WriteLine(lexico2.Compare(r1, r2) < 0);
+    Console.WriteLine(lexico2.Compare(r2, r3) < 0);
+    
+    SCG.IComparer<String> rev 
+      = ReverseComparer<String>(Comparer<String>.Default);
+    Console.WriteLine(rev.Compare("A", "A") == 0);
+    Console.WriteLine(rev.Compare("A", "B") > 0);
+    Console.WriteLine(rev.Compare("B", "A") < 0);
+  }
+
+  class Lexico : SCG.IComparer<Rec<String,int>> {
+    public int Compare(Rec<String,int> item1, Rec<String,int> item2) {
+      int major = item1.X1.CompareTo(item2.X1);
+      return major != 0 ? major : item1.X2.CompareTo(item2.X2);
+     }
+  }
+
+  class Lexico3 : SCG.IComparer<Rec<String,int,double>> {
+    public int Compare(Rec<String,int,double> item1, Rec<String,int,double> item2) {
+      int major1 = item1.X1.CompareTo(item2.X1);
+      int major2 = major1 != 0 ? major1 : item1.X2.CompareTo(item2.X2);
+      return major2 != 0 ? major2 : item1.X2.CompareTo(item2.X2);
+     }
+  }
+
+  public static SCG.IComparer<T> ReverseComparer<T>(SCG.IComparer<T> cmp) {
+    return new DelegateComparer<T>(
+       delegate(T item1, T item2) { return cmp.Compare(item2, item1); });
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/DecreaseIncreaseKey.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/DecreaseIncreaseKey.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/DecreaseIncreaseKey.cs	(revision 3)
@@ -0,0 +1,75 @@
+/*
+ Copyright (c) 2003-2008 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: Decrease key and increase key pattern chapter
+
+// Compile with 
+//   csc /r:C5.dll DecreaseIncreaseKey.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+class MyTest {
+  public static void Main(String[] args) {
+    IPriorityQueue<Prio<String>> pq = new IntervalHeap<Prio<String>>();
+    IPriorityQueueHandle<Prio<String>> h1, h2, h3;
+    h1 = h2 = h3 = null;
+    pq.Add(ref h1, new Prio<String>("surfing", 10));
+    pq.Add(ref h2, new Prio<String>("shopping", 6));
+    pq.Add(ref h3, new Prio<String>("cleaning", 4));
+    // The following is legal because +, - are overloaded on (Prio<D>,int):
+    pq[h2] -= 5;
+    pq[h1] += 5;
+    while (!pq.IsEmpty) 
+      Console.WriteLine(pq.DeleteMin());
+  }
+}
+
+struct Prio<D> : IComparable<Prio<D>> where D : class  {
+  public readonly D data;
+  private int priority;
+
+  public Prio(D data, int priority) {
+    this.data = data; 
+    this.priority = priority;
+  }
+  
+  public int CompareTo(Prio<D> that) {
+    return this.priority.CompareTo(that.priority);
+  }
+
+  public bool Equals(Prio<D> that) {
+    return this.priority == that.priority;
+  }
+
+  public static Prio<D> operator+(Prio<D> tp, int delta) {
+    return new Prio<D>(tp.data, tp.priority + delta);
+  }
+
+  public static Prio<D> operator-(Prio<D> tp, int delta) {
+    return new Prio<D>(tp.data, tp.priority - delta);
+  }
+
+  public override String ToString() {
+    return String.Format("{0}[{1}]", data, priority);
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/DistinctBag.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/DistinctBag.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/DistinctBag.cs	(revision 3)
@@ -0,0 +1,137 @@
+/*
+ Copyright (c) 2003-2007 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: A bag collection in which items that compare equal may
+// be distinct objects or values; that is, a collection with
+// AllowsDuplicates=true and DuplicatesByCounting=false.
+
+// The collection may contain distinct objects x1 and x2 for which the
+// equality comparer (or comparer) says that x1 and x2 are equal.
+// This can be implemented by a dictionary whose keys are the objects
+// themselves (using the given equality comparer or comparer), and
+// whose values are hashsets that use reference equality for equality
+// comparison.
+
+// Such a bag-with-actual-duplicates can be used to index objects, for
+// instance Person objects, by name and birthdate.  Several Person 
+// objects may have the same name, or the same birthdate, or even the 
+// same name and birthdate, yet be distinct Person objects.
+
+// How much of this can be implemented on top of CollectionBase<T>?
+
+// What should the meaning of Contains(x) be?
+
+// Compile with 
+//   csc /r:C5.dll DistinctBag.cs 
+
+using System;                           // Console
+using System.Text;                      // StringBuilder
+using C5; 
+using SCG = System.Collections.Generic;
+
+namespace DistinctBag
+{
+  static class DistinctBagMain
+  {
+    static void Main(String[] args)
+    {
+      DistinctHashBag<Person> nameColl 
+        = new DistinctHashBag<Person>(new Person.NameEqualityComparer());
+      Person p1 = new Person("Peter", 19620625), 
+        p2 = new Person("Carsten", 19640627), 
+        p3 = new Person("Carsten", 19640628);
+      nameColl.Add(p1);      
+      nameColl.Add(p2);
+      nameColl.Add(p3);
+      Console.WriteLine("nameColl = {0}", nameColl);
+    }
+  }
+
+  public class DistinctHashBag<T> where T : class { 
+    private HashDictionary<T, HashSet<T>> dict;
+
+    public DistinctHashBag(SCG.IEqualityComparer<T> eqc) {
+      dict = new HashDictionary<T,HashSet<T>>(eqc);
+    }
+
+    public DistinctHashBag() : this(EqualityComparer<T>.Default) {
+    }
+    
+    public bool Add(T item) { 
+      if (!dict.Contains(item)) 
+        dict.Add(item, new HashSet<T>(ReferenceEqualityComparer<T>.Default));
+      return dict[item].Add(item);
+    }
+
+    public bool Remove(T item) {
+      bool result = false;
+      if (dict.Contains(item)) {
+        HashSet<T> set = dict[item];
+        result = set.Remove(item);
+        if (set.IsEmpty) 
+          dict.Remove(item);
+      }
+      return result;
+    } 
+
+    public SCG.IEnumerator<T> GetEnumerator() { 
+      foreach (KeyValuePair<T,HashSet<T>> entry in dict) 
+	foreach (T item in entry.Value)
+	  yield return item;
+    }
+
+    public override String ToString() {
+      StringBuilder sb = new StringBuilder();
+      foreach (T item in this) 
+        sb.Append(item).Append(" ");
+      return sb.ToString();
+    }
+  }
+
+  public class Person {
+    String name;
+    int date;
+
+    public Person(String name, int date) {
+      this.name = name;
+      this.date = date;
+    }
+
+    public class NameEqualityComparer : SCG.IEqualityComparer<Person> {
+      public bool Equals(Person p1, Person p2) {
+        return p1.name == p2.name;
+      }
+      public int GetHashCode(Person p) { 
+        return p.name.GetHashCode();
+      }
+    }
+
+    public class DateComparer : SCG.IComparer<Person> {
+      public int Compare(Person p1, Person p2) { 
+        return p1.date.CompareTo(p2.date);
+      }
+    }
+
+    public override String ToString() {
+      return name + " (" + date + ")";
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/EventPatterns.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/EventPatterns.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/EventPatterns.cs	(revision 3)
@@ -0,0 +1,213 @@
+/*
+ Copyright (c) 2003-2008 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: EventPatterns.cs for pattern chapter
+
+// Compile with 
+//   csc /r:C5.dll EventPatterns.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace EventPatterns {
+  class EventPatterns {
+    public static void Main(String[] args) {
+      UnindexedCollectionEvents();
+      Console.WriteLine("--------------------");
+      IndexedCollectionEvents();
+      Console.WriteLine("--------------------");
+      UpdateEvent();
+    }
+
+    public static void UnindexedCollectionEvents() {
+      ICollection<int> coll = new ArrayList<int>();
+      ICollection<int> bag1 = new HashBag<int>();
+      bag1.AddAll(new int[] { 3, 2, 5, 5, 7, 7, 5, 3, 7, 7 });
+      // Add change handler
+      coll.CollectionChanged 
+        += delegate(Object c)  { 
+             Console.WriteLine("Collection changed"); 
+           };
+      // Add cleared handler
+      coll.CollectionCleared 
+        += delegate(Object c, ClearedEventArgs args) { 
+             Console.WriteLine("Collection cleared"); 
+           };
+      // Add added handler
+      coll.ItemsAdded 
+        += delegate(Object c, ItemCountEventArgs<int> args) { 
+             Console.WriteLine("Item {0} added", args.Item); 
+           };
+      // Add item count handler
+      AddItemsAddedCounter(coll);
+      AddItemsRemovedCounter(coll);
+      coll.AddAll(bag1);
+      coll.RemoveAll(new int[] { 2, 5, 6, 3, 7, 2 });
+      coll.Clear();
+      ICollection<int> bag2 = new HashBag<int>();
+      // Add added handler with multiplicity
+      bag2.ItemsAdded 
+        += delegate(Object c, ItemCountEventArgs<int> args) { 
+             Console.WriteLine("{0} copies of {1} added", 
+                               args.Count, args.Item);
+           };
+      bag2.AddAll(bag1);
+      // Add removed handler with multiplicity
+      bag2.ItemsRemoved 
+        += delegate(Object c, ItemCountEventArgs<int> args) { 
+             Console.WriteLine("{0} copies of {1} removed", 
+                               args.Count, args.Item);
+           };
+      bag2.RemoveAllCopies(7);
+    }
+
+    // This works for all kinds of collections, also those with bag
+    // semantics and representing duplicates by counting:
+
+    private static void AddItemsAddedCounter<T>(ICollection<T> coll) {
+      int addedCount = 0;
+      coll.ItemsAdded 
+        += delegate(Object c, ItemCountEventArgs<T> args) { 
+             addedCount += args.Count; 
+           };
+      coll.CollectionChanged 
+        += delegate(Object c) { 
+             if (addedCount > 0)
+               Console.WriteLine("{0} items were added", addedCount);
+             addedCount = 0;
+           };
+    }
+
+    // This works for all kinds of collections, also those with bag
+    // semantics and representing duplicates by counting:
+
+    private static void AddItemsRemovedCounter<T>(ICollection<T> coll) {
+      int removedCount = 0;
+      coll.ItemsRemoved 
+        += delegate(Object c, ItemCountEventArgs<T> args) { 
+             removedCount += args.Count; 
+           };
+      coll.CollectionChanged 
+        += delegate(Object c) { 
+             if (removedCount > 0)
+               Console.WriteLine("{0} items were removed", removedCount);
+             removedCount = 0;
+           };
+    }
+
+    // Event patterns on indexed collections
+
+    public static void IndexedCollectionEvents() {
+      IList<int> coll = new ArrayList<int>();
+      ICollection<int> bag = new HashBag<int>();
+      bag.AddAll(new int[] { 3, 2, 5, 5, 7, 7, 5, 3, 7, 7 });
+      // Add item inserted handler
+      coll.ItemInserted 
+        += delegate(Object c, ItemAtEventArgs<int> args)  { 
+             Console.WriteLine("Item {0} inserted at {1}", 
+                               args.Item, args.Index); 
+           };
+      coll.InsertAll(0, bag);
+      // Add item removed-at handler
+      coll.ItemRemovedAt 
+        += delegate(Object c, ItemAtEventArgs<int> args)  { 
+             Console.WriteLine("Item {0} removed at {1}", 
+                               args.Item, args.Index); 
+           };
+      coll.RemoveLast();
+      coll.RemoveFirst();
+      coll.RemoveAt(1);
+    }
+
+    // Recognizing Update event as a Removed-Added-Changed sequence
+
+    private enum State { Before, Removed, Updated };
+
+    private static void AddItemUpdatedHandler<T>(ICollection<T> coll) {
+      State state = State.Before;
+      T removed = default(T), added = default(T);
+      coll.ItemsRemoved 
+        += delegate(Object c, ItemCountEventArgs<T> args) { 
+             if (state==State.Before) {
+               state = State.Removed; 
+               removed = args.Item;
+             } else 
+               state = State.Before;
+           };
+      coll.ItemsAdded 
+        += delegate(Object c, ItemCountEventArgs<T> args) { 
+             if (state==State.Removed) { 
+               state = State.Updated; 
+               added = args.Item; 
+             } else 
+               state = State.Before;
+           };
+      coll.CollectionChanged 
+        += delegate(Object c)  { 
+             if (state==State.Updated) 
+               Console.WriteLine("Item {0} was updated to {1}", 
+                                 removed, added);
+             state = State.Before;
+           };
+    }
+
+    public static void UpdateEvent() {
+      ICollection<Teacher> coll = new HashSet<Teacher>();
+      AddItemUpdatedHandler(coll);
+      Teacher kristian = new Teacher("Kristian", "physics");
+      coll.Add(kristian);
+      coll.Add(new Teacher("Poul Einer", "mathematics"));
+      // This should be caught by the update handler:
+      coll.Update(new Teacher("Thomas", "mathematics"));
+      // This should not be caught by the update handler:
+      coll.Remove(kristian);
+      coll.Add(new Teacher("Jens", "physics"));
+      // The update handler is activated also by indexed updates
+      IList<int> list = new ArrayList<int>();
+      list.AddAll(new int[] { 7, 11, 13 });
+      AddItemUpdatedHandler(list);
+      list[1] = 9;
+    }
+  }
+
+  // Example class where objects may be equal yet display differently
+
+  class Teacher : IEquatable<Teacher> { 
+    private readonly String name, subject;
+
+    public Teacher(String name, String subject) { 
+      this.name = name; this.subject = subject;
+    }
+
+    public bool Equals(Teacher that) {
+      return this.subject.Equals(that.subject);
+    }
+
+    public override int GetHashCode() {
+      return subject.GetHashCode();
+    }
+
+    public override String ToString() {
+      return name + "[" + subject + "]";
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Extension.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Extension.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Extension.cs	(revision 3)
@@ -0,0 +1,49 @@
+// Experiment with extension methods and C5, 2007-10-31
+
+// Compile with 
+//   csc /r:C5.dll Extension.cs 
+
+using System;
+using System.Linq.Expressions;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace Extension {
+  static class AddOn {
+    public static int Added<T>(this ICollection<T> coll, int x) {
+      return coll.Count + x;
+    }
+
+    public static SCG.IEnumerable<T> Where<T>(this ICollection<T> coll, 
+					      Expression<Func<T,bool>> pred) 
+    {
+      Console.WriteLine("hallo");
+      //      Func<T,bool> p = pred.Compile();
+      Delegate p = pred.Compile();
+      foreach (T item in coll) 
+	//  	if (p(item))
+  	if ((bool)p.DynamicInvoke(item))
+  	  yield return item;
+    }
+
+    static void Main(String[] args) {
+      HashSet<Person> hs = new HashSet<Person>();
+      hs.Add(new Person("Ole"));
+      hs.Add(new Person("Hans"));
+      foreach (Person q in (from p in hs where p.name.Length == 4 select p))
+	Console.WriteLine(q);
+    }
+  }
+
+  class Person {
+    public readonly String name;
+
+    public Person(String name) {
+      this.name = name;
+    }
+    
+    public override String ToString() {
+      return name;
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Fileindex.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Fileindex.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Fileindex.cs	(revision 3)
@@ -0,0 +1,82 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: File index: read a text file, build and print a list of
+// words and the line numbers (without duplicates) on which they occur.
+
+// Compile with 
+//   csc /r:C5.dll Fileindex.cs 
+
+using System;                           // Console
+using System.IO;                        // StreamReader, TextReader
+using System.Text.RegularExpressions;   // Regex
+using C5;                               // IDictionary, TreeDictionary, TreeSet
+
+namespace FileIndex
+{
+  class Fileindex
+  {
+    static void Main(String[] args)
+    {
+      if (args.Length != 1)
+        Console.WriteLine("Usage: Fileindex <filename>\n");
+      else
+      {
+        IDictionary<String, TreeSet<int>> index = IndexFile(args[0]);
+        PrintIndex(index);
+      }
+    }
+
+    static IDictionary<String, TreeSet<int>> IndexFile(String filename)
+    {
+      IDictionary<String, TreeSet<int>> index = new TreeDictionary<String, TreeSet<int>>();
+      Regex delim = new Regex("[^a-zA-Z0-9]+");
+      using (TextReader rd = new StreamReader(filename))
+      {
+        int lineno = 0;
+        for (String line = rd.ReadLine(); line != null; line = rd.ReadLine())
+        {
+          String[] res = delim.Split(line);
+          lineno++;
+          foreach (String s in res)
+            if (s != "")
+            {
+              if (!index.Contains(s))
+                index[s] = new TreeSet<int>();
+              index[s].Add(lineno);
+            }
+        }
+      }
+      return index;
+    }
+
+    static void PrintIndex(IDictionary<String, TreeSet<int>> index)
+    {
+      foreach (String word in index.Keys)
+      {
+        Console.Write("{0}: ", word);
+        foreach (int ln in index[word])
+          Console.Write("{0} ", ln);
+        Console.WriteLine();
+      }
+    }
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/GCHForm.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/GCHForm.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/GCHForm.cs	(revision 3)
@@ -0,0 +1,271 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Drawing;
+using System.Collections;
+using System.ComponentModel;
+using System.Windows.Forms;
+using System.Diagnostics;
+using C5;
+
+namespace GConvexHull
+{
+	/// <summary>
+	/// Summary description for Form1.
+	/// </summary>
+  public class TesterForm : System.Windows.Forms.Form
+  {
+    //My data
+
+    //My GUI stuff
+    private System.Windows.Forms.Panel drawarea;
+
+    private Graphics drawg;
+
+    //Std stuff
+    private System.Windows.Forms.Button runButton;
+    private TextBox pointCount;
+
+    /// <summary>
+    /// Required designer variable.
+    /// </summary>
+    private System.ComponentModel.Container components = null;
+
+
+    public TesterForm()
+    {
+      //
+      // Required for Windows Form Designer support
+      //
+      InitializeComponent();
+
+      //
+      // TODO: Add any constructor code after InitializeComponent call
+      //
+      drawg = drawarea.CreateGraphics();
+      reset();
+    }
+
+
+    /// <summary>
+    /// Clean up any resources being used.
+    /// </summary>
+    protected override void Dispose(bool disposing)
+    {
+      if (disposing)
+      {
+        if (components != null)
+        {
+          components.Dispose();
+        }
+      }
+
+      base.Dispose(disposing);
+    }
+
+    #region Windows Form Designer generated code
+    /// <summary>
+    /// Required method for Designer support - do not modify
+    /// the contents of this method with the code editor.
+    /// </summary>
+    private void InitializeComponent()
+    {
+      this.drawarea = new System.Windows.Forms.Panel();
+      this.runButton = new System.Windows.Forms.Button();
+      this.pointCount = new System.Windows.Forms.TextBox();
+      this.SuspendLayout();
+      // 
+      // drawarea
+      // 
+      this.drawarea.BackColor = System.Drawing.Color.White;
+      this.drawarea.Location = new System.Drawing.Point(8, 9);
+      this.drawarea.Name = "drawarea";
+      this.drawarea.Size = new System.Drawing.Size(500, 500);
+      this.drawarea.TabIndex = 0;
+      this.drawarea.Paint += new System.Windows.Forms.PaintEventHandler(this.drawarea_Paint);
+      this.drawarea.Invalidated += new System.Windows.Forms.InvalidateEventHandler(this.drawarea_Invalidated);
+      this.drawarea.MouseMove += new System.Windows.Forms.MouseEventHandler(this.drawarea_MouseMove);
+      this.drawarea.MouseClick += new System.Windows.Forms.MouseEventHandler(this.drawarea_MouseClick);
+      // 
+      // runButton
+      // 
+      this.runButton.Location = new System.Drawing.Point(8, 516);
+      this.runButton.Name = "runButton";
+      this.runButton.Size = new System.Drawing.Size(42, 20);
+      this.runButton.TabIndex = 1;
+      this.runButton.Text = "Run";
+      this.runButton.Click += new System.EventHandler(this.runButton_Click);
+      // 
+      // pointCount
+      // 
+      this.pointCount.Location = new System.Drawing.Point(97, 517);
+      this.pointCount.Name = "pointCount";
+      this.pointCount.Size = new System.Drawing.Size(55, 20);
+      this.pointCount.TabIndex = 5;
+      // 
+      // TesterForm
+      // 
+      this.ClientSize = new System.Drawing.Size(524, 550);
+      this.Controls.Add(this.pointCount);
+      this.Controls.Add(this.runButton);
+      this.Controls.Add(this.drawarea);
+      this.Name = "TesterForm";
+      this.Text = "C5 Tester";
+      this.Load += new System.EventHandler(this.TesterForm_Load);
+      this.ResumeLayout(false);
+      this.PerformLayout();
+
+    }
+    #endregion
+
+    /// <summary>
+    /// The main entry point for the application.
+    /// </summary>
+    [STAThread]
+    static void Main()
+    {
+      Application.EnableVisualStyles();
+      Application.Run(new TesterForm());
+    }
+
+    Point[] pts;
+    Point[] chpts;
+
+    private void runButton_Click(object sender, System.EventArgs e)
+    {
+      int N = int.Parse(pointCount.Text);
+      pts = new Point[N];
+      for (int i = 0; i < N; i++)
+        pts[i] = Point.Random(500, 500);
+      chpts = Convexhull.ConvexHull(pts);
+
+      drawarea.Invalidate();
+    }
+
+
+    private void drawarea_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
+    {
+      mydraw();
+    }
+
+
+    private void resetButton_Click(object sender, System.EventArgs e)
+    {
+      reset();
+    }
+
+
+    private void reset()
+    {
+      drawarea.Invalidate();//(new Rectangle(0, 0, 40, 40));
+    }
+
+
+
+    public void mydraw()
+    {
+      if (pts == null)
+      {
+        return;
+      }
+      for (int i = 0; i < pts.Length; i++)
+      {
+        Point p = pts[i];
+        drawg.DrawEllipse(new Pen(Color.Red), transx(p.x) - 2, transy(p.y) - 2, 4, 4);
+      }
+      for (int i = 0; i < chpts.Length; i++)
+      {
+        int j = i + 1 < chpts.Length ? i + 1 : 0;
+        drawg.DrawEllipse(new Pen(Color.Blue), transx(chpts[i].x) - 2, transy(chpts[i].y) - 2, 4, 4);
+        drawg.DrawLine(new Pen(Color.LawnGreen), transx(chpts[i].x), transx(chpts[i].y), transx(chpts[j].x), transx(chpts[j].y));
+      }
+    }
+
+
+
+    private int transx(double x)
+    {
+      return (int)x;
+    }
+
+
+    private int transy(double y)
+    {
+      return (int)y;
+    }
+
+
+    private void dumpButton_Click(object sender, System.EventArgs e)
+    {
+      Debug.WriteLine("###############");
+      Debug.WriteLine("###############");
+    }
+
+
+    private void graphTypeControlArray_Click(object sender, System.EventArgs e)
+    {
+      Debug.WriteLine(e.GetType());
+      Debug.WriteLine(sender.GetType());
+      drawarea.Invalidate();
+    }
+
+
+    private void drawarea_MouseMove(object sender, MouseEventArgs e)
+    {
+    }
+
+
+    private void drawarea_MouseClick(object sender, MouseEventArgs e)
+    {
+      //double x = untransx(e.X), y = untransy(e.Y);
+
+    }
+
+
+    private void drawarea_Invalidated(object sender, InvalidateEventArgs e)
+    {
+      //msg.Text = e.InvalidRect + "";
+      //mydraw();
+    }
+
+
+    private void preparedFigureSelection_SelectedIndexChanged(object sender, System.EventArgs e)
+    {
+    }
+
+    private void voronoiButton_CheckedChanged(object sender, EventArgs e)
+    {
+      graphTypeControlArray_Click(sender, e);
+    }
+
+    private void delaunayButton_CheckedChanged(object sender, EventArgs e)
+    {
+      graphTypeControlArray_Click(sender, e);
+    }
+
+    private void TesterForm_Load(object sender, EventArgs e)
+    {
+
+    }
+
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/GCHForm.resx
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/GCHForm.resx	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/GCHForm.resx	(revision 3)
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="utf-8"?>
+<root>
+  <!-- 
+    Microsoft ResX Schema 
+    
+    Version 2.0
+    
+    The primary goals of this format is to allow a simple XML format 
+    that is mostly human readable. The generation and parsing of the 
+    various data types are done through the TypeConverter classes 
+    associated with the data types.
+    
+    Example:
+    
+    ... ado.net/XML headers & schema ...
+    <resheader name="resmimetype">text/microsoft-resx</resheader>
+    <resheader name="version">2.0</resheader>
+    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
+    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
+    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
+    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
+    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
+        <value>[base64 mime encoded serialized .NET Framework object]</value>
+    </data>
+    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
+        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
+        <comment>This is a comment</comment>
+    </data>
+                
+    There are any number of "resheader" rows that contain simple 
+    name/value pairs.
+    
+    Each data row contains a name, and value. The row also contains a 
+    type or mimetype. Type corresponds to a .NET class that support 
+    text/value conversion through the TypeConverter architecture. 
+    Classes that don't support this are serialized and stored with the 
+    mimetype set.
+    
+    The mimetype is used for serialized objects, and tells the 
+    ResXResourceReader how to depersist the object. This is currently not 
+    extensible. For a given mimetype the value must be set accordingly:
+    
+    Note - application/x-microsoft.net.object.binary.base64 is the format 
+    that the ResXResourceWriter will generate, however the reader can 
+    read any of the formats listed below.
+    
+    mimetype: application/x-microsoft.net.object.binary.base64
+    value   : The object must be serialized with 
+            : System.Serialization.Formatters.Binary.BinaryFormatter
+            : and then encoded with base64 encoding.
+    
+    mimetype: application/x-microsoft.net.object.soap.base64
+    value   : The object must be serialized with 
+            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
+            : and then encoded with base64 encoding.
+
+    mimetype: application/x-microsoft.net.object.bytearray.base64
+    value   : The object must be serialized into a byte array 
+            : using a System.ComponentModel.TypeConverter
+            : and then encoded with base64 encoding.
+    -->
+  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:element name="root" msdata:IsDataSet="true">
+      <xsd:complexType>
+        <xsd:choice maxOccurs="unbounded">
+          <xsd:element name="metadata">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" />
+              <xsd:attribute name="type" type="xsd:string" />
+              <xsd:attribute name="mimetype" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="assembly">
+            <xsd:complexType>
+              <xsd:attribute name="alias" type="xsd:string" />
+              <xsd:attribute name="name" type="xsd:string" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="data">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+            </xsd:complexType>
+          </xsd:element>
+          <xsd:element name="resheader">
+            <xsd:complexType>
+              <xsd:sequence>
+                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+              </xsd:sequence>
+              <xsd:attribute name="name" type="xsd:string" use="required" />
+            </xsd:complexType>
+          </xsd:element>
+        </xsd:choice>
+      </xsd:complexType>
+    </xsd:element>
+  </xsd:schema>
+  <resheader name="resmimetype">
+    <value>text/microsoft-resx</value>
+  </resheader>
+  <resheader name="version">
+    <value>2.0</value>
+  </resheader>
+  <resheader name="reader">
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <resheader name="writer">
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+  </resheader>
+  <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
+    <value>25</value>
+  </metadata>
+</root>
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/GConvexHull.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/GConvexHull.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/GConvexHull.cs	(revision 3)
@@ -0,0 +1,178 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// Compile with 
+//    csc /r:C5.dll GConvexHull.cs
+
+using System;
+using C5;
+
+namespace GConvexHull
+{
+// Find the convex hull of a point set in the plane
+
+// An implementation of Graham's (1972) point elimination algorithm,
+// as modified by Andrew (1979) to find lower and upper hull separately.
+
+// This implementation correctly handle duplicate points, and
+// multiple points with the same x-coordinate.
+
+// 1. Sort the points lexicographically by increasing (x,y), thus 
+//    finding also a leftmost point L and a rightmost point R.
+// 2. Partition the point set into two lists, upper and lower, according as 
+//    point is above or below the segment LR.  The upper list begins with 
+//    L and ends with R; the lower list begins with R and ends with L.
+// 3. Traverse the point lists clockwise, eliminating all but the extreme
+//    points (thus eliminating also duplicate points).
+// 4. Join the point lists (in clockwise order) in an array, 
+//    leaving out L from lower and R from upper.
+
+  public class Convexhull
+  {
+    public static Point[] ConvexHull(Point[] pts)
+    {
+      // 1. Sort points lexicographically by increasing (x, y)
+      int N = pts.Length;
+      Array.Sort(pts);
+      Point left = pts[0], right = pts[N - 1];
+      // 2. Partition into lower hull and upper hull
+      IList<Point> lower = new LinkedList<Point>(),
+        upper = new LinkedList<Point>();
+      lower.InsertFirst(left); upper.InsertLast(left);
+      for (int i = 0; i < N; i++)
+      {
+        double det = Point.Area2(left, right, pts[i]);
+        if (det < 0)
+          lower.InsertFirst(pts[i]);
+        else if (det > 0)
+          upper.InsertLast(pts[i]);
+      }
+      lower.InsertFirst(right);
+      upper.InsertLast(right);
+      // 3. Eliminate points not on the hull
+      Eliminate(lower);
+      Eliminate(upper);
+      // 4. Join the lower and upper hull, leaving out lower.Last and upper.Last
+      Point[] res = new Point[lower.Count + upper.Count - 2];
+      lower[0, lower.Count - 1].CopyTo(res, 0);
+      upper[0, upper.Count - 1].CopyTo(res, lower.Count - 1);
+      return res;
+    }
+
+    // Graham's scan
+    public static void Eliminate(IList<Point> lst)
+    {
+      IList<Point> view = lst.View(0, 0);
+      int slide = 0;
+      while (view.TrySlide(slide, 3))
+        if (Point.Area2(view[0], view[1], view[2]) < 0)   // right turn
+          slide = 1;
+        else
+        {                                                 // left or straight
+          view.RemoveAt(1);
+          slide = view.Offset != 0 ? -1 : 0;
+        }
+    }
+  }
+
+// ------------------------------------------------------------
+
+// Points in the plane
+
+  public class Point : IComparable<Point>
+  {
+    private static readonly C5Random rnd = new C5Random(42);
+
+    public readonly double x, y;
+
+    public Point(double x, double y)
+    {
+      this.x = x; this.y = y;
+    }
+
+    public override string ToString()
+    {
+      return "(" + x + ", " + y + ")";
+    }
+
+    public static Point Random(int w, int h)
+    {
+      return new Point(rnd.Next(w), rnd.Next(h));
+    }
+
+    public bool Equals(Point p2)
+    {
+      return x == p2.x && y == p2.y;
+    }
+
+    public int CompareTo(Point p2)
+    {
+      int major = x.CompareTo(p2.x);
+      return major != 0 ? major : y.CompareTo(p2.y);
+    }
+
+    // Twice the signed area of the triangle (p0, p1, p2)
+    public static double Area2(Point p0, Point p1, Point p2)
+    {
+      return p0.x * (p1.y - p2.y) + p1.x * (p2.y - p0.y) + p2.x * (p0.y - p1.y);
+    }
+  }
+
+// ------------------------------------------------------------
+
+  class GConvexHull
+  {
+    static void Main(String[] args)
+    {
+      if (args.Length == 1)
+      {
+        string arg = args[0];
+        int N = int.Parse(arg);
+        Point[] pts = new Point[N];
+        for (int i = 0; i < N; i++)
+          pts[i] = Point.Random(500, 500);
+        Point[] chpts = Convexhull.ConvexHull(pts);
+        Console.WriteLine("Area is " + Area(chpts));
+        Print(chpts);
+      }
+      else
+        Console.WriteLine("Usage: GConvexHull <pointcount>\n");
+    }
+
+    // The area of a polygon (represented by an array of ordered vertices)
+    public static double Area(Point[] pts)
+    {
+      int N = pts.Length;
+      Point origo = new Point(0, 0);
+      double area2 = 0;
+      for (int i = 0; i < N; i++)
+        area2 += Point.Area2(origo, pts[i], pts[(i + 1) % N]);
+      return Math.Abs(area2 / 2);
+    }
+
+    public static void Print(Point[] pts)
+    {
+      int N = pts.Length;
+      for (int i = 0; i < N; i++)
+        Console.WriteLine(pts[i]);
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/GNfaToDfa.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/GNfaToDfa.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/GNfaToDfa.cs	(revision 3)
@@ -0,0 +1,666 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// Compile with 
+//    csc /r:C5.dll GNfaToDfa.cs
+
+// C5 examples: RegExp -> NFA -> DFA -> Graph
+// Java 2000-10-07, GC# 2001-10-23, C# 2.0 2003-09-03, C# 2.0+C5 2004-08-08
+
+// This file contains, in order:
+//   * Helper class Set<T> defined in terms of C5 classes.
+//   * A class Nfa for representing an NFA (a nondeterministic finite 
+//     automaton), and for converting it to a DFA (a deterministic 
+//     finite automaton).  Most complexity is in this class.
+//   * A class Dfa for representing a DFA, a deterministic finite 
+//     automaton, and for writing a dot input file representing the DFA.
+//   * Classes for representing regular expressions, and for building an 
+//     NFA from a regular expression
+//   * A test class that creates an NFA, a DFA, and a dot input file 
+//     for a number of small regular expressions.  The DFAs are 
+//     not minimized.
+
+using System;
+using System.Text;
+using System.IO;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace GNfaToDfa
+{
+
+  public class Set<T> : HashSet<T> {
+    public Set(SCG.IEnumerable<T> enm) : base() {
+      AddAll(enm);
+    }
+
+    public Set(params T[] elems) : this((SCG.IEnumerable<T>)elems) { }
+
+    // Set union (+), difference (-), and intersection (*):
+
+    public static Set<T> operator +(Set<T> s1, Set<T> s2) {
+      if (s1 == null || s2 == null) 
+        throw new ArgumentNullException("Set+Set");
+      else {
+        Set<T> res = new Set<T>(s1);
+        res.AddAll(s2);
+        return res;
+      }
+    }
+
+    public static Set<T> operator -(Set<T> s1, Set<T> s2) {
+      if (s1 == null || s2 == null) 
+        throw new ArgumentNullException("Set-Set");
+      else {
+        Set<T> res = new Set<T>(s1);
+        res.RemoveAll(s2);
+        return res;
+      }
+    }
+
+    public static Set<T> operator *(Set<T> s1, Set<T> s2) {
+      if (s1 == null || s2 == null) 
+        throw new ArgumentNullException("Set*Set");
+      else {
+        Set<T> res = new Set<T>(s1);
+        res.RetainAll(s2);
+        return res;
+      }
+    }
+
+    // Equality of sets; take care to avoid infinite loops
+
+    public static bool operator ==(Set<T> s1, Set<T> s2) {
+      return EqualityComparer<Set<T>>.Default.Equals(s1, s2);
+    }
+
+    public static bool operator !=(Set<T> s1, Set<T> s2) {
+      return !(s1 == s2);
+    }
+
+    public override bool Equals(Object that) {
+      return this == (that as Set<T>);
+    }
+
+    public override int GetHashCode() {
+      return EqualityComparer<Set<T>>.Default.GetHashCode(this);
+    }
+
+    // Subset (<=) and superset (>=) relation:
+
+    public static bool operator <=(Set<T> s1, Set<T> s2) {
+      if (s1 == null || s2 == null) 
+        throw new ArgumentNullException("Set<=Set");
+      else
+        return s1.ContainsAll(s2);
+    }
+
+    public static bool operator >=(Set<T> s1, Set<T> s2) {
+      if (s1 == null || s2 == null) 
+        throw new ArgumentNullException("Set>=Set");
+      else
+        return s2.ContainsAll(s1);
+    }
+    
+    public override String ToString() {
+      StringBuilder sb = new StringBuilder();
+      sb.Append("{");
+      bool first = true;
+      foreach (T x in this) {
+        if (!first)
+          sb.Append(",");
+        sb.Append(x);
+        first = false;
+      }
+      sb.Append("}");
+      return sb.ToString();
+    }
+  }
+
+// ----------------------------------------------------------------------
+
+// Regular expressions, NFAs, DFAs, and dot graphs
+// sestoft@dina.kvl.dk * 
+// Java 2001-07-10 * C# 2001-10-22 * Gen C# 2001-10-23, 2003-09-03
+
+// In the Generic C# 2.0 version we 
+//  use Queue<int> and Queue<Set<int>> for worklists
+//  use Set<int> for pre-DFA states
+//  use ArrayList<Transition> for NFA transition relations
+//  use HashDictionary<Set<int>, HashDictionary<String, Set<int>>>
+//  and HashDictionary<int, HashDictionary<String, int>> for DFA transition relations
+
+/* Class Nfa and conversion from NFA to DFA ---------------------------
+
+  A nondeterministic finite automaton (NFA) is represented as a
+  dictionary mapping a state number (int) to an arraylist of
+  Transitions, a Transition being a pair of a label lab (a string,
+  null meaning epsilon) and a target state (an int).
+
+  A DFA is created from an NFA in two steps:
+
+    (1) Construct a DFA whose each of whose states is composite,
+        namely a set of NFA states (Set of int).  This is done by
+        methods CompositeDfaTrans and EpsilonClose.
+
+    (2) Replace composite states (Set of int) by simple states
+        (int).  This is done by methods Rename and MkRenamer.
+
+  Method CompositeDfaTrans works as follows: 
+
+    Create the epsilon-closure S0 (a Set of ints) of the start state
+    s0, and put it in a worklist (a Queue).  Create an empty DFA
+    transition relation, which is a dictionary mapping a composite
+    state (an epsilon-closed set of ints) to a dictionary mapping a
+    label (a non-null string) to a composite state.
+
+    Repeatedly choose a composite state S from the worklist.  If it is
+    not already in the keyset of the DFA transition relation, compute
+    for every non-epsilon label lab the set T of states reachable by
+    that label from some state s in S.  Compute the epsilon-closure
+    Tclose of every such state T and put it on the worklist.  Then add
+    the transition S -lab-> Tclose to the DFA transition relation, for
+    every lab.
+
+  Method EpsilonClose works as follows: 
+
+    Given a set S of states.  Put the states of S in a worklist.
+    Repeatedly choose a state s from the worklist, and consider all
+    epsilon-transitions s -eps-> s' from s.  If s' is in S already,
+    then do nothing; otherwise add s' to S and the worklist.  When the
+    worklist is empty, S is epsilon-closed; return S.
+
+  Method MkRenamer works as follows: 
+
+    Given a dictionary mapping a set of int to something, create an
+    injective dictionary mapping from set of int to int, by choosing a
+    fresh int for every key in the given dictionary.
+
+  Method Rename works as follows:
+
+    Given a dictionary mapping a set of int to a dictionary mapping a
+    string to set of int, use the result of MkRenamer to replace all
+    sets of ints by ints.
+
+*/
+
+  class Nfa {
+    private readonly int startState;
+    private readonly int exitState;    // This is the unique accept state
+    private readonly IDictionary<int, ArrayList<Transition>> trans;
+
+    public Nfa(int startState, int exitState) {
+      this.startState = startState; this.exitState = exitState;
+      trans = new HashDictionary<int, ArrayList<Transition>>();
+      if (!startState.Equals(exitState))
+        trans.Add(exitState, new ArrayList<Transition>());
+    }
+
+    public int Start { get { return startState; } }
+
+    public int Exit { get { return exitState; } }
+
+    public IDictionary<int, ArrayList<Transition>> Trans {
+      get { return trans; }
+    }
+
+    public void AddTrans(int s1, String lab, int s2) {
+      ArrayList<Transition> s1Trans;
+      if (trans.Contains(s1))
+        s1Trans = trans[s1];
+      else {
+        s1Trans = new ArrayList<Transition>();
+        trans.Add(s1, s1Trans);
+      }
+      s1Trans.Add(new Transition(lab, s2));
+    }
+
+    public void AddTrans(KeyValuePair<int, ArrayList<Transition>> tr) {
+      // Assumption: if tr is in trans, it maps to an empty list (end state)
+      trans.Remove(tr.Key);
+      trans.Add(tr.Key, tr.Value);
+    }
+
+    public override String ToString() {
+      return "NFA start=" + startState + " exit=" + exitState;
+    }
+
+    // Construct the transition relation of a composite-state DFA from
+    // an NFA with start state s0 and transition relation trans (a
+    // dictionary mapping int to arraylist of Transition).  The start
+    // state of the constructed DFA is the epsilon closure of s0, and
+    // its transition relation is a dictionary mapping a composite state
+    // (a set of ints) to a dictionary mapping a label (a string) to a
+    // composite state (a set of ints).
+
+    static IDictionary<Set<int>, IDictionary<String, Set<int>>>
+      CompositeDfaTrans(int s0, IDictionary<int, ArrayList<Transition>> trans) {
+      Set<int> S0 = EpsilonClose(new Set<int>(s0), trans);
+      IQueue<Set<int>> worklist = new CircularQueue<Set<int>>();
+      worklist.Enqueue(S0);
+      // The transition relation of the DFA
+      IDictionary<Set<int>, IDictionary<String, Set<int>>> res =
+        new HashDictionary<Set<int>, IDictionary<String, Set<int>>>();
+      while (!worklist.IsEmpty) {
+        Set<int> S = worklist.Dequeue();
+        if (!res.Contains(S)) {
+          // The S -lab-> T transition relation being constructed for a given S
+          IDictionary<String, Set<int>> STrans =
+            new HashDictionary<String, Set<int>>();
+          // For all s in S, consider all transitions s -lab-> t
+          foreach (int s in S) {
+            // For all non-epsilon transitions s -lab-> t, add t to T
+            foreach (Transition tr in trans[s]) {
+              if (tr.lab != null) {        // Non-epsilon transition
+                Set<int> toState;
+                if (STrans.Contains(tr.lab))   // Already a transition on lab
+                  toState = STrans[tr.lab];
+                else {                         // No transitions on lab yet
+                  toState = new Set<int>();
+                  STrans.Add(tr.lab, toState);
+                }
+                toState.Add(tr.target);
+              }
+            }
+          }
+          // Epsilon-close all T such that S -lab-> T, and put on worklist
+          IDictionary<String, Set<int>> STransClosed =
+            new HashDictionary<String, Set<int>>();
+          foreach (KeyValuePair<String, Set<int>> entry in STrans) {
+            Set<int> Tclose = EpsilonClose(entry.Value, trans);
+            STransClosed.Add(entry.Key, Tclose);
+            worklist.Enqueue(Tclose);
+          }
+          res.Add(S, STransClosed);
+        }
+      }
+      return res;
+    }
+
+    // Compute epsilon-closure of state set S in transition relation trans.  
+
+    static Set<int>
+      EpsilonClose(Set<int> S, IDictionary<int, ArrayList<Transition>> trans) {
+      // The worklist initially contains all S members
+      IQueue<int> worklist = new CircularQueue<int>();
+      S.Apply(worklist.Enqueue);
+      Set<int> res = new Set<int>(S);
+      while (!worklist.IsEmpty) {
+        int s = worklist.Dequeue();
+        foreach (Transition tr in trans[s]) {
+          if (tr.lab == null && !res.Contains(tr.target)) {
+            res.Add(tr.target);
+            worklist.Enqueue(tr.target);
+          }
+        }
+      }
+      return res;
+    }
+
+    // Compute a renamer, which is a dictionary mapping set of int to int
+
+    static IDictionary<Set<int>, int> MkRenamer(ICollectionValue<Set<int>> states)
+    {
+      IDictionary<Set<int>, int> renamer = new HashDictionary<Set<int>, int>();
+      int count = 0;
+      foreach (Set<int> k in states)
+        renamer.Add(k, count++);
+      return renamer;
+    }
+
+    // Using a renamer (a dictionary mapping set of int to int), replace
+    // composite (set of int) states with simple (int) states in the
+    // transition relation trans, which is a dictionary mapping set of
+    // int to a dictionary mapping from string to set of int.  The
+    // result is a dictionary mapping from int to a dictionary mapping
+    // from string to int.
+
+    static IDictionary<int, IDictionary<String, int>>
+      Rename(IDictionary<Set<int>, int> renamer,
+             IDictionary<Set<int>, IDictionary<String, Set<int>>> trans)
+    {
+      IDictionary<int, IDictionary<String, int>> newtrans =
+        new HashDictionary<int, IDictionary<String, int>>();
+      foreach (KeyValuePair<Set<int>, IDictionary<String, Set<int>>> entry
+         in trans) {
+        Set<int> k = entry.Key;
+        IDictionary<String, int> newktrans = new HashDictionary<String, int>();
+        foreach (KeyValuePair<String, Set<int>> tr in entry.Value)
+          newktrans.Add(tr.Key, renamer[tr.Value]);
+        newtrans.Add(renamer[k], newktrans);
+      }
+      return newtrans;
+    }
+
+    static Set<int> AcceptStates(ICollectionValue<Set<int>> states,
+               IDictionary<Set<int>, int> renamer,
+               int exit)
+    {
+      Set<int> acceptStates = new Set<int>();
+      foreach (Set<int> state in states)
+        if (state.Contains(exit))
+          acceptStates.Add(renamer[state]);
+      return acceptStates;
+    }
+
+    public Dfa ToDfa() {
+      IDictionary<Set<int>, IDictionary<String, Set<int>>>
+        cDfaTrans = CompositeDfaTrans(startState, trans);
+      Set<int> cDfaStart = EpsilonClose(new Set<int>(startState), trans);
+      ICollectionValue<Set<int>> cDfaStates = cDfaTrans.Keys;
+      IDictionary<Set<int>, int> renamer = MkRenamer(cDfaStates);
+      IDictionary<int, IDictionary<String, int>> simpleDfaTrans =
+        Rename(renamer, cDfaTrans);
+      int simpleDfaStart = renamer[cDfaStart];
+      Set<int> simpleDfaAccept = AcceptStates(cDfaStates, renamer, exitState);
+      return new Dfa(simpleDfaStart, simpleDfaAccept, simpleDfaTrans);
+    }
+
+    // Nested class for creating distinctly named states when constructing NFAs
+
+    public class NameSource {
+      private static int nextName = 0;
+
+      public int next() {
+        return nextName++;
+      }
+    }
+
+    // Write an input file for the dot program.  You can find dot at
+    // http://www.research.att.com/sw/tools/graphviz/
+
+    public void WriteDot(String filename) {
+      TextWriter wr =
+        new StreamWriter(new FileStream(filename, FileMode.Create,
+                                        FileAccess.Write));
+      wr.WriteLine("// Format this file as a Postscript file with ");
+      wr.WriteLine("//    dot " + filename + " -Tps -o out.ps\n");
+      wr.WriteLine("digraph nfa {");
+      wr.WriteLine("size=\"11,8.25\";");
+      wr.WriteLine("rotate=90;");
+      wr.WriteLine("rankdir=LR;");
+      wr.WriteLine("start [style=invis];");    // Invisible start node
+      wr.WriteLine("start -> d" + startState); // Edge into start state
+
+      // The accept state has a double circle
+      wr.WriteLine("d" + exitState + " [peripheries=2];");
+
+      // The transitions 
+      foreach (KeyValuePair<int, ArrayList<Transition>> entry in trans) {
+        int s1 = entry.Key;
+        foreach (Transition s1Trans in entry.Value) {
+          String lab = s1Trans.lab ?? "eps";
+          int s2 = s1Trans.target;
+          wr.WriteLine("d" + s1 + " -> d" + s2 + " [label=\"" + lab + "\"];");
+        }
+      }
+      wr.WriteLine("}");
+      wr.Close();
+    }
+  }
+
+// Class Transition, a transition from one state to another ----------
+
+  public class Transition {
+    public readonly String lab;
+    public readonly int target;
+
+    public Transition(String lab, int target) {
+      this.lab = lab; this.target = target;
+    }
+
+    public override String ToString() {
+      return "-" + lab + "-> " + target;
+    }
+  }
+
+// Class Dfa, deterministic finite automata --------------------------
+
+/*
+   A deterministic finite automaton (DFA) is represented as a
+   dictionary mapping state number (int) to a dictionary mapping label
+   (a non-null string) to a target state (an int).
+*/
+
+  class Dfa {
+    private readonly int startState;
+    private readonly Set<int> acceptStates;
+    private readonly IDictionary<int, IDictionary<String, int>> trans;
+
+    public Dfa(int startState, Set<int> acceptStates,
+	       IDictionary<int, IDictionary<String, int>> trans)
+    {
+      this.startState = startState;
+      this.acceptStates = acceptStates;
+      this.trans = trans;
+    }
+
+    public int Start { get { return startState; } }
+
+    public Set<int> Accept { get { return acceptStates; } }
+
+    public IDictionary<int, IDictionary<String, int>> Trans {
+      get { return trans; }
+    }
+
+    public override String ToString() {
+      return "DFA start=" + startState + "\naccept=" + acceptStates;
+    }
+
+    // Write an input file for the dot program.  You can find dot at
+    // http://www.research.att.com/sw/tools/graphviz/
+
+    public void WriteDot(String filename) {
+      TextWriter wr =
+        new StreamWriter(new FileStream(filename, FileMode.Create,
+                                        FileAccess.Write));
+      wr.WriteLine("// Format this file as a Postscript file with ");
+      wr.WriteLine("//    dot " + filename + " -Tps -o out.ps\n");
+      wr.WriteLine("digraph dfa {");
+      wr.WriteLine("size=\"11,8.25\";");
+      wr.WriteLine("rotate=90;");
+      wr.WriteLine("rankdir=LR;");
+      wr.WriteLine("start [style=invis];");    // Invisible start node
+      wr.WriteLine("start -> d" + startState); // Edge into start state
+
+      // Accept states are double circles
+      foreach (int state in trans.Keys)
+        if (acceptStates.Contains(state))
+          wr.WriteLine("d" + state + " [peripheries=2];");
+
+      // The transitions 
+      foreach (KeyValuePair<int, IDictionary<String, int>> entry in trans) {
+        int s1 = entry.Key;
+        foreach (KeyValuePair<String, int> s1Trans in entry.Value) {
+          String lab = s1Trans.Key;
+          int s2 = s1Trans.Value;
+          wr.WriteLine("d" + s1 + " -> d" + s2 + " [label=\"" + lab + "\"];");
+        }
+      }
+      wr.WriteLine("}");
+      wr.Close();
+    }
+  }
+
+// Regular expressions ----------------------------------------------
+//
+// Abstract syntax of regular expressions
+//    r ::= A | r1 r2 | (r1|r2) | r*
+//
+
+  abstract class Regex {
+    abstract public Nfa MkNfa(Nfa.NameSource names);
+  }
+
+  class Eps : Regex {
+    // The resulting nfa0 has form s0s -eps-> s0e
+
+    public override Nfa MkNfa(Nfa.NameSource names) {
+      int s0s = names.next();
+      int s0e = names.next();
+      Nfa nfa0 = new Nfa(s0s, s0e);
+      nfa0.AddTrans(s0s, null, s0e);
+      return nfa0;
+    }
+  }
+
+  class Sym : Regex {
+    String sym;
+
+    public Sym(String sym) {
+      this.sym = sym;
+    }
+
+    // The resulting nfa0 has form s0s -sym-> s0e
+
+    public override Nfa MkNfa(Nfa.NameSource names) {
+      int s0s = names.next();
+      int s0e = names.next();
+      Nfa nfa0 = new Nfa(s0s, s0e);
+      nfa0.AddTrans(s0s, sym, s0e);
+      return nfa0;
+    }
+  }
+
+  class Seq : Regex {
+    Regex r1, r2;
+
+    public Seq(Regex r1, Regex r2) {
+      this.r1 = r1; this.r2 = r2;
+    }
+
+    // If   nfa1 has form s1s ----> s1e 
+    // and  nfa2 has form s2s ----> s2e 
+    // then nfa0 has form s1s ----> s1e -eps-> s2s ----> s2e
+
+    public override Nfa MkNfa(Nfa.NameSource names) {
+      Nfa nfa1 = r1.MkNfa(names);
+      Nfa nfa2 = r2.MkNfa(names);
+      Nfa nfa0 = new Nfa(nfa1.Start, nfa2.Exit);
+      foreach (KeyValuePair<int, ArrayList<Transition>> entry in nfa1.Trans)
+        nfa0.AddTrans(entry);
+      foreach (KeyValuePair<int, ArrayList<Transition>> entry in nfa2.Trans)
+        nfa0.AddTrans(entry);
+      nfa0.AddTrans(nfa1.Exit, null, nfa2.Start);
+      return nfa0;
+    }
+  }
+
+  class Alt : Regex {
+    Regex r1, r2;
+
+    public Alt(Regex r1, Regex r2) {
+      this.r1 = r1; this.r2 = r2;
+    }
+
+    // If   nfa1 has form s1s ----> s1e 
+    // and  nfa2 has form s2s ----> s2e 
+    // then nfa0 has form s0s -eps-> s1s ----> s1e -eps-> s0e
+    //                    s0s -eps-> s2s ----> s2e -eps-> s0e
+
+    public override Nfa MkNfa(Nfa.NameSource names) {
+      Nfa nfa1 = r1.MkNfa(names);
+      Nfa nfa2 = r2.MkNfa(names);
+      int s0s = names.next();
+      int s0e = names.next();
+      Nfa nfa0 = new Nfa(s0s, s0e);
+      foreach (KeyValuePair<int, ArrayList<Transition>> entry in nfa1.Trans)
+        nfa0.AddTrans(entry);
+      foreach (KeyValuePair<int, ArrayList<Transition>> entry in nfa2.Trans)
+        nfa0.AddTrans(entry);
+      nfa0.AddTrans(s0s, null, nfa1.Start);
+      nfa0.AddTrans(s0s, null, nfa2.Start);
+      nfa0.AddTrans(nfa1.Exit, null, s0e);
+      nfa0.AddTrans(nfa2.Exit, null, s0e);
+      return nfa0;
+    }
+  }
+
+  class Star : Regex {
+    Regex r;
+
+    public Star(Regex r) {
+      this.r = r;
+    }
+
+    // If   nfa1 has form s1s ----> s1e 
+    // then nfa0 has form s0s ----> s0s
+    //                    s0s -eps-> s1s
+    //                    s1e -eps-> s0s
+
+    public override Nfa MkNfa(Nfa.NameSource names) {
+      Nfa nfa1 = r.MkNfa(names);
+      int s0s = names.next();
+      Nfa nfa0 = new Nfa(s0s, s0s);
+      foreach (KeyValuePair<int, ArrayList<Transition>> entry in nfa1.Trans)
+        nfa0.AddTrans(entry);
+      nfa0.AddTrans(s0s, null, nfa1.Start);
+      nfa0.AddTrans(nfa1.Exit, null, s0s);
+      return nfa0;
+    }
+  }
+
+// Trying the RE->NFA->DFA translation on three regular expressions
+
+  class TestNFA {
+    public static void Main(String[] args) {
+      Regex a = new Sym("A");
+      Regex b = new Sym("B");
+      Regex c = new Sym("C");
+      Regex abStar = new Star(new Alt(a, b));
+      Regex bb = new Seq(b, b);
+      Regex r = new Seq(abStar, new Seq(a, b));
+      // The regular expression (a|b)*ab
+      BuildAndShow("ex1", r);
+      // The regular expression ((a|b)*ab)*
+      BuildAndShow("ex2", new Star(r));
+      // The regular expression ((a|b)*ab)((a|b)*ab)
+      BuildAndShow("ex3", new Seq(r, r));
+      // The regular expression (a|b)*abb, from ASU 1986 p 136
+      BuildAndShow("ex4", new Seq(abStar, new Seq(a, bb)));
+      // SML reals: sign?((digit+(\.digit+)?))([eE]sign?digit+)?
+      Regex d = new Sym("digit");
+      Regex dPlus = new Seq(d, new Star(d));
+      Regex s = new Sym("sign");
+      Regex sOpt = new Alt(s, new Eps());
+      Regex dot = new Sym(".");
+      Regex dotDigOpt = new Alt(new Eps(), new Seq(dot, dPlus));
+      Regex mant = new Seq(sOpt, new Seq(dPlus, dotDigOpt));
+      Regex e = new Sym("e");
+      Regex exp = new Alt(new Eps(), new Seq(e, new Seq(sOpt, dPlus)));
+      Regex smlReal = new Seq(mant, exp);
+      BuildAndShow("ex5", smlReal);
+    }
+
+    public static void BuildAndShow(String fileprefix, Regex r) {
+      Nfa nfa = r.MkNfa(new Nfa.NameSource());
+      Console.WriteLine(nfa);
+      Console.WriteLine("Writing NFA graph to file");
+      nfa.WriteDot(fileprefix + "nfa.dot");
+      Console.WriteLine("---");
+      Dfa dfa = nfa.ToDfa();
+      Console.WriteLine(dfa);
+      Console.WriteLine("Writing DFA graph to file");
+      dfa.WriteDot(fileprefix + "dfa.dot");
+      Console.WriteLine();
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/GettingStarted.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/GettingStarted.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/GettingStarted.cs	(revision 3)
@@ -0,0 +1,50 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: GettingStarted 2005-01-18
+
+// Compile with 
+//   csc /r:C5.dll GettingStarted.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace GettingStarted {
+  class GettingStarted {
+    public static void Main(String[] args) {
+      IList<String> names = new ArrayList<String>();
+      names.AddAll(new String[] { "Hoover", "Roosevelt", 
+                                  "Truman", "Eisenhower", "Kennedy" });
+      // Print list:
+      Console.WriteLine(names);
+      // Print item 1 ("Roosevelt") in the list:
+      Console.WriteLine(names[1]);
+      // Create a list view comprising post-WW2 presidents:
+      IList<String> postWWII = names.View(2, 3);
+      // Print item 2 ("Kennedy") in the view:
+      Console.WriteLine(postWWII[2]);
+      // Enumerate and print the list view in reverse chronological order:
+      foreach (String name in postWWII.Backwards()) 
+        Console.WriteLine(name);
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Graph.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Graph.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Graph.cs	(revision 3)
@@ -0,0 +1,1679 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: Graph representation with basic algorithms using C5 
+
+
+// Compile with 
+//   csc /r:C5.dll Graph.cs 
+
+
+// The code is structured as a rudimentary Graph library, with an interface
+// for (edge)weighted graphs and a single implementation based on an
+// adjacency list representation using hash dictionaries. 
+
+
+// The algorithms implemented include:
+//
+// Breadth-First-Search and Depth-First-Search, with an interface based on actions
+// to be taken as edges are traversed. Applications are checking for connectedness,
+// counting components
+//
+// Priority-First-Search, where edges are traversed according to either weight or 
+// accumulated weight from the start of the search.
+// An application of the non-accumulating version is the construction of a minimal
+// spanning tree and therefore the following approximation algorithm. 
+// Applications of the accumulating version are the construction of a shortest path
+// and the computation of the distance from one vertex to another one.
+//
+// An approximation algorithm for Travelling Salesman Problems, 
+// where the weights satisfies the triangle inequality. 
+
+
+// Pervasive generic parameters:
+//                      V: The type of a vertex in a graph. Vertices are identified
+//                         by the Equals method inherited from object (or overridden).
+//                      E: The type of additional data associated with edges in a graph.
+//                      W: The type of values of weights on edges in a weighted graph, 
+//                         in practise usually int or double. Must be comparable and 
+//                         there must be given a compatible way to add values.
+           
+// Interfaces:
+//                      IGraph<V,E,W>: The interface for a graph implementation with
+//                         vertex type V, edge dat type E and weight values of type W.           
+//                      IWeight<E,W>: The interface of a weight function 
+
+// Classes:
+//                      HashGraph<V,E,W>: An implementation of IWeightedGraph<V,E,W> based on 
+//                          adjacency lists represented as hash dictionaries.
+//                      HashGraph<V,E,W>.EdgesValue: A helper class for the Edges() method
+//                      CountWeight<E>: A 
+//                      IntWeight:
+//                      DoubleWeight:
+
+// Value Types:
+//                      Edge<V,E>: 
+//                      EdgeAction<V,E,U>:
+
+// Some notes:
+// The code only supports "natural" equality of vertices.
+
+using C5;
+using System;
+using SCG = System.Collections.Generic;
+
+namespace Graph
+{
+  /// <summary>
+  /// (Duer ikke)
+  /// </summary>
+  /// <typeparam name="V"></typeparam>
+  /// <typeparam name="E"></typeparam>
+  interface IGraphVertex<V, E,W> where W : IComparable<W>
+  {
+    V Value { get;}
+    IGraph<V, E, W> Graph { get;}
+    ICollectionValue<KeyValuePair<V, E>> Adjacent { get;}
+
+  }
+
+  class Vertex<V>
+  {
+    //V v;
+  }
+/// <summary>
+/// 
+/// </summary>
+/// <typeparam name="V"></typeparam>
+/// <typeparam name="E"></typeparam>
+/// <typeparam name="W"></typeparam>
+  interface IGraph<V, E, W> where W : IComparable<W>
+  {
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>The weight object for this graph</value>
+    IWeight<E, W> Weight { get;}
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>The number of vertices in this graph</value>
+    int VertexCount { get;}
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>The number of edges in this graph</value>
+    int EdgeCount { get;}
+
+    /// <summary>
+    /// The collection of vertices of this graph.
+    /// The return value is a snapshot, not a live view onto the graph.
+    /// </summary>
+    /// <returns></returns>
+    ICollectionValue<V> Vertices();
+
+    /// <summary>
+    /// The collection of edges incident to a particular vertex.
+    /// The return value is a snapshot og (endvertex, edgedata) pairs.
+    /// </summary>
+    /// <param name="vertex"></param>
+    /// <returns></returns>
+    ICollectionValue<KeyValuePair<V, E>> Adjacent(V vertex);
+
+    /// <summary>
+    /// The collection of all edges in the graph. The return value is a snapshot
+    /// of Edge values. Each edge is present once for an undefined direction.
+    /// </summary>
+    /// <returns></returns>
+    ICollectionValue<Edge<V, E>> Edges();
+
+    /// <summary>
+    /// Add a(n isolated) vertex to the graph Ignore if vertex is already in the graph.
+    /// </summary>
+    /// <param name="vertex"></param>
+    /// <returns>True if the vertex was added.</returns>
+    bool AddVertex(V vertex);
+
+    /// <summary>
+    /// Add an edge to the graph. If the edge is already in the graph, update the 
+    /// edge data. Add vertices as needed.
+    /// </summary>
+    /// <param name="start"></param>
+    /// <param name="end"></param>
+    /// <param name="edgedata"></param>
+    /// <returns>True if the edge was added</returns>
+    bool AddEdge(V start, V end, E edgedata);
+
+    /// <summary>
+    /// Remove a vertex and all its incident edges from the graph.
+    /// </summary>
+    /// <returns>True if the vertex was already in the graph and hence was removed</returns>
+    bool RemoveVertex(V vertex);
+
+    /// <summary>
+    /// Remove an edge from the graph. Do not remove the vertices if they become isolated.
+    /// </summary>
+    /// <param name="start"></param>
+    /// <param name="end"></param>
+    /// <param name="edgedata">On output, the edge data associated with the removed edge.</param>
+    /// <returns>True if </returns>
+    bool RemoveEdge(V start, V end, out E edgedata);
+
+    /// <summary>
+    /// Is there an edge from start to end in this graph, and if so, what is 
+    /// the data on that edge.
+    /// </summary>
+    /// <param name="start"></param>
+    /// <param name="end"></param>
+    /// <param name="edge"></param>
+    /// <returns></returns>
+    bool FindEdge(V start, V end, out E edge);
+
+    /// <summary>
+    /// Construct the subgraph corresponding to a set of vertices.
+    /// </summary>
+    /// <param name="vs"></param>
+    /// <returns></returns>
+    IGraph<V, E, W> SubGraph(ICollectionValue<V> vs);
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>True if graph is connected</value>
+    bool IsConnected { get; }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <value>The number of connected components of this graph</value>
+    int ComponentCount { get;}
+
+    /// <summary>
+    /// Compute the connnected components of this graph. 
+    /// </summary>
+    /// <returns>A collection of (vertex,component) pairs, where the first part of the
+    /// pair is some vertex in the component.</returns>
+    ICollectionValue<KeyValuePair<V, IGraph<V, E, W>>> Components();
+
+    /// <summary>
+    /// Traverse the connected component containing the <code>start</code> vertex, 
+    /// in either BFS or DFS order, beginning at <code>start</code> and performing the action 
+    /// <code>act</code> on each edge part of the constructed tree.
+    /// </summary>
+    /// <param name="bfs">True if BFS, false if DFS</param>
+    /// <param name="start">The vertex to start at</param>
+    /// <param name="act">The action to perform at each node</param>
+    void TraverseVertices(bool bfs, V start, Action<Edge<V, E>> act);
+
+    /// <summary>
+    /// Traverse an undirected graph in either BFS or DFS order, performing the action 
+    /// <code>act</code> on each vertex. 
+    /// The start vertex of each component of the graph is undefinded. 
+    /// </summary>
+    /// <param name="bfs">True if BFS, false if DFS</param>
+    /// <param name="act"></param>
+    void TraverseVertices(bool bfs, Action<V> act);
+
+    /// <summary>
+    /// Traverse an undirected graph in either BFS or DFS order, performing the action 
+    /// <code>act</code> on each edge in the traversal and beforecomponent/aftercomponent 
+    /// at the start and end of each component (with argument: the start vertex of the component).
+    /// </summary>
+    /// <param name="bfs">True if BFS, false if DFS</param>
+    /// <param name="act"></param>
+    /// <param name="beforecomponent"></param>
+    /// <param name="aftercomponent"></param>
+    void TraverseVertices(bool bfs, Action<Edge<V, E>> act, Action<V> beforecomponent, Action<V> aftercomponent);
+
+    /// <summary>
+    /// A more advanced Depth First Search traversal.
+    /// </summary>
+    /// <param name="start">The vertex to start the search at</param>
+    /// <param name="beforevertex">Action to perform when a vertex is first encountered.</param>
+    /// <param name="aftervertex">Action to perform when all edges out of a vertex has been handles.</param>
+    /// <param name="onfollow">Action to perform as an edge is traversed.</param>
+    /// <param name="onfollowed">Action to perform when an edge is travesed back.</param>
+    /// <param name="onnotfollowed">Action to perform when an edge (a backedge)is seen, but not followed.</param>
+    void DepthFirstSearch(V start, Action<V> beforevertex, Action<V> aftervertex,
+            Action<Edge<V, E>> onfollow, Action<Edge<V, E>> onfollowed, Action<Edge<V, E>> onnotfollowed);
+
+    //TODO: perhaps we should avoid exporting this?
+    /// <summary>
+    /// Traverse the part of the graph reachable from start in order of least distance 
+    /// from start according to the weight function. Perform act on the edges of the 
+    /// traversal as they are recognised.
+    /// </summary>
+    /// <typeparam name="W"></typeparam>
+    /// <param name="weight"></param>
+    /// <param name="start"></param>
+    /// <param name="act"></param>
+    void PriorityFirstTraverse(bool accumulating, V start, EdgeAction<V, E, W> act);
+
+    /// <summary>
+    /// Compute the (a) shortest path from start to end. THrow an exception if end cannot be reached rom start.
+    /// </summary>
+    /// <param name="weight"></param>
+    /// <param name="start"></param>
+    /// <param name="end"></param>
+    /// <returns></returns>
+    ICollectionValue<Edge<V, E>> ShortestPath(V start, V end);
+
+    /// <summary>
+    /// Compute the Distance from start to end, i.e. the total weight of a shortest path from start to end. 
+    /// Throw an exception if end cannot be reached rom start.
+    /// </summary>
+    /// <param name="start"></param>
+    /// <param name="end"></param>
+    /// <returns></returns>
+    W Distance(V start, V end);
+
+    /// <summary>
+    /// Compute a minimum spanning tree for the graph.
+    /// Throw an exception if this graph is not connected.
+    /// </summary>
+    /// <param name="root">(The starting point of the PFS, to be removed)</param>
+    /// <returns></returns>
+    IGraph<V, E, W> MinimumSpanningTree(out V root);
+
+    /// <summary>
+    /// Compute a factor 2 approximation to a Minimum Weight
+    /// Perfect Matching in a graph using NNs
+    /// </summary>
+    /// <returns></returns>
+    ICollectionValue<Edge<V, E>> ApproximateMWPM();
+
+    /// <summary>
+    /// Construct a closed Euler tour of this graph if one exists, i.e. if 
+    /// the graph is connected and all vertices have even degrees. Throw an
+    /// ArgumentException if no closed Euler tour exists.
+    /// </summary>
+    /// <returns>A list of vertices in an Euler tour of this graph.</returns>
+    IList<V> EulerTour();
+
+    /// <summary>
+    /// This is intended for implementations of the very simple factor 2 approximation
+    /// algorithms for the travelling salesman problem for Euclidic weight/distance 
+    /// functions, i.e. distances that satisfy the triangle inequality. (We do not do 3/2)
+    /// </summary>
+    /// <returns></returns>
+    IDirectedCollectionValue<V> ApproximateTSP();
+
+    /// <summary>
+    /// Pretty-print the graph to the console (for debugging purposes).
+    /// </summary>
+    void Print(System.IO.TextWriter output);
+  }
+
+/// <summary>
+/// The type of an edge in a graph. An edge is identified by its pair of 
+/// vertices. The pair is considered ordered, and so an Edge really describes
+/// an edge of the graph in a particular traversal direction.
+/// </summary>
+/// <typeparam name="V">The type of a vertex.</typeparam>
+/// <typeparam name="E">The type of data asociated with edges.</typeparam>
+  struct Edge<V, E>
+  {
+    static SCG.IEqualityComparer<V> vequalityComparer = EqualityComparer<V>.Default;
+    public readonly V start, end;
+    public readonly E edgedata;
+    public Edge(V start, V end, E edgedata)
+    {
+      if (vequalityComparer.Equals(start, end))
+        throw new ArgumentException("Illegal: start and end are equal");
+      this.start = start; this.end = end; this.edgedata = edgedata;
+    }
+
+    public Edge<V, E> Reverse()
+    {
+      return new Edge<V, E>(end, start, edgedata);
+    }
+
+    public override string ToString()
+    {
+      return String.Format("(start='{0}', end='{1}', edgedata='{2}')", start, end, edgedata); ;
+    }
+
+    public override bool Equals(object obj)
+    {
+      if (obj is Edge<V, E>)
+      {
+        Edge<V, E> other = (Edge<V, E>)obj;
+        return vequalityComparer.Equals(start, other.start) && vequalityComparer.Equals(end, other.end);
+      }
+      return false;
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public override int GetHashCode()
+    {
+      //TODO: should we use xor? Or a random factor?
+      return start.GetHashCode() + 148712671 * end.GetHashCode();
+    }
+
+    /// <summary>
+    /// The unordered equalityComparer compares edges independent of the order of the vertices.
+    /// </summary>
+    public class UnorderedEqualityComparer : SCG.IEqualityComparer<Edge<V, E>>
+    {
+      /// <summary>
+      /// Check if two edges have the same vertices irrespective of order.
+      /// </summary>
+      /// <param name="i1"></param>
+      /// <param name="i2"></param>
+      /// <returns></returns>
+      public bool Equals(Edge<V, E> i1, Edge<V, E> i2)
+      {
+        return (vequalityComparer.Equals(i1.start, i2.start) && vequalityComparer.Equals(i1.end, i2.end)) ||
+            (vequalityComparer.Equals(i1.end, i2.start) && vequalityComparer.Equals(i1.start, i2.end));
+      }
+
+      /// <summary>
+      /// Return a hash code compatible with the unordered equals.
+      /// </summary>
+      /// <param name="item"></param>
+      /// <returns></returns>
+      public int GetHashCode(Edge<V, E> item)
+      {
+        return item.start.GetHashCode() ^ item.end.GetHashCode();
+      }
+    }
+  }
+
+/// <summary>
+/// The type of the weight object of a graph. This consists of a function mapping
+/// edge data values to weight values, and an operation to add two weight values.
+/// It is required that weight values are comparable.
+/// 
+/// The user must assure that the add operation is commutative and fulfills 
+/// Add(w1,w2) &le; w1 for all w1 and w2 that can appear as weights or sums of
+/// weights. In practise, W will be int or double, all weight values will be 
+/// non-negative and the addition will be the natural addition on W.
+/// </summary>
+/// <typeparam name="E"></typeparam>
+/// <typeparam name="W"></typeparam>
+  interface IWeight<E, W> where W : IComparable<W>
+  {
+    /// <summary>
+    /// Compute the weight value corresponding to specific edge data.
+    /// </summary>
+    /// <param name="edgedata"></param>
+    /// <returns></returns>
+    W Weight(E edgedata);
+
+    /// <summary>
+    /// Add two weight values.
+    /// </summary>
+    /// <param name="w1"></param>
+    /// <param name="w2"></param>
+    /// <returns></returns>
+    W Add(W w1, W w2);
+  }
+
+/// <summary>
+/// An action to perform when an edge is encountered during a traversal of the graph.
+/// The "extra" parameter is for additional information supplied by the traversal 
+/// algorithm. 
+/// The intention of the bool return value is that returning false is a signal to the
+/// traversal algorithm to abandon the traversl because the user has already found
+/// what he was looking for.
+/// </summary>
+/// <typeparam name="V"></typeparam>
+/// <typeparam name="E"></typeparam>
+/// <typeparam name="U"></typeparam>
+/// <param name="edge"></param>
+/// <param name="extra"></param>
+/// <returns></returns>
+  delegate bool EdgeAction<V, E, U>(Edge<V, E> edge, U extra);
+
+
+/*
+  For a dense graph, we would use data fields:
+
+  E'[,] or E'[][] for the matrix. Possibly E'[][] for a triangular one!
+  Here E' = struct{E edgedata, bool present} or class{E edgedata}, or if E is a class just E.
+  Thus E' is E! for value types. Or we could have two matrices: E[][] and bool[][]. 
+
+  HashDictionary<V,int> to map vertex ids to indices.
+  ArrayList<V> for the map the other way.
+  Or simply a HashedArrayList<V> to get both?
+
+  PresentList<int>, FreeList<int> or similar, if we do not want to compact the indices in the matrix on each delete.
+  If we compact, we always do a delete on the vertex<->index map by a replace and a removelast:
+    vimap[ind]=vimap[vimap.Count]; vimap.RemoveLast(); //also reorder matrix!
+  
+
+*/
+
+/// <summary>
+/// An implementation of IGraph&le;V,E,W&ge; based on an adjacency list representation using hash dictionaries.
+/// As a consequence, this will be most efficient for sparse graphs.
+/// </summary>
+/// <typeparam name="V"></typeparam>
+/// <typeparam name="E"></typeparam>
+/// <typeparam name="W"></typeparam>
+  class HashGraph<V, E, W> : IGraph<V, E, W> where W : IComparable<W>
+  {
+    int edgecount;
+
+    HashDictionary<V, HashDictionary<V, E>> graph;
+
+    IWeight<E, W> weight;
+
+    public IWeight<E, W> Weight { get { return weight; } }
+
+
+    /// <summary>
+    /// Create an initially empty graph.
+    /// </summary>
+    /// <param name="weight"></param>
+    [UsedBy("testTSP")]
+    public HashGraph(IWeight<E, W> weight)
+    {
+      this.weight = weight;
+      edgecount = 0;
+      graph = new HashDictionary<V, HashDictionary<V, E>>();
+    }
+
+    /// <summary>
+    /// Constructing a graph with no isolated vertices given a collection of edges.
+    /// </summary>
+    /// <param name="edges"></param>
+    [UsedBy()]
+    public HashGraph(IWeight<E, W> weight, SCG.IEnumerable<Edge<V, E>> edges) : this(weight)
+    {
+      foreach (Edge<V, E> edge in edges)
+      {
+        if (edge.start.Equals(edge.end))
+          throw new ApplicationException("Edge has equal start and end");
+        {
+          HashDictionary<V, E> edgeset;
+          //TODO: utilize upcoming FindOrAddSome operation
+          if (!graph.Find(edge.start, out edgeset))
+            graph.Add(edge.start, edgeset = new HashDictionary<V, E>());
+          if (!edgeset.UpdateOrAdd(edge.end, edge.edgedata))
+            edgecount++;
+          if (!graph.Find(edge.end, out edgeset))
+            graph.Add(edge.end, edgeset = new HashDictionary<V, E>());
+          edgeset.UpdateOrAdd(edge.start, edge.edgedata);
+        }
+      }
+    }
+
+    /// <summary>
+    /// This constructs a graph with a given set of vertices.
+    /// Will only allow these vertices.
+    /// Duplicate edges are allowed.
+    /// </summary>
+    /// <param name="vertices"></param>
+    /// <param name="edges"></param>
+    public HashGraph(IWeight<E, W> weight, SCG.IEnumerable<V> vertices, SCG.IEnumerable<Edge<V, E>> edges) : this(weight)
+    {
+      foreach (V v in vertices)
+        graph.Add(v, new HashDictionary<V, E>());
+      foreach (Edge<V, E> edge in edges)
+      {
+        HashDictionary<V, E> edgeset;
+        if (edge.start.Equals(edge.end))
+          throw new ApplicationException("Edge has equal start and end");
+        if (!graph.Find(edge.start, out edgeset))
+          throw new ApplicationException("Edge has unknown start");
+        if (!edgeset.UpdateOrAdd(edge.end, edge.edgedata))
+          edgecount++;
+        if (!graph.Find(edge.end, out edgeset))
+          throw new ApplicationException("Edge has unknown end");
+        edgeset.UpdateOrAdd(edge.start, edge.edgedata);
+      }
+    }
+
+    [UsedBy("testCOMP")]
+    public int VertexCount { get { return graph.Count; } }
+
+    [UsedBy("testCOMP")]
+    public int EdgeCount { get { return edgecount; } }
+
+    public ICollectionValue<V> Vertices()
+    {
+      return new GuardedCollectionValue<V>(graph.Keys);
+    }
+
+    public ICollectionValue<KeyValuePair<V, E>> Adjacent(V vertex)
+    {
+      return new GuardedCollectionValue<KeyValuePair<V, E>>(graph[vertex]);
+    }
+
+    class EdgesValue : CollectionValueBase<Edge<V, E>>
+    {
+      HashGraph<V, E, W> graph;
+      internal EdgesValue(HashGraph<V, E, W> g) { graph = g; }
+
+      public override bool IsEmpty { get { return graph.edgecount == 0; } }
+
+      public override int Count { get { return graph.edgecount; } }
+
+      public override Speed CountSpeed { get { return Speed.Constant; } }
+
+
+      public override Edge<V, E> Choose()
+      {
+        KeyValuePair<V, HashDictionary<V, E>> adjacent = graph.graph.Choose();
+        KeyValuePair<V, E> otherend = graph.graph[adjacent.Key].Choose();
+        return new Edge<V, E>(adjacent.Key, otherend.Key, otherend.Value);
+      }
+
+      public override SCG.IEnumerator<Edge<V, E>> GetEnumerator()
+      {
+        HashSet<Edge<V, E>> seen = new HashSet<Edge<V, E>>(new Edge<V, E>.UnorderedEqualityComparer());
+        foreach (V v in graph.graph.Keys)
+          foreach (KeyValuePair<V, E> p in graph.graph[v])
+          {
+            Edge<V, E> edge = new Edge<V, E>(v, p.Key, p.Value);
+            if (!seen.FindOrAdd(ref edge))
+              yield return edge;
+          }
+      }
+    }
+
+    public ICollectionValue<Edge<V, E>> Edges()
+    {
+      return new EdgesValue(this);
+    }
+
+    public bool AddVertex(V v)
+    {
+      if (graph.Contains(v))
+        return false;
+      graph.Add(v, new HashDictionary<V, E>());
+      return true;
+    }
+
+    //Note: no warning on update of edgedata!
+    //TODO: Shouldn�t Update or Add return the old value?
+    //Then it would be easy to check for updates 
+    public bool AddEdge(V start, V end, E edgedata)
+    {
+      bool retval = false;
+      HashDictionary<V, E> edgeset;
+      if (graph.Find(start, out edgeset))
+        retval = !edgeset.UpdateOrAdd(end, edgedata);
+      else
+      {
+        graph[start] = edgeset = new HashDictionary<V, E>();
+        edgeset[end] = edgedata;
+        retval = true;
+      }
+      if (graph.Find(end, out edgeset))
+        edgeset.UpdateOrAdd(start, edgedata);
+      else
+      {
+        graph[end] = edgeset = new HashDictionary<V, E>();
+        edgeset[start] = edgedata;
+      }
+      if (retval)
+        edgecount++;
+      return retval;
+    }
+
+    public bool RemoveVertex(V vertex)
+    {
+      HashDictionary<V, E> edgeset;
+      if (!graph.Find(vertex, out edgeset))
+        return false;
+      foreach (V othervertex in edgeset.Keys)
+        graph[othervertex].Remove(vertex); //Assert retval==true
+      edgecount -= edgeset.Count;
+      graph.Remove(vertex);
+      return true;
+    }
+
+    public bool RemoveEdge(V start, V end, out E edgedata)
+    {
+      HashDictionary<V, E> edgeset;
+      if (!graph.Find(start, out edgeset))
+      {
+        edgedata = default(E);
+        return false;
+      }
+      if (!edgeset.Remove(end, out edgedata))
+        return false;
+      graph[end].Remove(start);
+      edgecount--;
+      return true;
+    }
+
+    public bool FindEdge(V start, V end, out E edgedata)
+    {
+      HashDictionary<V, E> edges;
+      if (!graph.Find(start, out edges))
+      {
+        edgedata = default(E);
+        return false;
+      }
+      return edges.Find(end, out edgedata);
+    }
+
+    public IGraph<V, E, W> SubGraph(ICollectionValue<V> vs)
+    {
+      HashSet<V> vertexset = vs as HashSet<V>;
+      if (vertexset == null)
+      {
+        vertexset = new HashSet<V>();
+        vertexset.AddAll(vs);
+      }
+
+      return new HashGraph<V, E, W>(weight,
+          vs,
+          Edges().Filter(delegate(Edge<V, E> e) { return vertexset.Contains(e.start) && vertexset.Contains(e.end); }));
+    }
+
+    public bool IsConnected
+    {
+      //TODO: optimize: needs to change Action<Edge<V,E>> to EdgeAction to be able to break out
+      get { return ComponentCount <= 1; }
+    }
+
+    public int ComponentCount
+    {
+      get
+      {
+        int components = 0;
+        TraverseVertices(false, null, delegate(V v) { components++; }, null);
+        return components;
+      }
+    }
+
+    public ICollectionValue<KeyValuePair<V, IGraph<V, E, W>>> Components()
+    {
+      ArrayList<KeyValuePair<V, IGraph<V, E, W>>> retval = new ArrayList<KeyValuePair<V, IGraph<V, E, W>>>();
+      HashGraph<V, E, W> component;
+      ArrayList<V> vertices = null;
+      Action<Edge<V, E>> edgeaction = delegate(Edge<V, E> e)
+      {
+        vertices.Add(e.end);
+      };
+      Action<V> beforecomponent = delegate(V v)
+      {
+        vertices = new ArrayList<V>();
+        vertices.Add(v);
+      };
+      Action<V> aftercomponent = delegate(V v)
+      {
+        //component = SubGraph(vertices);
+        component = new HashGraph<V, E, W>(weight);
+        foreach (V start in vertices)
+        {
+          //component.graph[start] = graph[start].Clone();
+          HashDictionary<V, E> edgeset = component.graph[start] = new HashDictionary<V, E>();
+          foreach (KeyValuePair<V, E> adjacent in graph[start])
+            edgeset[adjacent.Key] = adjacent.Value;
+        }
+        retval.Add(new KeyValuePair<V, IGraph<V, E, W>>(v, component));
+      };
+      TraverseVertices(false, edgeaction, beforecomponent, aftercomponent);
+      return retval;
+    }
+
+    [UsedBy("test1")]
+    public void TraverseVertices(bool bfs, V start, Action<Edge<V, E>> act)
+    {
+      if (!graph.Contains(start))
+        throw new ArgumentException("start Vertex not in graph");
+      IList<Edge<V, E>> todo = new LinkedList<Edge<V, E>>();
+      todo.FIFO = bfs;
+      HashSet<V> seen = new HashSet<V>();
+      V v;
+      while (!todo.IsEmpty || seen.Count == 0)
+      {
+        if (seen.Count > 1)
+        {
+          Edge<V, E> e = todo.Remove();
+          if (act != null)
+            act(e);
+          v = e.end;
+        }
+        else
+        {
+          seen.Add(start);
+          v = start;
+        }
+
+        HashDictionary<V, E> adjacent;
+        if (graph.Find(v, out adjacent))
+        {
+          foreach (KeyValuePair<V, E> p in adjacent)
+          {
+            V end = p.Key;
+            if (!seen.FindOrAdd(ref end))
+              todo.Add(new Edge<V, E>(v, end, p.Value));
+          }
+        }
+      }
+    }
+
+    public void TraverseVertices(bool bfs, Action<V> act)
+    {
+      TraverseVertices(bfs, delegate(Edge<V, E> e) { act(e.end); }, act, null);
+    }
+
+    //TODO: merge the hash set here with the intra omponent one?
+    public void TraverseVertices(bool bfs, Action<Edge<V, E>> act, Action<V> beforecomponent, Action<V> aftercomponent)
+    {
+      HashSet<V> missing = new HashSet<V>();
+      missing.AddAll(Vertices());
+      Action<Edge<V, E>> myact = act + delegate(Edge<V, E> e) { missing.Remove(e.end); };
+      Action<V> mybeforecomponent = beforecomponent + delegate(V v) { missing.Remove(v); };
+      while (!missing.IsEmpty)
+      {
+        V start = default(V);
+        foreach (V v in missing)
+        { start = v; break; }
+        mybeforecomponent(start);
+        TraverseVertices(bfs, start, myact);
+        if (aftercomponent != null)
+          aftercomponent(start);
+      }
+    }
+
+    delegate void Visitor(V v, V parent, bool atRoot);
+
+    //TODO: allow actions to be null
+    [UsedBy("testDFS")]
+    public void DepthFirstSearch(V start, Action<V> before, Action<V> after,
+        Action<Edge<V, E>> onfollow, Action<Edge<V, E>> onfollowed, Action<Edge<V, E>> onnotfollowed)
+    {
+      HashSet<V> seen = new HashSet<V>();
+      seen.Add(start);
+      //If we do not first set visit = null, the compiler will complain at visit(end)
+      //that visit is uninitialized
+      Visitor visit = null;
+      visit = delegate(V v, V parent, bool atRoot)
+      {
+        before(v);
+        HashDictionary<V, E> adjacent;
+        if (graph.Find(v, out adjacent))
+          foreach (KeyValuePair<V, E> p in adjacent)
+          {
+            V end = p.Key;
+            Edge<V, E> e = new Edge<V, E>(v, end, p.Value);
+            if (!seen.FindOrAdd(ref end))
+            {
+              onfollow(e);
+              visit(end, v, false);
+              onfollowed(e);
+            }
+            else
+            {
+              if (!atRoot && !parent.Equals(end))
+                onnotfollowed(e);
+            }
+          }
+        after(v);
+      };
+      visit(start, default(V), true);
+    }
+
+    public void PriorityFirstTraverse(bool accumulated, V start, EdgeAction<V, E, W> act)
+    {
+      if (!graph.Contains(start))
+        throw new ArgumentException("Graph does not contain start");
+      IPriorityQueue<W> fringe = new IntervalHeap<W>();
+      HashDictionary<V, IPriorityQueueHandle<W>> seen = new HashDictionary<V, IPriorityQueueHandle<W>>();
+      HashDictionary<IPriorityQueueHandle<W>, Edge<V, E>> bestedge = new HashDictionary<IPriorityQueueHandle<W>, Edge<V, E>>();
+
+      IPriorityQueueHandle<W> h = null;
+      V current;
+      W currentdist;
+      while (!fringe.IsEmpty || seen.Count == 0)
+      {
+        if (seen.Count == 0)
+        {
+          seen.Add(start, h);
+          current = start;
+          currentdist = default(W);
+        }
+        else
+        {
+          currentdist = fringe.DeleteMin(out h);
+          Edge<V, E> e = bestedge[h];
+          if (!act(e, currentdist))
+            break;
+          bestedge.Remove(h);
+          current = e.end;
+        }
+        HashDictionary<V, E> adjacentnodes;
+        if (graph.Find(current, out adjacentnodes))
+          foreach (KeyValuePair<V, E> adjacent in adjacentnodes)
+          {
+            V end = adjacent.Key;
+            E edgedata = adjacent.Value;
+            W dist = weight.Weight(edgedata), olddist;
+            if (accumulated && !current.Equals(start)) dist = weight.Add(currentdist, weight.Weight(edgedata));
+            if (!seen.Find(end, out h))
+            {
+              h = null;
+              fringe.Add(ref h, dist);
+              seen[end] = h;
+              bestedge[h] = new Edge<V, E>(current, end, edgedata);
+            }
+            else if (fringe.Find(h, out olddist) && dist.CompareTo(olddist) < 0)
+            {
+              fringe[h] = dist;
+              bestedge[h] = new Edge<V, E>(current, end, edgedata);
+            }
+          }
+      }
+    }
+
+    public W Distance(V start, V end)
+    {
+      W dist = default(W);
+      bool found = false;
+      PriorityFirstTraverse(true, start, delegate(Edge<V, E> e, W w)
+      {
+        if (end.Equals(e.end)) { dist = w; found = true; return false; }
+        else return true;
+      });
+      if (found)
+        return dist;
+      throw new ArgumentException(String.Format("No path from {0} to {1}", start, end));
+    }
+
+
+    public ICollectionValue<Edge<V, E>> ShortestPath(V start, V end)
+    {
+      HashDictionary<V, Edge<V, E>> backtrack = new HashDictionary<V, Edge<V, E>>();
+      PriorityFirstTraverse(true, start, delegate(Edge<V, E> e, W w) { backtrack[e.end] = e; return !end.Equals(e.end); });
+      ArrayList<Edge<V, E>> path = new ArrayList<Edge<V, E>>();
+      Edge<V, E> edge;
+      V v = end;
+      while (backtrack.Find(v, out edge))
+      {
+        path.Add(edge);
+        v = edge.start;
+      }
+      if (path.IsEmpty)
+        throw new ArgumentException(String.Format("No path from {0} to {1}", start, end));
+      path.Reverse();
+      return path;
+    }
+
+    /// <summary>
+    /// NB: assume connected, throw exception if not
+    /// </summary>
+    /// <typeparam name="W"></typeparam>
+    /// <param name="edgeWeight"></param>
+    /// <returns></returns>
+    public IGraph<V, E, W> MinimumSpanningTree(out V start)
+    {
+      ArrayList<Edge<V, E>> edges = new ArrayList<Edge<V, E>>();
+      start = default(V);
+      foreach (V v in graph.Keys)
+      { start = v; break; }
+      PriorityFirstTraverse(false, start, delegate(Edge<V, E> e, W w) { edges.Add(e); return true; });
+      if (edges.Count != graph.Count - 1)
+        throw new ArgumentException("Graph not connected");
+      return new HashGraph<V, E, W>(weight, edges);
+    }
+
+    public ICollectionValue<Edge<V, E>> ApproximateMWPM()
+    {
+      //Assume graph complete and even number of vertices
+      HashGraph<V, E, W> clone = new HashGraph<V, E, W>(weight, Edges());
+      ArrayList<Edge<V, E>> evenpath = new ArrayList<Edge<V, E>>();
+      ArrayList<Edge<V, E>> oddpath = new ArrayList<Edge<V, E>>();
+      V start = default(V);
+      foreach (V v in clone.Vertices()) { start = v; break; }
+      V current = start;
+      W evenweight, oddweight;
+      evenweight = oddweight = default(W);
+      bool even = true;
+      while (clone.VertexCount > 0)
+      {
+        V bestvertex = default(V);
+        E bestedge = default(E);
+        W bestweight = default(W);
+        if (clone.VertexCount == 1)
+        {
+          bestvertex = start;
+          bestedge = graph[current][start];
+          bestweight = weight.Weight(bestedge);
+        }
+        else
+        {
+          bool first = true;
+          foreach (KeyValuePair<V, E> p in clone.graph[current])
+          {
+            W thisweight = weight.Weight(p.Value);
+            if (first || bestweight.CompareTo(thisweight) > 0)
+            {
+              bestvertex = p.Key;
+              bestweight = thisweight;
+              bestedge = p.Value;
+            }
+            first = false;
+          }
+        }
+        clone.RemoveVertex(current);
+        //Console.WriteLine("-* {0} / {1} / {2}", bestvertex, bestweight, tour.Count);
+        if (even)
+        {
+          evenweight = evenpath.Count < 1 ? bestweight : weight.Add(evenweight, bestweight);
+          evenpath.Add(new Edge<V, E>(current, bestvertex, bestedge));
+        }
+        else
+        {
+          oddweight = oddpath.Count < 1 ? bestweight : weight.Add(oddweight, bestweight);
+          oddpath.Add(new Edge<V, E>(current, bestvertex, bestedge));
+        }
+        current = bestvertex;
+        even = !even;
+      }
+      //Console.WriteLine("Totalweights: even: {0} and odd: {1}", evenweight, oddweight);
+      return evenweight.CompareTo(oddweight) < 0 ? evenpath : oddpath;
+    }
+
+    /// <summary>
+    /// The construction is performed as follows: 
+    /// Start at some vertex. Greedily construct a path starting there by 
+    /// following edges at random until no more unused edges are available
+    /// from the current node, which must be the start node. Then follow 
+    /// the path constructed so far and whenever we meet a vertex with 
+    /// unused edges, construct a path from there greedily as above, 
+    /// inserting into the path in front of us.
+    /// 
+    /// The algorithm will use constant time for each vertex added 
+    /// to the path and 
+    /// 
+    /// Illustrates use of views as a safe version of listnode pointers 
+    /// and hashed linked lists for choosing some item in constant time combined 
+    /// with (expected) constant time remove.
+    /// </summary>
+    /// <returns></returns>
+    public IList<V> EulerTour()
+    {
+      bool debug = false;
+      //Assert connected and all degrees even. (Connected is checked at the end)
+      string fmt = "Graph does not have a closed Euler tour: vertex {0} has odd degree {1}";
+      foreach (KeyValuePair<V, HashDictionary<V, E>> adj in graph)
+        if (adj.Value.Count % 2 != 0)
+          throw new ArgumentException(String.Format(fmt, adj.Key, adj.Value.Count));
+
+      LinkedList<V> path = new LinkedList<V>();
+      //Clone the graph data to keep track of used edges.
+      HashDictionary<V, HashedArrayList<V>> edges = new HashDictionary<V, HashedArrayList<V>>();
+      V start = default(V);
+      HashedArrayList<V> adjacent = null;
+      foreach (KeyValuePair<V, HashDictionary<V, E>> p in graph)
+      {
+        adjacent = new HashedArrayList<V>();
+        adjacent.AddAll(p.Value.Keys);
+        start = p.Key;
+        edges.Add(start, adjacent);
+      }
+
+      path.Add(start);
+      IList<V> view = path.View(0, 1);
+      while (adjacent.Count > 0)
+      {
+        V current = view[0];
+        if (debug) Console.WriteLine("==> {0}", current);
+        //Augment the path (randomly) until we return here and all edges
+        while (adjacent.Count > 0)
+        {
+          if (debug) Console.WriteLine(" => {0}, {1}", current, path.Count);
+          V next = adjacent.RemoveFirst();
+          view.Add(next);
+          if (debug) Console.WriteLine("EDGE: " + current + "->" + next);
+          if (!edges[next].Remove(current))
+            Console.WriteLine("Bad");
+          current = next;
+          adjacent = edges[current];
+        }
+        //When we get here, the view contains a closed path, i.e.
+        //view[view.Count-1] == view[0] and we have followed all edges from view[0]
+        //We slide forward along the rest of the path constructed so far and stop at the
+        //first vertex with still unfollwed edges.
+        while (view.Offset < path.Count - 1 && adjacent.Count == 0)
+        {
+          view.Slide(1, 1);
+          if (debug) Console.WriteLine(" -> {0}, {1}", view[0], path.Count);
+          adjacent = edges[view[0]];
+        }
+      }
+      if (path.Count <= edges.Count)
+        throw new ArgumentException("Graph was not connected");
+      return path;
+    }
+
+    /// <summary>
+    /// The purpose of this struct is to be able to create and add new,
+    /// synthetic vertices to a graph. 
+    /// </summary>
+    struct Vplus : IEquatable<Vplus>
+    {
+      internal readonly V vertex; internal readonly int id;
+      static SCG.IEqualityComparer<V> vequalityComparer = EqualityComparer<V>.Default;
+      internal Vplus(V v) { vertex = v; id = 0; }
+      internal Vplus(int i) { vertex = default(V); id = i; }
+      //We should override Equals and GetHashCode
+
+      public override string ToString()
+      { return id == 0 ? String.Format("real({0})", vertex) : String.Format("fake({0})", id); }
+
+      public override bool Equals(object obj) { throw new NotImplementedException(); }
+
+      public bool Equals(Vplus other) { return vequalityComparer.Equals(vertex, other.vertex) && id == other.id; }
+
+      public override int GetHashCode() { return vequalityComparer.GetHashCode(vertex) + id; }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    /// <returns></returns>
+    public IDirectedCollectionValue<V> ApproximateTSP2()
+    {
+      /* Construct a minimum spanning tree for the graph */
+      V root;
+      IGraph<V, E, W> tree = MinimumSpanningTree(out root);
+
+      //Console.WriteLine("========= Matching of odd vertices of mst =========");
+      ArrayList<V> oddvertices = new ArrayList<V>();
+      foreach (V v in tree.Vertices())
+        if (tree.Adjacent(v).Count % 2 != 0)
+          oddvertices.Add(v);
+
+      ICollectionValue<Edge<V, E>> matching = SubGraph(oddvertices).ApproximateMWPM();
+
+      //Console.WriteLine("========= Fuse matching and tree =========");
+      //We must split the edges of the matching with fake temporary vertices
+      //since the matching and the tree may have common edges
+
+      HashGraph<Vplus, E, W> fused = new HashGraph<Vplus, E, W>(weight);
+      foreach (Edge<V, E> e in tree.Edges())
+        fused.AddEdge(new Vplus(e.start), new Vplus(e.end), e.edgedata);
+      int fakeid = 1;
+      foreach (Edge<V, E> e in matching)
+      {
+        Vplus fakevertex = new Vplus(fakeid++);
+        fused.AddEdge(new Vplus(e.start), fakevertex, e.edgedata);
+        fused.AddEdge(fakevertex, new Vplus(e.end), e.edgedata);
+      }
+      fused.Print(Console.Out);
+
+      //Console.WriteLine("========= Remove fake vertices and perform shortcuts =========");
+      IList<Vplus> fusedtour = fused.EulerTour();
+      HashSet<V> seen = new HashSet<V>();
+      IList<V> tour = new ArrayList<V>();
+
+      foreach (Vplus vplus in fused.EulerTour())
+      {
+        V v = vplus.vertex;
+        if (vplus.id == 0 && !seen.FindOrAdd(ref v))
+          tour.Add(v);
+      }
+      return tour;
+    }
+
+    /// <summary>
+    /// (Refer to the litterature, Vazirani)
+    /// 
+    /// (Describe: MST+Euler+shortcuts)
+    /// </summary>
+    /// <returns></returns>
+    [UsedBy("testTSP")]
+    public IDirectedCollectionValue<V> ApproximateTSP()
+    {
+      /* Construct a minimum spanning tree for the graph */
+      V root;
+      IGraph<V, E, W> tree = MinimumSpanningTree(out root);
+
+      /* (Virtually) double all edges of MST and construct an Euler tour of the vertices*/
+      LinkedList<V> tour = new LinkedList<V>();
+      tour.Add(root);
+      tour.Add(root);
+      IList<V> view = tour.View(1, 1);
+
+      Action<Edge<V, E>> onfollow = delegate(Edge<V, E> e)
+      {
+        //slide the view until it points to the last copy of e.start
+        while (!view[0].Equals(e.start))
+          view.Slide(1);
+        //then insert two copies of e.end and slide the view one backwards
+        view.InsertFirst(e.end);
+        view.InsertFirst(e.end);
+        view.Slide(1, 1);
+      };
+
+      tree.TraverseVertices(false, root, onfollow);
+
+      /* Finally, slide along the Euler tour and shortcut by removing vertices already seen*/
+      HashSet<V> seen = new HashSet<V>();
+      view = tour.View(0, tour.Count);
+      while (view.Offset < tour.Count - 1)
+      {
+        V v = view[0];
+        if (seen.FindOrAdd(ref v))
+          view.RemoveFirst();
+        else
+          view.Slide(1, view.Count - 1);
+      }
+      return tour;
+    }
+
+    public void Print(System.IO.TextWriter output)
+    {
+      output.WriteLine("Graph has {0} vertices, {1} edges, {2} components", graph.Count, edgecount, ComponentCount);
+      foreach (KeyValuePair<V, HashDictionary<V, E>> p in graph)
+      {
+        output.Write(" {0} ->  ", p.Key);
+        foreach (KeyValuePair<V, E> p2 in p.Value)
+          output.Write("{1} (data {2}), ", p.Key, p2.Key, p2.Value);
+        output.WriteLine();
+      }
+    }
+  }
+
+/// <summary>
+/// A weight on a graph that assigns the weight 1 to every edge.
+/// </summary>
+/// <typeparam name="E">(Ignored) type of edgedata</typeparam>
+  class CountWeight<E> : IWeight<E, int>
+  {
+    public int Weight(E edgedata) { return 1; }
+
+    public int Add(int w1, int w2) { return w1 + w2; }
+  }
+
+/// <summary>
+/// A weight on an IGraph&lt;V,int&gt; that uses the value of the edgedata as the weight value.
+/// </summary>
+  class IntWeight : IWeight<int, int>
+  {
+
+    public int Weight(int edgedata) { return edgedata; }
+
+    public int Add(int w1, int w2) { return w1 + w2; }
+
+  }
+
+/// <summary>
+/// A weight on an IGraph&lt;V,double&gt; that uses the value of the edgedata as the weight value.
+/// </summary>
+  class DoubleWeight : IWeight<double, double>
+  {
+
+    public double Weight(double edgedata) { return edgedata; }
+
+    public double Add(double w1, double w2) { return w1 + w2; }
+
+  }
+
+/// <summary>
+/// Attribute used for marking which examples use a particuler graph method
+/// </summary>
+  class UsedByAttribute : Attribute
+  {
+    string[] tests;
+    internal UsedByAttribute(params string[] tests) { this.tests = tests; }
+
+    public override string ToString()
+    {
+      System.Text.StringBuilder sb = new System.Text.StringBuilder();
+      for (int i = 0; i < tests.Length; i++)
+      {
+        if (i > 0)
+          sb.Append(", ");
+        sb.Append(tests[i]);
+      }
+      return sb.ToString();
+    }
+  }
+
+/// <summary>
+/// Attribute for marking example methods with a description
+/// </summary>
+  class ExampleDescriptionAttribute : Attribute
+  {
+    string text;
+    internal ExampleDescriptionAttribute(string text) { this.text = text; }
+
+    public override string ToString() { return text; }
+  }
+
+/// <summary>
+/// A selection of test cases
+/// </summary>
+  class Test
+  {
+    static SCG.IEnumerable<Edge<int, int>> Grid(int n)
+    {
+      Random ran = new Random(1717);
+      for (int i = 1; i <= n; i++)
+      {
+        for (int j = 1; j <= n; j++)
+        {
+          yield return new Edge<int, int>(1000 * i + j, 1000 * (i + 1) + j, ran.Next(1, 100));
+          yield return new Edge<int, int>(1000 * i + j, 1000 * i + j + 1, ran.Next(1, 100));
+        }
+      }
+    }
+
+    static SCG.IEnumerable<Edge<string, int>> Snake(int n)
+    {
+      for (int i = 1; i <= n; i++)
+      {
+        yield return new Edge<string, int>("U" + i, "L" + i, 1);
+        yield return new Edge<string, int>("U" + i, "U" + (i + 1), i % 2 == 0 ? 1 : 10);
+        yield return new Edge<string, int>("L" + i, "L" + (i + 1), i % 2 == 0 ? 10 : 1);
+      }
+    }
+
+    /// <summary>
+    /// Create the edges of a forest of complete binary trees.
+    /// </summary>
+    /// <param name="treeCount">Number of trees</param>
+    /// <param name="height">Height of trees</param>
+    /// <returns></returns>
+    static SCG.IEnumerable<Edge<string, int>> Forest(int treeCount, int height)
+    {
+      for (int i = 0; i < treeCount; i++)
+      {
+        IList<string> q = new ArrayList<string>();
+        string root = String.Format("[{0}]", i);
+        int lmax = height + root.Length;
+        q.Add(root);
+        while (!q.IsEmpty)
+        {
+          string s = q.Remove();
+          string s2 = s + "L";
+          if (s2.Length < lmax)
+            q.Add(s2);
+          yield return new Edge<string, int>(s, s2, 0);
+          s2 = s + "R";
+          if (s2.Length < lmax)
+            q.Add(s2);
+          yield return new Edge<string, int>(s, s2, 0);
+        }
+      }
+    }
+
+    /// <summary>
+    /// Create edges of a graph correspondingto a "wheel" shape: the ecnter and equidistant 
+    /// points around the perimeter. The edgedata and edge weights are the euclidean distances.
+    /// </summary>
+    /// <param name="complete">True means the graph will be complete, false that the graph
+    /// will have edges for the spokes and between neighboring perimeter vetices.</param>
+    /// <param name="n">The number of perimeter vertices, must be at least 3.</param>
+    /// <returns>An enumerable with the edges</returns>
+    static SCG.IEnumerable<Edge<string, double>> Wheel(bool complete, int n)
+    {
+      if (n < 3)
+        throw new ArgumentOutOfRangeException("n must be at least 3");
+      string center = "C";
+      string[] perimeter = new string[n];
+      for (int i = 0; i < n; i++)
+      {
+        perimeter[i] = "P" + i;
+        yield return new Edge<string, double>(perimeter[i], center, 1);
+      }
+      if (complete)
+        for (int i = 0; i < n - 1; i++)
+          for (int j = i + 1; j < n; j++)
+            yield return new Edge<string, double>(perimeter[i], perimeter[j], 2 * Math.Sin((j - i) * Math.PI / n));
+      else
+      {
+        for (int i = 0; i < n - 1; i++)
+          yield return new Edge<string, double>(perimeter[i], perimeter[i + 1], 2 * Math.Sin(Math.PI / n));
+        yield return new Edge<string, double>(perimeter[n - 1], perimeter[0], 2 * Math.Sin(Math.PI / n));
+      }
+    }
+
+
+    /// <summary>
+    /// []
+    /// </summary>
+    [ExampleDescription("Basic BFS and DFS using TraverseVertices method")]
+    static void test1()
+    {
+      IGraph<int, int, int> g = new HashGraph<int, int, int>(new CountWeight<int>(), Grid(3));
+      Console.WriteLine("Edge count: {0}", g.Edges().Count);
+      Console.WriteLine("BFS:");
+      g.TraverseVertices(true, 1001, delegate(Edge<int, int> e) { Console.WriteLine(e); });
+      Console.WriteLine("DFS:");
+      g.TraverseVertices(false, 1001, delegate(Edge<int, int> e) { Console.WriteLine(e); });
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    [ExampleDescription("Component methods")]
+    static void testCOMP()
+    {
+      IGraph<string, int, int> g = new HashGraph<string, int, int>(new CountWeight<int>(), Forest(2, 2));
+      Console.WriteLine("Forest has: Vertices: {0}, Edges: {1}, Components: {2}", g.VertexCount, g.EdgeCount, g.ComponentCount);
+      //g.Print(Console.Out);
+      foreach (KeyValuePair<string, IGraph<string, int, int>> comp in g.Components())
+      {
+        Console.WriteLine("Component of {0}:", comp.Key);
+        comp.Value.Print(Console.Out);
+      }
+    }
+
+    //TODO: remove?
+    static void test3()
+    {
+      HashGraph<int, int, int> g = new HashGraph<int, int, int>(new CountWeight<int>(), Grid(5));
+      g.Print(Console.Out);
+      //EdgeWeight<int, IntWeight> weight = delegate(int i) { return i; };
+      Console.WriteLine("========= PFS accum =========");
+      g.PriorityFirstTraverse(
+          true,
+          2002,
+          delegate(Edge<int, int> e, int d) { Console.WriteLine("Edge: {0}, at distance {1}", e, d); return true; });
+      Console.WriteLine("========= PFS not accum =========");
+      g.PriorityFirstTraverse(
+          false,
+          2002,
+          delegate(Edge<int, int> e, int d) { Console.WriteLine("Edge: {0}, at distance {1}", e, d); return true; });
+      Console.WriteLine("========= MST =========");
+      int root;
+      g.MinimumSpanningTree(out root).Print(Console.Out);
+      Console.WriteLine("========= SP =========");
+      foreach (Edge<int, int> edge in g.ShortestPath(1001, 5005))
+        Console.WriteLine(edge);
+    }
+
+    static void test4()
+    {
+      IGraph<string, int, int> g = new HashGraph<string, int, int>(new IntWeight(), Snake(5));
+      Console.WriteLine("Edge count: {0}", g.Edges().Count);
+      Console.WriteLine("========= PFS =========");
+      g.PriorityFirstTraverse(false,
+          "U3",
+          delegate(Edge<string, int> e, int d) { Console.WriteLine("Edge: {0}, at distance {1}", e, d); return true; });
+      Console.WriteLine("========= MST =========");
+      string root;
+      IGraph<string, int, int> mst = g.MinimumSpanningTree(out root);
+      mst.Print(Console.Out);
+      Console.WriteLine("DFS:");
+      mst.TraverseVertices(false, root, delegate(Edge<string, int> e) { Console.WriteLine(e); });
+      Console.WriteLine("ATSP:");
+      int first = 0;
+      foreach (string s in g.ApproximateTSP())
+      {
+        Console.Write((first++ == 0 ? "" : " -> ") + s);
+      }
+    }
+
+    /// <summary>
+    /// This example examines the two variants of a priority-first search:
+    ///  with accumulated weights, leading to shortest paths from start;
+    ///  with non-acumulated weights, leading to a minimum spanning tree.
+    /// </summary>
+    [ExampleDescription("Priority-first-search with and without accumulated weights")]
+    static void testPFS()
+    {
+      IGraph<string, double, double> g = new HashGraph<string, double, double>(new DoubleWeight(), Wheel(false, 10));
+      g.Print(Console.Out);
+      Console.WriteLine("========= PFS non-accumulated weights (-> MST) =========");
+      g.PriorityFirstTraverse(false,
+          "P0",
+          delegate(Edge<string, double> e, double d) { Console.WriteLine("Edge: {0}, at distance {1}", e, d); return true; });
+      Console.WriteLine("========= PFS accumulated weights (-> Shortst paths from start) =========");
+      g.PriorityFirstTraverse(true,
+          "P0",
+          delegate(Edge<string, double> e, double d) { Console.WriteLine("Edge: {0}, at distance {1}", e, d); return true; });
+    }
+
+    /// <summary>
+    /// 
+    /// 
+    /// (Refer to Vazirani, or do that where ApproximateTSP is implemented)
+    /// 
+    /// Note that the tour created is not optimal. [Describe why]
+    /// </summary>
+    [ExampleDescription("Approximate TSP")]
+    static void testTSP()
+    {
+      IGraph<string, double, double> g = new HashGraph<string, double, double>(new DoubleWeight(), Wheel(true, 10));
+      //g.Print(Console.Out);
+      Console.WriteLine("========= MST =========");
+      string root;
+      IGraph<string, double, double> mst = g.MinimumSpanningTree(out root);
+      mst.TraverseVertices(false,
+         root,
+         delegate(Edge<string, double> e) { Console.WriteLine("Edge: {0} -> {1}", e.start, e.end); });
+      Console.WriteLine("========= Approximate TSP =========");
+      int first = 0;
+      foreach (string s in g.ApproximateTSP())
+      {
+        Console.Write((first++ == 0 ? "" : " -> ") + s);
+      }
+    }
+
+    /// <summary>
+    /// 
+    /// 
+    /// (Refer to Vazirani, or do that where ApproximateTSP is implemented)
+    /// 
+    /// Note that the tour created is not optimal. [Describe why]
+    /// </summary>
+    [ExampleDescription("Approximate TSP2")]
+    static void testTSP2()
+    {
+      HashGraph<string, double, double> g = new HashGraph<string, double, double>(new DoubleWeight(), Wheel(true, 20));
+
+      foreach (string s in g.ApproximateTSP2())
+        Console.WriteLine("# " + s);
+      //g.Print(Console.Out);
+      /*
+        Console.WriteLine("========= MST =========");
+        string root;
+        IGraph<string, double, double> mst = g.MinimumSpanningTree(out root);
+        mst.TraverseVertices(false,
+           root,
+           delegate(Edge<string, double> e) { Console.WriteLine("Edge: {0} -> {1}", e.start, e.end); });
+        ArrayList<string> oddvertices = new ArrayList<string>();
+        foreach (string v in mst.Vertices())
+            if (mst.Adjacent(v).Count % 2 != 0)
+                oddvertices.Add(v);
+
+        Console.WriteLine("========= Matching of odd vertices of mst =========");
+        ICollectionValue<Edge<string, double>> matching = g.SubGraph(oddvertices).ApproximateMWPM();
+
+        Console.WriteLine("========= Add matching to mst =========");
+        //We must split the edges of the matchin with fake temporary vertices
+        //(For a general vertex type, we would have to augment it to Pair<V,int> 
+        int fake = 0;
+        foreach (Edge<string, double> e in matching)
+        {
+            string fakevertex = "_" + (fake++);
+            mst.AddEdge(e.start, fakevertex, 0);
+            mst.AddEdge(fakevertex, e.end, e.edgedata);
+        }
+        //mst.Print(Console.Out);
+
+        IList<string> tour = mst.EulerTour(), view = tour.View(1, tour.Count - 1);
+
+        //Remove fake vertices
+         while (view.Count > 0)
+            if (view[0].StartsWith("_"))
+                view.RemoveFirst();
+            else
+                view.Slide(1, view.Count - 1);
+
+        Console.WriteLine("========= Approximate TSP 2 =========");
+        //Short cut
+        view = tour.View(1, tour.Count - 1);
+        HashSet<string> seen = new HashSet<string>();
+
+        while (view.Count > 0)
+        {
+            string s = view[0];
+            if (seen.FindOrAdd(ref s))
+                view.RemoveFirst();
+            else
+                view.Slide(1, view.Count - 1);
+        }
+
+        foreach (string s in tour)
+            Console.WriteLine(". " + s);*/
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    static void testEuler()
+    {
+      HashGraph<string, double, double> g = new HashGraph<string, double, double>(new DoubleWeight(), Wheel(true, 6));
+      foreach (string s in g.EulerTour())
+        Console.Write(s + " ");
+      Console.WriteLine();
+    }
+
+    /// <summary>
+    /// An articulation point in a graph is a vertex, whose removal will 
+    /// disconnect the graph (or its component). This example uses the 
+    /// extended DepthFirstSearch method to compute articulation points
+    /// of a graph.
+    /// 
+    /// (Refer to Sedgewick. )
+    /// 
+    /// Each vertex is given an index in traversal order. 
+    /// For each vertex, we compute the least index reachable by going downwards
+    /// in the DFS tree and then following a single non-dfs edge. 
+    /// 
+    /// Since we cannot store the DFS indices in the vertices without changing the 
+    /// (assumed given) vertex type, V, we remember the indices in a V-&gt;int 
+    /// hash dictionary, index. The "least reachable" values are then stored in an 
+    /// array keyed by the index.
+    /// 
+    /// The root of the search is an articulation point if it has more than one
+    /// outgoing DFS edges. Other articulation points are non-root vertices, va,
+    /// with an outgoing DFS edge, where the the least reachable index of the other 
+    /// vertex is greater or equal to the index of va. 
+    /// </summary>
+    [ExampleDescription("Using the advanced DFS to compute articulation points")]
+    static void testDFS()
+    {
+      HashGraph<string, int, int> g = new HashGraph<string, int, int>(new IntWeight());
+      g.AddEdge("A", "B", 0);
+      g.AddEdge("A", "E", 0);
+      g.AddEdge("B", "E", 0);
+      g.AddEdge("B", "C", 0);
+      g.AddEdge("B", "H", 0);
+      g.AddEdge("H", "I", 0);
+      g.AddEdge("B", "D", 0);
+      g.AddEdge("C", "D", 0);
+      g.AddEdge("C", "F", 0);
+      g.AddEdge("C", "G", 0);
+      g.AddEdge("F", "G", 0);
+
+      HashDictionary<string, int> index = new HashDictionary<string, int>();
+      int[] leastIndexReachableFrom = new int[g.VertexCount];
+      int nextindex = 0;
+      int outgoingFromRoot = 0;
+      Action<string> beforevertex = delegate(string v)
+      {
+        int i = (index[v] = nextindex++);
+        leastIndexReachableFrom[i] = i;
+      };
+      Action<string> aftervertex = delegate(string v)
+      {
+        int i = index[v];
+        if (i == 0 && outgoingFromRoot > 1)
+          Console.WriteLine("Articulation point: {0} ({1}>1 outgoing DFS edges from start)",
+              v, outgoingFromRoot);
+      };
+      Action<Edge<string, int>> onfollow = delegate(Edge<string, int> e)
+      {
+      };
+      Action<Edge<string, int>> onfollowed = delegate(Edge<string, int> e)
+      {
+        int startind = index[e.start], endind = index[e.end];
+        if (startind == 0)
+          outgoingFromRoot++;
+        else
+        {
+          int leastIndexReachable = leastIndexReachableFrom[endind];
+          if (leastIndexReachable >= startind)
+            Console.WriteLine("Articulation point: {0} (least index reachable via {3} is {1} >= this index {2})",
+                e.start, leastIndexReachable, startind, e);
+          if (leastIndexReachableFrom[startind] > leastIndexReachable)
+            leastIndexReachableFrom[startind] = leastIndexReachable;
+        }
+      };
+      Action<Edge<string, int>> onnotfollowed = delegate(Edge<string, int> e)
+      {
+        int startind = index[e.start], endind = index[e.end];
+        if (leastIndexReachableFrom[startind] > endind)
+          leastIndexReachableFrom[startind] = endind;
+      };
+
+      string root = "C";
+      g.DepthFirstSearch(root, beforevertex, aftervertex, onfollow, onfollowed, onnotfollowed);
+      Console.WriteLine("Edges:");
+      foreach (Edge<string, int> e in g.Edges())
+        Console.WriteLine("/ {0}", e);
+    }
+
+    static void Main(String[] args)
+    {
+      if (args.Length != 1)
+      {
+        Console.WriteLine("Usage: Graph.exe testno");
+        System.Reflection.MethodInfo[] mis = typeof(Test).GetMethods(
+            System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
+        foreach (System.Reflection.MethodInfo mi in mis)
+        {
+          if (mi.GetParameters().Length == 0 && mi.ReturnType == typeof(void) && mi.Name.StartsWith("test"))
+          {
+            object[] attrs = mi.GetCustomAttributes(typeof(ExampleDescriptionAttribute), false);
+            Console.WriteLine(" {0} : {1}", mi.Name.Substring(4), attrs.Length > 0 ? attrs[0] : "");
+          }
+        }
+      }
+      else
+      {
+        string testMethodName = String.Format("test{0}", args[0]);
+
+        System.Reflection.MethodInfo mi = typeof(Test).GetMethod(testMethodName,
+            System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic);
+
+        if (mi == null)
+          Console.WriteLine("No such testmethod, {0}", testMethodName);
+        else
+        {
+          object[] attrs = mi.GetCustomAttributes(typeof(ExampleDescriptionAttribute), false);
+          Console.WriteLine("============================== {0}() ==================================", testMethodName);
+          Console.WriteLine("Description: {0}", attrs.Length > 0 ? attrs[0] : "None");
+          Console.WriteLine("===========================================================================");
+          mi.Invoke(null, null);
+        }
+      }
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Graphcopy.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Graphcopy.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Graphcopy.cs	(revision 3)
@@ -0,0 +1,192 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: graph copying 2005-11-08
+
+// Compile with 
+//   csc /r:C5.dll Toposort.cs 
+
+using System;
+using System.Text;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace Graphcopy {
+  class TestGraphcopy {
+    public static void Main(String[] args) {
+      if (args.Length != 1) 
+	Console.WriteLine("Usage: Graphcopy <nodecount>\n");
+      else {
+	int count = int.Parse(args[0]);
+	Node<String> 
+	  d = new Node<String>("d"), 
+	  e = new Node<String>("e"),
+	  c = new Node<String>("c", d, e),
+	  b = new Node<String>("b", d),
+	  a = new Node<String>("a", d, b, c);
+	a[1] = a;
+	Node<String> newstart = CopyGraph1(a);
+	Console.WriteLine("Copy has same structure: " + Isomorphic1(newstart, a));
+	Console.WriteLine("newstart = " + newstart);
+	foreach (Node<String> node1 in newstart.children)
+	  Console.WriteLine(node1);
+	Node<String> node = new Node<String>("last");
+	for (int i=0; i<count; i++)
+	  node = new Node<String>(i.ToString(), node);
+	newstart = CopyGraph1(node);
+	Console.WriteLine("Copy has same structure: " 
+			  + Isomorphic1(newstart, node));
+      }
+    }
+    
+    // Graph copying 0
+    
+    public static Node<T> CopyGraph0<T>(Node<T> start) {
+      IDictionary<Node<T>,Node<T>> iso 
+        = new HashDictionary<Node<T>,Node<T>>
+              (ReferenceEqualityComparer<Node<T>>.Default);
+      return CopyNode0(iso, start);
+    }
+
+    private static Node<T> CopyNode0<T>(IDictionary<Node<T>,Node<T>> iso, 
+                                        Node<T> old) {
+      Node<T> copy;
+      if (!iso.Find(old, out copy)) {
+        copy = new Node<T>(old);
+        iso[old] = copy;
+        for (int i=0; i<copy.children.Length; i++)
+          copy.children[i] = CopyNode0(iso, old.children[i]);
+      }
+      return copy;
+    }
+
+    // Graph copying 1, using an explicit stack of pending nodes.
+    // Every new node is added to the stack exactly once.  Every node
+    // in the stack is also in the key set of the dictionary.
+    
+    public static Node<T> CopyGraph1<T>(Node<T> start) {
+      IDictionary<Node<T>,Node<T>> iso 
+        = new HashDictionary<Node<T>,Node<T>>
+              (ReferenceEqualityComparer<Node<T>>.Default);
+      IStack<Node<T>> work = new ArrayList<Node<T>>();
+      iso[start] = new Node<T>(start);
+      work.Push(start);
+      while (!work.IsEmpty) {
+        Node<T> node = work.Pop(), copy = iso[node];
+        for (int i=0; i<node.children.Length; i++) {
+          Node<T> child = node.children[i];
+          Node<T> childCopy;
+          if (!iso.Find(child, out childCopy)) {
+            iso[child] = childCopy = new Node<T>(child);
+            work.Push(child);
+          }
+          copy.children[i] = childCopy;
+        }
+      }
+      return iso[start];
+    }
+
+    // Graph equality 0
+
+    public static bool Isomorphic0<T>(Node<T> start1, Node<T> start2) {
+      IDictionary<Node<T>,Node<T>> iso
+        = new HashDictionary<Node<T>,Node<T>>
+              (ReferenceEqualityComparer<Node<T>>.Default);
+      return NodeEquals0(iso, start1, start2);
+    }
+
+    private static bool NodeEquals0<T>(IDictionary<Node<T>,Node<T>> iso, 
+                                       Node<T> left, Node<T> rght) {
+      Node<T> node;
+      if (iso.Find(left, out node))
+        return Object.ReferenceEquals(node, rght);
+      else if (left.children.Length != rght.children.Length)
+        return false;
+      else {
+        iso[left] = rght;
+        for (int i=0; i<left.children.Length; i++)
+          if (!NodeEquals0(iso, left.children[i], rght.children[i]))
+            return false;
+        return true;
+      } 
+    }
+
+    // Graph equality 1, using an explicit stack of pending nodes.
+    // If iso[left] = rght, we are trying to prove that left and rght
+    // are the roots of isomorphic subgraphs.  The work stack contains
+    // the assumptions needed to prove this.  Whenever node is on the
+    // work stack, then node is also in the key set of iso.  
+
+    public static bool Isomorphic1<T>(Node<T> start1, Node<T> start2) {
+      IDictionary<Node<T>,Node<T>> iso
+        = new HashDictionary<Node<T>,Node<T>>
+              (ReferenceEqualityComparer<Node<T>>.Default);
+      IStack<Node<T>> work = new ArrayList<Node<T>>();
+      iso[start1] = start2;
+      work.Push(start1);
+      while (!work.IsEmpty) {
+        Node<T> left = work.Pop(), rght = iso[left];
+        if (left.children.Length != rght.children.Length)
+          return false;
+        else {
+          for (int i=0; i<left.children.Length; i++) {
+            Node<T> lchild = left.children[i], rchild = rght.children[i];
+            Node<T> node;
+            if (iso.Find(lchild, out node)) {
+              if (!Object.ReferenceEquals(node, rchild))
+                return false;
+            } else {
+              iso[lchild] = rchild;
+              work.Push(lchild);
+            }
+          }
+        } 
+      }
+      return true;
+    }
+  }
+
+  public class Node<T> { 
+    public readonly T id;
+    public readonly Node<T>[] children;
+
+    public Node(T id, params Node<T>[] children) { 
+      this.id = id; this.children = children;
+    }
+
+    public Node(Node<T> node) : this(node.id, new Node<T>[node.children.Length])
+    { }
+
+    public override String ToString() { 
+      StringBuilder sb = new StringBuilder();
+      sb.Append(id).Append("[ ");
+      foreach (Node<T> child in children)
+        sb.Append(child.id).Append(" ");
+      sb.Append("]");
+      return sb.ToString();
+    }
+
+    public Node<T> this[int i] {
+      set { children[i] = value; }
+      get { return children[i]; }
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/GuardedView.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/GuardedView.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/GuardedView.cs	(revision 3)
@@ -0,0 +1,51 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: 2006-06-26
+
+// Compile with 
+//   csc /r:C5.dll Anagrams.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace MyTest {
+  class MyTest {
+    public static void Main(String[] args) {
+      IList<int> list1 = new ArrayList<int>();
+      list1.AddAll(new int[] { 2, 5, 7, 11, 37 });
+      IList<int> list2 = new GuardedList<int>(list1);
+      IList<int> 
+        gv = new GuardedList<int>(list1.View(1,2)),
+        vg = list2.View(1,2);
+      IList<int> 
+        gvu = gv.Underlying, 
+        vgu = vg.Underlying;
+      Console.WriteLine(gvu);  // Legal 
+      Console.WriteLine(vgu);  // Legal 
+      // gv.Slide(+1);         // Illegal: guarded view cannot be slid
+      vg.Slide(+1);            // Legal: view of guarded can be slid
+      // gvu[1] = 9;           // Illegal: list is guarded
+      // vgu[1] = 9;           // Illegal: list is guarded
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/HashCodes.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/HashCodes.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/HashCodes.cs	(revision 3)
@@ -0,0 +1,106 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: hash codes, good and bad 2005-02-28
+
+// Compile with 
+//   csc /r:C5.dll HashCodes.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace MyHashCodesTest {
+  class MyTest {
+    public static void Main(String[] args) {
+      int count = int.Parse(args[0]); 
+      {
+	Console.Write("Good hash function: ");
+	Timer t = new Timer();
+	HashSet<int> good 
+	  = MakeRandom(count, new GoodIntegerEqualityComparer());
+	Console.WriteLine("({0} sec, {1} items)", t.Check(), good.Count);
+	ISortedDictionary<int,int> bcd = good.BucketCostDistribution();
+	foreach (KeyValuePair<int,int> entry in bcd) 
+	  Console.WriteLine("{0,7} bucket(s) with cost {1,5}", 
+			    entry.Value, entry.Key);
+      }
+      {
+	Console.Write("Bad hash function:  ");
+	Timer t = new Timer();
+	HashSet<int> bad = MakeRandom(count, new BadIntegerEqualityComparer());
+	Console.WriteLine("({0} sec, {1} items)", t.Check(), bad.Count);
+	ISortedDictionary<int,int> bcd = bad.BucketCostDistribution();
+	foreach (KeyValuePair<int,int> entry in bcd) 
+	  Console.WriteLine("{0,7} bucket(s) with cost {1,5}", 
+			    entry.Value, entry.Key);
+      }
+    }
+
+    private static readonly C5Random rnd = new C5Random();
+    
+    public static HashSet<int> MakeRandom(int count, 
+					  SCG.IEqualityComparer<int> eqc) {
+      HashSet<int> res;
+      if (eqc == null) 
+	res = new HashSet<int>();
+      else
+	res = new HashSet<int>(eqc);
+      for (int i=0; i<count; i++)
+	res.Add(rnd.Next(1000000));    
+      return res;
+    }
+
+    private class BadIntegerEqualityComparer : SCG.IEqualityComparer<int> {
+      public bool Equals(int i1, int i2) {
+	return i1 == i2;
+      }
+      public int GetHashCode(int i) {
+	return i % 7;
+      }
+    }
+
+    private class GoodIntegerEqualityComparer : SCG.IEqualityComparer<int> {
+      public bool Equals(int i1, int i2) {
+	return i1 == i2;
+      }
+      public int GetHashCode(int i) {
+	return i;
+      }
+    }
+  }
+
+  // Crude timing utility
+   
+  public class Timer {
+    private DateTime start;
+    
+    public Timer() {
+      start = DateTime.Now;
+    }
+    
+    public double Check() {
+      TimeSpan dur = DateTime.Now - start;
+      return dur.TotalSeconds;
+    }
+  }
+}
+
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/IndexedObjects.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/IndexedObjects.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/IndexedObjects.cs	(revision 3)
@@ -0,0 +1,208 @@
+/*
+ Copyright (c) 2003-2007 Niels Kokholm and Peter Sestoft
+*/
+
+// IndexedObjects.cs sketch 2007-07-26 
+
+// Other approaches: Define an Indexed<T> class to which indexers can
+// be attached.  An object can add (or remove) itself to the indexers
+// that are attached to the Indexed class at the time of addition (or
+// removal).
+
+// Maintaining multiple indices on objects, each index defined by a
+// delegate.
+
+// Compile with 
+//   csc /r:C5.dll IndexedObjects.cs 
+
+using System;                           // Console
+using System.Text;                      // StringBuilder
+using C5; 
+using SCG = System.Collections.Generic;
+
+namespace IndexedObjects {
+  static class IndexedObjectsMain {
+    static void Main(String[] args) {
+      Indexed<Person> persons 
+        = new Indexed<Person>
+        (new IndexMaker<Person,String>
+         ("name", delegate(Person p) { return p.name; }),
+         new IndexMaker<Person,int>
+         ("year", delegate(Person p) { return p.date/10000; }),
+         new IndexMaker<Person,int>
+         ("day", delegate(Person p) { return p.date%100; }),
+         new IndexMaker<Person,String>
+         ("month", delegate(Person p) { return months[p.date/100%100-1]; })
+         );
+      persons.Add(new Person("Niels",   19470206));
+      persons.Add(new Person("Lone",    19600810));
+      persons.Add(new Person("Peter",   19620625));
+      persons.Add(new Person("Carsten", 19640627));
+      persons.Add(new Person("Hanne",   19641209));
+      persons.Add(new Person("Dorte",   19660930));
+      persons.Add(new Person("Dorte",   19610312));
+      persons.Add(new Person("J�rgen",  19340930));
+      persons.Add(new Person("Kirsten", 19360114));
+      persons.Add(new Person("Henrik",  19360630));
+      persons.Add(new Person("Lars",    19640625));
+      persons.Add(new Person("Thora",   19091129));
+      Console.WriteLine("Born in 1964:");
+      foreach (Person p in persons["year"][1964]) 
+        Console.WriteLine(p);
+      Console.WriteLine("Born in June:");
+      foreach (Person p in persons["month"]["Jun"]) 
+        Console.WriteLine(p);
+      Console.WriteLine("Named Dorte:");
+      foreach (Person p in persons["name"]["Dorte"]) 
+        Console.WriteLine(p);
+      Console.WriteLine(persons);
+    }
+    
+    private static readonly String[] months = { 
+      "Jan", "Feb", "Mar", "Apr", "May", "Jun", 
+      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" 
+    };
+  }
+
+  public interface IIndexer<Q,R> { 
+    ICollectionValue<R> this[Q x] { get; }
+  }
+
+  // An index maker has a name, it supports adding and removing items
+  // from the index, and looking up items by key (here of type
+  // Object).
+
+  public abstract class IndexMaker<T> : IIndexer<Object, T> {
+    public readonly String name;
+    public abstract bool Add(T item);
+    public abstract bool Remove(T item);
+    public abstract ICollectionValue<T> this[Object key] { get; }
+
+    public IndexMaker(String name) {
+      this.name = name;
+    }
+  }
+
+  // The implementation of an index maker consists of a function to
+  // map an item of type T to the index key type Q, and a dictionary
+  // that maps an index key (of type Q) to a set of items (each of
+  // type T).
+
+  public class IndexMaker<T,Q> : IndexMaker<T> 
+    where T : class 
+    where Q : IComparable<Q> 
+  {
+    private readonly Fun<T,Q> fun;
+    private TreeDictionary<Q, HashSet<T>> dict;
+
+    public IndexMaker(String name, Fun<T,Q> fun) : base(name) {
+      this.fun = fun;
+      dict = new TreeDictionary<Q, HashSet<T>>();
+    }
+
+    public override bool Add(T item) { 
+      Q key = fun(item);
+      if (!dict.Contains(key))
+        dict.Add(key, new HashSet<T>(ReferenceEqualityComparer<T>.Default));
+      return dict[key].Add(item);
+    }
+
+    public override bool Remove(T item) { 
+      Q key = fun(item);
+      if (!dict.Contains(key))
+        return false;
+      return dict[key].Remove(item);
+    }
+
+    public ICollectionValue<T> this[Q key] {
+      get { 
+        return dict[key];
+      }
+    }
+
+    public override ICollectionValue<T> this[Object key] {
+      get { 
+        return dict[(Q)key];
+      }
+    }
+
+    public override String ToString() {
+      return dict.ToString();
+    }
+  }
+
+  // Weakly typed implementation of multiple indexers on a class T.  
+
+  // The implementation is an array of index makers, each consisting
+  // of the index's name and its implementation which supports adding
+  // and removing T objects, and looking up T objects by the key
+  // relevant for that index.
+
+  public class Indexed<T> where T : class {
+    IndexMaker<T>[] indexMakers;
+
+    public Indexed(params IndexMaker<T>[] indexMakers) {
+      this.indexMakers = indexMakers;
+    }
+    
+    public bool Add(T item) { 
+      bool result = false;
+      foreach (IndexMaker<T> indexMaker in indexMakers)
+        result |= indexMaker.Add(item);
+      return result;    
+    }
+
+    public bool Remove(T item) { 
+      bool result = false;
+      foreach (IndexMaker<T> indexMaker in indexMakers)
+        result |= indexMaker.Remove(item);
+      return result;    
+    }
+
+    public IIndexer<Object, T> this[String name] {
+      get {
+        foreach (IndexMaker<T> indexMaker in indexMakers)
+          if (indexMaker.name == name) 
+            return indexMaker;
+        throw new Exception("Unknown index");
+      }
+    }
+
+    // For debugging
+
+    public override String ToString() {
+      StringBuilder sb = new StringBuilder();
+      foreach (IndexMaker<T> indexMaker in indexMakers) {
+        sb.Append("\n----- ").Append(indexMaker.name).Append("-----\n");
+        sb.Append(indexMaker);
+      }
+      return sb.ToString();
+    }
+  }
+
+  // Sample class with two fields but many possible indexes
+  
+  public class Person {
+    public readonly String name;
+    public readonly int date; // YYYYMMDD as in 20070725
+
+    public Person(String name, int date) {
+      this.name = name;
+      this.date = date;
+    }
+
+    public override String ToString() {
+      return name + " (" + date + ")";
+    }
+  }
+
+  // The interface of a strongly typed indexing of Person objects:
+  // (Not yet used)
+
+  public interface PersonIndexers {
+    IIndexer<String, Person> Name { get; }
+    IIndexer<int,    Person> Year { get; }
+    IIndexer<int,    Person> Day { get; }
+    IIndexer<String, Person> Month { get; }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/IndexedObjects2.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/IndexedObjects2.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/IndexedObjects2.cs	(revision 3)
@@ -0,0 +1,202 @@
+/*
+ Copyright (c) 2003-2007 Niels Kokholm and Peter Sestoft
+*/
+
+// IndexedObjects2.cs sketch 2007-07-28
+
+// Maintaining multiple type safe indices on objects using the C5
+// library.
+
+// Compile with 
+//   csc /r:C5.dll IndexedObjects2.cs 
+
+using System;                           // Console
+using System.Text;                      // StringBuilder
+using C5; 
+using SCG = System.Collections.Generic;
+
+namespace IndexedObjects {
+  static class IndexedObjectsMain {
+    static void Main(String[] args) {
+      // Create some Person objects:
+      new Person("Niels",   19470206);
+      new Person("Lone",    19600810);
+      new Person("Peter",   19620625);
+      new Person("Carsten", 19640627);
+      new Person("Hanne",   19641209);
+      new Person("Dorte",   19660930);
+      new Person("Dorte",   19610312);
+      new Person("J�rgen",  19340930);
+      new Person("Kirsten", 19360114);
+      new Person("Henrik",  19360630);
+      new Person("Lars",    19640625);
+      new Person("Thora",   19091129);
+      // Try the indexers:
+      Console.WriteLine("\nBorn in 1964:");
+      foreach (Person p in Person.Year[1964]) 
+        Console.WriteLine(p);
+      Console.WriteLine("\nNamed Dorte:");
+      foreach (Person p in Person.Name["Dorte"]) 
+        Console.WriteLine(p);
+      Console.WriteLine("\nBorn on the 30th:");
+      foreach (Person p in Person.Day[30]) 
+        Console.WriteLine(p);
+      Console.WriteLine("\nBorn June-October:");
+      foreach (Person p in Person.Month.RangeFromTo(Month.Jun, Month.Nov)) 
+        Console.WriteLine(p);
+    }
+  }
+
+  // The interface IIndex<Q,T> describes an index with keys of type Q
+  // on items of type T:
+
+  public interface IIndex<Q,T> { 
+    ICollection<T> this[Q x] { get; }
+    void Add(T item);
+  }
+
+  // A hash-based index supports adding items of type T to the index
+  // and looking up items by key of type Q.  The function toKey
+  // transforms an item to its index key.
+
+  // The hash-based index is implemented by a hash dictionary that
+  // maps each index key to a hash set of items.  The hash dictionary
+  // uses the key type's natural equality comparer.  The hash set uses
+  // a reference equality comparer for the item type -- it might also
+  // use the item type's natural comparer.
+
+  public class HashIndex<Q,T> : IIndex<Q,T> where T : class {
+    private readonly Fun<T,Q> toKey;
+    private HashDictionary<Q, HashSet<T>> dict;
+
+    public HashIndex(Fun<T,Q> toKey) {
+      this.toKey = toKey;
+      dict = new HashDictionary<Q, HashSet<T>>();
+    }
+
+    public void Add(T item) { 
+      Q key = toKey(item);
+      if (!dict.Contains(key))
+        dict.Add(key, new HashSet<T>(ReferenceEqualityComparer<T>.Default));
+      dict[key].Add(item);
+    }
+
+    public ICollection<T> this[Q key] {
+      get { 
+        return new GuardedCollection<T>(dict[key]);
+      }
+    }
+
+    public override String ToString() {
+      return dict.ToString();
+    }
+  }
+
+  // A tree-based index supports adding items of type T to the index,
+  // looking up items by key of type Q, and getting the items within a
+  // key range.  The function toKey transforms an item to its index
+  // key.  
+
+  // The tree-based index is implemented by a tree dictionary that
+  // maps each index key to a hash set of items.  The tree dictionary
+  // uses the key type's natural comparer.  The hash set uses a
+  // reference equality comparer for the item type -- it might also
+  // use the item type's natural comparer.
+
+  public class TreeIndex<Q,T> : IIndex<Q,T> where T : class {
+    private readonly Fun<T,Q> toKey;
+    private TreeDictionary<Q, HashSet<T>> dict;
+
+    public TreeIndex(Fun<T,Q> toKey) {
+      this.toKey = toKey;
+      dict = new TreeDictionary<Q, HashSet<T>>();
+    }
+
+    public void Add(T item) { 
+      Q key = toKey(item);
+      if (!dict.Contains(key))
+        dict.Add(key, new HashSet<T>(ReferenceEqualityComparer<T>.Default));
+      dict[key].Add(item);
+    }
+
+    public ICollection<T> this[Q key] {
+      get { 
+        return new GuardedCollection<T>(dict[key]);
+      }
+    }
+
+    // Bad implementation from a performance point of view: it may be
+    // costly to build the result collection and possibly only its
+    // size is ever used:
+
+    public ICollection<T> RangeFromTo(Q x, Q y) {
+      HashSet<T> result = new HashSet<T>(ReferenceEqualityComparer<T>.Default);
+      foreach (KeyValuePair<Q,HashSet<T>> kv in dict.RangeFromTo(x, y))
+	result.AddAll(kv.Value);
+      return result;
+    }
+
+    public override String ToString() {
+      return dict.ToString();
+    }
+  }
+
+  public enum Month { 
+    Jan=1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec 
+  }
+
+  // Sample class with two fields and four different indexes
+  
+  // All indexes are defined as static fields and are strongly typed.
+  // The definitions would be considerably shorter and clearer in C#
+  // 3.0 thanks to lambda notation and better type inference.
+
+  // Note all code related to indexing can be kept in one place, due
+  // to the use of an indexing delegate, except for the call
+  // Index(this), which must appear at the end of every constructor.
+  // By using reflection and a naming convention for the indexing
+  // delegate, one might be able to avoid explicitly adding the
+  // indexes to the event in the static constructor.  However, the
+  // present setup can be implemented using a static aspect weaver
+  // such as yiihaw (Johansen and Spangenberg 2007), avoiding the use
+  // of runtime reflection.
+
+  // For use with LINQ-to-C5, one can use runtime reflection to find
+  // the indexes on a type, as the public static fields of type
+  // HashIndex or TreeIndex or IIndex.
+
+  public class Person {
+    public readonly String name;
+    public readonly int date; // YYYYMMDD as in 20070725
+
+    // Defining the indexes
+    public static readonly IIndex<String, Person> Name 
+      = new HashIndex<String, Person>(delegate(Person p) { return p.name; });
+    public static readonly IIndex<int, Person> Year 
+      = new HashIndex<int, Person>(delegate(Person p) { return p.date/10000; });
+    public static readonly IIndex<int, Person> Day 
+      = new HashIndex<int, Person>(delegate(Person p) { return p.date%100; });
+    public static readonly TreeIndex<Month, Person> Month 
+      = new TreeIndex<Month, Person>
+        (delegate(Person p) { return (Month)(p.date/100%100); });
+
+    // Defining and initializing the indexing delegate
+    private static event Act<Person> Index;
+    static Person() { 
+      Index += Name.Add;
+      Index += Year.Add;
+      Index += Day.Add;
+      Index += Month.Add;
+    }
+
+    public Person(String name, int date) {
+      this.name = name;
+      this.date = date;
+      Index(this);
+    }
+
+    public override String ToString() {
+      return name + " (" + date + ")";
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Jobqueue.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Jobqueue.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Jobqueue.cs	(revision 3)
@@ -0,0 +1,147 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: job queue 2004-11-22
+
+// Compile with 
+//   csc /r:C5.dll Anagrams.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+class MyJobQueueTest {
+  public static void Main(String[] args) {
+    JobQueue jq = new JobQueue();
+    // One user submits three jobs at time=27
+    Rid rid1 = jq.Submit(new Ip("62.150.83.11"), 27),
+        rid2 = jq.Submit(new Ip("62.150.83.11"), 27),
+        rid3 = jq.Submit(new Ip("62.150.83.11"), 27);
+    // One job is executed
+    jq.ExecuteOne();
+    // Another user submits two jobs at time=55
+    Rid rid4 = jq.Submit(new Ip("130.225.17.5"), 55),
+        rid5 = jq.Submit(new Ip("130.225.17.5"), 55);
+    // One more job is executed
+    jq.ExecuteOne();
+    // The first user tries to cancel his first and last job
+    jq.Cancel(rid1);
+    jq.Cancel(rid3);
+    // The remaining jobs are executed
+    while (jq.ExecuteOne() != null) { } 
+  }
+}
+
+class JobQueue {
+  private readonly IPriorityQueue<Job> jobQueue;
+  private readonly IDictionary<Rid,IPriorityQueueHandle<Job>> jobs;
+  private readonly HashBag<Ip> userJobs;
+
+  public JobQueue() {
+    this.jobQueue = new IntervalHeap<Job>();
+    this.jobs = new HashDictionary<Rid,IPriorityQueueHandle<Job>>();
+    this.userJobs = new HashBag<Ip>();
+  }
+
+  public Rid Submit(Ip ip, int time) {
+    int jobCount = userJobs.ContainsCount(ip);
+    Rid rid = new Rid();
+    Job job = new Job(rid, ip, time + 60 * jobCount);
+    IPriorityQueueHandle<Job> h = null;
+    jobQueue.Add(ref h, job);
+    userJobs.Add(ip);
+    jobs.Add(rid, h);
+    Console.WriteLine("Submitted {0}", job);    
+    return rid;
+  }
+
+  public Job ExecuteOne() {
+    if (!jobQueue.IsEmpty) {
+      Job job = jobQueue.DeleteMin();
+      userJobs.Remove(job.ip);
+      jobs.Remove(job.rid);
+      Console.WriteLine("Executed {0}", job);    
+      return job;
+    } else
+      return null;
+  }
+
+  public void Cancel(Rid rid) {
+    IPriorityQueueHandle<Job> h;
+    if (jobs.Remove(rid, out h)) {
+      Job job = jobQueue.Delete(h);
+      userJobs.Remove(job.ip);
+      Console.WriteLine("Cancelled {0}", job);
+    }
+  }
+}
+
+class Job : IComparable<Job> {
+  public readonly Rid rid;
+  public readonly Ip ip;
+  public readonly int time;
+
+  public Job(Rid rid, Ip ip, int time) {
+    this.rid = rid;
+    this.ip = ip;
+    this.time = time;
+  }
+
+  public int CompareTo(Job that) {
+    return this.time - that.time;
+  }
+
+  public override String ToString() {
+    return rid.ToString();
+  }
+}
+
+class Rid { 
+  private readonly int ridNumber;
+  private static int nextRid = 1;
+  public Rid() {
+    ridNumber = nextRid++;
+  }
+  public override String ToString() {
+    return "rid=" + ridNumber;
+  }
+}
+
+class Ip { 
+  public readonly String ipString;
+
+  public Ip(String ipString) {
+    this.ipString = ipString;
+  }
+
+  public override int GetHashCode() {
+    return ipString.GetHashCode();
+  }
+
+  public override bool Equals(Object that) {
+    return 
+      that != null 
+      && that is Ip 
+      && this.ipString.Equals(((Ip)that).ipString);
+  }
+}
+ 
+
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/KeywordRecognition.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/KeywordRecognition.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/KeywordRecognition.cs	(revision 3)
@@ -0,0 +1,177 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: Keyword recognition 2004-12-20
+
+// Compile with 
+//   csc /r:C5.dll KeywordRecognition.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace KeywordRecognition {
+
+class KeywordRecognition {
+  // Array of 77 keywords:
+
+  static readonly String[] keywordArray = 
+    { "abstract", "as", "base", "bool", "break", "byte", "case", "catch",
+      "char", "checked", "class", "const", "continue", "decimal", "default",
+      "delegate", "do", "double", "else", "enum", "event", "explicit",
+      "extern", "false", "finally", "fixed", "float", "for", "foreach",
+      "goto", "if", "implicit", "in", "int", "interface", "internal", "is",
+      "lock", "long", "namespace", "new", "null", "object", "operator",
+      "out", "override", "params", "private", "protected", "public",
+      "readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof",
+      "stackalloc", "static", "string", "struct", "switch", "this", "throw",
+      "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe",
+      "ushort", "using", "virtual", "void", "volatile", "while" };
+  
+  private static readonly ICollection<String> kw1;
+
+  private static readonly ICollection<String> kw2;
+
+  private static readonly ICollection<String> kw3;
+
+  private static readonly SCG.IDictionary<String,bool> kw4 = 
+    new SCG.Dictionary<String,bool>();
+
+
+  class SC : SCG.IComparer<string>
+  {
+    public int Compare(string a, string b)
+    {
+      return StringComparer.InvariantCulture.Compare(a,b);
+    }
+  }
+
+  class SH : SCG.IEqualityComparer<string>
+  {
+    public int GetHashCode(string item)
+    {
+      return item.GetHashCode();
+    }
+
+    public bool Equals(string i1, string i2)
+    {
+      return i1 == null ? i2 == null : i1.Equals(i2,StringComparison.InvariantCulture);
+    }
+  }
+
+  static KeywordRecognition() { 
+    kw1 = new HashSet<String>();
+    kw1.AddAll<string>(keywordArray); 
+    kw2 = new TreeSet<String>(new SC());
+    kw2.AddAll<string>(keywordArray);
+    kw3 = new SortedArray<String>(new SC());
+    kw3.AddAll<string>(keywordArray);
+    kw4 = new SCG.Dictionary<String,bool>();
+    foreach (String keyword in keywordArray) 
+      kw4.Add(keyword, false);
+  }
+
+  public static bool IsKeyword1(String s) {
+    return kw1.Contains(s);
+  }
+
+  public static bool IsKeyword2(String s) {
+    return kw2.Contains(s);
+  }
+
+  public static bool IsKeyword3(String s) {
+    return kw3.Contains(s);
+  }
+
+  public static bool IsKeyword4(String s) { 
+    return kw4.ContainsKey(s); 
+  }
+
+  public static bool IsKeyword5(String s) { 
+    return Array.BinarySearch(keywordArray, s) >= 0; 
+  }
+
+  public static void Main(String[] args) {
+    if (args.Length != 2) 
+      Console.WriteLine("Usage: KeywordRecognition <iterations> <word>\n");
+    else {
+      int count = int.Parse(args[0]);
+      String id = args[1];
+
+      {
+        Console.Write("HashSet.Contains ");
+        Timer t = new Timer();
+        for (int i=0; i<count; i++)
+          IsKeyword1(id);
+        Console.WriteLine(t.Check());      
+      }
+
+      {
+        Console.Write("TreeSet.Contains ");
+        Timer t = new Timer();
+        for (int i=0; i<count; i++)
+          IsKeyword2(id);
+        Console.WriteLine(t.Check());      
+      }
+
+      {
+        Console.Write("SortedArray.Contains ");
+        Timer t = new Timer();
+        for (int i=0; i<count; i++)
+          IsKeyword3(id);
+        Console.WriteLine(t.Check());      
+      }
+
+      {
+        Console.Write("SCG.Dictionary.ContainsKey ");
+        Timer t = new Timer();
+        for (int i=0; i<count; i++)
+          IsKeyword4(id);
+        Console.WriteLine(t.Check());      
+      }
+
+      {
+        Console.Write("Array.BinarySearch ");
+        Timer t = new Timer();
+        for (int i=0; i<count; i++)
+          IsKeyword5(id);
+        Console.WriteLine(t.Check());      
+      }
+    }
+  }
+}
+
+// Crude timing utility ----------------------------------------
+   
+public class Timer {
+  private DateTime start;
+
+  public Timer() {
+    start = DateTime.Now;
+  }
+
+  public double Check() {
+    TimeSpan dur = DateTime.Now - start;
+    return dur.TotalSeconds;
+  }
+}
+
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Kwic.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Kwic.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Kwic.cs	(revision 3)
@@ -0,0 +1,49 @@
+// C5 example sketch -- not so interesting after all
+// 2004-08
+
+// KWIC = keyword-in-context.
+
+// Read a file of words and create an ordered list of keywords, giving
+// for each keyword a list of the contexts in which it appears.  For
+// instance, for this text
+
+This book presents C# version 2.0 as used in Microsoft Visual Studio
+2005, including generics, iterators, anonymous methods and partial
+type declarations, but excluding most of Microsoft's .Net Framework
+class libraries except threads, input-output, and generic collection
+classes.  The book does not cover unsafe code, destructors,
+finalization, reflection, pre-processing directives (#define,
+#if) or details of \textsc{ieee754} floating-point
+numbers.
+
+// the resulting list may look like this:
+// book 
+//   this book presents
+//   the book does
+// Microsoft
+//   in Microsoft Visual
+//   of Microsoft's .Net
+  
+// How to proceed: (1) read a stream of words from file; (2) turn this
+// into a stream of (2n+1)-tuples of words, namely a keyword
+// surrounded by n words on either side; (3) create a dictionary
+// mapping each keyword to a set of its contexts; (4) output the
+// entries of the dictionary sorted by keyword, for each keyword
+// building an HTML <item> list or similar.
+
+// Step (2) can be improved by not generating (2n+1)-tuples for
+// keywords that are stop words (in, of, the, a, ...).  Also, each
+// such triple may have an associated line number or page number on
+// which it appears, in which case the dictionary should map to a
+// dictionary that maps each context to a list of line numbers or page
+// numbers.
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+class MyTest {
+  public static void Main(String[] args) {
+
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/ListPatterns.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/ListPatterns.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/ListPatterns.cs	(revision 3)
@@ -0,0 +1,141 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: ListPatterns.cs for pattern chapter
+
+// Compile with 
+//   csc /r:C5.dll ListPatterns.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace ListPatterns {
+  class ListPatterns {
+    public static void Main(String[] args) {
+      IList<int> list = new ArrayList<int>();
+      list.AddAll(new int[] { 23, 29, 31, 37, 41, 43, 47, 53 });
+      // Reversing and swapping
+      Console.WriteLine(list);
+      list.Reverse();
+      Console.WriteLine(list);
+      ReverseInterval(list, 2, 3);
+      Console.WriteLine(list);
+      SwapInitialFinal(list, 2);
+      Console.WriteLine(list);
+      // Clearing all or part of list
+      list.CollectionCleared 
+	+= delegate(Object c, ClearedEventArgs eargs) {
+	     ClearedRangeEventArgs ceargs = eargs as ClearedRangeEventArgs;
+	     if (ceargs != null) 
+	       Console.WriteLine("Cleared [{0}..{1}]", 
+				 ceargs.Start, ceargs.Start+ceargs.Count-1);
+	   };
+      RemoveSublist1(list, 1, 2);
+      Console.WriteLine(list);
+      RemoveSublist2(list, 1, 2);
+      Console.WriteLine(list);
+      RemoveTail1(list, 3);
+      Console.WriteLine(list);
+      RemoveTail2(list, 2);
+      Console.WriteLine(list);
+    }
+
+    // Reverse list[i..i+n-1]
+
+    public static void ReverseInterval<T>(IList<T> list, int i, int n) {
+      list.View(i,n).Reverse();
+    }
+
+    // Swap list[0..i-1] with list[i..Count-1]
+
+    public static void SwapInitialFinal<T>(IList<T> list, int i) {
+      list.View(0,i).Reverse();
+      list.View(i,list.Count-i).Reverse();
+      list.Reverse();
+    }
+
+    // Remove sublist of a list
+
+    public static void RemoveSublist1<T>(IList<T> list, int i, int n) {
+      list.RemoveInterval(i, n);
+    }
+
+    public static void RemoveSublist2<T>(IList<T> list, int i, int n) {
+      list.View(i, n). Clear();
+    }
+
+
+    // Remove tail of a list
+
+    public static void RemoveTail1<T>(IList<T> list, int i) {
+      list.RemoveInterval(i, list.Count-i);
+    }
+
+    public static void RemoveTail2<T>(IList<T> list, int i) {
+      list.View(i, list.Count-i).Clear();
+    }
+
+    // Pattern for finding and using first (leftmost) x in list
+
+    private static void PatFirst<T>(IList<T> list, T x) { 
+      int j = list.IndexOf(x);
+      if (j >= 0) { 
+	// x is a position j in list
+      } else {
+	// x is not in list
+      }
+    }
+
+    // Pattern for finding and using last (rightmost) x in list
+
+    private static void PatLast<T>(IList<T> list, T x) { 
+      int j = list.LastIndexOf(x);
+      if (j >= 0) { 
+	// x is at position j in list
+      } else {
+	// x is not in list
+      }
+    }
+
+    // Pattern for finding and using first (leftmost) x in list[i..i+n-1]
+
+    private static void PatFirstSublist<T>(IList<T> list, T x, int i, int n) { 
+      int j = list.View(i,n).IndexOf(x);
+      if (j >= 0) { 
+	// x is at position j+i in list
+      } else {
+	// x is not in list[i..i+n-1]
+      }
+    }
+
+    // Pattern for finding and using last (rightmost) x in list[i..i+n-1]
+
+    private static void PatLastSublist<T>(IList<T> list, T x, int i, int n) { 
+      int j = list.View(i,n).LastIndexOf(x);
+      if (j >= 0) { 
+	// x is at position j+i in list
+      } else {
+	// x is not in list[i..i+n-1]
+      }
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/ListenableEvents.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/ListenableEvents.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/ListenableEvents.cs	(revision 3)
@@ -0,0 +1,55 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm <kokholm@itu.dk> and Peter Sestoft <sestoft@dina.kvl.dk>
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: 2006-06-17
+
+// Compile with 
+//   csc /r:C5.dll Anagrams.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace MyTest {
+  class MyTest {
+    public static void Main(String[] args) {
+      PrintEvents("CircularQueue", new CircularQueue<int>());
+      PrintEvents("ArrayList", new ArrayList<int>());
+      PrintEvents("LinkedList", new LinkedList<int>());
+      PrintEvents("HashedArrayList", new HashedArrayList<int>());
+      PrintEvents("HashedLinkedList", new HashedLinkedList<int>());
+      PrintEvents("SortedArray", new SortedArray<int>());
+      PrintEvents("WrappedArray", new WrappedArray<int>(new int[0]));
+      PrintEvents("TreeSet", new TreeSet<int>());
+      PrintEvents("TreeBag", new TreeBag<int>());
+      PrintEvents("HashSet", new HashSet<int>());
+      PrintEvents("HashBag", new HashBag<int>());
+      PrintEvents("IntervalHeap", new IntervalHeap<int>());
+
+      PrintEvents("HashDictionary", new HashDictionary<int,int>());
+      PrintEvents("TreeDictionary", new TreeDictionary<int,int>());
+    }
+
+    public static void PrintEvents<T>(String kind, ICollectionValue<T> coll) {
+      Console.WriteLine("{0,25} {1}", kind, coll.ListenableEvents);
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Locking.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Locking.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Locking.cs	(revision 3)
@@ -0,0 +1,97 @@
+// C5 example: locking 2005-11-07
+
+// Compile with 
+//   csc /r:C5.dll Locking.cs 
+
+using System;
+using System.Threading;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace Locking {
+  class Locking {
+    static ArrayList<int> coll = new ArrayList<int>();
+    // static SCG.List<int> coll = new SCG.List<int>();
+    static readonly int count = 1000;
+
+    public static void Main(String[] args) {
+      Console.WriteLine("Adding and removing without locking:");
+      RunTwoThreads(delegate { AddAndRemove(15000); });
+      Console.WriteLine("coll has {0} items, should be 0", coll.Count);
+
+      coll = new ArrayList<int>();
+      Console.WriteLine("Adding and removing with locking:");
+      RunTwoThreads(delegate { SafeAddAndRemove(15000); });
+      Console.WriteLine("coll has {0} items, should be 0", coll.Count);
+
+      Console.WriteLine("Moving items without locking:");
+      ArrayList<int> from, to;
+      from = new ArrayList<int>();
+      to = new ArrayList<int>();
+      for (int i=0; i<count; i++) 
+        from.Add(i);
+      RunTwoThreads(delegate { while (!from.IsEmpty) Move(from, to); });
+      Console.WriteLine("coll has {0} items, should be {1}", to.Count, count);
+
+      Console.WriteLine("Moving items with locking:");
+      from = new ArrayList<int>();
+      to = new ArrayList<int>();
+      for (int i=0; i<count; i++) 
+        from.Add(i);
+      RunTwoThreads(delegate { while (!from.IsEmpty) SafeMove(from, to); });
+      Console.WriteLine("coll has {0} items, should be {1}", to.Count, count);
+    }
+
+    public static void RunTwoThreads(Act run) {
+      Thread t1 = new Thread(new ThreadStart(run)),
+             t2 = new Thread(new ThreadStart(run));
+      t1.Start(); t2.Start();
+      t1.Join(); t2.Join();
+    }
+
+    // Concurrently adding to and removing from an arraylist
+
+    public static void AddAndRemove(int count) {
+      for (int i=0; i<count; i++) 
+        coll.Add(i);
+      for (int i=0; i<count; i++)
+        coll.Remove(i);
+    }
+
+    private static readonly Object sync = new Object();
+
+    public static void SafeAddAndRemove(int count) {
+      for (int i=0; i<count; i++) 
+        lock (sync)
+          coll.Add(i);
+      for (int i=0; i<count; i++)
+        lock (sync)
+          coll.Remove(i);
+    }
+
+    public static void SafeAdd<T>(IExtensible<T> coll, T x) { 
+      lock (sync) {
+        coll.Add(x);
+      }
+    }
+
+    public static void Move<T>(ICollection<T> from, ICollection<T> to) { 
+      if (!from.IsEmpty) {  
+        T x = from.Choose();
+        Thread.Sleep(0);        // yield processor to other threads
+        from.Remove(x);
+        to.Add(x);
+      }
+    }
+    
+    public static void SafeMove<T>(ICollection<T> from, ICollection<T> to) { 
+      lock (sync) 
+        if (!from.IsEmpty) {  
+          T x = from.Choose();
+          Thread.Sleep(0);      // yield processor to other threads
+          from.Remove(x);
+          to.Add(x);
+        }
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/LockstepCollections.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/LockstepCollections.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/LockstepCollections.cs	(revision 3)
@@ -0,0 +1,160 @@
+/*
+ Copyright (c) 2003-2007 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: LockstepCollections: A group collections lockstep, so
+// that they all contain the same items.  This is done by equipping
+// them all with event handlers, so that when one collection is
+// updated (item added or removed) then all the others are updated
+// too.  The collections must be initially empty.
+
+// The idea is to organize the N collections c0, ..., c(N-1) in a ring
+// in which c(i) is followed by c((i+1)%N), and then each collection
+// with event handlers that update the next collection.  The update to
+// that collection in turn will cause its event listeners to update
+// the next next collection, and so on.
+
+// Event cycles are prevented by using a common counter "steps",
+// initialized to the number N of collections, and reset to N by
+// CollectionChanged events.  All other events decrement the counter
+// and performing further updates only if it is positive.  Since the
+// CollectionChanged events are fired only after all the other events,
+// the counter will be reset only after all the updates have been
+// performed, but then it will (superfluously) be reset N times.  None
+// of this will work in a multithreaded setting, of course; but then
+// even plain updates wouldn't either.
+
+// If the (equality) comparer of one collection identifies more items
+// than that of another collection, then the lockstep collections do
+// not necessarily have the same number of items, even though they all
+// started out empty.  This also means that it matters what collection
+// one attempts to add an item to, and in what order the collections
+// are chained.  If one adds a new item to a collection that contains
+// one deemed equal to it, then nothing happens, the event is not
+// raised, and the item will not be added to any of the collections.
+// If instead one adds it to a collection where it is not deemed equal
+// to an existing item, it will be added to that collection but
+// possibly not to others.
+
+// Compile with 
+//   csc /r:C5.dll LockstepCollections.cs 
+
+using System;                           // Console
+using C5; 
+using SCG = System.Collections.Generic;
+
+namespace LockstepCollections
+{
+  static class LockstepCollections
+  {
+    static void Main(String[] args)
+    {
+      ICollection<Person> nameColl 
+        = new HashSet<Person>(new Person.NameEqualityComparer());
+      ICollection<Person> dateColl 
+        = new TreeSet<Person>(new Person.DateComparer());
+      MakeLockstep(nameColl, dateColl);
+      Person p1 = new Person("Peter", 19620625), 
+        p2 = new Person("Carsten", 19640627), 
+        p3 = new Person("Carsten", 19640628);
+      nameColl.Add(p1);      
+      nameColl.Add(p2);
+      dateColl.Add(p3);
+      Console.WriteLine("dateColl = {0}", dateColl);
+      Console.WriteLine("nameColl = {0}", nameColl);
+      dateColl.Remove(p1);
+      Console.WriteLine("dateColl = {0}", dateColl);
+      Console.WriteLine("nameColl = {0}", nameColl);
+      dateColl.Clear();
+      Console.WriteLine("dateColl = {0}", dateColl);
+      Console.WriteLine("nameColl = {0}", nameColl);
+    }
+
+    static void MakeLockstep<T>(params ICollection<T>[] colls)
+    {
+      // These will be captured in the event handler delegates below
+      int N = colls.Length;
+      int steps = N;
+      for (int i=0; i<N; i++) {
+        if (!colls[i].IsEmpty) 
+          throw new ApplicationException("Non-empty collection");
+      }
+      for (int i=0; i<N; i++) {
+        ICollection<T> thisColl = colls[i];
+        ICollection<T> nextColl = colls[(i+1)%N];
+        thisColl.CollectionChanged += 
+          delegate(Object coll) {
+            steps = N;
+          };
+        thisColl.CollectionCleared += 
+          delegate(Object coll, ClearedEventArgs args) {
+            // For now ignoring that the clearing may be partial
+            if (--steps > 0) {
+              nextColl.Clear();
+            }
+          };
+        thisColl.ItemsAdded +=
+          delegate(Object coll, ItemCountEventArgs<T> args) {
+            // For now ignoring the multiplicity
+            if (--steps > 0) {
+              T item = args.Item;
+              nextColl.FindOrAdd(ref item);
+            }
+          };
+        thisColl.ItemsRemoved +=
+          delegate(Object coll, ItemCountEventArgs<T> args) {
+            // For now ignoring the multiplicity
+            if (--steps > 0) {
+              nextColl.Remove(args.Item);
+            }
+          };
+      }
+    }
+  }
+
+  public class Person {
+    String name;
+    int date;
+
+    public Person(String name, int date) {
+      this.name = name;
+      this.date = date;
+    }
+
+    public class NameEqualityComparer : SCG.IEqualityComparer<Person> {
+      public bool Equals(Person p1, Person p2) {
+        return p1.name == p2.name;
+      }
+      public int GetHashCode(Person p) { 
+        return p.name.GetHashCode();
+      }
+    }
+
+    public class DateComparer : SCG.IComparer<Person> {
+      public int Compare(Person p1, Person p2) { 
+        return p1.date.CompareTo(p2.date);
+      }
+    }
+
+    public override String ToString() {
+      return name + " (" + date + ")";
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/MultiCollection.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/MultiCollection.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/MultiCollection.cs	(revision 3)
@@ -0,0 +1,131 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace MultiCollection
+{
+  class BasicCollectionValue<T> : CollectionValueBase<T>, ICollectionValue<T>
+  {
+    SCG.IEnumerable<T> enumerable;
+    Fun<T> chooser;
+    int count;
+    //TODO: add delegate for checking validity!
+
+    public BasicCollectionValue(SCG.IEnumerable<T> e, Fun<T> chooser, int c) { enumerable = e; count = c; this.chooser = chooser; }
+
+    public override int Count { get { return count; } }
+
+    public override Speed CountSpeed { get { return Speed.Constant; } }
+
+    public override bool IsEmpty { get { return count == 0; } }
+
+    public override T Choose() { return chooser(); }
+
+    public override System.Collections.Generic.IEnumerator<T> GetEnumerator()
+    {
+      return enumerable.GetEnumerator();
+    }
+  }
+
+  interface IMultiCollection<K, V>
+  {
+    SCG.IEqualityComparer<K> KeyEqualityComparer { get;}
+    SCG.IEqualityComparer<V> ValueEqualityComparer { get;}
+    bool Add(K k, V v);
+    bool Remove(K k, V v);
+    ICollectionValue<V> this[K k] { get;}
+    ICollectionValue<K> Keys { get;}
+    SCG.IEnumerable<V> Values { get;}
+
+  }
+
+  class BasicMultiCollection<K, V, W, U> : IMultiCollection<K, V>//: IDictionary<K, W>
+  where W : ICollection<V>, new()
+      where U : IDictionary<K, W>, new()
+  {
+    U dict = new U();
+
+    public SCG.IEqualityComparer<K> KeyEqualityComparer { get { return EqualityComparer<K>.Default; } }
+
+    public SCG.IEqualityComparer<V> ValueEqualityComparer { get { return EqualityComparer<V>.Default; } } //TODO: depends on W!
+
+    public bool Add(K k, V v)
+    {
+      W w;
+      if (!dict.Find(k, out w)) 
+        dict.Add(k,w = new W());
+      return w.Add(v);
+    }
+
+    public bool Remove(K k, V v)
+    {
+      W w;
+      if (dict.Find(k, out w) && w.Remove(v))
+      {
+        if (w.Count == 0)
+          dict.Remove(k);
+        return true;
+      }
+      return false;
+    }
+
+    public ICollectionValue<V> this[K k] { get { return dict[k]; } }
+
+    public ICollectionValue<K> Keys { get { return dict.Keys; } }
+
+    public SCG.IEnumerable<V> Values
+    {
+      get
+      {
+        foreach (W w in dict.Values)
+          foreach (V v in w)
+            yield return v;
+      }
+    }
+  }
+
+  class WordIndex : BasicMultiCollection<string,int,HashSet<int>,HashDictionary<string,HashSet<int>>>
+  {
+  }
+
+  class MyTest
+  {
+    public static void Main(String[] args)
+    {
+      WordIndex wi = new WordIndex();
+      wi.Add("ja", 2);
+      wi.Add("nej", 4);
+      wi.Add("ja", 7);
+      foreach (string s in wi.Keys)
+      {
+        Console.WriteLine(s + " -->");
+        foreach (int line in wi[s])
+        {
+          Console.WriteLine(" " + line);
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/MultiDictionary-njk.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/MultiDictionary-njk.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/MultiDictionary-njk.cs	(revision 3)
@@ -0,0 +1,494 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: 2006-01-29
+
+// Compile with 
+//   csc /r:C5.dll MultiDictionary.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace MultiDictionaries
+{
+  using Inner = HashSet<String>;
+
+  using MultiDictionary3;
+
+  public class MyTest
+  {
+    public static void Main()
+    {
+      MultiHashDictionary<int, String, Inner> mdict = new MultiHashDictionary<int, String, Inner>();
+      mdict.Add(2, "to");
+      mdict.Add(2, "deux");
+      mdict.Add(2, "two");
+      mdict.Add(20, "tyve");
+      mdict.Add(20, "tyve");
+      mdict.Add(20, "twenty");
+      Console.WriteLine(mdict);
+      Console.WriteLine("mdict.Count is {0}", mdict.Count);
+      Console.WriteLine("mdict.Count (keys) is {0}",
+                        ((IDictionary<int, Inner>)mdict).Count);
+      Console.WriteLine("mdict[2].Count is {0}", mdict[2].Count);
+      mdict.Remove(20, "tyve");
+      mdict.Remove(20, "twenty");
+      Console.WriteLine(mdict);
+      Console.WriteLine("mdict.Count is {0}", mdict.Count);
+      Inner zwei = new Inner();
+      zwei.Add("zwei");
+      mdict[2] = zwei;
+      mdict[-2] = zwei;
+      Console.WriteLine(mdict);
+      Console.WriteLine("mdict.Count is {0}", mdict.Count);
+      zwei.Add("kaksi");
+      Console.WriteLine(mdict);
+      Console.WriteLine("mdict.Count is {0}", mdict.Count);
+      Inner empty = new Inner();
+      mdict[0] = empty;
+      Console.WriteLine(mdict);
+      Console.WriteLine("mdict.Count is {0}", mdict.Count);
+      Console.WriteLine("mdict contains key 0: {0}", mdict.Contains(0));
+      mdict.Remove(-2);
+      Console.WriteLine(mdict);
+      Console.WriteLine("mdict.Count is {0}", mdict.Count);
+      zwei.Remove("kaksi");
+      Console.WriteLine(mdict);
+      Console.WriteLine("mdict.Count is {0}", mdict.Count);
+      zwei.Clear();
+      Console.WriteLine(mdict);
+      Console.WriteLine("mdict.Count is {0}", mdict.Count);
+    }
+  }
+}
+
+namespace MultiDictionary1
+{
+  // Here we implement a multivalued dictionary as a hash dictionary
+  // from keys to value collections.  The value collections may have set
+  // or bag semantics.
+
+  // The value collections are externally modifiable (as in Peter
+  // Golde's PowerCollections library), and therefore:
+  //
+  //  * A value collection associated with a key may be null or
+  //  non-empty.  Hence for correct semantics, the Contains(k) method
+  //  must check that the value collection associated with a key is
+  //  non-null and non-empty.
+  //  
+  //  * A value collection may be shared between two or more keys.
+  //
+
+  // A C5 hash dictionary each of whose keys map to a collection of values.
+
+  public class MultiHashDictionary<K, V> : HashDictionary<K, ICollection<V>>
+  {
+
+    // Return total count of values associated with keys.  This basic
+    // implementation simply sums over all value collections, and so
+    // is a linear-time operation in the total number of values.  
+
+    public new virtual int Count
+    {
+      get
+      {
+        int count = 0;
+        foreach (KeyValuePair<K, ICollection<V>> entry in this)
+          if (entry.Value != null)
+            count += entry.Value.Count;
+        return count;
+      }
+    }
+
+    public override Speed CountSpeed
+    {
+      get { return Speed.Linear; }
+    }
+
+    // Add a (key,value) pair
+
+    public virtual void Add(K k, V v)
+    {
+      ICollection<V> values;
+      if (!base.Find(k, out values) || values == null)
+      {
+        values = new HashSet<V>();
+        Add(k, values);
+      }
+      values.Add(v);
+    }
+
+    // Remove a single (key,value) pair, if present; return true if
+    // anything was removed, else false
+
+    public virtual bool Remove(K k, V v)
+    {
+      ICollection<V> values;
+      if (base.Find(k, out values) && values != null)
+      {
+        if (values.Remove(v))
+        {
+          if (values.IsEmpty)
+            base.Remove(k);
+          return true;
+        }
+      }
+      return false;
+    }
+
+    // Determine whether key k is associated with a value
+
+    public override bool Contains(K k)
+    {
+      ICollection<V> values;
+      return Find(k, out values) && values != null && !values.IsEmpty;
+    }
+
+    // Determine whether each key in ks is associated with a value
+
+    public override bool ContainsAll<U>(SCG.IEnumerable<U> ks)
+    {
+      foreach (K k in ks)
+        if (!Contains(k))
+          return false;
+      return true;
+    }
+
+    // Get or set the value collection associated with key k
+
+    public override ICollection<V> this[K k]
+    {
+      get
+      {
+        ICollection<V> values;
+        return base.Find(k, out values) && values != null ? values : new HashSet<V>();
+      }
+      set
+      {
+        base[k] = value;
+      }
+    }
+
+    // Inherited from base class HashDictionary<K,ICollection<V>>:
+
+    // Add(K k, ICollection<V> values) 
+    // AddAll(IEnumerable<KeyValuePair<K,ICollection<V>>> kvs) 
+    // Clear
+    // Clone
+    // Find(K k, out ICollection<V> values)
+    // Find(ref K k, out ICollection<V> values)
+    // FindOrAdd(K k, ref ICollection<V> values) 
+    // Remove(K k) 
+    // Remove(K k, out ICollection<V> values) 
+    // Update(K k, ICollection<V> values)
+    // Update(K k, ICollection<V> values, out ICollection<V> oldValues)
+    // UpdateOrAdd(K k, ICollection<V> values)
+    // UpdateOrAdd(K k, ICollection<V> values, out ICollection<V> oldValues)
+  }
+}
+
+
+namespace MultiDictionary2
+{
+  // Here we implement a multivalued dictionary as a hash dictionary
+  // from keys to value collections.  The value collections may have
+  // set or bag semantics.  This version uses event listeners to make
+  // the Count operation constant time.
+
+  //  * To avoid recomputing the total number of values for the Count
+  //  property, one may cache it and then use event listeners on the
+  //  value collections to keep the cached count updated.  In turn, this
+  //  requires such event listeners on the dictionary also.
+
+  // A C5 hash dictionary each of whose keys map to a collection of values.
+
+  public class MultiHashDictionary<K, V> : HashDictionary<K, ICollection<V>>
+  {
+    private int count = 0;      // Cached value count, updated by events only
+
+    private void IncrementCount(Object sender, ItemCountEventArgs<V> args)
+    {
+      count += args.Count;
+    }
+
+    private void DecrementCount(Object sender, ItemCountEventArgs<V> args)
+    {
+      count -= args.Count;
+    }
+
+    private void ClearedCount(Object sender, ClearedEventArgs args)
+    {
+      count -= args.Count;
+    }
+
+    public MultiHashDictionary()
+    {
+      ItemsAdded +=
+        delegate(Object sender, ItemCountEventArgs<KeyValuePair<K, ICollection<V>>> args)
+        {
+          ICollection<V> values = args.Item.Value;
+          if (values != null)
+          {
+            count += values.Count;
+            values.ItemsAdded += IncrementCount;
+            values.ItemsRemoved += DecrementCount;
+            values.CollectionCleared += ClearedCount;
+          }
+        };
+      ItemsRemoved +=
+        delegate(Object sender, ItemCountEventArgs<KeyValuePair<K, ICollection<V>>> args)
+        {
+          ICollection<V> values = args.Item.Value;
+          if (values != null)
+          {
+            count -= values.Count;
+            values.ItemsAdded -= IncrementCount;
+            values.ItemsRemoved -= DecrementCount;
+            values.CollectionCleared -= ClearedCount;
+          }
+        };
+    }
+
+    // Return total count of values associated with keys.  
+
+    public new virtual int Count
+    {
+      get
+      {
+        return count;
+      }
+    }
+
+    public override Speed CountSpeed
+    {
+      get { return Speed.Constant; }
+    }
+
+    // Add a (key,value) pair
+
+    public virtual void Add(K k, V v)
+    {
+      ICollection<V> values;
+      if (!base.Find(k, out values) || values == null)
+      {
+        values = new HashSet<V>();
+        Add(k, values);
+      }
+      values.Add(v);
+    }
+
+    // Remove a single (key,value) pair, if present; return true if
+    // anything was removed, else false
+
+    public virtual bool Remove(K k, V v)
+    {
+      ICollection<V> values;
+      if (base.Find(k, out values) && values != null)
+      {
+        if (values.Remove(v))
+        {
+          if (values.IsEmpty)
+            base.Remove(k);
+          return true;
+        }
+      }
+      return false;
+    }
+
+    // Determine whether key k is associated with a value
+
+    public override bool Contains(K k)
+    {
+      ICollection<V> values;
+      return Find(k, out values) && values != null && !values.IsEmpty;
+    }
+
+    // Determine whether each key in ks is associated with a value
+
+    public override bool ContainsAll<U>(SCG.IEnumerable<U> ks)
+    {
+      foreach (K k in ks)
+        if (!Contains(k))
+          return false;
+      return true;
+    }
+
+    // Get or set the value collection associated with key k
+
+    public override ICollection<V> this[K k]
+    {
+      get
+      {
+        ICollection<V> values;
+        return base.Find(k, out values) && values != null ? values : new HashSet<V>();
+      }
+      set
+      {
+        base[k] = value;
+      }
+    }
+  }
+}
+
+
+namespace MultiDictionary3
+{
+  // Here we implement a multivalued dictionary as a hash dictionary
+  // from keys to value collections.  The value collections may have
+  // set or bag semantics.  This version uses event listeners to make
+  // the Count operation constant time.
+
+  //  * To avoid recomputing the total number of values for the Count
+  //  property, one may cache it and then use event listeners on the
+  //  value collections to keep the cached count updated.  In turn, this
+  //  requires such event listeners on the dictionary also.
+
+  // A C5 hash dictionary each of whose keys map to a collection of values.
+
+  public class MultiHashDictionary<K, V, W> : HashDictionary<K, W> where W : ICollection<V>, new()
+  {
+    private int count = 0;      // Cached value count, updated by events only
+
+    private void IncrementCount(Object sender, ItemCountEventArgs<V> args)
+    {
+      count += args.Count;
+    }
+
+    private void DecrementCount(Object sender, ItemCountEventArgs<V> args)
+    {
+      count -= args.Count;
+    }
+
+    private void ClearedCount(Object sender, ClearedEventArgs args)
+    {
+      count -= args.Count;
+    }
+
+    public MultiHashDictionary()
+    {
+      ItemsAdded +=
+        delegate(Object sender, ItemCountEventArgs<KeyValuePair<K, W>> args)
+        {
+          ICollection<V> values = args.Item.Value;
+          if (values != null)
+          {
+            count += values.Count;
+            values.ItemsAdded += IncrementCount;
+            values.ItemsRemoved += DecrementCount;
+            values.CollectionCleared += ClearedCount;
+          }
+        };
+      ItemsRemoved +=
+        delegate(Object sender, ItemCountEventArgs<KeyValuePair<K, W>> args)
+        {
+          ICollection<V> values = args.Item.Value;
+          if (values != null)
+          {
+            count -= values.Count;
+            values.ItemsAdded -= IncrementCount;
+            values.ItemsRemoved -= DecrementCount;
+            values.CollectionCleared -= ClearedCount;
+          }
+        };
+    }
+
+    // Return total count of values associated with keys.  
+
+    public new virtual int Count
+    {
+      get
+      {
+        return count;
+      }
+    }
+
+    public override Speed CountSpeed
+    {
+      get { return Speed.Constant; }
+    }
+
+    // Add a (key,value) pair
+
+    public virtual void Add(K k, V v)
+    {
+      W values;
+      if (!base.Find(k, out values) || values == null)
+      {
+        values = new W();
+        Add(k, values);
+      }
+      values.Add(v);
+    }
+
+    // Remove a single (key,value) pair, if present; return true if
+    // anything was removed, else false
+
+    public virtual bool Remove(K k, V v)
+    {
+      W values;
+      if (base.Find(k, out values) && values != null)
+      {
+        if (values.Remove(v))
+        {
+          if (values.IsEmpty)
+            base.Remove(k);
+          return true;
+        }
+      }
+      return false;
+    }
+
+    // Determine whether key k is associated with a value
+
+    public override bool Contains(K k)
+    {
+      W values;
+      return Find(k, out values) && values != null && !values.IsEmpty;
+    }
+
+    // Determine whether each key in ks is associated with a value
+
+    public override bool ContainsAll<U>(SCG.IEnumerable<U> ks)
+    {
+      foreach (K k in ks)
+        if (!Contains(k))
+          return false;
+      return true;
+    }
+
+    // Get or set the value collection associated with key k
+
+    public override W this[K k]
+    {
+      get
+      {
+        W values;
+        return base.Find(k, out values) && values != null ? values : new W();
+      }
+      set
+      {
+        base[k] = value;
+      }
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/MultiDictionary.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/MultiDictionary.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/MultiDictionary.cs	(revision 3)
@@ -0,0 +1,548 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: 2006-01-29, 2006-06-26
+
+// Compile with 
+//   csc /r:C5.dll MultiDictionary.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace MultiDictionaries {
+
+  class MyTest {
+    public static void Main(String[] args) {
+      MultiDictionary1.TestIt.Run();
+      MultiDictionary2.TestIt.Run();
+    }
+  }
+}
+
+// --------------------------------------------------
+
+namespace MultiDictionary1 {
+  class TestIt {
+    public static void Run() { 
+      {
+	MultiHashDictionary<int,String> mdict 
+	  = new MultiHashDictionary<int,String>();
+	mdict.Add(2, "to");
+	mdict.Add(2, "deux");
+	mdict.Add(2, "two");
+	mdict.Add(20, "tyve");
+	mdict.Add(20, "twenty");
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	Console.WriteLine("mdict.Count (keys) is {0}", 
+			  ((IDictionary<int,ICollection<String>>)mdict).Count);
+	Console.WriteLine("mdict[2].Count is {0}", mdict[2].Count);
+	mdict.Remove(20, "tyve");
+	mdict.Remove(20, "twenty");
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	ICollection<String> zwei = new HashSet<String>();
+	zwei.Add("zwei");
+	mdict[2] = zwei;
+	mdict[-2] = zwei;
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	zwei.Add("kaksi");
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	ICollection<String> empty = new HashSet<String>();
+	mdict[0] = empty;
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	Console.WriteLine("mdict contains key 0: {0}", mdict.Contains(0));
+	mdict.Remove(-2);
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	zwei.Remove("kaksi");
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	zwei.Clear();
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	Console.WriteLine("------------------------------");
+      }
+    }
+  }
+
+  // Here we implement a multivalued dictionary as a hash dictionary
+  // from keys to value collections.  The value collections may have
+  // set or bag semantics.
+  
+  // The value collections are externally modifiable (as in Peter
+  // Golde's PowerCollections library), and therefore:
+  //
+  //  * A value collection associated with a key may be null or
+  //  non-empty.  Hence for correct semantics, the Contains(k) method
+  //  must check that the value collection associated with a key is
+  //  non-null and non-empty.
+  //  
+  //  * A value collection may be shared between two or more keys.
+  //
+
+  public class MultiHashDictionary<K,V> : HashDictionary<K, ICollection<V>> {
+
+    // Return total count of values associated with keys.  This basic
+    // implementation simply sums over all value collections, and so
+    // is a linear-time operation in the total number of values.  
+
+    public new virtual int Count { 
+      get { 
+        int count = 0;
+        foreach (KeyValuePair<K,ICollection<V>> entry in this) 
+          if (entry.Value != null)
+            count += entry.Value.Count;
+        return count;
+      }
+    }
+
+    public override Speed CountSpeed {
+      get { return Speed.Linear; }
+    }
+
+    // Add a (key,value) pair
+
+    public virtual void Add(K k, V v) {
+      ICollection<V> values;
+      if (!base.Find(k, out values) || values == null) {
+        values = new HashSet<V>();
+        Add(k, values);
+      } 
+      values.Add(v);
+    }
+
+    // Remove a single (key,value) pair, if present; return true if
+    // anything was removed, else false
+
+    public virtual bool Remove(K k, V v) {
+      ICollection<V> values;
+      if (base.Find(k, out values) && values != null) {
+        if (values.Remove(v)) {
+          if (values.IsEmpty)
+            base.Remove(k);
+          return true;
+        } 
+      }
+      return false;
+    }
+    
+    // Determine whether key k is associated with a value
+
+    public override bool Contains(K k) { 
+      ICollection<V> values;
+      return base.Find(k, out values) && values != null && !values.IsEmpty;
+    }
+
+    // Determine whether each key in ks is associated with a value
+
+    public override bool ContainsAll<U>(SCG.IEnumerable<U> ks) { 
+      foreach (K k in ks) 
+        if (!Contains(k))
+          return false;
+      return true;
+    }
+
+    // Get or set the value collection associated with key k
+
+    public override ICollection<V> this[K k] {
+      get {
+        ICollection<V> values;
+        return base.Find(k, out values) && values != null ? values : new HashSet<V>();
+      }
+      set {
+        base[k] = value;
+      }
+    }
+
+    // Inherited from base class HashDictionary<K,ICollection<V>>:
+
+    // Add(K k, ICollection<V> values) 
+    // AddAll(IEnumerable<KeyValuePair<K,ICollection<V>>> kvs) 
+    // Clear
+    // Clone
+    // Find(K k, out ICollection<V> values)
+    // Find(ref K k, out ICollection<V> values)
+    // FindOrAdd(K k, ref ICollection<V> values) 
+    // Remove(K k) 
+    // Remove(K k, out ICollection<V> values) 
+    // Update(K k, ICollection<V> values)
+    // Update(K k, ICollection<V> values, out ICollection<V> oldValues)
+    // UpdateOrAdd(K k, ICollection<V> values)
+    // UpdateOrAdd(K k, ICollection<V> values, out ICollection<V> oldValues)
+  }
+}
+
+// --------------------------------------------------
+
+namespace MultiDictionary2 {
+
+  class TestIt {
+    public static void Run() {
+      {
+	MultiHashDictionary<int,String> mdict 
+	  = new MultiHashDictionary<int,String>();
+	mdict.Add(2, "to");
+	mdict.Add(2, "deux");
+	mdict.Add(2, "two");
+	mdict.Add(20, "tyve");
+	mdict.Add(20, "twenty");
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	Console.WriteLine("mdict.Count (keys) is {0}", 
+			  ((IDictionary<int,ICollection<String>>)mdict).Count);
+	Console.WriteLine("mdict[2].Count is {0}", mdict[2].Count);
+	mdict.Remove(20, "tyve");
+	mdict.Remove(20, "twenty");
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	ICollection<String> zwei = new HashSet<String>();
+	zwei.Add("zwei");
+	mdict[2] = zwei;
+	mdict[-2] = zwei;
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	zwei.Add("kaksi");
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	ICollection<String> empty = new HashSet<String>();
+	mdict[0] = empty;
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	Console.WriteLine("mdict contains key 0: {0}", mdict.Contains(0));
+	mdict.Remove(-2);
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	zwei.Remove("kaksi");
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	zwei.Clear();
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	Console.WriteLine("------------------------------");
+      }
+      {
+	MultiHashDictionary<int,String,HashSet<String>> mdict 
+	  = new MultiHashDictionary<int,String,HashSet<String>>();
+	mdict.Add(2, "to");
+	mdict.Add(2, "deux");
+	mdict.Add(2, "two");
+	mdict.Add(20, "tyve");
+	mdict.Add(20, "twenty");
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	Console.WriteLine("mdict.Count (keys) is {0}", 
+			  ((IDictionary<int,HashSet<String>>)mdict).Count);
+	Console.WriteLine("mdict[2].Count is {0}", mdict[2].Count);
+	mdict.Remove(20, "tyve");
+	mdict.Remove(20, "twenty");
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	HashSet<String> zwei = new HashSet<String>();
+	zwei.Add("zwei");
+	mdict[2] = zwei;
+	mdict[-2] = zwei;
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	zwei.Add("kaksi");
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	HashSet<String> empty = new HashSet<String>();
+	mdict[0] = empty;
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	Console.WriteLine("mdict contains key 0: {0}", mdict.Contains(0));
+	mdict.Remove(-2);
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	zwei.Remove("kaksi");
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	zwei.Clear();
+	Console.WriteLine(mdict);
+	Console.WriteLine("mdict.Count is {0}", mdict.Count);
+	Console.WriteLine("------------------------------");
+      }
+    }
+  }
+
+  // This version of the multidictionary uses event listeners to make
+  // the Count operation constant time.
+  
+  // The total value count for the multidictionary is cached, and
+  // event listeners on the value collections keep this cached count
+  // updated.  Event listeners on the dictionary make sure that event
+  // listeners are added to and removed from value collections.
+  
+  public class MultiHashDictionary<K,V> : HashDictionary<K, ICollection<V>> {
+    private int count = 0;      // Cached value count, updated by events only
+
+    private void IncrementCount(Object sender, ItemCountEventArgs<V> args) {
+      count += args.Count;
+    }
+
+    private void DecrementCount(Object sender, ItemCountEventArgs<V> args) {
+      count -= args.Count;
+    }
+
+    private void ClearedCount(Object sender, ClearedEventArgs args) {
+      count -= args.Count;
+    }
+
+    public MultiHashDictionary() {
+      ItemsAdded += 
+        delegate(Object sender, ItemCountEventArgs<KeyValuePair<K,ICollection<V>>> args) {
+          ICollection<V> values = args.Item.Value;
+          if (values != null) {
+            count += values.Count;
+            values.ItemsAdded += IncrementCount;
+            values.ItemsRemoved += DecrementCount;
+            values.CollectionCleared += ClearedCount;
+          }
+        };
+      ItemsRemoved += 
+        delegate(Object sender, ItemCountEventArgs<KeyValuePair<K,ICollection<V>>> args) {
+          ICollection<V> values = args.Item.Value;
+          if (values != null) {
+            count -= values.Count;
+            values.ItemsAdded -= IncrementCount;
+            values.ItemsRemoved -= DecrementCount;
+            values.CollectionCleared -= ClearedCount;
+          }
+        };
+    }
+
+    // Return total count of values associated with keys.  
+
+    public new virtual int Count { 
+      get { 
+        return count;
+      }
+    }
+
+    public override Speed CountSpeed {
+      get { return Speed.Constant; }
+    }
+
+    // Add a (key,value) pair
+
+    public virtual void Add(K k, V v) {
+      ICollection<V> values;
+      if (!base.Find(k, out values) || values == null) {
+        values = new HashSet<V>();
+        Add(k, values);
+      } 
+      values.Add(v);
+    }
+
+    // Remove a single (key,value) pair, if present; return true if
+    // anything was removed, else false
+
+    public virtual bool Remove(K k, V v) {
+      ICollection<V> values;
+      if (base.Find(k, out values) && values != null) {
+        if (values.Remove(v)) {
+          if (values.IsEmpty)
+            base.Remove(k);
+          return true;
+        } 
+      }
+      return false;
+    }
+    
+    // Determine whether key k is associated with a value
+
+    public override bool Contains(K k) { 
+      ICollection<V> values;
+      return Find(k, out values) && values != null && !values.IsEmpty;
+    }
+
+    // Determine whether each key in ks is associated with a value
+
+    public override bool ContainsAll<U>(SCG.IEnumerable<U> ks) { 
+      foreach (K k in ks) 
+        if (!Contains(k))
+          return false;
+      return true;
+    }
+
+    // Get or set the value collection associated with key k
+
+    public override ICollection<V> this[K k] {
+      get {
+        ICollection<V> values;
+        return base.Find(k, out values) && values != null ? values : new HashSet<V>();
+      }
+      set {
+        base[k] = value;
+      }
+    }
+
+    // Clearing the multidictionary should remove event listeners
+
+    public override void Clear() { 
+      foreach (ICollection<V> values in Values) 
+        if (values != null) {
+          count -= values.Count;
+          values.ItemsAdded -= IncrementCount;
+          values.ItemsRemoved -= DecrementCount;
+          values.CollectionCleared -= ClearedCount;
+        }
+      base.Clear();
+    }
+  }
+
+  // --------------------------------------------------
+
+  // This version of the multidictionary also uses event listeners to
+  // make the Count operation constant time.
+
+  // The difference relative to the preceding version is that each
+  // value collection must be an instance of some type VS that has an
+  // argumentless constructor and that implements ICollection<V>.
+  // This provides additional flexibility: The creator of a
+  // multidictionary instance can determine the collection class VC
+  // used for value collections, instead of having to put up with the
+  // choice made by the multidictionary implementation.
+
+  public class MultiHashDictionary<K,V,VC> : HashDictionary<K, VC> 
+    where VC : ICollection<V>, new()
+  {
+    private int count = 0;      // Cached value count, updated by events only
+
+    private void IncrementCount(Object sender, ItemCountEventArgs<V> args) {
+      count += args.Count;
+    }
+
+    private void DecrementCount(Object sender, ItemCountEventArgs<V> args) {
+      count -= args.Count;
+    }
+
+    private void ClearedCount(Object sender, ClearedEventArgs args) {
+      count -= args.Count;
+    }
+
+    public MultiHashDictionary() {
+      ItemsAdded += 
+        delegate(Object sender, ItemCountEventArgs<KeyValuePair<K,VC>> args) {
+          VC values = args.Item.Value;
+          if (values != null) {
+            count += values.Count;
+            values.ItemsAdded += IncrementCount;
+            values.ItemsRemoved += DecrementCount;
+            values.CollectionCleared += ClearedCount;
+          }
+        };
+      ItemsRemoved += 
+        delegate(Object sender, ItemCountEventArgs<KeyValuePair<K,VC>> args) {
+          VC values = args.Item.Value;
+          if (values != null) {
+            count -= values.Count;
+            values.ItemsAdded -= IncrementCount;
+            values.ItemsRemoved -= DecrementCount;
+            values.CollectionCleared -= ClearedCount;
+          }
+        };
+    }
+
+    // Return total count of values associated with keys.  
+
+    public new virtual int Count { 
+      get { 
+        return count;
+      }
+    }
+
+    public override Speed CountSpeed {
+      get { return Speed.Constant; }
+    }
+
+    // Add a (key,value) pair
+
+    public virtual void Add(K k, V v) {
+      VC values;
+      if (!base.Find(k, out values) || values == null) {
+        values = new VC();
+        Add(k, values);
+      } 
+      values.Add(v);
+    }
+
+    // Remove a single (key,value) pair, if present; return true if
+    // anything was removed, else false
+
+    public virtual bool Remove(K k, V v) {
+      VC values;
+      if (base.Find(k, out values) && values != null) {
+        if (values.Remove(v)) {
+          if (values.IsEmpty)
+            base.Remove(k);
+          return true;
+        } 
+      }
+      return false;
+    }
+    
+    // Determine whether key k is associated with a value
+
+    public override bool Contains(K k) { 
+      VC values;
+      return Find(k, out values) && values != null && !values.IsEmpty;
+    }
+
+    // Determine whether each key in ks is associated with a value
+
+    public override bool ContainsAll<U>(SCG.IEnumerable<U> ks) { 
+      foreach (K k in ks) 
+        if (!Contains(k))
+          return false;
+      return true;
+    }
+
+    // Get or set the value collection associated with key k
+
+    public override VC this[K k] {
+      get {
+        VC values;
+        return base.Find(k, out values) && values != null ? values : new VC();
+      }
+      set {
+        base[k] = value;
+      }
+    }
+
+    public override void Clear() { 
+      foreach (VC values in Values) 
+	if (values != null) {
+	  count -= values.Count;
+	  values.ItemsAdded -= IncrementCount;
+	  values.ItemsRemoved -= DecrementCount;
+	  values.CollectionCleared -= ClearedCount;
+	}
+      base.Clear();
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/PointLocation.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/PointLocation.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/PointLocation.cs	(revision 3)
@@ -0,0 +1,774 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.Diagnostics;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace PointLocation
+{
+  //public enum Site { Cell,Edge,Outside}
+  /// <summary>
+  /// A line segment with associated data of type T for the cell 
+  /// to its right respectively left.
+  /// </summary>
+  public struct Edge<T>
+    {
+      public double xs, ys, xe, ye;
+      
+      public T right, left;
+      
+      public Edge(double xs, double ys, double xe, double ye, T right, T left)
+	{
+	  this.xs = xs;
+	  this.ys = ys;
+	  this.xe = xe;
+	  this.ye = ye;
+	  this.right = right;
+	  this.left = left;
+	}
+      
+      
+      public T Cell(bool upper)
+	{
+	  return (DoubleComparer.StaticCompare(xs, xe) < 0) == upper ? left : right;
+	}
+      
+      
+      public override string ToString()
+	{
+	  return String.Format("[({0:G5};{1:G5})->({2:G5};{3:G5})/R:{4} L:{5}]", xs, ys, xe, ye, right, left);
+	}
+    }
+  
+  
+  
+  /// <summary>
+  /// A data structure for point location in a plane divided into
+  /// cells by edges. This is the classical use of persistent trees
+  /// by Sarnak and Tarjan [?]. See de Berg et al for alternatives.
+  /// 
+  /// The internal data is an outer sorted dictionary that maps each
+  /// x coordinate of an endpoint of some edge to an inner sorted set
+  /// of the edges crossing or touching the vertical line at that x
+  /// coordinate, the edges being ordered by their y coordinates
+  /// to the immediate right of x. Lookup of a point (x,y) is done by
+  /// finding the predecessor of x cell the outer dictionary and then locating
+  /// the edges above and below (x,y) by searching in the inner sorted set.
+  /// 
+  /// The creation of the inner sorted sets is done by maintaining a
+  /// (persistent) tree of edges, inserting and deleting edges according
+  /// to a horzontal sweep of the edges while saving a snapshot of the
+  /// inner tree in the outer dictionary at each new x coordinate.
+  ///
+  /// If there are n edges, there will be 2n updates to the inner tree,
+  /// and in the worst case, the inner tree will have size Omega(n) for
+  /// Omega(n) snapshots. We will use O(n*logn) time and O(n) space for
+  /// sorting the endpoints. If we use a nodecopying persistent inner tree,
+  /// we will use O(n) space and time for building the data structure proper.
+  /// If we use a pathcopy persistent tree, we will use O(n*logn) time and
+  /// space for the data struicture. Finally, if we use a non-persistent
+  /// tree with a full copy for snapshot, we may use up to O(n^2) space and
+  /// time for building the datastructure.
+  ///
+  /// Lookup will take O(logn) time in any case, but taking the memory
+  /// hierarchy into consideration, a low space use is very beneficial
+  /// for large problems.
+  ///
+  /// The code assumes that the given set of edges is correct, in particular
+  /// that they do not touch at interior points (e.g. cross or coincide). 
+  /// </summary>
+	
+  public class PointLocator<T>
+  {
+    private TreeDictionary<double,ISorted<Edge<T>>> htree;
+    
+    private EdgeComparer<T> lc = new EdgeComparer<T>();
+    
+    private SCG.IComparer<EndPoint> epc = new EndPoint(0, 0, true, 0);
+    
+    private DoubleComparer dc = new DoubleComparer();
+    
+    private TreeDictionary<EndPoint,Edge<T>> endpoints;
+    
+    private int count;
+    
+    private bool built = false;
+    
+    public PointLocator()
+    {
+      //htree = new TreeDictionary<double,TreeSet<Edge<T>>>(dc);
+      endpoints = new TreeDictionary<EndPoint,Edge<T>>(epc);
+    }
+    
+    public PointLocator(SCG.IEnumerable<Edge<T>> edges)
+    {
+      //htree = new TreeDictionary<double,TreeSet<Edge<T>>>(dc);
+      endpoints = new TreeDictionary<EndPoint,Edge<T>>(epc);
+      foreach (Edge<T> edge in edges)
+	add(edge);
+    }
+    
+    private void add(Edge<T> edge)
+    {
+      int c = DoubleComparer.StaticCompare(edge.xs, edge.xe);
+      
+      if (c == 0)
+	return;
+      
+      endpoints.Add(new EndPoint(edge.xs, edge.ys, c < 0, count), edge);
+      endpoints.Add(new EndPoint(edge.xe, edge.ye, c > 0, count++), edge);
+    }
+
+    public void Add(Edge<T> edge)
+    {
+      if (built)
+	throw new InvalidOperationException("PointLocator static when built");
+      add(edge);
+    }
+    
+    public void AddAll(SCG.IEnumerable<Edge<T>> edges)
+    {
+      if (built)
+	throw new InvalidOperationException("PointLocator static when built");
+      
+      foreach (Edge<T> edge in edges)
+	add(edge);
+    }
+    
+    public void Build()
+    {
+      //htree.Clear();
+      htree = new TreeDictionary<double,ISorted<Edge<T>>>(dc);
+      
+      TreeSet<Edge<T>> vtree = new TreeSet<Edge<T>>(lc);
+      double lastx = Double.NegativeInfinity;
+      
+      foreach (KeyValuePair<EndPoint,Edge<T>> p in endpoints)
+	{
+	  if (dc.Compare(p.Key.x,lastx)>0)
+	    {
+	      //Put an empty snapshot at -infinity!
+	      htree[lastx] = (ISorted<Edge<T>>)(vtree.Snapshot());
+	      lc.X = lastx = p.Key.x;
+	      lc.compareToRight = false;
+	    }
+	  
+	  if (p.Key.start)
+	    {
+	      if (!lc.compareToRight)
+		lc.compareToRight = true;
+	      Debug.Assert(vtree.Check());
+	      bool chk = vtree.Add(p.Value);
+	      Debug.Assert(vtree.Check());
+	      
+	      Debug.Assert(chk,"edge was not added!",""+p.Value);
+	    }
+	  else
+	    {
+	      Debug.Assert(!lc.compareToRight);
+	      
+	      Debug.Assert(vtree.Check("C"));
+	      
+	      bool chk = vtree.Remove(p.Value);
+	      Debug.Assert(vtree.Check("D"));
+	      
+	      Debug.Assert(chk,"edge was not removed!",""+p.Value);
+	    }
+	}
+      lc.compareToRight = true;
+      
+      htree[lastx] = (TreeSet<Edge<T>>)(vtree.Snapshot());
+      built = true;
+    }
+    
+    
+    /*public void Clear()
+      {
+      endpoints.Clear();
+      htree.Clear();
+      }*/
+    /// <summary>
+    /// Find the cell, if any, containing (x,y).
+    /// </summary>
+    /// <param name="x">x coordinate of point</param>
+    /// <param name="y">y coordinate of point</param>
+    /// <param name="below">Associate data of cell according to edge below</param>
+    /// <param name="above">Associate data of cell according to edge above</param>
+    /// <returns>True if point is inside some cell</returns>
+    public bool Place(double x, double y, out T cell)
+    {
+      if (!built)
+	throw new InvalidOperationException("PointLocator must be built first");
+      
+      KeyValuePair<double,ISorted<Edge<T>>> p = htree.WeakPredecessor(x);
+      
+      //if (DoubleComparer.StaticCompare(cell.key,x)==0)
+      //Just note it, we have thrown away the vertical edges!
+      Edge<T> low, high;
+      bool lval, hval;
+      PointComparer<T> c = new PointComparer<T>(x, y);
+      
+      //Return value true here means we are at an edge.
+      //But note that if x is in htree.Keys, we may be at a
+      //vertical edge even if the return value is false here.
+      //Therefore we do not attempt to sort out completely the case
+      //where (x,y) is on an edge or even on several edges,
+      //and just deliver some cell it is in.
+      p.Value.Cut(c, out low, out lval, out high, out hval);
+      if (!lval || !hval)
+	{
+	  cell = default(T);
+	  return false;
+	}
+      else
+	{
+	  cell = low.Cell(true);//high.Cell(false);
+	  return true;
+	}
+    }
+    
+    public void Place(double x, double y, out T upper, out bool hval, out T lower, out bool lval)
+    {
+      if (!built)
+	throw new InvalidOperationException("PointLocator must be built first");
+      
+      KeyValuePair<double,ISorted<Edge<T>>> p = htree.WeakPredecessor(x);
+      
+      //if (DoubleComparer.StaticCompare(cell.key,x)==0)
+      //Just note it, we have thrown away the vertical edges!
+      Edge<T> low, high;
+      PointComparer<T> c = new PointComparer<T>(x, y);
+      
+      //Return value true here means we are at an edge.
+      //But note that if x is in htree.Keys, we may be at a
+      //vertical edge even if the return value is false here.
+      //Therefore we do not attempt to sort out completely the case
+      //where (x,y) is on an edge or even on several edges,
+      //and just deliver some cell it is in.
+      p.Value.Cut(c, out low, out lval, out high, out hval);
+      upper = hval ? high.Cell(false) : default(T);
+      lower = lval ? low.Cell(true) : default(T);
+      return; 
+    }
+    
+    public void Test(double x, double y)
+    {
+      T cell;
+      
+      if (Place(x, y, out cell))
+	Console.WriteLine("({0}; {1}): <- {2} ", x, y, cell);
+      else
+	Console.WriteLine("({0}; {1}): -", x, y);
+    }
+    
+    /// <summary>
+    /// Endpoint of an edge with ordering/comparison according to x
+    /// coordinates with arbitration by the id field. 
+    /// The client is assumed to keep the ids unique.
+    /// </summary>
+    public /*private*/ struct EndPoint: SCG.IComparer<EndPoint>
+    {
+      public double x, y;
+      
+      public bool start;
+      
+      private int id;
+      
+      
+      public EndPoint(double x, double y, bool left, int id)
+	{
+	  this.x = x;this.y = y;this.start = left;this.id = id;
+	}
+      
+      
+      public int Compare(EndPoint a, EndPoint b)
+	{
+	  int c = DoubleComparer.StaticCompare(a.x, b.x);
+	  
+	  return c != 0 ? c : (a.start && !b.start) ? 1 : (!a.start && b.start) ? -1 : a.id < b.id ? -1 : a.id > b.id ? 1 : 0;
+	}
+    }
+  }
+
+  /// <summary>
+  /// Compare two doubles with tolerance. 
+  /// </summary>
+  class DoubleComparer: SCG.IComparer<double>
+  {
+    private const double eps = 1E-10;
+    
+    public int Compare(double a, double b)
+    {
+      return a > b + eps ? 1 : a < b - eps ? -1 : 0;
+    }
+
+    public static int StaticCompare(double a, double b)
+    {
+      return a > b + eps ? 1 : a < b - eps ? -1 : 0;
+    }
+  }
+
+  /// <summary>
+  /// Compare a given point (x,y) to edges: is the point above, at or below
+  /// the edge. Assumes edges not vertical. 
+  /// </summary>
+  class PointComparer<T>: IComparable<Edge<T>>
+  {
+    private double x, y;
+    
+    public PointComparer(double x, double y)
+    {
+      this.x = x; this.y = y;
+    }
+    
+    public int CompareTo(Edge<T> a)
+    {
+      double ya = (a.ye - a.ys) / (a.xe - a.xs) * (x - a.xs) + a.ys;
+      
+      return DoubleComparer.StaticCompare(y, ya);
+    }
+    
+    public bool Equals(Edge<T> a) { return CompareTo(a) == 0; }
+  }
+
+  /// <summary>
+  /// Compare two edges at a given x coordinate:
+  /// Compares the y-coordinate  to the immediate right of x of the two edges.
+  /// Assumes edges to be compared are not vertical.
+  /// </summary>
+  class EdgeComparer<T>: SCG.IComparer<Edge<T>>
+  {
+    private double x;
+    
+    public bool compareToRight = true;
+    
+    public double X { get { return x; } set { x = value; } }
+    
+    public int Compare(Edge<T> line1, Edge<T> line2)
+    {
+      double a1 = (line1.ye - line1.ys) / (line1.xe - line1.xs);
+      double a2 = (line2.ye - line2.ys) / (line2.xe - line2.xs);
+      double ya = a1 * (x - line1.xs) + line1.ys;
+      double yb = a2 * (x - line2.xs) + line2.ys;
+      int c = DoubleComparer.StaticCompare(ya, yb);
+      
+      return c != 0 ? c : (compareToRight ? 1 : -1) * DoubleComparer.StaticCompare(a1, a2);
+    }
+  }
+
+  namespace Test
+    {
+      public class Ugly : EnumerableBase<Edge<int>>, SCG.IEnumerable<Edge<int>>, SCG.IEnumerator<Edge<int>>
+      {
+	private int level = -1, maxlevel;
+	
+	private bool leftend = false;
+	
+	public Ugly(int maxlevel)
+	{
+	  this.maxlevel = maxlevel;
+	}
+	
+	public override SCG.IEnumerator<Edge<int>> GetEnumerator()
+	{
+	  return (SCG.IEnumerator<Edge<int>>)MemberwiseClone();
+	}
+	
+	public void Reset()
+	{
+	  level = -1;
+	  leftend = false;
+	}
+	
+	public bool MoveNext()
+	{
+	  if (level > maxlevel)
+	    throw new InvalidOperationException();
+	  
+	  if (leftend)
+	    {
+	      leftend = false;
+	      return true;
+	    }
+	  else
+	    {
+	      leftend = true;
+	      return ++level <= maxlevel;
+	    }
+	}
+	
+	public Edge<int> Current
+	{
+	  get
+	    {
+	      if (level < 0 || level > maxlevel)
+		throw new InvalidOperationException();
+	      
+	      double y = (level * 37) % maxlevel;
+	      double deltax = leftend ? 1 : maxlevel;
+	      
+	      if (leftend)
+		return new Edge<int>(0, y, level, y - 0.5, 0, 0);
+	      else
+		return new Edge<int>(level, y - 0.5, level, y, 0, 0);
+	    }
+	}
+	
+	
+	public void Dispose() { }
+	
+#region IEnumerable Members
+
+	System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+	{
+	  throw new Exception("The method or operation is not implemented.");
+	}
+
+#endregion
+	
+#region IEnumerator Members
+	
+	object System.Collections.IEnumerator.Current
+	{
+	  get { throw new Exception("The method or operation is not implemented."); }
+	}
+	
+	void System.Collections.IEnumerator.Reset()
+	{
+	  throw new Exception("The method or operation is not implemented.");
+	}
+	
+#endregion
+      }
+
+      public class TestUgly
+      {
+	private Ugly ugly;
+	
+	private int d;
+	
+	private PointLocator<int> pointlocator;
+	
+	
+	public TestUgly(int d)
+	{
+	  this.d = d;
+	  ugly = new Ugly(d);
+	}
+	
+	
+	public double Traverse()
+	{
+	  double xsum = 0;
+	  
+	  foreach (Edge<int> e in ugly)	xsum += e.xe;
+	  
+	  return xsum;
+	}
+	
+	public bool LookUp(int count, int seed)
+	{
+	  Random random = new Random(seed);
+	  bool res = false;
+	  
+	  for (int i = 0; i < count; i++)
+	    {
+	      int cell;
+	      
+	      res ^= pointlocator.Place(random.NextDouble() * d, random.NextDouble() * d, out cell);
+	    }
+	  
+	  return res;
+	}
+
+	public static void Run(string[] args)
+	{
+	  int d = args.Length >= 2 ? int.Parse(args[1]) : 400;//00;
+	  int repeats = args.Length >= 3 ? int.Parse(args[2]) : 10;
+	  int lookups = args.Length >= 4 ? int.Parse(args[3]) : 500;//00;
+	  
+	  new TestUgly(d).run(lookups);
+	}
+	
+	
+	public void run(int lookups)
+	{
+	  double s = 0;
+	  
+	  s += Traverse();
+	  
+	  pointlocator = new PointLocator<int>(ugly);
+	  pointlocator.Build();
+	  
+	  LookUp(lookups, 567);
+	}
+      }
+      
+      public class Lattice : EnumerableBase<Edge<string>>, SCG.IEnumerable<Edge<string>>, SCG.IEnumerator<Edge<string>>, System.Collections.IEnumerator
+      {
+	private int currenti = -1, currentj = 0, currentid = 0;
+	
+	private bool currenthoriz = true;
+	
+	private int maxi, maxj;
+	
+	private double a11 = 1, a21 = -1, a12 = 1, a22 = 1;
+	
+	public Lattice(int maxi, int maxj, double a11, double a21, double a12, double a22)
+	{
+	  this.maxi = maxi;
+	  this.maxj = maxj;
+	  this.a11 = a11;
+	  this.a12 = a12;
+	  this.a21 = a21;
+	  this.a22 = a22;
+	}
+
+	public Lattice(int maxi, int maxj)
+	{
+	  this.maxi = maxi;
+	  this.maxj = maxj;
+	}
+	
+	public override SCG.IEnumerator<Edge<string>> GetEnumerator()
+	{
+	  return (SCG.IEnumerator<Edge<string>>)MemberwiseClone();
+	}
+	
+	public void Reset()
+	{
+	  currenti = -1;
+	  currentj = 0;
+	  currentid = -1;
+	  currenthoriz = true;
+	}
+	
+	public bool MoveNext()
+	{
+	  currentid++;
+	  if (currenthoriz)
+	    {
+	      if (++currenti >= maxi)
+		{
+		  if (currentj >= maxj)
+		    return false;
+		  
+		  currenti = 0;
+		  currenthoriz = false;
+		}
+	      
+	      return true;
+	    }
+	  else
+	    {
+	      if (++currenti > maxi)
+		{
+		  currenti = 0;
+		  currenthoriz = true;
+		  if (++currentj > maxj)
+		    return false;
+		}
+	      
+	      return true;
+	    }
+	}
+	
+	
+	private string i2l(int i)
+	{
+	  int ls = 0, j = i;
+	  
+	  do { ls++; j = j / 26 - 1; } while (j >= 0);
+	  
+	  char[] res = new char[ls];
+	  
+	  while (ls > 0) { res[--ls] = (char)(65 + i % 26); i = i / 26 - 1; }
+	  
+	  //res[0]--;
+	  return new String(res);
+	}
+	
+	
+	private string fmtid(int i, int j)
+	{
+	  return "";//cell + ";" + cell;
+	  /*if (cell < 0 || cell < 0 || cell >= maxi || cell >= maxj)
+	    return "Outside";
+	    
+	    return String.Format("{0}{1}", i2l(cell), cell);*/
+	}
+	
+	
+	public Edge<string> Current
+	{
+	  get
+	    {
+	      if (currenti >= maxi && currentj >= maxj)
+		throw new InvalidOperationException();
+	      
+	      double xs = currenti * a11 + currentj * a12;
+	      double ys = currenti * a21 + currentj * a22;
+	      double deltax = currenthoriz ? a11 : a12;
+	      double deltay = currenthoriz ? a21 : a22;
+	      string r = fmtid(currenti, currenthoriz ? currentj - 1 : currentj);
+	      string l = fmtid(currenthoriz ? currenti : currenti - 1, currentj);
+	      
+	      return new Edge<string>(xs, ys, xs + deltax, ys + deltay, r, l);
+	    }
+	}
+	
+	
+	public void Dispose() { }
+	
+#region IEnumerable Members
+	
+	System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+	{
+	  throw new Exception("The method or operation is not implemented.");
+	}
+	
+#endregion
+	
+#region IEnumerator Members
+	
+	object System.Collections.IEnumerator.Current
+	{
+	  get { throw new Exception("The method or operation is not implemented."); }
+	}
+	
+	bool System.Collections.IEnumerator.MoveNext()
+	{
+	  throw new Exception("The method or operation is not implemented.");
+	}
+	
+	void System.Collections.IEnumerator.Reset()
+	{
+	  throw new Exception("The method or operation is not implemented.");
+	}
+	
+#endregion
+      }
+      
+      public class TestLattice
+      {
+	private Lattice lattice;
+	
+	private int d;
+	
+	private PointLocator<string> pointlocator;
+	
+	
+	public TestLattice(int d)
+	{
+	  this.d = d;
+	  lattice = new Lattice(d, d, 1, 0, 0, 1);
+	}
+
+	public TestLattice(int d, double shear)
+	{
+	  this.d = d;
+	  lattice = new Lattice(d, d, 1, 0, shear, 1);
+	}
+
+	public double Traverse()
+	{
+	  double xsum = 0;
+	  
+	  foreach (Edge<string> e in lattice)	xsum += e.xe;
+	  
+	  return xsum;
+	}
+	
+	
+	public bool LookUp(int count, int seed)
+	{
+	  Random random = new Random(seed);
+	  bool res = false;
+	  
+	  for (int i = 0; i < count; i++)
+	    {
+	      string cell;
+	      
+	      res ^= pointlocator.Place(random.NextDouble() * d, random.NextDouble() * d, out cell);
+	    }
+	  
+	  return res;
+	}
+	
+	
+	public static void Run()
+	{
+ 	  int d = 200;
+ 	  int repeats = 2;
+ 	  int lookups = 50000;
+ 	  TestLattice tl = null;
+	  
+ 	  Console.WriteLine("TestLattice Run({0}), means over {1} repeats:", d, repeats);
+ 	  tl = new TestLattice(d, 0.000001);
+
+ 	  tl.Traverse();
+	  
+ 	  tl.pointlocator = new PointLocator<string>();
+	  
+ 	  tl.pointlocator.AddAll(tl.lattice);
+	  
+ 	  tl.pointlocator.Build();
+	  
+ 	  tl.LookUp(lookups, 567);
+	}
+	
+	
+	public void BasicRun()
+	{
+	  pointlocator.Test(-0.5, -0.5);
+	  pointlocator.Test(-0.5, 0.5);
+	  pointlocator.Test(-0.5, 1.5);
+	  pointlocator.Test(0.5, -0.5);
+	  pointlocator.Test(0.5, 0.5);
+	  pointlocator.Test(0.5, 1.5);
+	  pointlocator.Test(1.5, -0.5);
+	  pointlocator.Test(1.5, 0.5);
+	  pointlocator.Test(1.5, 1.5);
+	  pointlocator.Test(1.5, 4.99);
+	  pointlocator.Test(1.5, 5);
+	  pointlocator.Test(1.5, 5.01);
+	  pointlocator.Test(1.99, 4.99);
+	  pointlocator.Test(1.99, 5);
+	  pointlocator.Test(1.99, 5.01);
+	  pointlocator.Test(2, 4.99);
+	  pointlocator.Test(2, 5);
+	  pointlocator.Test(2, 5.01);
+	  pointlocator.Test(2.01, 4.99);
+	  pointlocator.Test(2.01, 5);
+	  pointlocator.Test(2.01, 5.01);
+	}
+      }
+    }
+
+  public class TestPointLocation {
+    public static void Main(String[] args) {
+      Test.TestUgly.Run(new String[0]);
+    }
+  }
+}
+
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/RandomSelection.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/RandomSelection.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/RandomSelection.cs	(revision 3)
@@ -0,0 +1,86 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: RandomSelection.cs for pattern chapter
+
+// Compile with 
+//   csc /r:C5.dll RandomSelection.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace RandomSelection {
+  class RandomSelection {
+    public static void Main(String[] args) {
+      ArrayList<int> list = new ArrayList<int>(), copy1, copy2;
+      list.AddAll(new int[] { 2, 3, 5, 7, 11, 13, 17, 19 });
+      copy1 = (ArrayList<int>)list.Clone();
+      copy2 = (ArrayList<int>)list.Clone();
+      const int N = 7;
+      Console.WriteLine("-- With replacement:");
+      foreach (int x in RandomWith(list, N))
+        Console.Write("{0} ", x);
+      Console.WriteLine("\n-- Without replacement:");
+      foreach (int x in RandomWithout1(copy1, N))
+        Console.Write("{0} ", x);
+      Console.WriteLine("\n-- Without replacement:");
+      foreach (int x in RandomWithout2(copy2, N))
+        Console.Write("{0} ", x);
+      Console.WriteLine();
+    }
+
+    private static readonly C5Random rnd = new C5Random();
+
+    // Select N random items from coll, with replacement.
+    // Does not modify the given list.
+
+    public static SCG.IEnumerable<T> RandomWith<T>(IIndexed<T> coll, int N) {
+      for (int i=N; i>0; i--) { 
+        T x = coll[rnd.Next(coll.Count)];
+        yield return x;
+      }
+    }
+
+    // Select N random items from list, without replacement.
+    // Modifies the given list.
+
+    public static SCG.IEnumerable<T> RandomWithout1<T>(IList<T> list, int N) {
+      list.Shuffle(rnd);     
+      foreach (T x in list.View(0, N)) 
+        yield return x;
+    }
+
+    // Select N random items from list, without replacement.
+    // Faster when list is efficiently indexable and modifiable.
+    // Modifies the given list.
+
+    public static SCG.IEnumerable<T> RandomWithout2<T>(ArrayList<T> list, int N) {
+      for (int i=N; i>0; i--) { 
+        int j = rnd.Next(list.Count);
+        T x = list[j], replacement = list.RemoveLast();
+        if (j < list.Count) 
+          list[j] = replacement;
+        yield return x;
+      }
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/ReadOnlyPatterns.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/ReadOnlyPatterns.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/ReadOnlyPatterns.cs	(revision 3)
@@ -0,0 +1,96 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: ReadOnlyPatterns.cs for pattern chapter
+
+// Compile with 
+//   csc /r:C5.dll ReadOnlyPatterns.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace ReadOnlyPatterns {
+  class ReadOnlyPatterns {
+    public static void Main(String[] args) {
+      GuardHashSet<int>();
+      GuardTreeSet<int>();
+      GuardList<int>();
+      GuardHashDictionary<int,int>();
+      GuardSortedDictionary<int,int>();
+    }
+
+    // Read-only access to a hash-based collection
+    
+    static void GuardHashSet<T>() {
+      ICollection<T> coll = new HashSet<T>();
+      DoWork(new GuardedCollection<T>(coll));
+    }
+
+    static void DoWork<T>(ICollection<T> gcoll) { 
+      // Use gcoll ... 
+    }
+
+    // Read-only access to an indexed sorted collection
+
+    static void GuardTreeSet<T>() {
+      IIndexedSorted<T> coll = new TreeSet<T>(); 
+      DoWork(new GuardedIndexedSorted<T>(coll));
+    }
+    
+    static void DoWork<T>(IIndexedSorted<T> gcoll) { 
+      // Use gcoll ...
+    }
+
+    // Read-only access to a list
+
+    static void GuardList<T>() {
+      IList<T> coll = new ArrayList<T>(); 
+      DoWork(new GuardedList<T>(coll));
+    }
+    
+    static void DoWork<T>(IList<T> gcoll) { 
+      // Use gcoll ...
+    }
+
+    // Read-only access to a dictionary
+
+    static void GuardHashDictionary<K,V>() {
+      IDictionary<K,V> dict = new HashDictionary<K,V>(); 
+      DoWork(new GuardedDictionary<K,V>(dict));
+    }
+    
+    static void DoWork<K,V>(IDictionary<K,V> gdict) { 
+      // Use gdict ...
+    }
+
+    // Read-only access to a sorted dictionary
+
+    static void GuardSortedDictionary<K,V>() {
+      ISortedDictionary<K,V> dict = new TreeDictionary<K,V>(); 
+      DoWork(new GuardedSortedDictionary<K,V>(dict));
+    }
+    
+    static void DoWork<K,V>(ISortedDictionary<K,V> gdict) { 
+      // Use gdict ...
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/SerializationExample.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/SerializationExample.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/SerializationExample.cs	(revision 3)
@@ -0,0 +1,72 @@
+/*
+ Copyright (c) 2003-2008 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: serialization and deserialization 
+
+// Compile with 
+//   csc /r:C5.dll SerializationExample.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+using System.IO;                                        // FileStream, Stream
+using System.Runtime.Serialization.Formatters.Binary;   // BinaryFormatter
+
+namespace SerializationExample
+{
+  class MyTest
+  {
+    private static readonly BinaryFormatter formatter = new BinaryFormatter();
+
+    public static void ToFile<T>(IExtensible<T> coll, String filename) {
+      Stream outstream = new FileStream(filename, FileMode.OpenOrCreate);
+      formatter.Serialize(outstream, coll);
+      outstream.Close();
+    }
+
+    public static T FromFile<T>(String filename) {
+      Stream instream = new FileStream(filename, FileMode.Open);
+      Object obj = formatter.Deserialize(instream);
+      instream.Close();
+      return (T)obj;
+    }
+
+    public static void Main() {
+      IList<String> names = new LinkedList<String>();
+      String reagan = "Reagan";
+      names.AddAll(new String[] { reagan, reagan, "Bush", "Clinton", 
+                                  "Clinton", "Bush", "Bush" });
+      ToFile(names, "prez.bin");
+      IList<String> namesFromFile = FromFile<IList<String>>("prez.bin");
+
+      foreach (String s in namesFromFile) 
+        Console.WriteLine(s);
+
+      Console.Write("Deserialization preserves sequenced equality: ");
+      Console.WriteLine(names.SequencedEquals(namesFromFile));
+      Console.Write("Deserialization reuses the same strings: ");
+      Console.WriteLine(Object.ReferenceEquals(reagan, namesFromFile[1]));
+      Console.Write("Deserialization preserves sharing: ");
+      Console.WriteLine(Object.ReferenceEquals(namesFromFile[0], namesFromFile[1]));
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Sets.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Sets.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Sets.cs	(revision 3)
@@ -0,0 +1,175 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: functional sets 2004-12-21
+
+// Compile with 
+//   csc /r:C5.dll Sets.cs 
+
+using System;
+using System.Text;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace Sets {
+  // The class of sets with item type T, implemented as a subclass of
+  // HashSet<T> but with functional infix operators * + - that compute
+  // intersection, union and difference functionally.  That is, they
+  // create a new set object instead of modifying an existing one.
+  // The hasher is automatically created so that it is appropriate for
+  // T.  In particular, this is true when T has the form Set<W> for
+  // some W, since Set<W> implements ICollectionValue<W>.
+
+  public class Set<T> : HashSet<T> {
+    public Set(SCG.IEnumerable<T> enm) : base() {
+      AddAll(enm);
+    }
+
+    public Set(params T[] elems) : this((SCG.IEnumerable<T>)elems) { }
+
+    // Set union (+), difference (-), and intersection (*):
+
+    public static Set<T> operator +(Set<T> s1, Set<T> s2) {
+      if (s1 == null || s2 == null) 
+        throw new ArgumentNullException("Set+Set");
+      else {
+        Set<T> res = new Set<T>(s1);
+        res.AddAll(s2);
+        return res;
+      }
+    }
+
+    public static Set<T> operator -(Set<T> s1, Set<T> s2) {
+      if (s1 == null || s2 == null) 
+        throw new ArgumentNullException("Set-Set");
+      else {
+        Set<T> res = new Set<T>(s1);
+        res.RemoveAll(s2);
+        return res;
+      }
+    }
+
+    public static Set<T> operator *(Set<T> s1, Set<T> s2) {
+      if (s1 == null || s2 == null) 
+        throw new ArgumentNullException("Set*Set");
+      else {
+        Set<T> res = new Set<T>(s1);
+        res.RetainAll(s2);
+        return res;
+      }
+    }
+
+    // Equality of sets; take care to avoid infinite loops
+
+    public static bool operator ==(Set<T> s1, Set<T> s2) {
+      return EqualityComparer<Set<T>>.Default.Equals(s1, s2);
+    }
+
+    public static bool operator !=(Set<T> s1, Set<T> s2) {
+      return !(s1 == s2);
+    }
+
+    public override bool Equals(Object that) {
+      return this == (that as Set<T>);
+    }
+
+    public override int GetHashCode() {
+      return EqualityComparer<Set<T>>.Default.GetHashCode(this);
+    }
+
+    // Subset (<=) and superset (>=) relation:
+
+    public static bool operator <=(Set<T> s1, Set<T> s2) {
+      if (s1 == null || s2 == null) 
+        throw new ArgumentNullException("Set<=Set");
+      else
+        return s1.ContainsAll(s2);
+    }
+
+    public static bool operator >=(Set<T> s1, Set<T> s2) {
+      if (s1 == null || s2 == null) 
+        throw new ArgumentNullException("Set>=Set");
+      else
+        return s2.ContainsAll(s1);
+    }
+    
+    public override String ToString() {
+      StringBuilder sb = new StringBuilder();
+      sb.Append("{");
+      bool first = true;
+      foreach (T x in this) {
+        if (!first)
+          sb.Append(",");
+        sb.Append(x);
+        first = false;
+      }
+      sb.Append("}");
+      return sb.ToString();
+    }
+  }
+
+  class MyTest {
+    public static void Main(String[] args) {
+      Set<int> s1 = new Set<int>(2, 3, 5, 7, 11);
+      Set<int> s2 = new Set<int>(2, 4, 6, 8, 10);
+      Console.WriteLine("s1 + s2 = {0}", s1 + s2);
+      Console.WriteLine("s1 * s2 = {0}", s1 * s2);
+      Console.WriteLine("s1 - s2 = {0}", s1 - s2);
+      Console.WriteLine("s1 - s1 = {0}", s1 - s1);
+      Console.WriteLine("s1 + s1 == s1 is {0}", s1 + s1 == s1);
+      Console.WriteLine("s1 * s1 == s1 is {0}", s1 * s1 == s1);
+      Set<Set<int>> ss1 = new Set<Set<int>>(s1, s2, s1 + s2);
+      Console.WriteLine("ss1 = {0}", ss1);
+      Console.WriteLine("IntersectionClose(ss1) = {0}", IntersectionClose(ss1));
+      Set<Set<int>> ss2 =
+        new Set<Set<int>>(new Set<int>(2, 3), new Set<int>(1, 3), new Set<int>(1, 2));
+      Console.WriteLine("ss2 = {0}", ss2);
+      Console.WriteLine("IntersectionClose(ss2) = {0}", IntersectionClose(ss2));
+    }
+
+    // Given a set SS of sets of Integers, compute its intersection
+    // closure, that is, the least set TT such that SS is a subset of TT
+    // and such that for any two sets t1 and t2 in TT, their
+    // intersection is also in TT.  
+
+    // For instance, if SS is {{2,3}, {1,3}, {1,2}}, 
+    // then TT is {{2,3}, {1,3}, {1,2}, {3}, {2}, {1}, {}}.
+
+    // Both the argument and the result is a Set<Set<int>>
+
+    static Set<Set<T>> IntersectionClose<T>(Set<Set<T>> ss) {
+      IQueue<Set<T>> worklist = new CircularQueue<Set<T>>();
+      foreach (Set<T> s in ss)
+        worklist.Enqueue(s);
+      HashSet<Set<T>> tt = new HashSet<Set<T>>();
+      while (worklist.Count != 0) {
+        Set<T> s = worklist.Dequeue();
+        foreach (Set<T> t in tt) {
+          Set<T> ts = t * s;
+          if (!tt.Contains(ts))
+            worklist.Enqueue(ts);
+        }
+        tt.Add(s);
+      }
+      return new Set<Set<T>>((SCG.IEnumerable<Set<T>>)tt);
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/SortedIterationPatterns.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/SortedIterationPatterns.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/SortedIterationPatterns.cs	(revision 3)
@@ -0,0 +1,247 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: SortedIterationPatterns.cs for pattern chapter
+
+// Compile with 
+//   csc /r:C5.dll SortedIterationPatterns.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace SortedIterationPatterns {
+  class SortedIterationPatterns {
+    public static void Main(String[] args) {
+      ISorted<int> sorted = new TreeSet<int>();
+      sorted.AddAll(new int[] { 23, 29, 31, 37, 41, 43, 47, 53 });
+      Console.WriteLine(sorted);
+      if (args.Length == 1) { 
+        int n = int.Parse(args[0]);
+        int res;
+        if (Predecessor(sorted, n, out res))
+          Console.WriteLine("{0} has predecessor {1}", n, res);
+        if (WeakPredecessor(sorted, n, out res))
+          Console.WriteLine("{0} has weak predecessor {1}", n, res);
+        if (Successor(sorted, n, out res))
+          Console.WriteLine("{0} has successor {1}", n, res);
+        if (WeakSuccessor(sorted, n, out res))
+          Console.WriteLine("{0} has weak successor {1}", n, res);
+      }
+      IterBeginEnd(sorted);
+      IterBeginEndBackwards(sorted);
+      IterIncExc(sorted, 29, 47);
+      IterIncExcBackwards(sorted, 29, 47);
+      IterIncEnd(sorted, 29);
+      IterBeginExc(sorted, 47);
+      IterIncInc(sorted, 29, 47);
+      IterBeginInc(sorted, 47);
+      IterExcExc(sorted, 29, 47);
+      IterExcEnd(sorted, 29);
+      IterExcInc(sorted, 29, 47);
+    }
+
+    // --- Predecessor and successor patterns --------------------
+
+    // Find weak successor of y in coll, or return false
+
+    public static bool WeakSuccessor<T>(ISorted<T> coll, T y, out T ySucc) 
+      where T : IComparable<T>
+    {
+      T yPred;
+      bool hasPred, hasSucc, 
+        hasY = coll.Cut(y, out yPred, out hasPred, out ySucc, out hasSucc);
+      if (hasY)
+        ySucc = y;
+      return hasY || hasSucc;
+    }
+
+    // Find weak predecessor of y in coll, or return false
+
+    public static bool WeakPredecessor<T>(ISorted<T> coll, T y, out T yPred) 
+      where T : IComparable<T>
+    {
+      T ySucc;
+      bool hasPred, hasSucc, 
+        hasY = coll.Cut(y, out yPred, out hasPred, out ySucc, out hasSucc);
+      if (hasY) 
+        yPred = y;
+      return hasY || hasPred;
+    }
+
+    // Find (strict) successor of y in coll, or return false
+
+    public static bool Successor<T>(ISorted<T> coll, T y, out T ySucc) 
+      where T : IComparable<T>
+    {
+      bool hasPred, hasSucc;
+      T yPred;
+      coll.Cut(y, out yPred, out hasPred, out ySucc, out hasSucc);
+      return hasSucc;
+    }
+
+    // Find (strict) predecessor of y in coll, or return false
+
+    public static bool Predecessor<T>(ISorted<T> coll, T y, out T yPred) 
+      where T : IComparable<T>
+    {
+      bool hasPred, hasSucc;
+      T ySucc;
+      coll.Cut(y, out yPred, out hasPred, out ySucc, out hasSucc);
+      return hasPred;
+    }
+
+    // --- Sorted iteration patterns -----------------------------
+
+    // Iterate over all items
+    
+    public static void IterBeginEnd<T>(ISorted<T> coll) {
+      foreach (T x in coll) { 
+        Console.Write("{0} ", x);
+      }
+      Console.WriteLine();
+    }
+
+    // Iterate over all items, backwards
+    
+    public static void IterBeginEndBackwards<T>(ISorted<T> coll) {
+      foreach (T x in coll.Backwards()) { 
+        Console.Write("{0} ", x);
+      }
+      Console.WriteLine();
+    }
+
+    // Iterate over [x1,x2[
+    
+    public static void IterIncExc<T>(ISorted<T> coll, T x1, T x2) {
+      foreach (T x in coll.RangeFromTo(x1, x2)) { 
+        Console.Write("{0} ", x);
+      }
+      Console.WriteLine();
+    }
+
+    // Iterate over [x1,x2[, backwards
+    
+    public static void IterIncExcBackwards<T>(ISorted<T> coll, T x1, T x2) {
+      foreach (T x in coll.RangeFromTo(x1, x2).Backwards()) { 
+        Console.Write("{0} ", x);
+      }
+      Console.WriteLine();
+    }
+
+    // Iterate over [x1...]
+    
+    public static void IterIncEnd<T>(ISorted<T> coll, T x1) {
+      foreach (T x in coll.RangeFrom(x1)) { 
+        Console.Write("{0} ", x);
+      }
+      Console.WriteLine();
+    }
+
+    // Iterate over [...x2[
+    
+    public static void IterBeginExc<T>(ISorted<T> coll, T x2) {
+      foreach (T x in coll.RangeTo(x2)) { 
+        Console.Write("{0} ", x);
+      }
+      Console.WriteLine();
+    }
+
+    // Iterate over [x1...x2]
+    
+    public static void IterIncInc<T>(ISorted<T> coll, T x1, T x2) 
+      where T : IComparable<T>
+    {
+      T x2Succ; 
+      bool x2HasSucc = Successor(coll, x2, out x2Succ);
+      IDirectedEnumerable<T> range = 
+        x2HasSucc ? coll.RangeFromTo(x1, x2Succ) : coll.RangeFrom(x1);
+      foreach (T x in range) {
+        Console.Write("{0} ", x);
+      } 
+      Console.WriteLine();
+    }
+
+    // Iterate over [...x2]
+    
+    public static void IterBeginInc<T>(ISorted<T> coll, T x2) 
+      where T : IComparable<T>
+    {
+      T x2Succ; 
+      bool x2HasSucc = Successor(coll, x2, out x2Succ);
+      IDirectedEnumerable<T> range = 
+        x2HasSucc ? coll.RangeTo(x2Succ) : coll.RangeAll();
+      foreach (T x in range) {
+        Console.Write("{0} ", x);
+      } 
+      Console.WriteLine();
+    }
+
+    // Iterate over ]x1...x2[
+    
+    public static void IterExcExc<T>(ISorted<T> coll, T x1, T x2)
+      where T : IComparable<T>
+    {
+      T x1Succ;
+      bool x1HasSucc = Successor(coll, x1, out x1Succ);
+      IDirectedEnumerable<T> range = 
+        x1HasSucc ? coll.RangeFromTo(x1Succ, x2) : new ArrayList<T>();
+      foreach (T x in range) {
+        Console.Write("{0} ", x);
+      } 
+      Console.WriteLine();
+    }
+
+    // Iterate over ]x1...]
+    
+    public static void IterExcEnd<T>(ISorted<T> coll, T x1) 
+      where T : IComparable<T>
+    {
+      T x1Succ;
+      bool x1HasSucc = Successor(coll, x1, out x1Succ);
+      IDirectedEnumerable<T> range = 
+        x1HasSucc ? coll.RangeFrom(x1Succ) : new ArrayList<T>();
+      foreach (T x in range) {
+        Console.Write("{0} ", x);
+      } 
+      Console.WriteLine();
+    }
+
+    // Iterate over ]x1...x2]
+    
+    public static void IterExcInc<T>(ISorted<T> coll, T x1, T x2) 
+      where T : IComparable<T>
+    {
+      T x1Succ, x2Succ;
+      bool x1HasSucc = Successor(coll, x1, out x1Succ),
+           x2HasSucc = Successor(coll, x2, out x2Succ);
+      IDirectedEnumerable<T> range = 
+        x1HasSucc ? (x2HasSucc ? coll.RangeFromTo(x1Succ, x2Succ) 
+                               : coll.RangeFrom(x1Succ))
+                  : new ArrayList<T>();
+      foreach (T x in range) {
+        Console.Write("{0} ", x);
+      } 
+      Console.WriteLine();
+    }
+
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/SortingPermutation.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/SortingPermutation.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/SortingPermutation.cs	(revision 3)
@@ -0,0 +1,80 @@
+// C5 example
+// 2004-11
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace SortingPermutation
+{
+  class MyTest
+  {
+    public static void Main(String[] args)
+    {
+      String[] cities = 
+      { "Tokyo", "Beijing", "Hangzhou", "Kyoto", "Beijing", "Copenhagen", "Seattle" };
+      IList<String> alst = new ArrayList<String>();
+      alst.AddAll<String>(cities);
+      foreach (int i in MySort.GetPermutation1(alst))
+        Console.Write("{0} ", i);
+      Console.WriteLine();
+      IList<String> llst = new LinkedList<String>();
+      llst.AddAll<String>(cities);
+      foreach (int i in MySort.GetPermutation2(llst))
+        Console.Write("{0} ", i);
+      Console.WriteLine();
+      Console.WriteLine("The rank of the cities:");
+      ArrayList<int> res = MySort.GetPermutation1(MySort.GetPermutation2(llst));
+      foreach (int i in res)
+        Console.Write("{0} ", i);
+      Console.WriteLine();
+    }
+  }
+
+  class MySort
+  {
+    // Fast for array lists and similar, but not stable; slow for linked lists
+
+    public static ArrayList<int> GetPermutation1<T>(IList<T> lst)
+      where T : IComparable<T>
+    {
+      ArrayList<int> res = new ArrayList<int>(lst.Count);
+      for (int i = 0; i < lst.Count; i++)
+        res.Add(i);
+      res.Sort(new DelegateComparer<int>
+               (delegate(int i, int j) { return lst[i].CompareTo(lst[j]); }));
+      return res;
+    }
+
+    // Stable and fairly fast both for array lists and linked lists, 
+    // but does copy the collection's items. 
+
+    public static ArrayList<int> GetPermutation2<T>(IList<T> lst)
+      where T : IComparable<T>
+    {
+      int i = 0;
+      IList<KeyValuePair<T, int>> zipList =
+        lst.Map<KeyValuePair<T, int>>
+            (delegate(T x) { return new KeyValuePair<T, int>(x, i++); });
+      zipList.Sort(new KeyValueComparer<T>(lst));
+      ArrayList<int> res = new ArrayList<int>(lst.Count);
+      foreach (KeyValuePair<T, int> p in zipList)
+        res.Add(p.Value);
+      return res;
+    }
+
+    private class KeyValueComparer<T> : SCG.IComparer<KeyValuePair<T, int>>
+      where T : IComparable<T>
+    {
+      private readonly IList<T> lst;
+      public KeyValueComparer(IList<T> lst)
+      {
+        this.lst = lst;
+      }
+      public int Compare(KeyValuePair<T, int> p1, KeyValuePair<T, int> p2)
+      {
+        return p1.Key.CompareTo(p2.Key);
+      }
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/TestSortedArray.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/TestSortedArray.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/TestSortedArray.cs	(revision 3)
@@ -0,0 +1,31 @@
+// C5 example: This should fail because C5 does not know how to build
+// a comparer for Object.
+
+// Similarly for Rec<string,int>
+
+// Compile with 
+//   csc /r:C5.dll TestSortedArray.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace TestSortedArray {
+  class TestSortedArray {
+    public static void Main(String[] args) {
+      //       SortedArray<Object> sarr = new SortedArray<Object>();
+      SCG.IComparer<Rec<string,int>> lexico =
+	new DelegateComparer<Rec<string,int>>(
+	    delegate(Rec<string,int> r1, Rec<string,int> r2) { 
+	      int order = r1.X1.CompareTo(r2.X1);
+	      return order==0 ? r1.X2.CompareTo(r2.X2) : order;
+	    });
+      SortedArray<Rec<string,int>> sarr = new SortedArray<Rec<string,int>>(lexico);
+      sarr.Add(new Rec<string,int>("ole", 32));
+      sarr.Add(new Rec<string,int>("hans", 77));
+      sarr.Add(new Rec<string,int>("ole", 63));
+      foreach (Rec<string,int> r in sarr)
+	Console.WriteLine(r);
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/ThisFun.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/ThisFun.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/ThisFun.cs	(revision 3)
@@ -0,0 +1,46 @@
+// Experiment: implicit conversion of indexer to function
+// sestoft@dina.kvl.dk * 2005-11-08
+
+using System;
+using C5;
+
+class MyFunTest {
+  public static void Main(String[] args) {
+    FooBar fb = new FooBar();
+    IList<int> list = new LinkedList<int>();
+    list.AddAll(new int[] { 2, 3, 5, 7, 11 });
+    list.Map<double>(fb).Apply(Console.WriteLine);
+    list.Apply(fb);
+  }
+}
+
+class FooBar {
+  public double this[int x] { 
+    get { 
+      Console.WriteLine(x); 
+      return x + 1.5; 
+    } 
+  }
+
+  public Fun<int,double> Fun {
+    get { 
+      return delegate(int x) { return this[x]; };
+    }
+  }
+
+  public Act<int> Act {
+    get { 
+      return delegate(int x) { double junk = this[x]; };
+    }
+  }
+  
+  public static implicit operator Fun<int,double>(FooBar fb) {
+    return delegate(int x) { return fb[x]; };
+  }  
+
+  public static implicit operator Act<int>(FooBar fb) {
+    return delegate(int x) { double junk = fb[x]; };
+  }  
+}
+
+
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Toposort.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Toposort.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Toposort.cs	(revision 3)
@@ -0,0 +1,139 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: topological sorting 2005-09-09
+
+// Compile with 
+//   csc /r:C5.dll Toposort.cs 
+
+using System;
+using System.Text;
+using C5;
+using SCG = System.Collections.Generic;
+using SDD = System.Diagnostics.Debug;
+
+namespace Toposort {
+  class TestToposort {
+    public static void Main(String[] args) {
+      Node<String> 
+        d = new Node<String>("d"), 
+        e = new Node<String>("e"),
+        c = new Node<String>("c", d, e),
+        b = new Node<String>("b", d),
+        a = new Node<String>("a", d, b, c);
+      foreach (Node<String> n in Toposort0(a))
+        Console.WriteLine(n);
+      Console.WriteLine();
+      foreach (Node<String> n in Toposort1(a))
+        Console.WriteLine(n);
+      Console.WriteLine();
+      foreach (Node<String> n in Toposort2(a))
+        Console.WriteLine(n);
+    }
+
+    // Toposort 0, adding each node when finished, after its descendants.
+    // Classic depth-first search.  Does not terminate on cyclic graphs.
+    
+    public static IList<Node<T>> Toposort0<T>(params Node<T>[] starts) {
+      HashedLinkedList<Node<T>> sorted = new HashedLinkedList<Node<T>>();
+      foreach (Node<T> start in starts) 
+        if (!sorted.Contains(start)) 
+          AddNode0(sorted, start);
+      return sorted; 
+    }
+
+    private static void AddNode0<T>(IList<Node<T>> sorted, Node<T> node) {
+      SDD.Assert(!sorted.Contains(node));
+      foreach (Node<T> child in node.children) 
+        if (!sorted.Contains(child)) 
+          AddNode0(sorted, child);
+      sorted.InsertLast(node);
+    }
+
+    // Toposort 1, using hash index to add each node before its descendants.
+    // Terminates also on cyclic graphs.
+    
+    public static IList<Node<T>> Toposort1<T>(params Node<T>[] starts) {
+      HashedLinkedList<Node<T>> sorted = new HashedLinkedList<Node<T>>();
+      foreach (Node<T> start in starts) 
+        if (!sorted.Contains(start)) {
+          sorted.InsertLast(start);
+          AddNode1(sorted, start);
+        }
+      return sorted; 
+    }
+
+    private static void AddNode1<T>(IList<Node<T>> sorted, Node<T> node) {
+      SDD.Assert(sorted.Contains(node));
+      foreach (Node<T> child in node.children) 
+        if (!sorted.Contains(child)) {
+          sorted.ViewOf(node).InsertFirst(child);
+          AddNode1(sorted, child);
+        }
+    }
+
+    // Toposort 2, node rescanning using a view.
+    // Uses no method call stack and no extra data structures, but slower.
+
+    public static IList<Node<T>> Toposort2<T>(params Node<T>[] starts) {
+      HashedLinkedList<Node<T>> sorted = new HashedLinkedList<Node<T>>();
+      foreach (Node<T> start in starts) 
+        if (!sorted.Contains(start)) {
+          sorted.InsertLast(start);
+          using (IList<Node<T>> cursor = sorted.View(sorted.Count-1,1)) {
+            do { 
+              Node<T> child;
+              while (null != (child = PendingChild(sorted, cursor.First))) {
+                cursor.InsertFirst(child);
+                cursor.Slide(0,1);
+              }
+            } while (cursor.TrySlide(+1));
+          }
+        }
+      return sorted; 
+    }
+
+    static Node<T> PendingChild<T>(IList<Node<T>> sorted, Node<T> node) {
+      foreach (Node<T> child in node.children) 
+        if (!sorted.Contains(child))
+          return child;
+      return null;
+    }
+  }
+
+  class Node<T> { 
+    public readonly T id;
+    public readonly Node<T>[] children;
+
+    public Node(T id, params Node<T>[] children) { 
+      this.id = id; this.children = children;
+    }
+
+    public override String ToString() { 
+      return id.ToString();
+    }
+
+    public Node<T> this[int i] {
+      set { children[i] = value; }
+      get { return children[i]; }
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/TreeTraversal.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/TreeTraversal.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/TreeTraversal.cs	(revision 3)
@@ -0,0 +1,107 @@
+// C5 example
+// 2004-11-09
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace TreeTraversal
+{
+  class MyTest
+  {
+    public static void Main(String[] args)
+    {
+      Tree<int> t = MakeTree(1, 15);
+      Act<int> act = delegate(int val) { Console.Write("{0} ", val); };
+      Console.WriteLine("Depth-first:");
+      Tree<int>.DepthFirst(t, act);
+      Console.WriteLine("\nBreadth-first:");
+      Tree<int>.BreadthFirst(t, act);
+      Console.WriteLine("\nDepth-first:");
+      Tree<int>.Traverse(t, act, new ArrayList<Tree<int>>());
+      Console.WriteLine("\nBreadth-first:");
+      Tree<int>.Traverse(t, act, new LinkedList<Tree<int>>());
+      Console.WriteLine();
+    }
+
+    // Build n-node tree with root numbered b and other nodes numbered b+1..b+n
+    public static Tree<int> MakeTree(int b, int n)
+    {
+      if (n == 0)
+        return null;
+      else
+      {
+        int k = n / 2;
+        Tree<int> t1 = MakeTree(b + 1, k), t2 = MakeTree(b + k + 1, n - 1 - k);
+        return new Tree<int>(b, t1, t2);
+      }
+    }
+  }
+
+  class Tree<T>
+  {
+    private T val;
+    private Tree<T> t1, t2;
+    public Tree(T val) : this(val, null, null) { }
+    public Tree(T val, Tree<T> t1, Tree<T> t2)
+    {
+      this.val = val; this.t1 = t1; this.t2 = t2;
+    }
+
+    public static void DepthFirst(Tree<T> t, Act<T> act)
+    {
+      IStack<Tree<T>> work = new ArrayList<Tree<T>>();
+      work.Push(t);
+      while (!work.IsEmpty)
+      {
+        Tree<T> cur = work.Pop();
+        if (cur != null)
+        {
+          work.Push(cur.t2);
+          work.Push(cur.t1);
+          act(cur.val);
+        }
+      }
+    }
+
+    public static void BreadthFirst(Tree<T> t, Act<T> act)
+    {
+      IQueue<Tree<T>> work = new CircularQueue<Tree<T>>();
+      work.Enqueue(t);
+      while (!work.IsEmpty)
+      {
+        Tree<T> cur = work.Dequeue();
+        if (cur != null)
+        {
+          work.Enqueue(cur.t1);
+          work.Enqueue(cur.t2);
+          act(cur.val);
+        }
+      }
+    }
+
+    public static void Traverse(Tree<T> t, Act<T> act, IList<Tree<T>> work)
+    {
+      work.Clear();
+      work.Add(t);
+      while (!work.IsEmpty)
+      {
+        Tree<T> cur = work.Remove();
+        if (cur != null)
+        {
+          if (work.FIFO)
+          {
+            work.Add(cur.t1);
+            work.Add(cur.t2);
+          }
+          else
+          {
+            work.Add(cur.t2);
+            work.Add(cur.t1);
+          }
+          act(cur.val);
+        }
+      }
+    }
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Try.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Try.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Try.cs	(revision 3)
@@ -0,0 +1,79 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: various tests 2005 and later
+
+// Compile with 
+//   csc /r:C5.dll Try.cs 
+
+using System;
+using System.Text;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace Try
+{
+  class MyTest
+  {
+    public static void Main(String[] args)
+    {
+      SCG.IEqualityComparer<int> natural = EquatableEqualityComparer<int>.Default;
+      SCG.IEqualityComparer<int> c5comp = EqualityComparer<int>.Default;
+      int count = int.Parse(args[0]);
+      {
+        bool res = false;
+        Timer t = new Timer();
+        for (int i = count; i > 0; i--)
+        {
+          res = natural.Equals(4, 5);
+        }
+        Console.WriteLine("Time = {0} ns/comparison\n", t.Check() * 1E9 / count);
+      }
+      {
+        bool res = false;
+        Timer t = new Timer();
+        for (int i = count; i > 0; i--)
+        {
+          res = c5comp.Equals(4, 5);
+        }
+        Console.WriteLine("Time = {0} ns/comparison\n", t.Check() * 1E9 / count);
+      }
+    }
+  }
+
+  // Crude timing utility ----------------------------------------
+
+  public class Timer
+  {
+    private DateTime start;
+
+    public Timer()
+    {
+      start = DateTime.Now;
+    }
+
+    public double Check()
+    {
+      TimeSpan dur = DateTime.Now - start;
+      return dur.TotalSeconds;
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/UnionFind.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/UnionFind.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/UnionFind.cs	(revision 3)
@@ -0,0 +1,145 @@
+/*
+ Copyright (c) 2003-2008 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: union find structure 2007-11-23
+
+// Compile with 
+//   csc /r:C5.dll UnionFind.cs 
+
+/*
+
+The union-find algorithm (Tarjan 1983) is a fast way to build and
+maintain a partition of a set into disjoint subsets.  It supports the
+following operations on a collection of objects:
+
+ * Create a new one-element subset consisting of a single object.
+
+ * Union (join) two subsets into one.
+
+ * Find the canonical representative of the subset containing a given
+   object.
+
+Idea: A subset of values of type T, disjoint from other such subsets ,
+is represented by an object Subset<T>.  A HashDictionary<T, Subset<T>>
+maps each value to its subset.  
+
+ */
+
+
+using System;
+using System.Text;			// Encoding
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace UnionFind {
+  class MyTest {
+    public static void Main(String[] args) {
+      Eqclass<int> x = Eqclass<int>.Make(3), 
+	y = Eqclass<int>.Make(4), 
+	z = Eqclass<int>.Make(5);
+      x.Union(y);
+      y.Union(z);
+      Console.WriteLine(x.Find().Item);
+      Console.WriteLine(y.Find().Item);
+      Console.WriteLine(z.Find().Item);
+    }
+  }
+
+
+  // Problem: The link and rank fields are never used at the same
+  // time.  Hence it is tempting to make Eqclass<T> abstract and then
+  // have two subclasses, one being canonical and containing only a
+  // rank, the other being a non-canonical and containing only a link.
+  // However, every subset is born as a Canonical and then may turns
+  // into a NonCanonical because of Union operations, and this switch
+  // of class while retaining object identity is not possible (Find
+  // operations just update the link field; the object remains
+  // NonCanonical).  
+
+  // The right thing is to leave Eqclass<T> alone and introduce another
+  // class hierarchy Node, Canonical : Node, NonCanonical : Node, and
+  // let Eqclass<T> have a field of type Node that can be updated from
+  // Canonical to NonCanonical.  But this wastes the space that would
+  // be saved by the subclassing idea.
+
+  // Note: Also, this would inadvertently allow two Eqclass<T> objects
+  // to share a common Node.  Java and C# confuse things by tying
+  // variants (subclasses) together with references (classes).  Since
+  // the languages admit (side) effects, sharing is observable and
+  // sharability should be decoupled from specialization.
+
+  public class Eqclass<T> {
+    private static HashDictionary<T,Eqclass<T>> dict 
+      = new HashDictionary<T,Eqclass<T>>();
+    private readonly T item;
+    private Eqclass<T> link = null;
+    private int rank = 0;
+
+    private Eqclass(T item) {
+      this.item = item;
+    }
+
+    public static Eqclass<T> Make(T item) {
+      Eqclass<T> result;
+      if (!dict.Find(item, out result)) 
+	dict[item] = result = new Eqclass<T>(item);
+      return result;
+    }
+
+    public void Union(Eqclass<T> that) {
+      Eqclass<T> thatRep = that.Find(), thisRep = this.Find();
+      if (thatRep != thisRep) {
+	if (thatRep.rank == thisRep.rank) {
+	  thisRep.link = thatRep;
+	  thatRep.rank++;
+	} else if (thatRep.rank > thisRep.rank)
+	  thisRep.link = thatRep;
+	else
+	  thatRep.link = thisRep;
+      }
+    }
+
+    // Find, with path halving: avoids recursion
+
+    public Eqclass<T> Find() {
+      if (link == null) 
+	return this;
+      else if (link.link == null) 
+	return link;
+      else {
+	// Grandparent, parent, and link
+	Eqclass<T> pp = this, p = link, plink = p.link;
+	while (plink != null) {
+	  // Invariant: pp -> p -> plink
+	  pp.link = plink;
+	  pp = p;
+	  p = plink;
+	  plink = p.link;
+	}
+	return p;
+      }
+    }
+
+    public T Item { 
+      get { return item; } 
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/UserGuideExamples.csproj
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/UserGuideExamples.csproj	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/UserGuideExamples.csproj	(revision 3)
@@ -0,0 +1,110 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <RootNamespace>UserGuideExamples</RootNamespace>
+    <AssemblyName>UserGuideExamples</AssemblyName>
+    <WarningLevel>4</WarningLevel>
+    <StartupObject>
+    </StartupObject>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <UpgradeBackupLocation>
+    </UpgradeBackupLocation>
+    <OldToolsVersion>2.0</OldToolsVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>.\bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugSymbols>false</DebugSymbols>
+    <Optimize>true</Optimize>
+    <OutputPath>.\bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugSnk|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\DebugSnk\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <DebugType>full</DebugType>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseSnk|AnyCPU' ">
+    <OutputPath>bin\ReleaseSnk\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+  </PropertyGroup>
+  <ItemGroup>
+    <Compile Include="AnagramHashBag.cs" />
+    <Compile Include="Anagrams.cs" />
+    <Compile Include="AnagramStrings.cs" />
+    <Compile Include="AnagramTreeBag.cs" />
+    <None Include="Antipatterns.cs" />
+    <Compile Include="BipartiteMatching.cs" />
+    <Compile Include="Cloning.cs" />
+    <Compile Include="CollectionCollection.cs" />
+    <Compile Include="CollectionSanity.cs" />
+    <Compile Include="EventPatterns.cs" />
+    <Compile Include="GettingStarted.cs" />
+    <Compile Include="Graph.cs" />
+    <Compile Include="Fileindex.cs" />
+    <Compile Include="GCHForm.cs">
+      <SubType>Form</SubType>
+    </Compile>
+    <Compile Include="GConvexHull.cs" />
+    <Compile Include="GNfaToDfa.cs" />
+    <Compile Include="HashCodes.cs" />
+    <Compile Include="Jobqueue.cs" />
+    <Compile Include="KeywordRecognition.cs" />
+    <Compile Include="ListPatterns.cs" />
+    <Compile Include="Locking.cs" />
+    <Compile Include="MultiCollection.cs" />
+    <Compile Include="MultiDictionary.cs" />
+    <Compile Include="PointLocation.cs" />
+    <Compile Include="RandomSelection.cs" />
+    <Compile Include="ReadOnlyPatterns.cs" />
+    <Compile Include="Sets.cs" />
+    <Compile Include="SortedIterationPatterns.cs" />
+    <Compile Include="SortingPermutation.cs" />
+    <Compile Include="TestSortedArray.cs" />
+    <Compile Include="ThisFun.cs" />
+    <Compile Include="Toposort.cs" />
+    <Compile Include="TreeTraversal.cs" />
+    <Compile Include="Try.cs" />
+    <Compile Include="ViewPatterns.cs" />
+    <Compile Include="Views.cs" />
+    <Compile Include="WrappedArray.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <EmbeddedResource Include="GCHForm.resx">
+      <DependentUpon>GCHForm.cs</DependentUpon>
+      <SubType>Designer</SubType>
+    </EmbeddedResource>
+  </ItemGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\C5\C5.csproj">
+      <Project>{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}</Project>
+      <Package>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Package>
+      <Name>C5</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="Makefile" />
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Windows.Forms" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
+</Project>
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/ViewPatterns.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/ViewPatterns.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/ViewPatterns.cs	(revision 3)
@@ -0,0 +1,340 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: ViewPatterns 2005-07-22
+
+// Compile with 
+//   csc /r:C5.dll ViewPatterns.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace ViewPatterns {
+  class Views {
+    public static void Main(String[] args) {
+      IList<char> lst = new ArrayList<char>();
+      lst.AddAll<char>(new char[] { 'a', 'b', 'c', 'd' });
+      IList<char> v1 = lst.View(1, 1);
+      Console.WriteLine("v1 = {0}", v1);
+      InsertBeforeFirst(v1, '<', 'b');
+      InsertAfterFirst(v1, '>', 'b');
+      Console.WriteLine("v1 = {0}", v1);
+      char x; 
+      if (SequencePredecessor(v1, 'b', out x)) 
+        Console.WriteLine("Predecessor of b is " + x);
+      if (SequenceSuccessor(v1, 'b', out x)) 
+        Console.WriteLine("Successor of b is " + x);
+      if (!SequencePredecessor(v1, 'c', out x)) 
+        Console.WriteLine("c has no predecessor");
+      if (!SequenceSuccessor(v1, 'a', out x)) 
+        Console.WriteLine("a has no successor");
+      IList<char> lst2 = new ArrayList<char>();
+      lst2.AddAll<char>(new char[] { 'a', 'b', 'c', 'A', 'a', 'd', 'a' });
+      foreach (int i in IndexesOf(lst2, 'a')) 
+        Console.Write("{0} ", i);
+      Console.WriteLine();
+      foreach (int i in ReverseIndexesOf(lst2, 'a')) 
+        Console.Write("{0} ", i);
+      Console.WriteLine();
+      Console.WriteLine(lst2);
+      IList<char> view = lst2.View(2,0);
+      InsertAtView(lst2, view, 'y');
+      Console.WriteLine(lst2);
+      InsertIntoView(view, 'x');
+      Console.WriteLine(lst2);
+    }
+
+    // --- Patterns for zero-item views -----------------------------
+
+    // Number of items before zero-item view
+   
+    public static int ItemsBefore<T>(IList<T> view) {
+      return view.Offset;
+    }
+
+    // Number of items after zero-item view
+   
+    public static int ItemsAfter<T>(IList<T> view) {
+      return view.Underlying.Count - view.Offset;
+    }
+
+    // Move (zero-item) view one item to the left
+   
+    public static void MoveLeft<T>(IList<T> view) {
+      // One of these:
+      view.Slide(-1);
+      view.TrySlide(-1);
+    }
+
+    // Move (zero-item) view one item to the right
+   
+    public static void MoveRight<T>(IList<T> view) {
+      // One of these:
+      view.Slide(+1);
+      view.TrySlide(+1);
+    }
+
+    // Test whether (zero-item) view is at beginning of list
+   
+    public static bool AtBeginning<T>(IList<T> view) {
+      return view.Offset == 0;
+    }
+
+    // Test whether (zero-item) view is at end of list
+   
+    public static bool AtEnd<T>(IList<T> view) {
+      return view.Offset == view.Underlying.Count;
+    }
+
+    // Insert x into zero-item view and into underlying list
+   
+    public static void InsertIntoView<T>(IList<T> view, T x) {
+      view.Add(x);
+    }
+
+    // Insert x into list at zero-item view 
+   
+    public static void InsertAtView<T>(IList<T> list, IList<T> view, T x) {
+      list.Insert(view, x);
+    }
+
+    // Delete the item before zero-item view 
+   
+    public static void DeleteBefore<T>(IList<T> view) {
+      view.Slide(-1,1).RemoveFirst();
+    }
+
+    // Delete the item after zero-item view 
+   
+    public static void DeleteAfter<T>(IList<T> view) {
+      view.Slide(0,1).RemoveFirst();
+    }
+
+    // Get the zero-item view at left endpoint.  Succeeds on all lists
+    // and valid views.
+
+    public static IList<T> LeftEndView<T>(IList<T> list) {
+      return list.View(0,0);
+    }
+
+    // Get the zero-item view at right endpoint.  Succeeds on all
+    // lists and valid views.
+
+    public static IList<T> RightEndView<T>(IList<T> list) {
+      return list.View(list.Count,0);
+    }
+
+
+    // --- Patterns for one-item views ------------------------------
+
+    // Find the sequence predecessor x of y; or throw exception
+
+    public static T SequencePredecessor<T>(IList<T> list, T y) {
+      return list.ViewOf(y).Slide(-1)[0];
+    }  
+    
+    // Find the sequence predecessor x of y; or return false 
+
+    public static bool SequencePredecessor<T>(IList<T> list, T y, out T x) {
+      IList<T> view = list.ViewOf(y);
+      bool ok = view != null && view.TrySlide(-1);
+      x = ok ? view[0] : default(T);
+      return ok;
+    }  
+
+    // Find the sequence successor x of y; or throw exception
+
+    public static T SequenceSuccessor<T>(IList<T> list, T y) {
+      return list.ViewOf(y).Slide(+1)[0];
+    }  
+
+    // Find the sequence successor x of y; or return false
+
+    public static bool SequenceSuccessor<T>(IList<T> list, T y, out T x) {
+      IList<T> view = list.ViewOf(y);
+      bool ok = view != null && view.TrySlide(+1);
+      x = ok ? view[0] : default(T);
+      return ok;
+    }  
+
+    // Insert x into list after first occurrence of y (or throw
+    // NullReferenceException).
+    
+    public static void InsertAfterFirst<T>(IList<T> list, T x, T y) {
+      list.Insert(list.ViewOf(y), x);
+    }
+
+    // Insert x into list before first occurrence of y (or throw
+    // NullReferenceException)
+    
+    public static void InsertBeforeFirst<T>(IList<T> list, T x, T y) {
+      list.Insert(list.ViewOf(y).Slide(0, 0), x);
+    }
+
+    // Insert x into list after last occurrence of y (or throw
+    // NullReferenceException).
+    
+    public static void InsertAfterLast<T>(IList<T> list, T x, T y) {
+      list.Insert(list.LastViewOf(y), x);
+    }
+
+    // Insert x into list before last occurrence of y (or throw
+    // NullReferenceException)
+    
+    public static void InsertBeforeLast<T>(IList<T> list, T x, T y) {
+      list.Insert(list.LastViewOf(y).Slide(0, 0), x);
+    }
+
+    // Same meaning as InsertBeforeFirst on a proper list, but not on
+    // a view
+
+    public static void InsertBeforeFirstAlt<T>(IList<T> list, T x, T y) {
+      list.ViewOf(y).InsertFirst(x);
+    }
+
+    // Delete the sequence predecessor of first y; or throw exception
+
+    public static T RemovePredecessorOfFirst<T>(IList<T> list, T y) {
+      return list.ViewOf(y).Slide(-1).Remove();
+    }
+
+    // Delete the sequence successor of first y; or throw exception
+
+    public static T RemoveSuccessorOfFirst<T>(IList<T> list, T y) {
+      return list.ViewOf(y).Slide(+1).Remove();
+    }
+
+    // --- Other view patterns --------------------------------------
+
+    // Replace the first occurrence of each x from xs by y in list:
+    
+    public static void ReplaceXsByY<T>(HashedLinkedList<T> list, T[] xs, T y) {
+      foreach (T x in xs) {
+        using (IList<T> view = list.ViewOf(x)) {
+          if (view != null) { 
+            view.Remove();
+            view.Add(y);
+          }
+        }
+      }
+    }
+
+    // Get index in underlying list of view's left end
+    
+    public static int LeftEndIndex<T>(IList<T> view) { 
+      return view.Offset;
+    }
+
+    // Get index in underlying list of view's right end
+
+    public static int RightEndIndex<T>(IList<T> view) { 
+      return view.Offset + view.Count;
+    }
+
+    // Test whether views overlap 
+
+    public static bool Overlap<T>(IList<T> u, IList<T> w) { 
+      if (u.Underlying == null || u.Underlying != w.Underlying) 
+        throw new ArgumentException("views must have same underlying list");
+      else
+        return u.Offset < w.Offset+w.Count && w.Offset < u.Offset+u.Count;
+    }
+
+    // Find the length of the overlap between two views
+
+    public static int OverlapLength<T>(IList<T> u, IList<T> w) { 
+      if (Overlap(u, w))
+        return Math.Min(u.Offset+u.Count, w.Offset+w.Count) 
+             - Math.Max(u.Offset, w.Offset);
+      else
+        return -1; // No overlap
+    }
+
+    // Test whether view u contains view v 
+
+    public static bool ContainsView<T>(IList<T> u, IList<T> w) { 
+      if (u.Underlying == null || u.Underlying != w.Underlying) 
+        throw new ArgumentException("views must have same underlying list");
+      else
+        if (w.Count > 0)
+          return u.Offset <= w.Offset && w.Offset+w.Count <= u.Offset+u.Count;
+        else
+          return u.Offset < w.Offset && w.Offset < u.Offset+u.Count;
+    }
+
+    // Test whether views u and v have (or are) the same underlying list
+
+    public static bool SameUnderlying<T>(IList<T> u, IList<T> w) { 
+      return (u.Underlying ?? u) == (w.Underlying ?? w);
+    }
+
+    // Find the index of the first item that satisfies p
+
+    public static int FindFirstIndex<T>(IList<T> list, Fun<T,bool> p) {
+      using (IList<T> view = list.View(0, 0)) {
+        while (view.TrySlide(0, 1)) {
+          if (p(view.First)) 
+            return view.Offset;
+          view.Slide(+1, 0);
+        }
+      }
+      return -1;
+    }
+
+    // Find the index of the last item that satisfies p
+    
+    public static int FindLastIndex<T>(IList<T> list, Fun<T,bool> p) {
+      using (IList<T> view = list.View(list.Count, 0)) {
+        while (view.TrySlide(-1, 1)) {
+          if (p(view.First)) 
+            return view.Offset;
+        }
+      }
+      return -1;
+    }
+
+    // Yield indexes of all items equal to x, in list order:
+
+    public static SCG.IEnumerable<int> IndexesOf<T>(IList<T> list, T x) { 
+      IList<T> tail = list.View(0, list.Count);
+      tail = tail.ViewOf(x);
+      while (tail != null) {
+        yield return tail.Offset;
+        tail = tail.Slide(+1,0).Span(list);
+        tail = tail.ViewOf(x); 
+      }
+    }
+
+    // Yield indexes of items equal to x, in reverse list order.
+
+    public static SCG.IEnumerable<int> ReverseIndexesOf<T>(IList<T> list, T x) {
+      IList<T> head = list.View(0, list.Count);
+      head = head.LastViewOf(x);
+      while (head != null) {
+        yield return head.Offset;
+        head = list.Span(head.Slide(0,0));
+        head = head.LastViewOf(x);
+      }
+    }
+
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Views.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Views.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/Views.cs	(revision 3)
@@ -0,0 +1,160 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: Views 2004-12-29 OBSOLETE
+
+// Compile with 
+//   csc /r:C5.dll Views.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace Views {
+  class Views {
+    public static void Main(String[] args) {
+      IList<char> lst = new LinkedList<char>();
+      lst.AddAll<char>(new char[] { 'a', 'b', 'c', 'd' });
+      IList<char> 
+        A = lst.View(0, 2),
+        B = lst.View(2, 0),
+        C = lst.View(2, 1),
+        D = lst.View(3, 1),
+        E = lst.View(4, 0),
+        F = lst.View(1, 2),
+        G = lst.View(0, 4);
+      IList<char>[] views = { A, B, C, D, E, F, G };
+      Console.WriteLine("ABCDEFG overlaps with:");
+      foreach (IList<char> u in views) {
+        foreach (IList<char> w in views) 
+          Console.Write(Overlap(u, w) ? '+' : '-');
+        Console.WriteLine();
+      }   
+      Console.WriteLine("ABCDEFG overlap length:");
+      foreach (IList<char> u in views) {
+        foreach (IList<char> w in views) {
+          int len = OverlapLength(u, w);
+          Console.Write(len >= 0 ? String.Format("{0}", len) : " ");
+        }
+        Console.WriteLine();
+      }   
+      Console.WriteLine("ABCDEFG contained in:");
+      foreach (IList<char> u in views) {
+        foreach (IList<char> w in views) 
+          Console.Write(ContainsView(u, w) ? '+' : '-');
+        Console.WriteLine();
+      }   
+    }
+    
+    public static int LeftEndIndex<T>(IList<T> u) { 
+      return u.Offset;
+    }
+
+    public static int RightEndIndex<T>(IList<T> u) { 
+      return u.Offset+u.Count;
+    }
+
+    public static bool Overlap<T>(IList<T> u, IList<T> w) { 
+      if (u.Underlying == null || u.Underlying != w.Underlying) 
+        throw new ArgumentException("views must have same underlying list");
+      else
+        return u.Offset < w.Offset+w.Count && w.Offset < u.Offset+u.Count;
+    }
+
+    public static int OverlapLength<T>(IList<T> u, IList<T> w) { 
+      if (Overlap(u, w))
+	return Math.Min(u.Offset+u.Count, w.Offset+w.Count) 
+	     - Math.Max(u.Offset, w.Offset);
+      else
+	return -1; // No overlap
+    }
+
+    public static bool ContainsView<T>(IList<T> u, IList<T> w) { 
+      if (u.Underlying == null || u.Underlying != w.Underlying) 
+        throw new ArgumentException("views must have same underlying list");
+      else
+        if (w.Count > 0)
+          return u.Offset <= w.Offset && w.Offset+w.Count <= u.Offset+u.Count;
+        else
+          return u.Offset < w.Offset && w.Offset < u.Offset+u.Count;
+    }
+
+    public static bool SameUnderlying<T>(IList<T> u, IList<T> w) { 
+      return (u.Underlying ?? u) == (w.Underlying ?? w);
+    }
+
+    // Replace the first occurrence of each x from xs by y in list:
+    
+    public static void ReplaceXsByY<T>(HashedLinkedList<T> list, T[] xs, T y) {
+      foreach (T x in xs) {
+        using (IList<T> view = list.ViewOf(x)) {
+          if (view != null) { 
+            view.Remove();
+            view.Add(y);
+          }
+        }
+      }
+    }
+
+    // Find first item that satisfies p
+
+    public static bool Find<T>(IList<T> list, Fun<T,bool> p, out T res) {
+      IList<T> view = list.View(0, 0);
+      while (view.Offset < list.Count) {
+        view.Slide(+1, 1);
+        if (p(view.First)) {
+          res = view.First;
+          return true;
+        }
+      }
+      res = default(T);
+      return false;
+    }
+
+    // Or, using that the list is enumerable:
+
+    public static bool Find1<T>(IList<T> list, Fun<T,bool> p, out T res) {
+      foreach (T x in list) { 
+        if (p(x)) {
+          res = x;
+          return true;
+        }
+      }
+      res = default(T);
+      return false;
+    }
+
+    // Find last item that satisfies p
+
+    public static bool FindLast<T>(IList<T> list, Fun<T,bool> p, out T res) {
+      IList<T> view = list.View(list.Count, 0);
+      while (view.Offset > 0) {
+        view.Slide(-1, 1);
+        if (p(view.First)) {
+          res = view.First;
+          return true;
+        }
+      }
+      res = default(T);
+      return false;
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/WrappedArray.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/WrappedArray.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/WrappedArray.cs	(revision 3)
@@ -0,0 +1,191 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// C5 example: WrappedArray 2005-07-21
+
+// Compile with 
+//   csc /r:C5.dll WrappedArray.cs 
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+namespace WrappedArray {
+  class WrappedArray {
+    public static void Main(String[] args) {
+    }
+
+
+    // System.Array.Exists
+
+    public static bool Exists<T>(T[] arr, Fun<T,bool> p) {
+      return new WrappedArray<T>(arr).Exists(p);
+    }  
+
+    // System.Array.TrueForAll
+
+    public static bool TrueForAll<T>(T[] arr, Fun<T,bool> p) {
+      return new WrappedArray<T>(arr).All(p);
+    }  
+
+    // System.Array.Find(T[], Predicate)
+    // This loses the valuable bool returned by C5 Find.
+
+    public static T Find<T>(T[] arr, Fun<T,bool> p) {
+      T res; 
+      new WrappedArray<T>(arr).Find(p, out res);
+      return res;
+    }  
+
+    // System.Array.FindAll(T[], Predicate)
+
+    public static T[] FindAll<T>(T[] arr, Fun<T,bool> p) {
+      return new WrappedArray<T>(arr).FindAll(p).ToArray();
+    }  
+
+    // System.Array.FindIndex(T[], Predicate)
+
+    public static int FindIndex<T>(T[] arr, Fun<T,bool> p) {
+      return new WrappedArray<T>(arr).FindIndex(p);
+    }  
+
+    // System.Array.FindIndex(T[], int, Predicate)
+
+    public static int FindIndex<T>(T[] arr, int i, Fun<T,bool> p) {
+      int j = new WrappedArray<T>(arr).View(i,arr.Length-i).FindIndex(p);
+      return j < 0 ? j : j+i;
+    }  
+
+    // System.Array.FindIndex(T[], int, int, Predicate)
+
+    public static int FindIndex<T>(T[] arr, int i, int n, Fun<T,bool> p) {
+      int j = new WrappedArray<T>(arr).View(i,n).FindIndex(p);
+      return j < 0 ? j : j+i;
+    }  
+
+    // System.Array.FindLast(T[], Predicate)
+    // This loses the valuable bool returned by C5 Find.
+
+    public static T FindLast<T>(T[] arr, Fun<T,bool> p) {
+      T res; 
+      new WrappedArray<T>(arr).FindLast(p, out res);
+      return res;
+    }  
+
+    // System.Array.FindLastIndex(T[], Predicate)
+
+    public static int FindLastIndex<T>(T[] arr, Fun<T,bool> p) {
+      return new WrappedArray<T>(arr).FindIndex(p);
+    }  
+
+    // System.Array.FindLastIndex(T[], int, Predicate)
+
+    public static int FindLastIndex<T>(T[] arr, int i, Fun<T,bool> p) {
+      int j = new WrappedArray<T>(arr).View(i,arr.Length-i).FindIndex(p);
+      return j < 0 ? j : j+i;
+    }  
+
+    // System.Array.FindLastIndex(T[], int, int, Predicate)
+
+    public static int FindLastIndex<T>(T[] arr, int i, int n, Fun<T,bool> p) {
+      int j = new WrappedArray<T>(arr).View(i,n).FindIndex(p);
+      return j < 0 ? j : j+i;
+    }  
+    
+    // System.Array.ForEach(T[], Action)
+
+    public static void ForEach<T>(T[] arr, Act<T> act) {
+      new WrappedArray<T>(arr).Apply(act);
+    }  
+
+    // System.Array.IndexOf(T[], T)
+
+    public static int IndexOf<T>(T[] arr, T x) {
+      int j = new WrappedArray<T>(arr).IndexOf(x);
+      return j < 0 ? -1 : j;
+    }  
+    
+    // System.Array.IndexOf(T[], T, int)
+
+    public static int IndexOf<T>(T[] arr, T x, int i) {
+      int j = new WrappedArray<T>(arr).View(i, arr.Length-i).IndexOf(x);
+      return j < 0 ? -1 : j+i;
+    }  
+    
+    // System.Array.IndexOf(T[], T, int, int)
+
+    public static int IndexOf<T>(T[] arr, T x, int i, int n) {
+      int j = new WrappedArray<T>(arr).View(i, n).IndexOf(x);
+      return j < 0 ? -1 : j+i;
+    }  
+
+    // System.Array.LastIndexOf(T[], T)
+
+    public static int LastIndexOf<T>(T[] arr, T x) {
+      int j = new WrappedArray<T>(arr).LastIndexOf(x);
+      return j < 0 ? -1 : j;
+    }  
+    
+    // System.Array.LastIndexOf(T[], T, int)
+
+    public static int LastIndexOf<T>(T[] arr, T x, int i) {
+      int j = new WrappedArray<T>(arr).View(i, arr.Length-i).LastIndexOf(x);
+      return j < 0 ? -1 : j+i;
+    }  
+    
+    // System.Array.LastIndexOf(T[], T, int, int)
+
+    public static int LastIndexOf<T>(T[] arr, T x, int i, int n) {
+      int j = new WrappedArray<T>(arr).View(i, n).LastIndexOf(x);
+      return j < 0 ? -1 : j+i;
+    }  
+
+    // System.Array.Sort(T[])
+
+    public static void Sort<T>(T[] arr) {
+      new WrappedArray<T>(arr).Sort();
+    }  
+
+    // System.Array.Sort(T[], int, int)
+
+    public static void Sort<T>(T[] arr, int i, int n) {
+      new WrappedArray<T>(arr).View(i, n).Sort();
+    }  
+
+    // System.Array.Sort(T[], SCG.IComparer<T>)
+
+    public static void Sort<T>(T[] arr, SCG.IComparer<T> cmp) {
+      new WrappedArray<T>(arr).Sort(cmp);
+    }  
+    
+    // System.Array.Sort(T[], int, int, SCG.IComparer<T>)
+
+    public static void Sort<T>(T[] arr, int i, int n, SCG.IComparer<T> cmp) {
+      new WrappedArray<T>(arr).View(i, n).Sort(cmp);
+    }  
+    
+    // System.Array.Sort(T[], Comparison)
+
+    public static void Sort<T>(T[] arr, Comparison<T> csn) {
+      new WrappedArray<T>(arr).Sort(new DelegateComparer<T>(csn));
+    }  
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/boilerplate.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/boilerplate.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/UserGuideExamples/boilerplate.cs	(revision 3)
@@ -0,0 +1,12 @@
+// C5 example
+// 2004-08
+
+using System;
+using C5;
+using SCG = System.Collections.Generic;
+
+class MyTest {
+  public static void Main(String[] args) {
+
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/c5doc/banner.htm
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/c5doc/banner.htm	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/c5doc/banner.htm	(revision 3)
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html >
+<head>
+    <link rel="stylesheet" type="text/css" href="docnet.css">
+</head>
+<body>
+    <p>
+        <font size="6"><b>C5 documentation</b></font> Legend: <code class="greenbg">A</code>:
+        abstract, <code class="greenbg">F</code>: final, <code class="greenbg">N</code>:
+        non-virtual, <code class="greenbg">P</code>: protected, <code class="greenbg">S</code>:
+        static. </p>
+</body>
+</html>
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/c5doc/docnet.css
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/c5doc/docnet.css	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/c5doc/docnet.css	(revision 3)
@@ -0,0 +1,131 @@
+BODY
+{
+    FONT-FAMILY: "Verdana", sans-serif;
+    FONT-SIZE: x-small;
+}
+CODE 
+{
+    FONT-SIZE: x-small;
+}
+A:link
+{
+    COLOR: #4e4887
+}
+A:visited
+{
+    COLOR: #8080c8
+}
+A:active
+{
+    COLOR: #f16043
+}
+A:hover
+{
+    COLOR: #f16043
+}
+P
+{
+    MARGIN-BOTTOM: 0.5em;
+    MARGIN-TOP: 0.5em
+}
+.greenbg
+{
+    BACKGROUND-COLOR: #00ff00;
+    font-weight:bold
+}
+TABLE
+{
+    BORDER-BOTTOM: medium none;
+    BORDER-LEFT: medium none;
+    BORDER-RIGHT: medium none;
+    BORDER-TOP: medium none;
+}
+TD
+{
+    BACKGROUND-COLOR: #bedfff;
+    BORDER-BOTTOM: medium none;
+    BORDER-LEFT: medium none;
+    BORDER-RIGHT: medium none;
+    BORDER-TOP: medium none;
+    FONT-SIZE:x-small;
+    MARGIN: 2px;
+    PADDING-BOTTOM: 2px;
+    PADDING-LEFT: 2px;
+    PADDING-RIGHT: 2px;
+    PADDING-TOP: 2px;
+    TEXT-ALIGN: left
+}
+TH
+{
+    BACKGROUND-COLOR: #ffdfbe;
+    BORDER-BOTTOM: medium none;
+    BORDER-LEFT: medium none;
+    BORDER-RIGHT: medium none;
+    BORDER-TOP: medium none;
+    FONT-SIZE: x-small;
+    MARGIN: 2px;
+    PADDING-BOTTOM: 2px;
+    PADDING-LEFT: 2px;
+    PADDING-RIGHT: 2px;
+    PADDING-TOP: 2px;
+    TEXT-ALIGN: left
+}
+TH
+{
+    BACKGROUND-COLOR: #ffaa57
+}
+UL
+{
+    MARGIN-TOP: 0.5em
+}
+OL
+{
+    MARGIN-TOP: 0.5em
+}
+H1
+{
+    COLOR: #336699;
+    FONT-SIZE: x-large;
+    MARGIN-BOTTOM: 0.5em;
+    MARGIN-TOP: 1em;
+    PADDING-LEFT: 4px
+}
+H2
+{
+    BORDER-LEFT: #4e4887 8px solid;
+    BORDER-TOP: #4e4887 1px solid;
+    COLOR: #4e4887;
+    FONT-SIZE: medium;
+    MARGIN-BOTTOM: 0.5em;
+    MARGIN-TOP: 1em;
+    PADDING-LEFT: 4px
+}
+H3
+{
+    BORDER-LEFT: #4e4887 4px solid;
+    BORDER-TOP: #4e4887 1px solid;
+    COLOR: #4e4887;
+    FONT-SIZE: small;
+    MARGIN-BOTTOM: 0.5em;
+    MARGIN-TOP: 1em;
+    PADDING-LEFT: 4px
+}
+H4
+{
+    COLOR: #4e4887;
+    FONT-SIZE: small;
+    MARGIN-BOTTOM: 0.5em
+}
+H5
+{
+    COLOR: #4e4887;
+    FONT-SIZE: x-small;
+    MARGIN-BOTTOM: 0.5em
+}
+H6
+{
+    COLOR: #4e4887;
+    FONT-SIZE: x-small;
+    FONT-STYLE: italic;
+    MARGIN-BOTTOM: 0.5em
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/c5doc/frames.htm
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/c5doc/frames.htm	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/c5doc/frames.htm	(revision 3)
@@ -0,0 +1,12 @@
+<html>
+<frameset rows="84,*">
+	<frame name="banner" scrolling="no" noresize src="banner.htm">
+	<frameset cols="200,*">
+		<frame name="contents" src="contents.htm">
+		<frame name="main" >
+	</frameset>
+	<noframes>
+		<p>This page requires frames, but your browser does not support them.</p>
+	</noframes>
+</frameset>
+</html>
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/c5doc/litterature.htm
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/c5doc/litterature.htm	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/c5doc/litterature.htm	(revision 3)
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+<title>C5 collection classes - litterature references</title>
+<meta name="GENERATOR" content="Microsoft Visual Studio.NET 7.0">
+<meta name=ProgId content=VisualStudio.HTML>
+<meta name=Originator content="Microsoft Visual Studio.NET 7.0">
+</head>
+<body>
+<h1>C5 collection classes - litterature references</h1>
+<table border="1" cellspacing="0">
+    <tr>
+        <td>
+            <a name="CLRS">CLRS</a></td>
+        <td>Cormen, Leiserson, Rivest, Shamir: ...</td>
+    </tr>
+    <tr>
+        <td>
+            <a name="DSST">DSST</a></td>
+        <td>D, Sarnak, Sleator, Tarjan, ...</td>
+    </tr>
+    <tr>
+        <td>
+            <a name="Tarjan1">Tarjan1</a>Tarjan: (the booklet)</td>
+        <td></td>
+    </tr>
+    <tr>
+        <td>
+            <a name=""></a></td>
+        <td></td>
+    </tr>
+    <tr>
+        <td>
+            <a name=""></a></td>
+        <td></td>
+    </tr>
+    <tr>
+        <td>
+            <a name=""></a></td>
+        <td></td>
+    </tr>
+    <tr>
+        <td>
+            <a name=""></a></td>
+        <td></td>
+    </tr>
+    <tr>
+        <td>
+            <a name=""></a></td>
+        <td></td>
+    </tr>
+    <tr>
+        <td>
+            <a name=""></a></td>
+        <td></td>
+    </tr>
+</table>
+
+
+</body>
+</html>
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/c5doc/userguide.htm
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/c5doc/userguide.htm	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/c5doc/userguide.htm	(revision 3)
@@ -0,0 +1,2519 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+  <title>C5 User's Guide</title>
+  <style>
+<!--
+.revvid      { color: #FFFFFF; background-color: #00AA00; font-weight: bold }
+-->
+  </style>
+</head>
+<body>
+<h1><a class="mozTocH1" name="mozTocId905770"></a>C5 User's guide for
+prerelease version 0.5</h1>
+<h2><a class="mozTocH2" name="mozTocId507311"></a>Table of contents</h2>
+<ul class="readonly" id="mozToc">
+<!--mozToc h1 1 h2 2 h3 3 h4 4 h5 5 h6 6--><li><a href="#mozTocId905770">C5
+User's guide for prerelease version 0.5</a>
+    <ul>
+      <li><a href="#mozTocId507311">Table of contents</a></li>
+    </ul>
+  </li>
+  <li><a href="#mozTocId564527">Overview</a></li>
+  <li><a href="#mozTocId86956">Interfaces</a>
+    <ul>
+      <li><a href="#mozTocId21725">"Proper" collection interfaces</a></li>
+      <li><a href="#mozTocId721827">Dictionary interfaces</a></li>
+      <li><a href="#mozTocId908053">Query result interfaces</a></li>
+    </ul>
+  </li>
+  <li><a href="#mozTocId110895">To construct a collection</a>
+    <ul>
+      <li><a href="#mozTocId850165">To use an external equalityComparer</a></li>
+      <li><a href="#mozTocId162938">To use an external comparer</a></li>
+      <li><a href="#mozTocId957374">To make collections of collections</a></li>
+    </ul>
+  </li>
+  <li><a href="#mozTocId486186">Special topics</a>
+    <ul>
+      <li><a href="#mozTocId48263">To choose a set or bag collection</a></li>
+      <li><a href="#mozTocId929755">To work on part of a list: list
+views</a></li>
+      <li><a href="#mozTocId650306">To work with persistent red-black
+trees</a></li>
+      <li><a href="#mozTocId553609">To implement new collection classes
+or subclass an existing one</a></li>
+      <li><a href="#mozTocId753674">To present a read only view of a
+collection</a></li>
+    </ul>
+  </li>
+  <li><a href="#mozTocId6619">Collection classes by data structure/class</a></li>
+  <li><a href="#mozTocId393559">Planned architecture or interface
+changes for first release</a></li>
+  <li><a href="#mozTocId336849">Performance details for proper
+collection classes</a></li>
+  <li><a href="#mozTocId712409">Performance details for dictionary
+classes</a></li>
+</ul>
+<h1><a class="mozTocH1" name="mozTocId564527"></a>Overview<br>
+</h1>
+<p>C5 is a comprehensive library of collection classes for the <a
+ href="http://www.ecma-international.org/publications/standards/Ecma-335.htm">Common
+Language Infrastructure</a> (CLI). This guide describes prerelease
+version 0.5 of&nbsp; C5. <br>
+</p>
+<p>C5 is a
+refactoring and extension of the <a
+ href="http://www.dina.kvl.dk/%7Esestoft/gcsharp/index.html#collection">generic
+collection classes</a> developed by Peter Sestoft while visiting
+Microsoft
+Research in Cambridge.</p>
+<p> Unless stated otherwise types mentioned below will belong to the
+"C5"
+namespace; and all code examples assume a "using C5;" clause (and no
+"using System.Collection.Generics;" clause)..&nbsp;</p>
+<p>The goals in the development of the library has been</p>
+<ul>
+  <li>
+    <p class="MsoNormal"><span style="" lang="EN-US">To create a
+library of collection classes for the CLI that can assist expert and
+non-expert programmers on the platform to develop correct and efficient
+applications.</span> </p>
+  </li>
+  <li>
+    <p class="MsoNormal"><span style="" lang="EN-US">The library should
+at least fill the gaps in the standard &#8220;System.Collections.Generics&#8221;
+namespace compared to standard collection class libraries for related
+object oriented languages like Java, and utilize the new facilities for
+generic </span><span style="" lang="EN-US">programming. Microsoft
+recently (mid 2004) seems to have changed their minds and ntend to
+bridge that gap in the beta2 version of VS 2005 due at the end of 2004.</span>
+    </p>
+  </li>
+</ul>
+<p>In order to fulfill the efficiency goal, the library utilizes
+first-class <a href="#datastructures">data structures</a>
+inside its collection classes. The library has been constructed with
+the modern
+object oriented programming principle of&nbsp; "<a href="#Interfaces">code
+to interfaces, not to implementations</a>" in mind, while the interface
+architecture has been carefully crafted to reflect the efficient data
+structures
+actually existence.</p>
+<p>A collection in the sense of this library is a plain "collection of
+items of a single type". A collection does not impose any other logical
+structure on its items than perhaps uniqueness or sequence ordering.</p>
+<p>The main division line among the collection classes of this library
+is the
+distinction between <a href="#Proper%20collection%20interfaces">"proper"
+collections</a> and <a href="#Dictionary%20interfaces">dictionaries</a>.
+A
+dictionary is a class that defines a partial function (or map) from one
+item
+type (the keys) to another one (the values). A dictionary can be viewed
+as a
+collection of (key,value) pairs having the property of defining a
+partial
+function.</p>
+<p>The item type for the collection classes are always given by generic
+parameters. For a proper collection, there will be a single parameter,
+customarily called T, as in HashSet&lt;T&gt;. For a dictionary there
+will be two - the key and value types -
+as in HashDictionary&lt;K,V&gt;.</p>
+<p>A collection class, or rather the data structure inside, can be
+either
+equality based or comparison based. An equality based collection will
+have an
+associated so-called equalityComparer of type <a href="main.htm#T:C5.IEqualityComparer%601">IEqualityComparer&lt;T&gt;</a>,
+where T is the item type of the collection. A comparison based
+collection has an
+associated comparer of type <a href="main.htm#T:C5.IComparer%601">IComparer&lt;T&gt;</a>.
+The section below on <a href="#Constructing">creation</a> of
+collection classes
+explains how the equalityComparers and comparers are chosen. NB: this design will
+be modified soon, cf. <a href="#planned">Planned changes</a>.<br>
+</p>
+<p>Collection classes in the library have either set or bag semantics.
+A set
+collection can at most contain one copy of an item, while bag
+collections may
+contain several. One can programmatically see at runtime if an editable
+collection class has set or bag semantics by checking the <a
+ href="main.htm#P:C5.IExtensible%601.AllowsDuplicates">
+AllowsDuplicates</a>
+property. At compile time, refer to the <a href="#set%20or%20bag">set
+or bag table</a>
+below for an overview. <br>
+</p>
+<h1><a class="mozTocH1" name="mozTocId86956"></a><a name="Interfaces">Interfaces</a></h1>
+<p>The C5 library is designed to make it easy to program to interfaces
+instead
+of implementations. In particular, all public properties and methods of
+the
+collection classes belong to their implemented interfaces (except for
+the odd
+special diagnostic method and the odd mistake to be weeded out before
+release). The typical programming style
+would be</p>
+<blockquote>
+  <p><code>IList&lt;int&gt; lst = new LinkedList&lt;int&gt;();<br>
+lst.Add(7);</code></p>
+</blockquote>
+<p>instead of&nbsp;</p>
+<blockquote>
+  <p><code> LinkedList&lt;int&gt; lst = new LinkedList&lt;int&gt;();<br>
+lst.Add(7);</code></p>
+</blockquote>
+<p>Note that with this programming style, the Add call will be compiled
+to an
+interface call instead of a (virtual) method call, but interface calls
+on the
+CLR (at least the Microsoft implementation) are at most very slightly
+slower
+than virtual calls, so one should not shun the interface style for
+performance
+reasons.</p>
+<p>We will discuss the collection classes available in C5 structured
+according
+to the main functional interfaces of the <a
+ href="#Proper%20collection%20interfaces">proper
+collections</a>, the <a href="#Dictionary%20interfaces">dictionaries</a>
+and the
+interfaces of <a href="#Query%20result%20interfaces">query results</a>.</p>
+<h2><a class="mozTocH2" name="mozTocId21725"></a><a
+ name="Proper collection interfaces">"Proper" collection interfaces</a></h2>
+<p>The following diagam shows the type hierarchy of the proper
+collection classes:</p>
+<p><img alt="Interface hierarchy" src="ClsdiagWork.png"
+ style="width: 757px; height: 498px;"><br>
+The&nbsp;most important interfaces - those that are directly
+implemented by
+collection classes - are listed to the left in this table with a short
+description in the middle and all implementing classes to the
+right.&nbsp;</p>
+<p>Please see also the <a href="#PerformanceProper">complete
+complexity table</a>
+for more comprehensive guidance.</p>
+<p>To identify which classes are equalityComparer or comparer based and which
+classes
+implement set or bag we use the following symbols:</p>
+<table border="1" width="471">
+  <tbody>
+    <tr>
+      <td width="116">set: <code class="revvid">S</code> </td>
+      <td width="117"> bag: <code class="revvid">B</code> </td>
+      <td width="117"> equalityComparer: <code class="revvid">H</code> </td>
+      <td width="117"> comparer: <code class="revvid">C</code> </td>
+    </tr>
+  </tbody>
+</table>
+<table border="1" width="100%">
+  <tbody>
+    <tr>
+      <th width="19%">Interface</th>
+      <th width="52%">Short description</th>
+      <th width="29%">Implementing classes</th>
+    </tr>
+    <tr>
+      <td valign="top" width="19%"><a
+ href="main.htm#T:C5.ICollection%601">ICollection&lt;T&gt;</a>&nbsp;</td>
+      <td valign="top" width="52%">This is the fundamental&nbsp;type
+of&nbsp; updateable collections. It has operations for searching for
+items, for adding, updating and removing one or a bunch of items, for
+clearing the collection and transforming the collection to an
+array.&nbsp;
+      <p>If one only needs these operations, the hash set and hash bag
+classes are fastest for if we have a equalityComparer for the items and the
+red-black tree classes are fastest if we must use a comparer.</p>
+      </td>
+      <td valign="top" width="29%"><code class="revvid">SH</code> <a
+ href="main.htm#T:C5.HashSet%601">HashSet&lt;T&gt;</a><br>
+      <code class="revvid">BH</code> <a
+ href="main.htm#T:C5.HashBag%601">HashBag&lt;T&gt;</a><br>
+      <code class="revvid">BH</code> <a
+ href="main.htm#T:C5.LinkedList%601">LinkedList&lt;T&gt;</a><br>
+      <code class="revvid">SH</code> <a
+ href="main.htm#T:C5.HashedLinkedList%601">HashedLinkedList&lt;T&gt;</a><br>
+      <code class="revvid">BH</code> <a
+ href="main.htm#T:C5.ArrayList%601">ArrayList&lt;T&gt;</a><br>
+      <code class="revvid">SH</code> <a
+ href="main.htm#T:C5.HashedArrayList%601"> HashedArrayList&lt;T&gt;<br>
+      </a> <code class="revvid">SC</code> <a
+ href="main.htm#T:C5.SortedArray%601"> SortedArray&lt;T&gt;</a><br>
+      <code class="revvid">SC</code> <a
+ href="main.htm#T:C5.TreeSet%601"> TreeSet&lt;T&gt;</a><br>
+      <code class="revvid">BC</code> <a
+ href="main.htm#T:C5.TreeBag%601"> TreeBag&lt;T&gt;</a></td>
+    </tr>
+    <tr>
+      <td valign="top" width="19%"><a
+ href="main.htm#T:C5.IPriorityQueue%601">IPriorityQueue&lt;T&gt;</a>&nbsp;</td>
+      <td valign="top" width="52%">This is a special case in the
+library, being the only type of updateable collection interface that
+does not implement IEditableCollection&lt;T&gt;. The reason for its
+presence is the specialized "heap" data structures for priority queues
+that only support these operations.
+      <p>If one only needs these the priority queue operations and is
+satisfied with bag semantics, then IntervalHeap&lt;P&gt;&nbsp; is the
+fastest choice. </p>
+      </td>
+      <td valign="top" width="29%"> <code class="revvid">BC</code> <a
+ href="main.htm#T:C5.IntervalHeap%601">IntervalHeap&lt;T&gt;</a><br>
+      <code class="revvid">SC</code> <a
+ href="main.htm#T:C5.TreeSet%601"> TreeSet&lt;T&gt;</a><br>
+      <code class="revvid">BC</code> <a
+ href="main.htm#T:C5.TreeBag%601"> TreeBag&lt;T&gt;</a></td>
+    </tr>
+    <tr>
+      <td valign="top" width="19%"><a href="main.htm#T:C5.IList%601">IList&lt;T&gt;</a>&nbsp;</td>
+      <td valign="top" width="52%">This is an updateable collection
+with sequence order imposed on the items by the user at insertion time
+or by later rearrangements.&nbsp;
+      <p>There are two main base data structures: dynamic arrays and
+doubly linked lists with very different complexity profile.&nbsp;The
+plain linked list is fast for operations at the end points only, while
+the plain array list have very fast lookups by index, but update
+operations are only fast at the right end point.&nbsp;</p>
+      <p>The Hashed- variants employ an index based on a hash table.
+This speeds up lookups by item considerably and for the linked list
+variant also insertions before or after specific items. The index
+changes the classes from bags to sets.&nbsp;</p>
+      <p>The hashed variants more than double the time of otherwise
+fast update operations, and should only be used when really
+needed.&nbsp;</p>
+      </td>
+      <td valign="top" width="29%"> <code class="revvid">BH</code> <a
+ href="main.htm#T:C5.LinkedList%601"> LinkedList&lt;T&gt;</a><br>
+      <code class="revvid">SH</code> <a
+ href="main.htm#T:C5.HashedLinkedList%601"> HashedLinkedList&lt;T&gt;</a><br>
+      <code class="revvid">BH</code> <a
+ href="main.htm#T:C5.ArrayList%601"> ArrayList&lt;T&gt;</a><br>
+      <code class="revvid">SH</code> <a
+ href="main.htm#T:C5.HashedArrayList%601"> HashedArrayList&lt;T&gt;</a></td>
+    </tr>
+    <tr>
+      <td valign="top" width="19%"><a
+ href="main.htm#T:C5.IIndexedSorted%601">IIndexedSorted&lt;T&gt;</a>&nbsp;</td>
+      <td valign="top" width="52%">This is an updateable collection
+with sequence order given by a comparer.&nbsp;
+      <p>There are two main data structures inside the implementations:
+red-black search trees and a dynamic array kept sorted at all times.</p>
+      <p>The differences are chiefly that the trees have much faster
+update operations, while the sorted array is somewhat faster at index
+lookups. In fact, the sorted array should only be used for static
+operation, where the collection is created and populated and then not
+changed again. </p>
+      </td>
+      <td valign="top" width="29%"> <code class="revvid">SC</code> <a
+ href="main.htm#T:C5.SortedArray%601"> SortedArray&lt;T&gt;</a><br>
+      <code class="revvid">SC</code> <a
+ href="main.htm#T:C5.TreeSet%601"> TreeSet&lt;T&gt;</a><br>
+      <code class="revvid">BC</code> <a
+ href="main.htm#T:C5.TreeBag%601"> TreeBag&lt;T&gt;</a></td>
+    </tr>
+    <tr>
+      <td valign="top" width="19%"><a
+ href="main.htm#T:C5.IPersistentSorted%601">IPersistentSorted&lt;T&gt;</a>&nbsp;</td>
+      <td valign="top" width="52%">This is a sorted collection that
+support very fast clones that themselves are sorted. The only
+implementation is the tree implementation with set and bag variants. </td>
+      <td valign="top" width="29%"> <code class="revvid">SC</code> <a
+ href="main.htm#T:C5.TreeSet%601"> TreeSet&lt;T&gt;</a><br>
+      <code class="revvid">BC</code> <a
+ href="main.htm#T:C5.TreeBag%601"> TreeBag&lt;T&gt;</a></td>
+    </tr>
+  </tbody>
+</table>
+<h2><a class="mozTocH2" name="mozTocId721827"></a><a
+ name="Dictionary interfaces">Dictionary interfaces</a></h2>
+<p>There are two dictionary interfaces:</p>
+<table border="1" width="100%">
+  <tbody>
+    <tr>
+      <th valign="top" width="19%">Interface</th>
+      <th width="56%">Short description</th>
+      <th width="25%">Implementing classes</th>
+    </tr>
+    <tr>
+      <td valign="top" width="19%"><a
+ href="main.htm#T:C5.IDictionary%602">IDictionary&lt;K,V&gt;</a> </td>
+      <td width="56%">This is the base dictionary interface.&nbsp;
+      <p>The choice is that one should use the hash dictionary unless
+one only has a comparer for the items, in which case the tree
+dictionary can be used.&nbsp; </p>
+      </td>
+      <td width="25%"><a href="main.htm#T:C5.HashDictionary%602">HashDictionary&lt;K,V&gt;</a><br>
+      <a href="main.htm#T:C5.TreeDictionary%602">TreeDictionary&lt;K,V&gt;</a></td>
+    </tr>
+    <tr>
+      <td valign="top" width="19%"><a
+ href="main.htm#T:C5.ISortedDictionary%602">ISortedDictionary&lt;K,V&gt;</a>
+      </td>
+      <td width="56%">This is a dictionary based on a comparer for the
+keys. There is only the tree implementation.&nbsp; </td>
+      <td width="25%"><a href="main.htm#T:C5.TreeDictionary%602">TreeDictionary&lt;K,V&gt;</a></td>
+    </tr>
+  </tbody>
+</table>
+<h2><a class="mozTocH2" name="mozTocId908053"></a><a
+ name="Query result interfaces">Query result interfaces</a></h2>
+<p>Some of the most basic collection interfaces have an important usage
+as the
+types of results of queries to collections, although these interfaces
+also
+appear at the base of the other collection interfaces and even as the
+types of
+synthetic collections. The interfaces in question are the standard
+System.Collections.Generics.IEnumerable&lt;T&gt;,
+<a href="main.htm#T:C5.ICollectionValue%601">ICollectionValue&lt;T&gt;</a>,
+<a href="main.htm#T:C5.IDirectedEnumerable%601">IDirectedEnumerable&lt;T&gt;</a>
+and <a href="main.htm#T:C5.IDirectedCollectionValue%601">IDirectedCollectionValue&lt;T&gt;</a>.</p>
+<p>The differences between the "Enumerable" and "Collection"
+variants are that the "Enumerable" variant only knows how to
+enumerate through its items, the "Collection" variants also knows how
+many items it has (without having to walk through an enumeration). The
+"Directed" variants are used for results of queries to sequenced
+collections (implementing <a href="main.htm#T:C5.ISequenced%601">ISequenced&lt;T&gt;</a>)
+and therefore have a non-implementation dependent enumeration order.
+The
+"Directed" variants supports two operations, <a
+ href="main.htm#M:C5.IDirectedCollectionValue%601.Backwards">Backwards()</a>
+to enable enumeration in the opposite direction and <a
+ href="main.htm#P:C5.IDirectedEnumerable%601.Direction">Direction</a>
+to tell if the enumeration order is forwards or backwards with respect
+to the
+original collection.</p>
+<p>Note: operations on an enumerator created by the GetEnumerator()
+method on System.Collections.Generics.IEnumerable&lt;T&gt; cannot be
+interleaved with update
+operations on
+the underlying collection.</p>
+<p>Note: for all enumerators in the library the operations have O(1)
+amortized
+complexity.</p>
+<h1><a class="mozTocH1" name="mozTocId110895"></a>To <a
+ name="Constructing">construct</a> a collection</h1>
+<p>All collections classes in C5 have (zero parameter) default
+constructors. So
+if we want to make a linked list of items of some type, <code>TheType</code>,
+and add an item to the list we will do</p>
+<p><code>&nbsp;&nbsp;&nbsp; IList&lt;TheType&gt; lst = new
+LinkedList&lt;TheType&gt;();<br>
+&nbsp;&nbsp;&nbsp; TheType t = ...;<br>
+&nbsp;&nbsp;&nbsp; lst.Add(t);</code></p>
+<p>The collection classes have no constructors that will take an array
+or a
+collection as parameter for prepopulating the collection, use the <a
+ href="file:///C:/home/kokholm/c5/vs/C5/main.htm#M:C5.ISink%601.AddAll%28C5.IEnumerable%7B%210%7D%29">
+AddAll</a> method
+instead. NB: in the released version, expect constructors with an
+enumerable as argument and constructors with a variable number of
+arguments ("params") for the initialization of the collection, see the <a
+ href="#planned">planned changes</a> section.<br>
+</p>
+<p>Some collection classes are governed by internal parameters that one
+can give
+non-default values at creation time (<code>fill</code> in <a
+ href="main.htm#T:C5.HashSet%601">HashSet&lt;T&gt;</a>,&nbsp;
+<a href="main.htm#T:C5.HashBag%601">HashBag&lt;T&gt;</a>, <a
+ href="main.htm#T:C5.HashDictionary%602">HashDictionary&lt;K,V&gt;</a>)
+or use internal tables that one can expand in advance if one has
+expectations of
+how large the collection will grow (HashSet&lt;T&gt;,&nbsp;
+HashBag&lt;T&gt;, HashDictionary&lt;K,V&gt;, <a
+ href="main.htm#T:C5.ArrayList%601">ArrayList&lt;T&gt;</a>,
+<a href="main.htm#T:C5.HashedArrayList%601"> HashedArrayList&lt;T&gt;</a>,
+<a href="main.htm#T:C5.SortedArray%601">SortedArray&lt;T&gt;</a>,
+<a href="main.htm#T:C5.IntervalHeap%601">IntervalHeap&lt;T&gt;</a>).</p>
+<p>For equality-based collection classes, these constructors will use a
+default
+equalityComparer to define equality of items according to the following table:</p>
+<table border="1">
+  <tbody>
+    <tr>
+      <th>T</th>
+      <th>default equalityComparer (implements IEqualityComparer&lt;T&gt;)</th>
+      <th>Equality and hash code by</th>
+    </tr>
+    <tr>
+      <td>int</td>
+      <td><a href="main.htm#T:C5.IntEqualityComparer">IntEqualityComparer</a></td>
+      <td>Equals and hash code of integer</td>
+    </tr>
+    <tr>
+      <td>other value type</td>
+      <td><a href="main.htm#T:C5.DefaultValueTypeEqualityComparer%601">DefaultValueTypeEqualityComparer&lt;T&gt;</a></td>
+      <td>methods inherited from object</td>
+    </tr>
+    <tr>
+      <td>IEditableCollection&lt;S&gt;</td>
+      <td><a href="main.htm#T:C5.EqualityComparerBuilder.UnsequencedEqualityComparer%602">EqualityComparerBuilder.UnsequencedEqualityComparer&lt;S,IEditableCollection&lt;S&gt;&gt;</a></td>
+      <td>contents without regards to sequence</td>
+    </tr>
+    <tr>
+      <td>ISequenced&lt;S&gt;</td>
+      <td><a href="main.htm#T:C5.EqualityComparerBuilder.SequencedEqualityComparer%602">EqualityComparerBuilder.SequencedEqualityComparer&lt;S,IEditableCollection&lt;S&gt;&gt;</a></td>
+      <td>contents with regards to sequence</td>
+    </tr>
+    <tr>
+      <td>other reference type</td>
+      <td><a href="main.htm#T:C5.DefaultReferenceTypeEqualityComparer%601">DefaultReferenceTypeEqualityComparer&lt;T&gt;</a></td>
+      <td>methods inherited from object</td>
+    </tr>
+  </tbody>
+</table>
+<p>For comparison-based collection classes, these constructors will use
+a
+default comparer:</p>
+<table border="1">
+  <tbody>
+    <tr>
+      <th>T</th>
+      <th>default comparer&nbsp;<br>
+(implements IComparer&lt;T&gt;)</th>
+      <th>Comparison by</th>
+    </tr>
+    <tr>
+      <td>int</td>
+      <td>IC</td>
+      <td>Standard integer comparison</td>
+    </tr>
+    <tr>
+      <td>implementing IComparable&lt;T&gt;</td>
+      <td><a href="main.htm#T:C5.NaturalComparer%601">NaturalComparer&lt;T&gt;</a></td>
+      <td>The CompareTo(T o)&nbsp; instance method</td>
+    </tr>
+    <tr>
+      <td>other implementing System.IComparable</td>
+      <td><a href="main.htm#T:C5.NaturalComparerO%601">NaturalComparerO&lt;T&gt;</a></td>
+      <td>The CompareTo(object o) instance method</td>
+    </tr>
+    <tr>
+      <td>other</td>
+      <td>-</td>
+      <td><i>collection class constructor throws an exception</i></td>
+    </tr>
+  </tbody>
+</table>
+<p>Sometimes, the default equalityComparer or comparer is not the right one for
+the
+problem at hand. In that case one must get hold on a equalityComparer or comparer
+of the
+right kind and supply it to one of the constructors of the collection
+classes
+that supports such a parameter. The procedure is demonstrated in the
+sections
+below on <a href="#external%20equalityComparer">external equalityComparers</a>, <a
+ href="#external%20comparer">external
+comparers</a> and <a href="#collections%20of%20collections">collections
+as items</a>.<br>
+</p>
+<p>NB: in the released version, expect the equalityComparers and comparers to be
+of the System.Collections.Generics.IComparer&lt;T&gt; type, see the <a
+ href="userguide.htm#planned">planned changes</a> section.</p>
+<h2><a class="mozTocH2" name="mozTocId850165"></a>To use an <a
+ name="external equalityComparer"> external equalityComparer</a></h2>
+<p>In addition to the helper classes referenced above, the library has
+the
+helper class <a href="main.htm#T:C5.KeyValuePairEqualityComparer%602">KeyValuePairEqualityComparer&lt;K,V&gt;</a>
+to construct a equalityComparer for pairs of the type <a
+ href="main.htm#T:C5.KeyValuePair%602">KeyValuePair&lt;K,V&gt;</a>,
+the type of entry of a K to V dictionary. The constructed equalityComparer will
+only take
+the first component of the pair into account. We can use these classes
+in the
+following way to make a linked list (with hash index) of pairs of
+strings
+identified by their first components using some custom equalityComparer on
+strings:</p>
+<blockquote>
+  <p><code>IEqualityComparer&lt;string&gt; csh = ...;<br>
+IEqualityComparer&lt;KeyValuePair&lt;string,string&gt;&gt; cph =&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+new KeyValuePairEqualityComparer&lt;string,string&gt;(csh);<br>
+IList&lt;KeyValuePair&lt;string,string&gt;&gt; lst =<br>
+  </code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>
+new HashedLinkedList&lt;KeyValuePair&lt;string,string&gt;&gt;(cph);<br>
+lst.Add(new KeyValuePair&lt;string,string&gt;("abe","kat"));</code></p>
+</blockquote>
+<p>One may, of course, program a equalityComparer oneself. This one should always
+do if
+the item type is defined as a struct (value type) that does not
+override the
+Equals and GetHashCode methods of object, since in that case the
+default equalityComparer
+will use the slow default versions of those methods supplied by the
+runtime via
+reflection.&nbsp;</p>
+<h2><a class="mozTocH2" name="mozTocId162938"></a>To use an <a
+ name="external comparer"> external comparer</a></h2>
+<p>There is a helper class for comparer of pairs: <a
+ href="main.htm#T:C5.KeyValuePairEqualityComparer%602">KeyValuePairComparer&lt;K,V&gt;</a>.
+We will show an example of a custom comparer. Imagine wanting to
+compare double
+precision floating point numbers with a tolerance. The following code
+snippet
+shows how one could make a tree set out of such numbers:</p>
+<blockquote>
+  <p><code>class DC : IComparer&lt;double&gt; {<br>
+&nbsp;&nbsp; const double eps = 1E-10;<br>
+&nbsp;&nbsp; int Compare(double a, double b)&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {return a &gt; b + eps ? 1 : a &lt; b -
+eps ? -1 : 0;}<br>
+}<br>
+  <br>
+void dowork() {<br>
+&nbsp;&nbsp; IComparer&lt;double&gt; dc = new DC();<br>
+&nbsp;&nbsp; ISorted&lt;double&gt; tree = new TreeSet&lt;double&gt;(dc);<br>
+&nbsp;&nbsp; tree.Add(3.45);<br>
+&nbsp;&nbsp; ...<br>
+}</code></p>
+</blockquote>
+<p>In this particular case, one would have to make sure, that two
+different
+floating point numbers are only identified by the comparer if they
+really should
+represent the same value and not by coincidence.</p>
+<h2><a class="mozTocH2" name="mozTocId957374"></a>To make <a
+ name="collections of collections"> collections of collections</a></h2>
+<p>When one wants to use a collection whose items itself are of
+collection type,
+one usually wants the interior collections to be identified by contents
+- either
+according to or irrespective of sequence order. An example could be
+transformations of <a
+ href="http://www.dina.kvl.dk/%7Esestoft/gcsharp/index.html#regexp">Finite
+Automatons</a>. The default equalityComparers and the EqualityComparerBuilder classes
+mentioned
+above may help to construct such collections of collections as in the
+examples
+that follow:</p>
+<p>To make an array list of sequenced collections identified by
+contents in
+sequenced fashion one would simply do:</p>
+<blockquote>
+  <p><code>ArrayList&lt;ISequenced&lt;int&gt;&gt; lst = new
+ArrayList&lt;ISequenced&lt;int&gt;&gt;();</code></p>
+</blockquote>
+<p>To make a linked list of linked lists identified by contents
+unsequenced, explicitly
+construct the collection equalityComparer:</p>
+<blockquote>
+  <p><code>IEqualityComparer&lt;LinkedList&lt;int&gt;&gt; lsth =<br>
+  </code>&nbsp;&nbsp;&nbsp;&nbsp; <code>new
+EqualityComparerBuilder.UnsequencedEqualityComparer&lt;int,LinkedList&lt;int&gt;&gt;();<br>
+LinkedList&lt;LinkedList&lt;int&gt;&gt; lst =<br>
+&nbsp;&nbsp; new LinkedList&lt;LinkedList&lt;int&gt;&gt;(lsth);</code></p>
+</blockquote>
+<p>If for some strange reason one would like to make a hash set of
+linked lists
+with the lists identified by reference equality one would simply do:</p>
+<blockquote>
+  <p><code>HashSet&lt;LinkedList&lt;int&gt;&gt; lst = new
+HashSet&lt;LinkedList&lt;int&gt;&gt;();</code></p>
+</blockquote>
+<p>If for even stranger reasons one would make a hash set of
+ISequenced&lt;int&gt; collections with the collections identified by
+reference
+equality one would do like this:</p>
+<blockquote>
+  <p><code>IEqualityComparer&lt;</code><code>ISequenced</code><code>&lt;int&gt;&gt;
+lsth =<br>
+  </code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <code>new
+DefaultReferenceTypeEqualityComparer&lt;</code><code>ISequenced</code><code>&lt;int&gt;&gt;();<br>
+HashSet&lt;</code><code>ISequenced</code><code>&lt;int&gt;&gt; lst =<br>
+&nbsp;&nbsp; new HashSet&lt;</code><code>ISequenced</code><code>&lt;int&gt;&gt;(lsth);</code></p>
+</blockquote>
+<h1><a class="mozTocH1" name="mozTocId486186"></a>Special topics</h1>
+<h2><a class="mozTocH2" name="mozTocId48263"></a>To choose a <a
+ name="set or bag"> set or bag</a> collection</h2>
+<p>The following table shows which of the collection classes have set
+semantics
+and which have bag semantics. All the implemented classes have fixed,
+compiled in semantics. <br>
+</p>
+<p>Note: when in a set collection, methods with an Add in the name will
+ignore
+attempts to add an item already there or flag the failed attempt by a
+Boolean return value; methods with an Insert in the name (only in
+lists) will throw an
+exception.</p>
+<table border="1" width="38%">
+  <tbody>
+    <tr>
+      <td valign="top" width="6%"><a href="main.htm#T:C5.HashSet%601">HashSet&lt;T&gt;</a></td>
+      <td valign="top" width="5%">set</td>
+    </tr>
+    <tr>
+      <td valign="top" width="6%"> <a href="main.htm#T:C5.HashBag%601">HashBag&lt;T&gt;</a></td>
+      <td valign="top" width="5%">bag</td>
+    </tr>
+    <tr>
+      <td valign="top" width="6%"> <a
+ href="main.htm#T:C5.LinkedList%601"> LinkedList&lt;T&gt;</a></td>
+      <td valign="top" width="5%">bag</td>
+    </tr>
+    <tr>
+      <td valign="top" width="6%"> <a
+ href="main.htm#T:C5.HashedLinkedList%601"> HashedLinkedList&lt;T&gt;</a></td>
+      <td valign="top" width="5%">set</td>
+    </tr>
+    <tr>
+      <td valign="top" width="6%"> <a
+ href="main.htm#T:C5.ArrayList%601"> ArrayList&lt;T&gt;</a></td>
+      <td valign="top" width="5%">bag</td>
+    </tr>
+    <tr>
+      <td valign="top" width="6%"> <a
+ href="main.htm#T:C5.HashedArrayList%601"> HashedArrayList&lt;T&gt; </a>
+      </td>
+      <td valign="top" width="5%">set</td>
+    </tr>
+    <tr>
+      <td valign="top" width="6%"> <a
+ href="main.htm#T:C5.SortedArray%601"> SortedArray&lt;T&gt;</a></td>
+      <td valign="top" width="5%">set</td>
+    </tr>
+    <tr>
+      <td valign="top" width="6%"> <a href="main.htm#T:C5.TreeSet%601">TreeSet&lt;T&gt;</a></td>
+      <td valign="top" width="5%">set</td>
+    </tr>
+    <tr>
+      <td valign="top" width="6%"> <a href="main.htm#T:C5.TreeBag%601">TreeBag&lt;T&gt;</a></td>
+      <td valign="top" width="5%">bag</td>
+    </tr>
+    <tr>
+      <td valign="top" width="6%"><a
+ href="main.htm#T:C5.IntervalHeap%601">IntervalHeap&lt;T&gt;</a></td>
+      <td valign="top" width="5%">bag</td>
+    </tr>
+  </tbody>
+</table>
+<h2><a class="mozTocH2" name="mozTocId929755"></a>To work on part of a
+list: list views</h2>
+<p>The IList&lt;T&gt; interface supports via the <a
+ href="main.htm#M:C5.IList%601.View%28System.Int32,System.Int32%29">
+View</a>
+method the functionality that one can zoom in on part of a list and use
+it as an
+IList&lt;T&gt; in its own right while having updates to the view passed
+through
+to the base (original) IList&lt;T&gt;. Using the <a
+ href="main.htm#M:C5.IList%601.Slide%28System.Int32%29">Slide</a>
+method calls, one may move the view around the base list. Using Slide
+repeatedly
+one can implement safe ways to iterate over a list while updating it.
+The
+IList&lt;T&gt; interface also has properties <a
+ href="main.htm#P:C5.IList%601.Underlying">Underlying</a>
+and <a href="main.htm#P:C5.IList%601.Offset">Offset</a> showing the
+base list of a
+view and the current site of a view.</p>
+<p>One can create a view on a view, but the new view will have the
+original base
+list as base. A view will be invalidated if an update operation is
+performed on
+the base list by any other means than through this particular view.</p>
+<p>The following code snippet shows a silly example of iterating over a
+list,
+doing an insertion each time certain combination of items are seen (the
+example
+iterates right to left and inserts 666 whenever two consecutive items
+have an
+odd difference):</p>
+<blockquote>
+  <p><code>IList&lt;int&gt; lst = ...;<br>
+IList&lt;int&gt; view = lst.CreateView(lst.Count-2, 2);<br>
+while (true) {<br>
+&nbsp;&nbsp;&nbsp; if ((view.Last - view.First) % 2 == 1)<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; view.Insert(1, 666);<br>
+&nbsp;&nbsp;&nbsp; if (view.Offset == 0)<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>
+&nbsp;&nbsp;&nbsp; else<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; view.Slide(-1,2);<br>
+}</code></p>
+</blockquote>
+<h2><a class="mozTocH2" name="mozTocId650306"></a>To work with
+persistent red-black trees</h2>
+<p>The search tree implementation in the library is based on node copy
+persistent red-black trees. The persistence is exposed in the <a
+ href="main.htm#M:C5.IPersistentSorted%601.Snapshot">Snapshot</a>
+method that can be considered a very fast and space-saving way of
+making a
+read-only clone of the tree. When using persistence, the space use of a
+red-black tree in this implementation is linear in the number of
+operations
+since the creation of the tree.</p>
+<p>One use of persistence could be to safely enumerate a tree
+interleaved with
+updates:</p>
+<blockquote>
+  <p><code>IPersistentSorted&lt;int&gt; tree = new TreeSet&lt;int&gt;();<br>
+tree.Add(5);<br>
+...<br>
+ISorted&lt;int&gt; snap = tree.Snapshot();<br>
+foreach (int i in snap)<br>
+&nbsp;&nbsp;&nbsp; tree.Add(i+7);</code></p>
+</blockquote>
+<p>The GUITester project of the complete library source code contains
+an
+interesting (standard) usage of persistent search trees to the
+geometric problem
+of constructing an efficient data structure for point location in a
+division of
+the plane given by a list of line segments.</p>
+<h2><a class="mozTocH2" name="mozTocId553609"></a>To implement new
+collection classes or subclass an existing one</h2>
+<p>All interface methods and properties of the collection classes
+implemented in
+the library are virtual and so it should be safe to subclass these
+classes. Some
+classes may have protected members if they are subclassed in the
+library itself.
+We refer to the detailed reference manuals and the library source for
+information on the protected members and their role in subclassing.</p>
+<p>There is a sequence of helper classes designed to be used as base
+classes of
+collection classes: <a href="main.htm#T:C5.EnumerableBase%601">EnumerableBase&lt;T&gt;</a>,
+<a href="main.htm#T:C5.CollectionValueBase%601">CollectionValueBase&lt;T&gt;</a>,
+<a href="main.htm#T:C5.CollectionBase%601">CollectionBase&lt;T&gt;</a>,
+<a href="main.htm#T:C5.SequencedBase%601">SequencedBase&lt;T&gt;</a>
+and <a href="main.htm#T:C5.ArrayBase%601">ArrayBase&lt;T&gt;</a>.
+Please see the reference manual and the library source code for
+documentation
+and examples.</p>
+<p>As for dictionaries, the DictionaryBase&lt;K,V&gt; class will
+construct a
+class implementing IDictionary&lt;K,V&gt; by simply plugging in a set
+implementation.</p>
+<h2><a class="mozTocH2" name="mozTocId753674"></a>To present a read
+only view of a collection</h2>
+<p>The library contains a long list of wrapper classes all with name
+starting
+with Guarded having the purpose of creating a read-only view of an
+existing
+collection. The wrapping is done by the constructors of the classes. If
+we want
+to give some code access to only lookup operations on a, say, list we
+can do as
+follows:</p>
+<blockquote>
+  <p><code>IList&lt;int&gt; lst;<br>
+...<br>
+IList&lt;int&gt; rolst = new GList&lt;int&gt;(lst);<br>
+OtherObject.dowork(rolst);</code></p>
+</blockquote>
+<p>Please see the reference manual for details on available wrapper
+classes.</p>
+<h1><a class="mozTocH1" name="mozTocId6619"></a><a name="datastructures">Collection
+classes by data structure/class</a></h1>
+<p>The following table&nbsp;shows the underlying data structure of the
+various collection classes.</p>
+<table border="1">
+  <tbody>
+    <tr>
+      <th>Data structure</th>
+      <th>Classes</th>
+      <th>Primary Interfaces</th>
+    </tr>
+    <tr>
+      <td>hash table</td>
+      <td>HashSet&lt;T&gt;</td>
+      <td> ICollection&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>hash table</td>
+      <td>HashBag&lt;T&gt;</td>
+      <td> ICollection&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>hash table</td>
+      <td>HashDictionary&lt;K,V&gt;</td>
+      <td>IDictionary&lt;K,V&gt;</td>
+    </tr>
+    <tr>
+      <td>linked list</td>
+      <td>LinkedList&lt;T&gt;</td>
+      <td>IList&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>linked list with hash index</td>
+      <td>HashedLinkedList&lt;T&gt;</td>
+      <td>IList&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>dynamic array</td>
+      <td>ArrayList&lt;T&gt;</td>
+      <td>IList&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>dynamic array with hash index</td>
+      <td>HashedArrayList&lt;T&gt;</td>
+      <td>IList&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>sorted dynamic array</td>
+      <td>SortedArray&lt;T&gt;</td>
+      <td>IIndexedSorted&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>heap</td>
+      <td>IntervalHeap&lt;T&gt;</td>
+      <td>IPriorityQueue&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>red-black search tree</td>
+      <td>TreeSet&lt;T&gt;</td>
+      <td>IIndexedSorted&lt;T&gt;, IPersistentSorted&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>red-black search tree</td>
+      <td>TreeBag&lt;T&gt;</td>
+      <td>IIndexedSorted&lt;T&gt;, IPersistentSorted&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>red-black search tree</td>
+      <td>TreeDictionary&lt;K,V&gt;</td>
+      <td>ISortedDictionary&lt;K,V&gt;</td>
+    </tr>
+  </tbody>
+</table>
+<br>
+<h1><a class="mozTocH1" name="mozTocId393559"></a>&lt;&gt;<a
+ name="planned"></a>Planned<span style="font-weight: bold;"> </span>architecture
+or interface changes
+for first release<br>
+</h1>
+<ol>
+  <li>Eliminate the use of our own generic equality/comparator types,
+C5.IComparer&lt;T&gt; and C5.IEqualityComparer&lt;T&gt; and use the new design of
+VS 2005 beta1 in the form of the combined
+System.Collections.Generic.IComparer&lt;T&gt;.</li>
+  <li>Vararg (params) constructors? (And IEnum do.)</li>
+  <li>Possibly extended use of "wildcard style" operations like
+AddAll&lt;U&gt;(IEnumerable&lt;U&gt; items)?</li>
+  <li>Make all collection classes clonable and serializable.</li>
+</ol>
+<h1><a class="mozTocH1" name="mozTocId336849"></a><a
+ name="PerformanceProper">Performance</a> details for proper collection
+classes</h1>
+<p>This section overviews the complexities of cc public methods and
+property
+accesses.</p>
+<p>In the table below, for lack of space we use the following numbers
+to
+identify collection classes:</p>
+<table border="1">
+  <tbody>
+    <tr>
+      <th>Class</th>
+      <th>Column</th>
+    </tr>
+    <tr>
+      <td>HashSet&lt;T&gt;</td>
+      <td>HS</td>
+    </tr>
+    <tr>
+      <td>HashBag&lt;T&gt;</td>
+      <td>HB</td>
+    </tr>
+    <tr>
+      <td>ArrayList&lt;T&gt;</td>
+      <td>AL</td>
+    </tr>
+    <tr>
+      <td>LinkedList&lt;T&gt;</td>
+      <td>LL</td>
+    </tr>
+    <tr>
+      <td>HashedArrayList&lt;T&gt;</td>
+      <td>HAL</td>
+    </tr>
+    <tr>
+      <td>HashedLinkedList&lt;T&gt;</td>
+      <td>HLL</td>
+    </tr>
+    <tr>
+      <td>TreeSet&lt;T&gt;</td>
+      <td>RBTS</td>
+    </tr>
+    <tr>
+      <td>TreeBag&lt;T&gt;</td>
+      <td>RBTB</td>
+    </tr>
+    <tr>
+      <td>SortedArray&lt;T&gt;</td>
+      <td>SA</td>
+    </tr>
+    <tr>
+      <td>IntervalHeap&lt;T&gt;</td>
+      <td>IH</td>
+    </tr>
+  </tbody>
+</table>
+<p>And the following special symbols:&nbsp;</p>
+<p>
+n size of collection,&nbsp;<br>
+m size of argument if collection-: not supported<br>
+*: means: suboptimal complexity (library is in error)<br>
+$: special at end: the operation is much faster at the start and/or end
+(end for
+array list, both for linked list)
+</p>
+<p>Note: we do not show return type&nbsp; or parameters for methods,
+just mark
+with ()<br>
+Note: we ignore time for reclaiming of internal array space (e.g. Clear)<br>
+User supplied operations like comparers or equalityComparers are assumed to be
+O(1)</p>
+<table border="1" height="2893" width="100%">
+  <tbody>
+    <tr>
+      <th height="23" width="9%">Member</th>
+      <th height="23" width="8%">HS</th>
+      <th height="23" width="8%">HB</th>
+      <th height="23" width="8%">AL</th>
+      <th height="23" width="8%">LL</th>
+      <th height="23" width="8%">HAL</th>
+      <th height="23" width="8%">HLL</th>
+      <th height="23" width="8%">RBTS</th>
+      <th height="23" width="8%">RBTB</th>
+      <th height="23" width="9%">SA</th>
+      <th height="23" width="9%">IH</th>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">&nbsp;IEnumerable&lt;T&gt;</font></i></td>
+      <td height="22" width="8%">&nbsp;&nbsp;</td>
+      <td height="22" width="8%">&nbsp;</td>
+      <td height="22" width="8%">&nbsp;</td>
+      <td height="22" width="8%">&nbsp;</td>
+      <td height="22" width="8%">&nbsp;</td>
+      <td height="22" width="8%">&nbsp;</td>
+      <td height="22" width="8%">&nbsp;</td>
+      <td height="22" width="8%">&nbsp;</td>
+      <td height="22" width="9%">&nbsp;</td>
+      <td height="22" width="9%">&nbsp;</td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">GetEnumerator()</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">IDirectedEnumerable&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HB</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">AL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">LL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HAL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HLL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTB</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">SA</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="18%"><font size="2">Direction</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="18%"><font size="2">Backwards()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">ICollectionValue&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HB</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">AL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">LL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HAL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HLL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTB</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">SA</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Count</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="18%"><font size="2">CopyTo</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">ToArray</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Apply()</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Exists()</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">All()</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">IDirectedCollectionValue&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HB</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">AL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">LL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HAL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HLL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTB</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">SA</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="18%"><font size="2">Backwards()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="13%"><i><font color="#808080" size="2">IExtensible&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HB</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">AL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">LL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HAL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HLL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTB</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">SA</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">AllowsDuplicates</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">SyncRoot</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">IsEmpty</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Add</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">AddAll</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(mlog n)</font></td>
+      <td height="22" width="8%"><font size="2">O(mlog n)</font></td>
+      <td height="22" width="9%"><font size="2">O(mlog n)</font></td>
+      <td height="22" width="9%"><font size="2">??</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">ICollection&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HB</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">AL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">LL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HAL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HLL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTB</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">SA</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">IsReadOnly</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">ContainsSpeed</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">GetHashCode</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Equals</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Contains</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">ContainsCount</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">ContainsAll</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(mn)*</font></td>
+      <td height="22" width="8%"><font size="2">O(mn)*</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m logn)</font></td>
+      <td height="22" width="8%"><font size="2">O(m logn)</font></td>
+      <td height="22" width="9%"><font size="2">O(m logn)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Find</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">FindOrAdd</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Update</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">UpdateOrAdd</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Remove</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveWithReturn</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveAllCopies</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveAll</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(mn)*</font></td>
+      <td height="22" width="8%"><font size="2">O(mn)*</font></td>
+      <td height="22" width="8%"><font size="2">O(m+n)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m logn)</font></td>
+      <td height="22" width="8%"><font size="2">O(m logn)</font></td>
+      <td height="22" width="9%"><font size="2">O(m logn)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Clear</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RetainAll</font></td>
+      <td height="22" width="8%"><font size="2">O(m)?</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(mn)*</font></td>
+      <td height="22" width="8%"><font size="2">O(mn)*</font></td>
+      <td height="22" width="8%"><font size="2">O(m+n)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m logn)</font></td>
+      <td height="22" width="8%"><font size="2">O(m logn)</font></td>
+      <td height="22" width="9%"><font size="2">O(m logn)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">ISequenced&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HB</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">AL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">LL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HAL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HLL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTB</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">SA</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">GetHashCode</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Equals</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">IIndexed&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HB</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">AL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">LL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HAL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HLL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTB</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">SA</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">this[i]</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">this[start,end]</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">IndexOf()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">LastIndexOf()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveAt</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveInterval</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n log n)*</font></td>
+      <td height="22" width="8%"><font size="2">O(n log n)*</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">IList&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HB</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">AL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">LL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HAL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HLL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTB</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">SA</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">First</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Last</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">FIFO</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">this[i]</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Base</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Offset</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Map()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Insert()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">InsertFirst()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">InsertLast()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">InsertBefore()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">InsertAfter()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">InsertAll()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(m+n)</font></td>
+      <td height="22" width="8%"><font size="2">O(m+n)</font></td>
+      <td height="22" width="8%"><font size="2">O(m+n)</font></td>
+      <td height="22" width="8%"><font size="2">O(m+n)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">FindAll()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Remove()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveFirst()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveLast()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">View()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Slide() (amount: d)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(d)</font></td>
+      <td height="22" width="8%"><font size="2">O(d)</font></td>
+      <td height="22" width="8%"><font size="2">O(d)</font></td>
+      <td height="22" width="8%"><font size="2">O(d)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Reverse()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">IsSorted()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Sort()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n log n)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Shuffle()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">IPriorityQueue&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HB</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">AL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">LL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HAL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HLL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">RBTS</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">RBTB</font></i></td>
+      <td height="22" width="9%"><i><font color="#808080" size="2">SA</font></i></td>
+      <td height="22" width="9%"><i><font color="#808080" size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">FindMin()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">DeleteMin()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">FindMax()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td height="30" width="9%"><font size="2">DeleteMax()</font></td>
+      <td height="30" width="8%"><font size="2">-</font></td>
+      <td height="30" width="8%"><font size="2">-</font></td>
+      <td height="30" width="8%"><font size="2">-</font></td>
+      <td height="30" width="8%"><font size="2">-</font></td>
+      <td height="30" width="8%"><font size="2">-</font></td>
+      <td height="30" width="8%"><font size="2">-</font></td>
+      <td height="30" width="8%"><font size="2">O(log n)</font></td>
+      <td height="30" width="8%"><font size="2">O(log n)</font></td>
+      <td height="30" width="9%"><font size="2">O(log n)</font></td>
+      <td height="30" width="9%"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td height="30" width="9%"> <font size="2">Comparer</font></td>
+      <td height="30" width="8%"> <font size="2">-</font></td>
+      <td height="30" width="8%"> <font size="2">-</font></td>
+      <td height="30" width="8%"> <font size="2">-</font></td>
+      <td height="30" width="8%"> <font size="2">-</font></td>
+      <td height="30" width="8%"> <font size="2">-</font></td>
+      <td height="30" width="8%"> <font size="2">-</font></td>
+      <td height="30" width="8%"> <font size="2">O(1)</font></td>
+      <td height="30" width="8%"> <font size="2">O(1)</font></td>
+      <td height="30" width="9%"> <font size="2">O(1)</font></td>
+      <td height="30" width="9%"> <font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">ISorted&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HB</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">AL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">LL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HAL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HLL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">RBTS</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">RBTB</font></i></td>
+      <td height="22" width="9%"><i><font color="#808080" size="2">SA</font></i></td>
+      <td height="22" width="9%"><i><font color="#808080" size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Predecessor</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Successor</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">WeakPredecessor</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">WeakSuccessor</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Cut</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RangeFrom</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RangeFromTo</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RangeTo</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RangeAll</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">AddSorted</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">?</font></td>
+      <td height="22" width="8%"><font size="2">?</font></td>
+      <td height="22" width="9%"><font size="2">?</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveRangeFrom</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(nlog n)*</font></td>
+      <td height="22" width="8%"><font size="2">O(nlog n)*</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveRangeFromTo</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(nlog n)*</font></td>
+      <td height="22" width="8%"><font size="2">O(nlog n)*</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveRangeTo</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(nlog n)*</font></td>
+      <td height="22" width="8%"><font size="2">O(nlog n)*</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">IIndexedSorted&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HB</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">AL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">LL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HAL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HLL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">RBTS</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">RBTB</font></i></td>
+      <td height="22" width="9%"><i><font color="#808080" size="2">SA</font></i></td>
+      <td height="22" width="9%"><i><font color="#808080" size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Map</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">CountFrom</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">CountFromTo</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">CountTo</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RangeFrom</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RangeFromTo</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RangeTo</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">FindAll</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">IPersistentSorted&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HB</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">AL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">LL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HAL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HLL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">RBTS</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">RBTB</font></i></td>
+      <td height="22" width="9%"><i><font color="#808080" size="2">SA</font></i></td>
+      <td height="22" width="9%"><i><font color="#808080" size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Snapshot()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+  </tbody>
+</table>
+<h1><a class="mozTocH1" name="mozTocId712409"></a><a
+ name="PerformanceDict">Performance</a> details for dictionary classes</h1>
+<table border="1" width="467">
+  <tbody>
+    <tr>
+      <th width="302">Member</th>
+      <th width="79">HashDictionary&lt;K,V&gt;</th>
+      <th width="64">TreeDictionary&lt;K,V&gt;</th>
+    </tr>
+    <tr>
+      <td width="302"><i><font color="#808080" size="2">IEnumerable&lt;KeyValuePair&lt;K,V&gt;&gt;</font></i></td>
+      <td width="79"><font color="#808080">&nbsp;</font></td>
+      <td width="64">&nbsp;</td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">GetEnumerator()</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td width="64"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><i><font color="#808080" size="2">IDictionary&lt;K,V&gt;</font></i></td>
+      <td width="79"><font color="#808080">&nbsp;</font></td>
+      <td width="64">&nbsp;</td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">this[key]</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">Count</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td width="64"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">IsReadOnly</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td width="64"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">SyncRoot</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td width="64"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">Keys</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td width="64"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">Values</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td width="64"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">Add()</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">Remove()</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">Clear()</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td height="22" width="64"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">Contains()</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">Find()</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">Update()</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">FindOrAdd</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">UpdateOrAdd</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><i><font color="#808080" size="2">ISortedDictionary&lt;K,V&gt;</font></i></td>
+      <td width="79"><font color="#808080">&nbsp;</font></td>
+      <td width="64">&nbsp;</td>
+    </tr>
+    <tr>
+      <td height="22" width="302"><font size="2">Predecessor</font></td>
+      <td width="79"><font size="2">-</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="302"><font size="2">Successor</font></td>
+      <td width="79"><font size="2">-</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="302"><font size="2">WeakPredecessor</font></td>
+      <td width="79"><font size="2">-</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="302"><font size="2">WeakSuccessor</font></td>
+      <td width="79"><font size="2">-</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+  </tbody>
+</table>
+</body>
+</html>
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docbuild/banner.htm
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docbuild/banner.htm	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docbuild/banner.htm	(revision 3)
@@ -0,0 +1,13 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html >
+<head>
+    <link rel="stylesheet" type="text/css" href="docnet.css">
+</head>
+<body>
+    <p>
+        <font size="6"><b>C5 documentation</b></font> Legend: <code class="greenbg">A</code>:
+        abstract, <code class="greenbg">F</code>: final, <code class="greenbg">N</code>:
+        non-virtual, <code class="greenbg">P</code>: protected, <code class="greenbg">S</code>:
+        static. </p>
+</body>
+</html>
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docbuild/docnet.css
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docbuild/docnet.css	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docbuild/docnet.css	(revision 3)
@@ -0,0 +1,131 @@
+BODY
+{
+    FONT-FAMILY: "Verdana", sans-serif;
+    FONT-SIZE: x-small;
+}
+CODE 
+{
+    FONT-SIZE: x-small;
+}
+A:link
+{
+    COLOR: #4e4887
+}
+A:visited
+{
+    COLOR: #8080c8
+}
+A:active
+{
+    COLOR: #f16043
+}
+A:hover
+{
+    COLOR: #f16043
+}
+P
+{
+    MARGIN-BOTTOM: 0.5em;
+    MARGIN-TOP: 0.5em
+}
+.greenbg
+{
+    BACKGROUND-COLOR: #00ff00;
+    font-weight:bold
+}
+TABLE
+{
+    BORDER-BOTTOM: medium none;
+    BORDER-LEFT: medium none;
+    BORDER-RIGHT: medium none;
+    BORDER-TOP: medium none;
+}
+TD
+{
+    BACKGROUND-COLOR: #bedfff;
+    BORDER-BOTTOM: medium none;
+    BORDER-LEFT: medium none;
+    BORDER-RIGHT: medium none;
+    BORDER-TOP: medium none;
+    FONT-SIZE:x-small;
+    MARGIN: 2px;
+    PADDING-BOTTOM: 2px;
+    PADDING-LEFT: 2px;
+    PADDING-RIGHT: 2px;
+    PADDING-TOP: 2px;
+    TEXT-ALIGN: left
+}
+TH
+{
+    BACKGROUND-COLOR: #ffdfbe;
+    BORDER-BOTTOM: medium none;
+    BORDER-LEFT: medium none;
+    BORDER-RIGHT: medium none;
+    BORDER-TOP: medium none;
+    FONT-SIZE: x-small;
+    MARGIN: 2px;
+    PADDING-BOTTOM: 2px;
+    PADDING-LEFT: 2px;
+    PADDING-RIGHT: 2px;
+    PADDING-TOP: 2px;
+    TEXT-ALIGN: left
+}
+TH
+{
+    BACKGROUND-COLOR: #ffaa57
+}
+UL
+{
+    MARGIN-TOP: 0.5em
+}
+OL
+{
+    MARGIN-TOP: 0.5em
+}
+H1
+{
+    COLOR: #336699;
+    FONT-SIZE: x-large;
+    MARGIN-BOTTOM: 0.5em;
+    MARGIN-TOP: 1em;
+    PADDING-LEFT: 4px
+}
+H2
+{
+    BORDER-LEFT: #4e4887 8px solid;
+    BORDER-TOP: #4e4887 1px solid;
+    COLOR: #4e4887;
+    FONT-SIZE: medium;
+    MARGIN-BOTTOM: 0.5em;
+    MARGIN-TOP: 1em;
+    PADDING-LEFT: 4px
+}
+H3
+{
+    BORDER-LEFT: #4e4887 4px solid;
+    BORDER-TOP: #4e4887 1px solid;
+    COLOR: #4e4887;
+    FONT-SIZE: small;
+    MARGIN-BOTTOM: 0.5em;
+    MARGIN-TOP: 1em;
+    PADDING-LEFT: 4px
+}
+H4
+{
+    COLOR: #4e4887;
+    FONT-SIZE: small;
+    MARGIN-BOTTOM: 0.5em
+}
+H5
+{
+    COLOR: #4e4887;
+    FONT-SIZE: x-small;
+    MARGIN-BOTTOM: 0.5em
+}
+H6
+{
+    COLOR: #4e4887;
+    FONT-SIZE: x-small;
+    FONT-STYLE: italic;
+    MARGIN-BOTTOM: 0.5em
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docbuild/frames.htm
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docbuild/frames.htm	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docbuild/frames.htm	(revision 3)
@@ -0,0 +1,12 @@
+<html>
+<frameset rows="84,*">
+	<frame name="banner" scrolling="no" noresize src="banner.htm">
+	<frameset cols="200,*">
+		<frame name="contents" src="contents.htm">
+		<frame name="main" >
+	</frameset>
+	<noframes>
+		<p>This page requires frames, but your browser does not support them.</p>
+	</noframes>
+</frameset>
+</html>
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docbuild/litterature.htm
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docbuild/litterature.htm	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docbuild/litterature.htm	(revision 3)
@@ -0,0 +1,61 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+<head>
+<title>C5 collection classes - litterature references</title>
+<meta name="GENERATOR" content="Microsoft Visual Studio.NET 7.0">
+<meta name=ProgId content=VisualStudio.HTML>
+<meta name=Originator content="Microsoft Visual Studio.NET 7.0">
+</head>
+<body>
+<h1>C5 collection classes - litterature references</h1>
+<table border="1" cellspacing="0">
+    <tr>
+        <td>
+            <a name="CLRS">CLRS</a></td>
+        <td>Cormen, Leiserson, Rivest, Shamir: ...</td>
+    </tr>
+    <tr>
+        <td>
+            <a name="DSST">DSST</a></td>
+        <td>D, Sarnak, Sleator, Tarjan, ...</td>
+    </tr>
+    <tr>
+        <td>
+            <a name="Tarjan1">Tarjan1</a>Tarjan: (the booklet)</td>
+        <td></td>
+    </tr>
+    <tr>
+        <td>
+            <a name=""></a></td>
+        <td></td>
+    </tr>
+    <tr>
+        <td>
+            <a name=""></a></td>
+        <td></td>
+    </tr>
+    <tr>
+        <td>
+            <a name=""></a></td>
+        <td></td>
+    </tr>
+    <tr>
+        <td>
+            <a name=""></a></td>
+        <td></td>
+    </tr>
+    <tr>
+        <td>
+            <a name=""></a></td>
+        <td></td>
+    </tr>
+    <tr>
+        <td>
+            <a name=""></a></td>
+        <td></td>
+    </tr>
+</table>
+
+
+</body>
+</html>
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docbuild/userguide.htm
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docbuild/userguide.htm	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docbuild/userguide.htm	(revision 3)
@@ -0,0 +1,2519 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+<head>
+  <title>C5 User's Guide</title>
+  <style>
+<!--
+.revvid      { color: #FFFFFF; background-color: #00AA00; font-weight: bold }
+-->
+  </style>
+</head>
+<body>
+<h1><a class="mozTocH1" name="mozTocId905770"></a>C5 User's guide for
+prerelease version 0.5</h1>
+<h2><a class="mozTocH2" name="mozTocId507311"></a>Table of contents</h2>
+<ul class="readonly" id="mozToc">
+<!--mozToc h1 1 h2 2 h3 3 h4 4 h5 5 h6 6--><li><a href="#mozTocId905770">C5
+User's guide for prerelease version 0.5</a>
+    <ul>
+      <li><a href="#mozTocId507311">Table of contents</a></li>
+    </ul>
+  </li>
+  <li><a href="#mozTocId564527">Overview</a></li>
+  <li><a href="#mozTocId86956">Interfaces</a>
+    <ul>
+      <li><a href="#mozTocId21725">"Proper" collection interfaces</a></li>
+      <li><a href="#mozTocId721827">Dictionary interfaces</a></li>
+      <li><a href="#mozTocId908053">Query result interfaces</a></li>
+    </ul>
+  </li>
+  <li><a href="#mozTocId110895">To construct a collection</a>
+    <ul>
+      <li><a href="#mozTocId850165">To use an external equalityComparer</a></li>
+      <li><a href="#mozTocId162938">To use an external comparer</a></li>
+      <li><a href="#mozTocId957374">To make collections of collections</a></li>
+    </ul>
+  </li>
+  <li><a href="#mozTocId486186">Special topics</a>
+    <ul>
+      <li><a href="#mozTocId48263">To choose a set or bag collection</a></li>
+      <li><a href="#mozTocId929755">To work on part of a list: list
+views</a></li>
+      <li><a href="#mozTocId650306">To work with persistent red-black
+trees</a></li>
+      <li><a href="#mozTocId553609">To implement new collection classes
+or subclass an existing one</a></li>
+      <li><a href="#mozTocId753674">To present a read only view of a
+collection</a></li>
+    </ul>
+  </li>
+  <li><a href="#mozTocId6619">Collection classes by data structure/class</a></li>
+  <li><a href="#mozTocId393559">Planned architecture or interface
+changes for first release</a></li>
+  <li><a href="#mozTocId336849">Performance details for proper
+collection classes</a></li>
+  <li><a href="#mozTocId712409">Performance details for dictionary
+classes</a></li>
+</ul>
+<h1><a class="mozTocH1" name="mozTocId564527"></a>Overview<br>
+</h1>
+<p>C5 is a comprehensive library of collection classes for the <a
+ href="http://www.ecma-international.org/publications/standards/Ecma-335.htm">Common
+Language Infrastructure</a> (CLI). This guide describes prerelease
+version 0.5 of&nbsp; C5. <br>
+</p>
+<p>C5 is a
+refactoring and extension of the <a
+ href="http://www.dina.kvl.dk/%7Esestoft/gcsharp/index.html#collection">generic
+collection classes</a> developed by Peter Sestoft while visiting
+Microsoft
+Research in Cambridge.</p>
+<p> Unless stated otherwise types mentioned below will belong to the
+"C5"
+namespace; and all code examples assume a "using C5;" clause (and no
+"using System.Collection.Generics;" clause)..&nbsp;</p>
+<p>The goals in the development of the library has been</p>
+<ul>
+  <li>
+    <p class="MsoNormal"><span style="" lang="EN-US">To create a
+library of collection classes for the CLI that can assist expert and
+non-expert programmers on the platform to develop correct and efficient
+applications.</span> </p>
+  </li>
+  <li>
+    <p class="MsoNormal"><span style="" lang="EN-US">The library should
+at least fill the gaps in the standard &#8220;System.Collections.Generics&#8221;
+namespace compared to standard collection class libraries for related
+object oriented languages like Java, and utilize the new facilities for
+generic </span><span style="" lang="EN-US">programming. Microsoft
+recently (mid 2004) seems to have changed their minds and ntend to
+bridge that gap in the beta2 version of VS 2005 due at the end of 2004.</span>
+    </p>
+  </li>
+</ul>
+<p>In order to fulfill the efficiency goal, the library utilizes
+first-class <a href="#datastructures">data structures</a>
+inside its collection classes. The library has been constructed with
+the modern
+object oriented programming principle of&nbsp; "<a href="#Interfaces">code
+to interfaces, not to implementations</a>" in mind, while the interface
+architecture has been carefully crafted to reflect the efficient data
+structures
+actually existence.</p>
+<p>A collection in the sense of this library is a plain "collection of
+items of a single type". A collection does not impose any other logical
+structure on its items than perhaps uniqueness or sequence ordering.</p>
+<p>The main division line among the collection classes of this library
+is the
+distinction between <a href="#Proper%20collection%20interfaces">"proper"
+collections</a> and <a href="#Dictionary%20interfaces">dictionaries</a>.
+A
+dictionary is a class that defines a partial function (or map) from one
+item
+type (the keys) to another one (the values). A dictionary can be viewed
+as a
+collection of (key,value) pairs having the property of defining a
+partial
+function.</p>
+<p>The item type for the collection classes are always given by generic
+parameters. For a proper collection, there will be a single parameter,
+customarily called T, as in HashSet&lt;T&gt;. For a dictionary there
+will be two - the key and value types -
+as in HashDictionary&lt;K,V&gt;.</p>
+<p>A collection class, or rather the data structure inside, can be
+either
+equality based or comparison based. An equality based collection will
+have an
+associated so-called equalityComparer of type <a href="main.htm#T:C5.IEqualityComparer%601">IEqualityComparer&lt;T&gt;</a>,
+where T is the item type of the collection. A comparison based
+collection has an
+associated comparer of type <a href="main.htm#T:C5.IComparer%601">IComparer&lt;T&gt;</a>.
+The section below on <a href="#Constructing">creation</a> of
+collection classes
+explains how the equalityComparers and comparers are chosen. NB: this design will
+be modified soon, cf. <a href="#planned">Planned changes</a>.<br>
+</p>
+<p>Collection classes in the library have either set or bag semantics.
+A set
+collection can at most contain one copy of an item, while bag
+collections may
+contain several. One can programmatically see at runtime if an editable
+collection class has set or bag semantics by checking the <a
+ href="main.htm#P:C5.IExtensible%601.AllowsDuplicates">
+AllowsDuplicates</a>
+property. At compile time, refer to the <a href="#set%20or%20bag">set
+or bag table</a>
+below for an overview. <br>
+</p>
+<h1><a class="mozTocH1" name="mozTocId86956"></a><a name="Interfaces">Interfaces</a></h1>
+<p>The C5 library is designed to make it easy to program to interfaces
+instead
+of implementations. In particular, all public properties and methods of
+the
+collection classes belong to their implemented interfaces (except for
+the odd
+special diagnostic method and the odd mistake to be weeded out before
+release). The typical programming style
+would be</p>
+<blockquote>
+  <p><code>IList&lt;int&gt; lst = new LinkedList&lt;int&gt;();<br>
+lst.Add(7);</code></p>
+</blockquote>
+<p>instead of&nbsp;</p>
+<blockquote>
+  <p><code> LinkedList&lt;int&gt; lst = new LinkedList&lt;int&gt;();<br>
+lst.Add(7);</code></p>
+</blockquote>
+<p>Note that with this programming style, the Add call will be compiled
+to an
+interface call instead of a (virtual) method call, but interface calls
+on the
+CLR (at least the Microsoft implementation) are at most very slightly
+slower
+than virtual calls, so one should not shun the interface style for
+performance
+reasons.</p>
+<p>We will discuss the collection classes available in C5 structured
+according
+to the main functional interfaces of the <a
+ href="#Proper%20collection%20interfaces">proper
+collections</a>, the <a href="#Dictionary%20interfaces">dictionaries</a>
+and the
+interfaces of <a href="#Query%20result%20interfaces">query results</a>.</p>
+<h2><a class="mozTocH2" name="mozTocId21725"></a><a
+ name="Proper collection interfaces">"Proper" collection interfaces</a></h2>
+<p>The following diagam shows the type hierarchy of the proper
+collection classes:</p>
+<p><img alt="Interface hierarchy" src="ClsdiagWork.png"
+ style="width: 757px; height: 498px;"><br>
+The&nbsp;most important interfaces - those that are directly
+implemented by
+collection classes - are listed to the left in this table with a short
+description in the middle and all implementing classes to the
+right.&nbsp;</p>
+<p>Please see also the <a href="#PerformanceProper">complete
+complexity table</a>
+for more comprehensive guidance.</p>
+<p>To identify which classes are equalityComparer or comparer based and which
+classes
+implement set or bag we use the following symbols:</p>
+<table border="1" width="471">
+  <tbody>
+    <tr>
+      <td width="116">set: <code class="revvid">S</code> </td>
+      <td width="117"> bag: <code class="revvid">B</code> </td>
+      <td width="117"> equalityComparer: <code class="revvid">H</code> </td>
+      <td width="117"> comparer: <code class="revvid">C</code> </td>
+    </tr>
+  </tbody>
+</table>
+<table border="1" width="100%">
+  <tbody>
+    <tr>
+      <th width="19%">Interface</th>
+      <th width="52%">Short description</th>
+      <th width="29%">Implementing classes</th>
+    </tr>
+    <tr>
+      <td valign="top" width="19%"><a
+ href="main.htm#T:C5.ICollection%601">ICollection&lt;T&gt;</a>&nbsp;</td>
+      <td valign="top" width="52%">This is the fundamental&nbsp;type
+of&nbsp; updateable collections. It has operations for searching for
+items, for adding, updating and removing one or a bunch of items, for
+clearing the collection and transforming the collection to an
+array.&nbsp;
+      <p>If one only needs these operations, the hash set and hash bag
+classes are fastest for if we have a equalityComparer for the items and the
+red-black tree classes are fastest if we must use a comparer.</p>
+      </td>
+      <td valign="top" width="29%"><code class="revvid">SH</code> <a
+ href="main.htm#T:C5.HashSet%601">HashSet&lt;T&gt;</a><br>
+      <code class="revvid">BH</code> <a
+ href="main.htm#T:C5.HashBag%601">HashBag&lt;T&gt;</a><br>
+      <code class="revvid">BH</code> <a
+ href="main.htm#T:C5.LinkedList%601">LinkedList&lt;T&gt;</a><br>
+      <code class="revvid">SH</code> <a
+ href="main.htm#T:C5.HashedLinkedList%601">HashedLinkedList&lt;T&gt;</a><br>
+      <code class="revvid">BH</code> <a
+ href="main.htm#T:C5.ArrayList%601">ArrayList&lt;T&gt;</a><br>
+      <code class="revvid">SH</code> <a
+ href="main.htm#T:C5.HashedArrayList%601"> HashedArrayList&lt;T&gt;<br>
+      </a> <code class="revvid">SC</code> <a
+ href="main.htm#T:C5.SortedArray%601"> SortedArray&lt;T&gt;</a><br>
+      <code class="revvid">SC</code> <a
+ href="main.htm#T:C5.TreeSet%601"> TreeSet&lt;T&gt;</a><br>
+      <code class="revvid">BC</code> <a
+ href="main.htm#T:C5.TreeBag%601"> TreeBag&lt;T&gt;</a></td>
+    </tr>
+    <tr>
+      <td valign="top" width="19%"><a
+ href="main.htm#T:C5.IPriorityQueue%601">IPriorityQueue&lt;T&gt;</a>&nbsp;</td>
+      <td valign="top" width="52%">This is a special case in the
+library, being the only type of updateable collection interface that
+does not implement IEditableCollection&lt;T&gt;. The reason for its
+presence is the specialized "heap" data structures for priority queues
+that only support these operations.
+      <p>If one only needs these the priority queue operations and is
+satisfied with bag semantics, then IntervalHeap&lt;P&gt;&nbsp; is the
+fastest choice. </p>
+      </td>
+      <td valign="top" width="29%"> <code class="revvid">BC</code> <a
+ href="main.htm#T:C5.IntervalHeap%601">IntervalHeap&lt;T&gt;</a><br>
+      <code class="revvid">SC</code> <a
+ href="main.htm#T:C5.TreeSet%601"> TreeSet&lt;T&gt;</a><br>
+      <code class="revvid">BC</code> <a
+ href="main.htm#T:C5.TreeBag%601"> TreeBag&lt;T&gt;</a></td>
+    </tr>
+    <tr>
+      <td valign="top" width="19%"><a href="main.htm#T:C5.IList%601">IList&lt;T&gt;</a>&nbsp;</td>
+      <td valign="top" width="52%">This is an updateable collection
+with sequence order imposed on the items by the user at insertion time
+or by later rearrangements.&nbsp;
+      <p>There are two main base data structures: dynamic arrays and
+doubly linked lists with very different complexity profile.&nbsp;The
+plain linked list is fast for operations at the end points only, while
+the plain array list have very fast lookups by index, but update
+operations are only fast at the right end point.&nbsp;</p>
+      <p>The Hashed- variants employ an index based on a hash table.
+This speeds up lookups by item considerably and for the linked list
+variant also insertions before or after specific items. The index
+changes the classes from bags to sets.&nbsp;</p>
+      <p>The hashed variants more than double the time of otherwise
+fast update operations, and should only be used when really
+needed.&nbsp;</p>
+      </td>
+      <td valign="top" width="29%"> <code class="revvid">BH</code> <a
+ href="main.htm#T:C5.LinkedList%601"> LinkedList&lt;T&gt;</a><br>
+      <code class="revvid">SH</code> <a
+ href="main.htm#T:C5.HashedLinkedList%601"> HashedLinkedList&lt;T&gt;</a><br>
+      <code class="revvid">BH</code> <a
+ href="main.htm#T:C5.ArrayList%601"> ArrayList&lt;T&gt;</a><br>
+      <code class="revvid">SH</code> <a
+ href="main.htm#T:C5.HashedArrayList%601"> HashedArrayList&lt;T&gt;</a></td>
+    </tr>
+    <tr>
+      <td valign="top" width="19%"><a
+ href="main.htm#T:C5.IIndexedSorted%601">IIndexedSorted&lt;T&gt;</a>&nbsp;</td>
+      <td valign="top" width="52%">This is an updateable collection
+with sequence order given by a comparer.&nbsp;
+      <p>There are two main data structures inside the implementations:
+red-black search trees and a dynamic array kept sorted at all times.</p>
+      <p>The differences are chiefly that the trees have much faster
+update operations, while the sorted array is somewhat faster at index
+lookups. In fact, the sorted array should only be used for static
+operation, where the collection is created and populated and then not
+changed again. </p>
+      </td>
+      <td valign="top" width="29%"> <code class="revvid">SC</code> <a
+ href="main.htm#T:C5.SortedArray%601"> SortedArray&lt;T&gt;</a><br>
+      <code class="revvid">SC</code> <a
+ href="main.htm#T:C5.TreeSet%601"> TreeSet&lt;T&gt;</a><br>
+      <code class="revvid">BC</code> <a
+ href="main.htm#T:C5.TreeBag%601"> TreeBag&lt;T&gt;</a></td>
+    </tr>
+    <tr>
+      <td valign="top" width="19%"><a
+ href="main.htm#T:C5.IPersistentSorted%601">IPersistentSorted&lt;T&gt;</a>&nbsp;</td>
+      <td valign="top" width="52%">This is a sorted collection that
+support very fast clones that themselves are sorted. The only
+implementation is the tree implementation with set and bag variants. </td>
+      <td valign="top" width="29%"> <code class="revvid">SC</code> <a
+ href="main.htm#T:C5.TreeSet%601"> TreeSet&lt;T&gt;</a><br>
+      <code class="revvid">BC</code> <a
+ href="main.htm#T:C5.TreeBag%601"> TreeBag&lt;T&gt;</a></td>
+    </tr>
+  </tbody>
+</table>
+<h2><a class="mozTocH2" name="mozTocId721827"></a><a
+ name="Dictionary interfaces">Dictionary interfaces</a></h2>
+<p>There are two dictionary interfaces:</p>
+<table border="1" width="100%">
+  <tbody>
+    <tr>
+      <th valign="top" width="19%">Interface</th>
+      <th width="56%">Short description</th>
+      <th width="25%">Implementing classes</th>
+    </tr>
+    <tr>
+      <td valign="top" width="19%"><a
+ href="main.htm#T:C5.IDictionary%602">IDictionary&lt;K,V&gt;</a> </td>
+      <td width="56%">This is the base dictionary interface.&nbsp;
+      <p>The choice is that one should use the hash dictionary unless
+one only has a comparer for the items, in which case the tree
+dictionary can be used.&nbsp; </p>
+      </td>
+      <td width="25%"><a href="main.htm#T:C5.HashDictionary%602">HashDictionary&lt;K,V&gt;</a><br>
+      <a href="main.htm#T:C5.TreeDictionary%602">TreeDictionary&lt;K,V&gt;</a></td>
+    </tr>
+    <tr>
+      <td valign="top" width="19%"><a
+ href="main.htm#T:C5.ISortedDictionary%602">ISortedDictionary&lt;K,V&gt;</a>
+      </td>
+      <td width="56%">This is a dictionary based on a comparer for the
+keys. There is only the tree implementation.&nbsp; </td>
+      <td width="25%"><a href="main.htm#T:C5.TreeDictionary%602">TreeDictionary&lt;K,V&gt;</a></td>
+    </tr>
+  </tbody>
+</table>
+<h2><a class="mozTocH2" name="mozTocId908053"></a><a
+ name="Query result interfaces">Query result interfaces</a></h2>
+<p>Some of the most basic collection interfaces have an important usage
+as the
+types of results of queries to collections, although these interfaces
+also
+appear at the base of the other collection interfaces and even as the
+types of
+synthetic collections. The interfaces in question are the standard
+System.Collections.Generics.IEnumerable&lt;T&gt;,
+<a href="main.htm#T:C5.ICollectionValue%601">ICollectionValue&lt;T&gt;</a>,
+<a href="main.htm#T:C5.IDirectedEnumerable%601">IDirectedEnumerable&lt;T&gt;</a>
+and <a href="main.htm#T:C5.IDirectedCollectionValue%601">IDirectedCollectionValue&lt;T&gt;</a>.</p>
+<p>The differences between the "Enumerable" and "Collection"
+variants are that the "Enumerable" variant only knows how to
+enumerate through its items, the "Collection" variants also knows how
+many items it has (without having to walk through an enumeration). The
+"Directed" variants are used for results of queries to sequenced
+collections (implementing <a href="main.htm#T:C5.ISequenced%601">ISequenced&lt;T&gt;</a>)
+and therefore have a non-implementation dependent enumeration order.
+The
+"Directed" variants supports two operations, <a
+ href="main.htm#M:C5.IDirectedCollectionValue%601.Backwards">Backwards()</a>
+to enable enumeration in the opposite direction and <a
+ href="main.htm#P:C5.IDirectedEnumerable%601.Direction">Direction</a>
+to tell if the enumeration order is forwards or backwards with respect
+to the
+original collection.</p>
+<p>Note: operations on an enumerator created by the GetEnumerator()
+method on System.Collections.Generics.IEnumerable&lt;T&gt; cannot be
+interleaved with update
+operations on
+the underlying collection.</p>
+<p>Note: for all enumerators in the library the operations have O(1)
+amortized
+complexity.</p>
+<h1><a class="mozTocH1" name="mozTocId110895"></a>To <a
+ name="Constructing">construct</a> a collection</h1>
+<p>All collections classes in C5 have (zero parameter) default
+constructors. So
+if we want to make a linked list of items of some type, <code>TheType</code>,
+and add an item to the list we will do</p>
+<p><code>&nbsp;&nbsp;&nbsp; IList&lt;TheType&gt; lst = new
+LinkedList&lt;TheType&gt;();<br>
+&nbsp;&nbsp;&nbsp; TheType t = ...;<br>
+&nbsp;&nbsp;&nbsp; lst.Add(t);</code></p>
+<p>The collection classes have no constructors that will take an array
+or a
+collection as parameter for prepopulating the collection, use the <a
+ href="file:///C:/home/kokholm/c5/vs/C5/main.htm#M:C5.ISink%601.AddAll%28C5.IEnumerable%7B%210%7D%29">
+AddAll</a> method
+instead. NB: in the released version, expect constructors with an
+enumerable as argument and constructors with a variable number of
+arguments ("params") for the initialization of the collection, see the <a
+ href="#planned">planned changes</a> section.<br>
+</p>
+<p>Some collection classes are governed by internal parameters that one
+can give
+non-default values at creation time (<code>fill</code> in <a
+ href="main.htm#T:C5.HashSet%601">HashSet&lt;T&gt;</a>,&nbsp;
+<a href="main.htm#T:C5.HashBag%601">HashBag&lt;T&gt;</a>, <a
+ href="main.htm#T:C5.HashDictionary%602">HashDictionary&lt;K,V&gt;</a>)
+or use internal tables that one can expand in advance if one has
+expectations of
+how large the collection will grow (HashSet&lt;T&gt;,&nbsp;
+HashBag&lt;T&gt;, HashDictionary&lt;K,V&gt;, <a
+ href="main.htm#T:C5.ArrayList%601">ArrayList&lt;T&gt;</a>,
+<a href="main.htm#T:C5.HashedArrayList%601"> HashedArrayList&lt;T&gt;</a>,
+<a href="main.htm#T:C5.SortedArray%601">SortedArray&lt;T&gt;</a>,
+<a href="main.htm#T:C5.IntervalHeap%601">IntervalHeap&lt;T&gt;</a>).</p>
+<p>For equality-based collection classes, these constructors will use a
+default
+equalityComparer to define equality of items according to the following table:</p>
+<table border="1">
+  <tbody>
+    <tr>
+      <th>T</th>
+      <th>default equalityComparer (implements IEqualityComparer&lt;T&gt;)</th>
+      <th>Equality and hash code by</th>
+    </tr>
+    <tr>
+      <td>int</td>
+      <td><a href="main.htm#T:C5.IntEqualityComparer">IntEqualityComparer</a></td>
+      <td>Equals and hash code of integer</td>
+    </tr>
+    <tr>
+      <td>other value type</td>
+      <td><a href="main.htm#T:C5.DefaultValueTypeEqualityComparer%601">DefaultValueTypeEqualityComparer&lt;T&gt;</a></td>
+      <td>methods inherited from object</td>
+    </tr>
+    <tr>
+      <td>IEditableCollection&lt;S&gt;</td>
+      <td><a href="main.htm#T:C5.EqualityComparerBuilder.UnsequencedEqualityComparer%602">EqualityComparerBuilder.UnsequencedEqualityComparer&lt;S,IEditableCollection&lt;S&gt;&gt;</a></td>
+      <td>contents without regards to sequence</td>
+    </tr>
+    <tr>
+      <td>ISequenced&lt;S&gt;</td>
+      <td><a href="main.htm#T:C5.EqualityComparerBuilder.SequencedEqualityComparer%602">EqualityComparerBuilder.SequencedEqualityComparer&lt;S,IEditableCollection&lt;S&gt;&gt;</a></td>
+      <td>contents with regards to sequence</td>
+    </tr>
+    <tr>
+      <td>other reference type</td>
+      <td><a href="main.htm#T:C5.DefaultReferenceTypeEqualityComparer%601">DefaultReferenceTypeEqualityComparer&lt;T&gt;</a></td>
+      <td>methods inherited from object</td>
+    </tr>
+  </tbody>
+</table>
+<p>For comparison-based collection classes, these constructors will use
+a
+default comparer:</p>
+<table border="1">
+  <tbody>
+    <tr>
+      <th>T</th>
+      <th>default comparer&nbsp;<br>
+(implements IComparer&lt;T&gt;)</th>
+      <th>Comparison by</th>
+    </tr>
+    <tr>
+      <td>int</td>
+      <td>IC</td>
+      <td>Standard integer comparison</td>
+    </tr>
+    <tr>
+      <td>implementing IComparable&lt;T&gt;</td>
+      <td><a href="main.htm#T:C5.NaturalComparer%601">NaturalComparer&lt;T&gt;</a></td>
+      <td>The CompareTo(T o)&nbsp; instance method</td>
+    </tr>
+    <tr>
+      <td>other implementing System.IComparable</td>
+      <td><a href="main.htm#T:C5.NaturalComparerO%601">NaturalComparerO&lt;T&gt;</a></td>
+      <td>The CompareTo(object o) instance method</td>
+    </tr>
+    <tr>
+      <td>other</td>
+      <td>-</td>
+      <td><i>collection class constructor throws an exception</i></td>
+    </tr>
+  </tbody>
+</table>
+<p>Sometimes, the default equalityComparer or comparer is not the right one for
+the
+problem at hand. In that case one must get hold on a equalityComparer or comparer
+of the
+right kind and supply it to one of the constructors of the collection
+classes
+that supports such a parameter. The procedure is demonstrated in the
+sections
+below on <a href="#external%20equalityComparer">external equalityComparers</a>, <a
+ href="#external%20comparer">external
+comparers</a> and <a href="#collections%20of%20collections">collections
+as items</a>.<br>
+</p>
+<p>NB: in the released version, expect the equalityComparers and comparers to be
+of the System.Collections.Generics.IComparer&lt;T&gt; type, see the <a
+ href="userguide.htm#planned">planned changes</a> section.</p>
+<h2><a class="mozTocH2" name="mozTocId850165"></a>To use an <a
+ name="external equalityComparer"> external equalityComparer</a></h2>
+<p>In addition to the helper classes referenced above, the library has
+the
+helper class <a href="main.htm#T:C5.KeyValuePairEqualityComparer%602">KeyValuePairEqualityComparer&lt;K,V&gt;</a>
+to construct a equalityComparer for pairs of the type <a
+ href="main.htm#T:C5.KeyValuePair%602">KeyValuePair&lt;K,V&gt;</a>,
+the type of entry of a K to V dictionary. The constructed equalityComparer will
+only take
+the first component of the pair into account. We can use these classes
+in the
+following way to make a linked list (with hash index) of pairs of
+strings
+identified by their first components using some custom equalityComparer on
+strings:</p>
+<blockquote>
+  <p><code>IEqualityComparer&lt;string&gt; csh = ...;<br>
+IEqualityComparer&lt;KeyValuePair&lt;string,string&gt;&gt; cph =&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+new KeyValuePairEqualityComparer&lt;string,string&gt;(csh);<br>
+IList&lt;KeyValuePair&lt;string,string&gt;&gt; lst =<br>
+  </code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<code>
+new HashedLinkedList&lt;KeyValuePair&lt;string,string&gt;&gt;(cph);<br>
+lst.Add(new KeyValuePair&lt;string,string&gt;("abe","kat"));</code></p>
+</blockquote>
+<p>One may, of course, program a equalityComparer oneself. This one should always
+do if
+the item type is defined as a struct (value type) that does not
+override the
+Equals and GetHashCode methods of object, since in that case the
+default equalityComparer
+will use the slow default versions of those methods supplied by the
+runtime via
+reflection.&nbsp;</p>
+<h2><a class="mozTocH2" name="mozTocId162938"></a>To use an <a
+ name="external comparer"> external comparer</a></h2>
+<p>There is a helper class for comparer of pairs: <a
+ href="main.htm#T:C5.KeyValuePairEqualityComparer%602">KeyValuePairComparer&lt;K,V&gt;</a>.
+We will show an example of a custom comparer. Imagine wanting to
+compare double
+precision floating point numbers with a tolerance. The following code
+snippet
+shows how one could make a tree set out of such numbers:</p>
+<blockquote>
+  <p><code>class DC : IComparer&lt;double&gt; {<br>
+&nbsp;&nbsp; const double eps = 1E-10;<br>
+&nbsp;&nbsp; int Compare(double a, double b)&nbsp;<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {return a &gt; b + eps ? 1 : a &lt; b -
+eps ? -1 : 0;}<br>
+}<br>
+  <br>
+void dowork() {<br>
+&nbsp;&nbsp; IComparer&lt;double&gt; dc = new DC();<br>
+&nbsp;&nbsp; ISorted&lt;double&gt; tree = new TreeSet&lt;double&gt;(dc);<br>
+&nbsp;&nbsp; tree.Add(3.45);<br>
+&nbsp;&nbsp; ...<br>
+}</code></p>
+</blockquote>
+<p>In this particular case, one would have to make sure, that two
+different
+floating point numbers are only identified by the comparer if they
+really should
+represent the same value and not by coincidence.</p>
+<h2><a class="mozTocH2" name="mozTocId957374"></a>To make <a
+ name="collections of collections"> collections of collections</a></h2>
+<p>When one wants to use a collection whose items itself are of
+collection type,
+one usually wants the interior collections to be identified by contents
+- either
+according to or irrespective of sequence order. An example could be
+transformations of <a
+ href="http://www.dina.kvl.dk/%7Esestoft/gcsharp/index.html#regexp">Finite
+Automatons</a>. The default equalityComparers and the EqualityComparerBuilder classes
+mentioned
+above may help to construct such collections of collections as in the
+examples
+that follow:</p>
+<p>To make an array list of sequenced collections identified by
+contents in
+sequenced fashion one would simply do:</p>
+<blockquote>
+  <p><code>ArrayList&lt;ISequenced&lt;int&gt;&gt; lst = new
+ArrayList&lt;ISequenced&lt;int&gt;&gt;();</code></p>
+</blockquote>
+<p>To make a linked list of linked lists identified by contents
+unsequenced, explicitly
+construct the collection equalityComparer:</p>
+<blockquote>
+  <p><code>IEqualityComparer&lt;LinkedList&lt;int&gt;&gt; lsth =<br>
+  </code>&nbsp;&nbsp;&nbsp;&nbsp; <code>new
+EqualityComparerBuilder.UnsequencedEqualityComparer&lt;int,LinkedList&lt;int&gt;&gt;();<br>
+LinkedList&lt;LinkedList&lt;int&gt;&gt; lst =<br>
+&nbsp;&nbsp; new LinkedList&lt;LinkedList&lt;int&gt;&gt;(lsth);</code></p>
+</blockquote>
+<p>If for some strange reason one would like to make a hash set of
+linked lists
+with the lists identified by reference equality one would simply do:</p>
+<blockquote>
+  <p><code>HashSet&lt;LinkedList&lt;int&gt;&gt; lst = new
+HashSet&lt;LinkedList&lt;int&gt;&gt;();</code></p>
+</blockquote>
+<p>If for even stranger reasons one would make a hash set of
+ISequenced&lt;int&gt; collections with the collections identified by
+reference
+equality one would do like this:</p>
+<blockquote>
+  <p><code>IEqualityComparer&lt;</code><code>ISequenced</code><code>&lt;int&gt;&gt;
+lsth =<br>
+  </code>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <code>new
+DefaultReferenceTypeEqualityComparer&lt;</code><code>ISequenced</code><code>&lt;int&gt;&gt;();<br>
+HashSet&lt;</code><code>ISequenced</code><code>&lt;int&gt;&gt; lst =<br>
+&nbsp;&nbsp; new HashSet&lt;</code><code>ISequenced</code><code>&lt;int&gt;&gt;(lsth);</code></p>
+</blockquote>
+<h1><a class="mozTocH1" name="mozTocId486186"></a>Special topics</h1>
+<h2><a class="mozTocH2" name="mozTocId48263"></a>To choose a <a
+ name="set or bag"> set or bag</a> collection</h2>
+<p>The following table shows which of the collection classes have set
+semantics
+and which have bag semantics. All the implemented classes have fixed,
+compiled in semantics. <br>
+</p>
+<p>Note: when in a set collection, methods with an Add in the name will
+ignore
+attempts to add an item already there or flag the failed attempt by a
+Boolean return value; methods with an Insert in the name (only in
+lists) will throw an
+exception.</p>
+<table border="1" width="38%">
+  <tbody>
+    <tr>
+      <td valign="top" width="6%"><a href="main.htm#T:C5.HashSet%601">HashSet&lt;T&gt;</a></td>
+      <td valign="top" width="5%">set</td>
+    </tr>
+    <tr>
+      <td valign="top" width="6%"> <a href="main.htm#T:C5.HashBag%601">HashBag&lt;T&gt;</a></td>
+      <td valign="top" width="5%">bag</td>
+    </tr>
+    <tr>
+      <td valign="top" width="6%"> <a
+ href="main.htm#T:C5.LinkedList%601"> LinkedList&lt;T&gt;</a></td>
+      <td valign="top" width="5%">bag</td>
+    </tr>
+    <tr>
+      <td valign="top" width="6%"> <a
+ href="main.htm#T:C5.HashedLinkedList%601"> HashedLinkedList&lt;T&gt;</a></td>
+      <td valign="top" width="5%">set</td>
+    </tr>
+    <tr>
+      <td valign="top" width="6%"> <a
+ href="main.htm#T:C5.ArrayList%601"> ArrayList&lt;T&gt;</a></td>
+      <td valign="top" width="5%">bag</td>
+    </tr>
+    <tr>
+      <td valign="top" width="6%"> <a
+ href="main.htm#T:C5.HashedArrayList%601"> HashedArrayList&lt;T&gt; </a>
+      </td>
+      <td valign="top" width="5%">set</td>
+    </tr>
+    <tr>
+      <td valign="top" width="6%"> <a
+ href="main.htm#T:C5.SortedArray%601"> SortedArray&lt;T&gt;</a></td>
+      <td valign="top" width="5%">set</td>
+    </tr>
+    <tr>
+      <td valign="top" width="6%"> <a href="main.htm#T:C5.TreeSet%601">TreeSet&lt;T&gt;</a></td>
+      <td valign="top" width="5%">set</td>
+    </tr>
+    <tr>
+      <td valign="top" width="6%"> <a href="main.htm#T:C5.TreeBag%601">TreeBag&lt;T&gt;</a></td>
+      <td valign="top" width="5%">bag</td>
+    </tr>
+    <tr>
+      <td valign="top" width="6%"><a
+ href="main.htm#T:C5.IntervalHeap%601">IntervalHeap&lt;T&gt;</a></td>
+      <td valign="top" width="5%">bag</td>
+    </tr>
+  </tbody>
+</table>
+<h2><a class="mozTocH2" name="mozTocId929755"></a>To work on part of a
+list: list views</h2>
+<p>The IList&lt;T&gt; interface supports via the <a
+ href="main.htm#M:C5.IList%601.View%28System.Int32,System.Int32%29">
+View</a>
+method the functionality that one can zoom in on part of a list and use
+it as an
+IList&lt;T&gt; in its own right while having updates to the view passed
+through
+to the base (original) IList&lt;T&gt;. Using the <a
+ href="main.htm#M:C5.IList%601.Slide%28System.Int32%29">Slide</a>
+method calls, one may move the view around the base list. Using Slide
+repeatedly
+one can implement safe ways to iterate over a list while updating it.
+The
+IList&lt;T&gt; interface also has properties <a
+ href="main.htm#P:C5.IList%601.Underlying">Underlying</a>
+and <a href="main.htm#P:C5.IList%601.Offset">Offset</a> showing the
+base list of a
+view and the current site of a view.</p>
+<p>One can create a view on a view, but the new view will have the
+original base
+list as base. A view will be invalidated if an update operation is
+performed on
+the base list by any other means than through this particular view.</p>
+<p>The following code snippet shows a silly example of iterating over a
+list,
+doing an insertion each time certain combination of items are seen (the
+example
+iterates right to left and inserts 666 whenever two consecutive items
+have an
+odd difference):</p>
+<blockquote>
+  <p><code>IList&lt;int&gt; lst = ...;<br>
+IList&lt;int&gt; view = lst.CreateView(lst.Count-2, 2);<br>
+while (true) {<br>
+&nbsp;&nbsp;&nbsp; if ((view.Last - view.First) % 2 == 1)<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; view.Insert(1, 666);<br>
+&nbsp;&nbsp;&nbsp; if (view.Offset == 0)<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; break;<br>
+&nbsp;&nbsp;&nbsp; else<br>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; view.Slide(-1,2);<br>
+}</code></p>
+</blockquote>
+<h2><a class="mozTocH2" name="mozTocId650306"></a>To work with
+persistent red-black trees</h2>
+<p>The search tree implementation in the library is based on node copy
+persistent red-black trees. The persistence is exposed in the <a
+ href="main.htm#M:C5.IPersistentSorted%601.Snapshot">Snapshot</a>
+method that can be considered a very fast and space-saving way of
+making a
+read-only clone of the tree. When using persistence, the space use of a
+red-black tree in this implementation is linear in the number of
+operations
+since the creation of the tree.</p>
+<p>One use of persistence could be to safely enumerate a tree
+interleaved with
+updates:</p>
+<blockquote>
+  <p><code>IPersistentSorted&lt;int&gt; tree = new TreeSet&lt;int&gt;();<br>
+tree.Add(5);<br>
+...<br>
+ISorted&lt;int&gt; snap = tree.Snapshot();<br>
+foreach (int i in snap)<br>
+&nbsp;&nbsp;&nbsp; tree.Add(i+7);</code></p>
+</blockquote>
+<p>The GUITester project of the complete library source code contains
+an
+interesting (standard) usage of persistent search trees to the
+geometric problem
+of constructing an efficient data structure for point location in a
+division of
+the plane given by a list of line segments.</p>
+<h2><a class="mozTocH2" name="mozTocId553609"></a>To implement new
+collection classes or subclass an existing one</h2>
+<p>All interface methods and properties of the collection classes
+implemented in
+the library are virtual and so it should be safe to subclass these
+classes. Some
+classes may have protected members if they are subclassed in the
+library itself.
+We refer to the detailed reference manuals and the library source for
+information on the protected members and their role in subclassing.</p>
+<p>There is a sequence of helper classes designed to be used as base
+classes of
+collection classes: <a href="main.htm#T:C5.EnumerableBase%601">EnumerableBase&lt;T&gt;</a>,
+<a href="main.htm#T:C5.CollectionValueBase%601">CollectionValueBase&lt;T&gt;</a>,
+<a href="main.htm#T:C5.CollectionBase%601">CollectionBase&lt;T&gt;</a>,
+<a href="main.htm#T:C5.SequencedBase%601">SequencedBase&lt;T&gt;</a>
+and <a href="main.htm#T:C5.ArrayBase%601">ArrayBase&lt;T&gt;</a>.
+Please see the reference manual and the library source code for
+documentation
+and examples.</p>
+<p>As for dictionaries, the DictionaryBase&lt;K,V&gt; class will
+construct a
+class implementing IDictionary&lt;K,V&gt; by simply plugging in a set
+implementation.</p>
+<h2><a class="mozTocH2" name="mozTocId753674"></a>To present a read
+only view of a collection</h2>
+<p>The library contains a long list of wrapper classes all with name
+starting
+with Guarded having the purpose of creating a read-only view of an
+existing
+collection. The wrapping is done by the constructors of the classes. If
+we want
+to give some code access to only lookup operations on a, say, list we
+can do as
+follows:</p>
+<blockquote>
+  <p><code>IList&lt;int&gt; lst;<br>
+...<br>
+IList&lt;int&gt; rolst = new GList&lt;int&gt;(lst);<br>
+OtherObject.dowork(rolst);</code></p>
+</blockquote>
+<p>Please see the reference manual for details on available wrapper
+classes.</p>
+<h1><a class="mozTocH1" name="mozTocId6619"></a><a name="datastructures">Collection
+classes by data structure/class</a></h1>
+<p>The following table&nbsp;shows the underlying data structure of the
+various collection classes.</p>
+<table border="1">
+  <tbody>
+    <tr>
+      <th>Data structure</th>
+      <th>Classes</th>
+      <th>Primary Interfaces</th>
+    </tr>
+    <tr>
+      <td>hash table</td>
+      <td>HashSet&lt;T&gt;</td>
+      <td> ICollection&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>hash table</td>
+      <td>HashBag&lt;T&gt;</td>
+      <td> ICollection&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>hash table</td>
+      <td>HashDictionary&lt;K,V&gt;</td>
+      <td>IDictionary&lt;K,V&gt;</td>
+    </tr>
+    <tr>
+      <td>linked list</td>
+      <td>LinkedList&lt;T&gt;</td>
+      <td>IList&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>linked list with hash index</td>
+      <td>HashedLinkedList&lt;T&gt;</td>
+      <td>IList&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>dynamic array</td>
+      <td>ArrayList&lt;T&gt;</td>
+      <td>IList&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>dynamic array with hash index</td>
+      <td>HashedArrayList&lt;T&gt;</td>
+      <td>IList&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>sorted dynamic array</td>
+      <td>SortedArray&lt;T&gt;</td>
+      <td>IIndexedSorted&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>heap</td>
+      <td>IntervalHeap&lt;T&gt;</td>
+      <td>IPriorityQueue&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>red-black search tree</td>
+      <td>TreeSet&lt;T&gt;</td>
+      <td>IIndexedSorted&lt;T&gt;, IPersistentSorted&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>red-black search tree</td>
+      <td>TreeBag&lt;T&gt;</td>
+      <td>IIndexedSorted&lt;T&gt;, IPersistentSorted&lt;T&gt;</td>
+    </tr>
+    <tr>
+      <td>red-black search tree</td>
+      <td>TreeDictionary&lt;K,V&gt;</td>
+      <td>ISortedDictionary&lt;K,V&gt;</td>
+    </tr>
+  </tbody>
+</table>
+<br>
+<h1><a class="mozTocH1" name="mozTocId393559"></a>&lt;&gt;<a
+ name="planned"></a>Planned<span style="font-weight: bold;"> </span>architecture
+or interface changes
+for first release<br>
+</h1>
+<ol>
+  <li>Eliminate the use of our own generic equality/comparator types,
+C5.IComparer&lt;T&gt; and C5.IEqualityComparer&lt;T&gt; and use the new design of
+VS 2005 beta1 in the form of the combined
+System.Collections.Generic.IComparer&lt;T&gt;.</li>
+  <li>Vararg (params) constructors? (And IEnum do.)</li>
+  <li>Possibly extended use of "wildcard style" operations like
+AddAll&lt;U&gt;(IEnumerable&lt;U&gt; items)?</li>
+  <li>Make all collection classes clonable and serializable.</li>
+</ol>
+<h1><a class="mozTocH1" name="mozTocId336849"></a><a
+ name="PerformanceProper">Performance</a> details for proper collection
+classes</h1>
+<p>This section overviews the complexities of cc public methods and
+property
+accesses.</p>
+<p>In the table below, for lack of space we use the following numbers
+to
+identify collection classes:</p>
+<table border="1">
+  <tbody>
+    <tr>
+      <th>Class</th>
+      <th>Column</th>
+    </tr>
+    <tr>
+      <td>HashSet&lt;T&gt;</td>
+      <td>HS</td>
+    </tr>
+    <tr>
+      <td>HashBag&lt;T&gt;</td>
+      <td>HB</td>
+    </tr>
+    <tr>
+      <td>ArrayList&lt;T&gt;</td>
+      <td>AL</td>
+    </tr>
+    <tr>
+      <td>LinkedList&lt;T&gt;</td>
+      <td>LL</td>
+    </tr>
+    <tr>
+      <td>HashedArrayList&lt;T&gt;</td>
+      <td>HAL</td>
+    </tr>
+    <tr>
+      <td>HashedLinkedList&lt;T&gt;</td>
+      <td>HLL</td>
+    </tr>
+    <tr>
+      <td>TreeSet&lt;T&gt;</td>
+      <td>RBTS</td>
+    </tr>
+    <tr>
+      <td>TreeBag&lt;T&gt;</td>
+      <td>RBTB</td>
+    </tr>
+    <tr>
+      <td>SortedArray&lt;T&gt;</td>
+      <td>SA</td>
+    </tr>
+    <tr>
+      <td>IntervalHeap&lt;T&gt;</td>
+      <td>IH</td>
+    </tr>
+  </tbody>
+</table>
+<p>And the following special symbols:&nbsp;</p>
+<p>
+n size of collection,&nbsp;<br>
+m size of argument if collection-: not supported<br>
+*: means: suboptimal complexity (library is in error)<br>
+$: special at end: the operation is much faster at the start and/or end
+(end for
+array list, both for linked list)
+</p>
+<p>Note: we do not show return type&nbsp; or parameters for methods,
+just mark
+with ()<br>
+Note: we ignore time for reclaiming of internal array space (e.g. Clear)<br>
+User supplied operations like comparers or equalityComparers are assumed to be
+O(1)</p>
+<table border="1" height="2893" width="100%">
+  <tbody>
+    <tr>
+      <th height="23" width="9%">Member</th>
+      <th height="23" width="8%">HS</th>
+      <th height="23" width="8%">HB</th>
+      <th height="23" width="8%">AL</th>
+      <th height="23" width="8%">LL</th>
+      <th height="23" width="8%">HAL</th>
+      <th height="23" width="8%">HLL</th>
+      <th height="23" width="8%">RBTS</th>
+      <th height="23" width="8%">RBTB</th>
+      <th height="23" width="9%">SA</th>
+      <th height="23" width="9%">IH</th>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">&nbsp;IEnumerable&lt;T&gt;</font></i></td>
+      <td height="22" width="8%">&nbsp;&nbsp;</td>
+      <td height="22" width="8%">&nbsp;</td>
+      <td height="22" width="8%">&nbsp;</td>
+      <td height="22" width="8%">&nbsp;</td>
+      <td height="22" width="8%">&nbsp;</td>
+      <td height="22" width="8%">&nbsp;</td>
+      <td height="22" width="8%">&nbsp;</td>
+      <td height="22" width="8%">&nbsp;</td>
+      <td height="22" width="9%">&nbsp;</td>
+      <td height="22" width="9%">&nbsp;</td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">GetEnumerator()</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">IDirectedEnumerable&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HB</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">AL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">LL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HAL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HLL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTB</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">SA</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="18%"><font size="2">Direction</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="18%"><font size="2">Backwards()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">ICollectionValue&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HB</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">AL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">LL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HAL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HLL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTB</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">SA</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Count</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="18%"><font size="2">CopyTo</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">ToArray</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Apply()</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Exists()</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">All()</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">IDirectedCollectionValue&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HB</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">AL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">LL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HAL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HLL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTB</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">SA</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="18%"><font size="2">Backwards()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="13%"><i><font color="#808080" size="2">IExtensible&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HB</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">AL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">LL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HAL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HLL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTB</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">SA</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">AllowsDuplicates</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">SyncRoot</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">IsEmpty</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Add</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">AddAll</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(mlog n)</font></td>
+      <td height="22" width="8%"><font size="2">O(mlog n)</font></td>
+      <td height="22" width="9%"><font size="2">O(mlog n)</font></td>
+      <td height="22" width="9%"><font size="2">??</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">ICollection&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HB</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">AL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">LL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HAL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HLL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTB</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">SA</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">IsReadOnly</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">ContainsSpeed</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">GetHashCode</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Equals</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Contains</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">ContainsCount</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">ContainsAll</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(mn)*</font></td>
+      <td height="22" width="8%"><font size="2">O(mn)*</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m logn)</font></td>
+      <td height="22" width="8%"><font size="2">O(m logn)</font></td>
+      <td height="22" width="9%"><font size="2">O(m logn)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Find</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">FindOrAdd</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Update</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">UpdateOrAdd</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Remove</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveWithReturn</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveAllCopies</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveAll</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(mn)*</font></td>
+      <td height="22" width="8%"><font size="2">O(mn)*</font></td>
+      <td height="22" width="8%"><font size="2">O(m+n)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m logn)</font></td>
+      <td height="22" width="8%"><font size="2">O(m logn)</font></td>
+      <td height="22" width="9%"><font size="2">O(m logn)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Clear</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RetainAll</font></td>
+      <td height="22" width="8%"><font size="2">O(m)?</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(mn)*</font></td>
+      <td height="22" width="8%"><font size="2">O(mn)*</font></td>
+      <td height="22" width="8%"><font size="2">O(m+n)</font></td>
+      <td height="22" width="8%"><font size="2">O(m)</font></td>
+      <td height="22" width="8%"><font size="2">O(m logn)</font></td>
+      <td height="22" width="8%"><font size="2">O(m logn)</font></td>
+      <td height="22" width="9%"><font size="2">O(m logn)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">ISequenced&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HB</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">AL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">LL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HAL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HLL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTB</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">SA</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">GetHashCode</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Equals</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">IIndexed&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HB</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">AL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">LL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HAL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HLL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTB</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">SA</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">this[i]</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">this[start,end]</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">IndexOf()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">LastIndexOf()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveAt</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveInterval</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n log n)*</font></td>
+      <td height="22" width="8%"><font size="2">O(n log n)*</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">IList&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HB</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">AL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">LL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HAL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">HLL</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTS</font></i></td>
+      <td align="center" height="22" width="8%"><i><font color="#808080"
+ size="2">RBTB</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">SA</font></i></td>
+      <td align="center" height="22" width="9%"><i><font color="#808080"
+ size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">First</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Last</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">FIFO</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">this[i]</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Base</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Offset</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Map()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Insert()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">InsertFirst()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">InsertLast()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">InsertBefore()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">InsertAfter()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">InsertAll()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(m+n)</font></td>
+      <td height="22" width="8%"><font size="2">O(m+n)</font></td>
+      <td height="22" width="8%"><font size="2">O(m+n)</font></td>
+      <td height="22" width="8%"><font size="2">O(m+n)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">FindAll()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Remove()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)$</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveFirst()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveLast()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">View()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Slide() (amount: d)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(d)</font></td>
+      <td height="22" width="8%"><font size="2">O(d)</font></td>
+      <td height="22" width="8%"><font size="2">O(d)</font></td>
+      <td height="22" width="8%"><font size="2">O(d)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Reverse()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">IsSorted()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Sort()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n log n)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Shuffle()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">IPriorityQueue&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HB</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">AL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">LL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HAL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HLL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">RBTS</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">RBTB</font></i></td>
+      <td height="22" width="9%"><i><font color="#808080" size="2">SA</font></i></td>
+      <td height="22" width="9%"><i><font color="#808080" size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">FindMin()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">DeleteMin()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">FindMax()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td height="30" width="9%"><font size="2">DeleteMax()</font></td>
+      <td height="30" width="8%"><font size="2">-</font></td>
+      <td height="30" width="8%"><font size="2">-</font></td>
+      <td height="30" width="8%"><font size="2">-</font></td>
+      <td height="30" width="8%"><font size="2">-</font></td>
+      <td height="30" width="8%"><font size="2">-</font></td>
+      <td height="30" width="8%"><font size="2">-</font></td>
+      <td height="30" width="8%"><font size="2">O(log n)</font></td>
+      <td height="30" width="8%"><font size="2">O(log n)</font></td>
+      <td height="30" width="9%"><font size="2">O(log n)</font></td>
+      <td height="30" width="9%"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td height="30" width="9%"> <font size="2">Comparer</font></td>
+      <td height="30" width="8%"> <font size="2">-</font></td>
+      <td height="30" width="8%"> <font size="2">-</font></td>
+      <td height="30" width="8%"> <font size="2">-</font></td>
+      <td height="30" width="8%"> <font size="2">-</font></td>
+      <td height="30" width="8%"> <font size="2">-</font></td>
+      <td height="30" width="8%"> <font size="2">-</font></td>
+      <td height="30" width="8%"> <font size="2">O(1)</font></td>
+      <td height="30" width="8%"> <font size="2">O(1)</font></td>
+      <td height="30" width="9%"> <font size="2">O(1)</font></td>
+      <td height="30" width="9%"> <font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">ISorted&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HB</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">AL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">LL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HAL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HLL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">RBTS</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">RBTB</font></i></td>
+      <td height="22" width="9%"><i><font color="#808080" size="2">SA</font></i></td>
+      <td height="22" width="9%"><i><font color="#808080" size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Predecessor</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Successor</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">WeakPredecessor</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">WeakSuccessor</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Cut</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RangeFrom</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RangeFromTo</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RangeTo</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RangeAll</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">AddSorted</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">?</font></td>
+      <td height="22" width="8%"><font size="2">?</font></td>
+      <td height="22" width="9%"><font size="2">?</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveRangeFrom</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(nlog n)*</font></td>
+      <td height="22" width="8%"><font size="2">O(nlog n)*</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveRangeFromTo</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(nlog n)*</font></td>
+      <td height="22" width="8%"><font size="2">O(nlog n)*</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RemoveRangeTo</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(nlog n)*</font></td>
+      <td height="22" width="8%"><font size="2">O(nlog n)*</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">IIndexedSorted&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HB</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">AL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">LL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HAL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HLL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">RBTS</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">RBTB</font></i></td>
+      <td height="22" width="9%"><i><font color="#808080" size="2">SA</font></i></td>
+      <td height="22" width="9%"><i><font color="#808080" size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Map</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">CountFrom</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">CountFromTo</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">CountTo</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RangeFrom</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RangeFromTo</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">RangeTo</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="8%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">O(log n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">FindAll</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="8%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">O(n)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="14%"><i><font color="#808080" size="2">IPersistentSorted&lt;T&gt;</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HS</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HB</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">AL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">LL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HAL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">HLL</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">RBTS</font></i></td>
+      <td height="22" width="8%"><i><font color="#808080" size="2">RBTB</font></i></td>
+      <td height="22" width="9%"><i><font color="#808080" size="2">SA</font></i></td>
+      <td height="22" width="9%"><i><font color="#808080" size="2">IH</font></i></td>
+    </tr>
+    <tr>
+      <td height="22" width="9%"><font size="2">Snapshot()</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">-</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="8%"><font size="2">O(1)</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+      <td height="22" width="9%"><font size="2">-</font></td>
+    </tr>
+  </tbody>
+</table>
+<h1><a class="mozTocH1" name="mozTocId712409"></a><a
+ name="PerformanceDict">Performance</a> details for dictionary classes</h1>
+<table border="1" width="467">
+  <tbody>
+    <tr>
+      <th width="302">Member</th>
+      <th width="79">HashDictionary&lt;K,V&gt;</th>
+      <th width="64">TreeDictionary&lt;K,V&gt;</th>
+    </tr>
+    <tr>
+      <td width="302"><i><font color="#808080" size="2">IEnumerable&lt;KeyValuePair&lt;K,V&gt;&gt;</font></i></td>
+      <td width="79"><font color="#808080">&nbsp;</font></td>
+      <td width="64">&nbsp;</td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">GetEnumerator()</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td width="64"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><i><font color="#808080" size="2">IDictionary&lt;K,V&gt;</font></i></td>
+      <td width="79"><font color="#808080">&nbsp;</font></td>
+      <td width="64">&nbsp;</td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">this[key]</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">Count</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td width="64"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">IsReadOnly</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td width="64"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">SyncRoot</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td width="64"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">Keys</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td width="64"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">Values</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td width="64"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">Add()</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">Remove()</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">Clear()</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td height="22" width="64"><font size="2">O(1)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">Contains()</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">Find()</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">Update()</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">FindOrAdd</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><font size="2">UpdateOrAdd</font></td>
+      <td width="79"><font size="2">O(1)</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td width="302"><i><font color="#808080" size="2">ISortedDictionary&lt;K,V&gt;</font></i></td>
+      <td width="79"><font color="#808080">&nbsp;</font></td>
+      <td width="64">&nbsp;</td>
+    </tr>
+    <tr>
+      <td height="22" width="302"><font size="2">Predecessor</font></td>
+      <td width="79"><font size="2">-</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="302"><font size="2">Successor</font></td>
+      <td width="79"><font size="2">-</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="302"><font size="2">WeakPredecessor</font></td>
+      <td width="79"><font size="2">-</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+    <tr>
+      <td height="22" width="302"><font size="2">WeakSuccessor</font></td>
+      <td width="79"><font size="2">-</font></td>
+      <td height="22" width="64"><font size="2">O(log n)</font></td>
+    </tr>
+  </tbody>
+</table>
+</body>
+</html>
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/AssemblyInfo.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/AssemblyInfo.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/AssemblyInfo.cs	(revision 3)
@@ -0,0 +1,79 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+//
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+//
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+
+[assembly: AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the 
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing. 
+//
+// Notes: 
+//   (*) If no key is specified, the assembly is not signed.
+//   (*) KeyName refers to a key that has been installed in the Crypto Service
+//       Provider (CSP) on your machine. KeyFile refers to a file which contains
+//       a key.
+//   (*) If the KeyFile and the KeyName values are both specified, the 
+//       following processing occurs:
+//       (1) If the KeyName can be found in the CSP, that key is used.
+//       (2) If the KeyName does not exist and the KeyFile does exist, the key 
+//           in the KeyFile is installed into the CSP and used.
+//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+//       When specifying the KeyFile, the location of the KeyFile should be
+//       relative to the project output directory which is
+//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+//       located in the project directory, you would specify the AssemblyKeyFile 
+//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+//       documentation for more information on this.
+//
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyKeyName("")]
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/Test.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/Test.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/Test.cs	(revision 3)
@@ -0,0 +1,137 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using MSG = System.Collections.Generic;
+
+namespace Try
+{
+/*
+	/// <summary>
+	/// Affenpinscher 
+	/// </summary>
+	public class SSS<T,U>
+	{
+		/// <summary>
+		/// GGGGGGG <cell>tidlig <seealso cref="T:Try.Foo!3"/> <b alk="foo">bonny</b> namse</cell> efter
+		/// </summary>
+		/// <param name="u">zeU</param>
+		/// <param name="cell">zeI</param>
+		/// <param name="t">zeT</param>
+		/// <returns>zeReturn</returns>
+		public static T g(out U u, ref int cell, T t) { u = default(U); return default(T); }
+		
+		/// <summary>
+		/// Nested klasse
+		/// </summary>
+		public class Inner<K>
+		{
+			/// <summary>
+			/// IIIIIIIIII
+			/// </summary>
+			/// <param name="t">TTTTTTTTTT</param>
+			/// <param name="k">KKKKKKK</param>
+			/// <returns>RRRRRRRRRRR</returns>
+			public U indre(T t, K k) { return default(U); }
+		}
+        /// <summary>
+        /// Jaj ja
+        /// </summary>
+        public class NongenNested
+        {
+            /// <summary>
+            /// Det er et y
+            /// </summary>
+            public int y;
+        }
+        /// <summary>
+		/// Lolololola
+		/// </summary>
+		public U lefield;
+		/// <summary>
+		/// Cococococola
+		/// </summary>
+		public static Foo<T,U,U> gramse;
+		/// <summary>
+		/// zesum
+		/// </summary>
+		/// <value>zeval</value>
+		public SSS<T,T> leprop { get { return default(SSS<T,T>); } }
+		/// <summary>
+		/// Sju
+		/// </summary>
+		/// <param name="f">ffffffff</param>
+		/// <param name="johndoe">ffffffff</param>
+		public string s<V,X,Y,Z>(Foo<T,Y,SSS<Z,T>> f, int johndoe) { return "7"; }
+		/// <summary>
+		/// intuism
+		/// </summary>
+		/// <param name="tudse">froe</param>
+		/// <param name="frank">sin</param>
+		public SSS(T[] tudse, double frank) { }
+	}
+
+	/// <summary>
+	/// ooh 
+	/// </summary>
+
+	public class HHH
+	{
+		/// <summary>
+		/// MusseKom
+		/// </summary>
+		public class Musse { }
+	}
+
+
+
+	/// <summary>
+	/// Hejsa 
+	/// </summary>
+	public class Foo<K,L,M> { }
+
+*/
+	/// <summary>
+	/// Hejsa
+	/// </summary>
+	public delegate void Mapper<T,U>(T t);
+
+
+
+	/// <summary>
+	/// Los accoutables
+	/// </summary>
+	public interface IEnumerable<T>
+	{
+		// <summary>
+		// getegetegeteg
+		// </summary>
+		// <returns>leturn</returns>
+		//MSG.IEnumerator<T> GetEnumerator();
+
+
+		/// <summary>
+		/// Apply a delegate to all items of this collection.
+		/// </summary>
+		/// <param name="a">The delegate to apply</param>
+		void Map<U>(Mapper<T,U> a);
+	}
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/Timer.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/Timer.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/Timer.cs	(revision 3)
@@ -0,0 +1,84 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using System.IO;
+using System.Reflection;
+using System.Xml;
+using System.Diagnostics;
+
+namespace DocNet
+{
+    class Timer
+    {
+        static System.Diagnostics.Process p;
+
+        static long sws;
+
+        static long svm;
+
+        static double stt;
+
+        static DateTime swc;
+
+        public long ws;
+
+        public long vm;
+
+        public double tt;
+
+        public DateTime wc;
+
+        public double deltat;
+
+        public double deltac;
+
+
+        public Timer()
+        {
+            if (p == null)
+            {
+                p = System.Diagnostics.Process.GetCurrentProcess();
+                stt = p.TotalProcessorTime.TotalMilliseconds;
+                sws = p.WorkingSet64;
+                svm = p.VirtualMemorySize64;
+                swc = DateTime.Now;
+            }
+        }
+
+
+        public double snap()
+        {
+            double oldt = tt;
+            DateTime oldc = wc; p.Refresh();
+            tt = p.TotalProcessorTime.TotalMilliseconds - stt;
+            deltat = tt - oldt;
+            ws = p.WorkingSet64 - sws;
+            vm = p.VirtualMemorySize64 - svm;
+            wc = DateTime.Now;
+
+            TimeSpan x = oldc.Subtract(wc);
+
+            deltac = -x.TotalMilliseconds;
+            return deltac;
+        }
+    }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docNet.csproj
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docNet.csproj	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docNet.csproj	(revision 3)
@@ -0,0 +1,99 @@
+﻿<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <ProductVersion>8.0.50727</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{42811A81-6A99-4C7A-A6DA-DF104C767B72}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <StartupObject>
+    </StartupObject>
+    <RootNamespace>docNet</RootNamespace>
+    <NoStandardLibraries>false</NoStandardLibraries>
+    <AssemblyName>docNet</AssemblyName>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <UpgradeBackupLocation>
+    </UpgradeBackupLocation>
+    <OldToolsVersion>2.0</OldToolsVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
+    <DebugSymbols>true</DebugSymbols>
+    <Optimize>false</Optimize>
+    <OutputPath>.\bin\Debug\</OutputPath>
+    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
+    <DefineConstants>DEBUG</DefineConstants>
+    <WarningLevel>4</WarningLevel>
+    <IncrementalBuild>false</IncrementalBuild>
+    <DocumentationFile>docnet.xml</DocumentationFile>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
+    <DebugSymbols>false</DebugSymbols>
+    <Optimize>true</Optimize>
+    <OutputPath>.\bin\Release\</OutputPath>
+    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
+    <DefineConstants>TRACE</DefineConstants>
+    <WarningLevel>4</WarningLevel>
+    <IncrementalBuild>false</IncrementalBuild>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'DebugSnk' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\DebugSnk\</OutputPath>
+    <DefineConstants>DEBUG</DefineConstants>
+    <DocumentationFile>docnet.xml</DocumentationFile>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'ReleaseSnk' ">
+    <OutputPath>bin\ReleaseSnk\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="System" />
+    <Reference Include="System.Xml">
+      <HintPath>..\..\..\..\..\WINDOWS\Microsoft.NET\Framework\v1.2.30703\System.XML.dll</HintPath>
+      <Name>System.XML</Name>
+    </Reference>
+    <ProjectReference Include="..\C5\C5.csproj">
+      <Project>{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}</Project>
+      <Package>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Package>
+      <Name>C5</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="AssemblyInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="docnet.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Content Include="docbuild\banner.htm" />
+    <Content Include="docbuild\docnet.css" />
+    <Content Include="docbuild\frames.htm" />
+    <Content Include="docbuild\litterature.htm" />
+    <Content Include="docbuild\userguide.htm" />
+    <Content Include="overview.xslt" />
+    <Compile Include="Test.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="Timer.cs" />
+    <Content Include="trans.xslt" />
+  </ItemGroup>
+  <ItemGroup>
+    <None Include="dodoc.cmd" />
+    <None Include="mkcurrent.cmd" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
+  <PropertyGroup>
+    <PreBuildEvent>
+    </PreBuildEvent>
+    <PostBuildEvent>
+    </PostBuildEvent>
+    <ApplicationIcon>
+    </ApplicationIcon>
+  </PropertyGroup>
+  <ProjectExtensions>
+    <VisualStudio>
+    </VisualStudio>
+  </ProjectExtensions>
+</Project>
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docnet.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docnet.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/docnet.cs	(revision 3)
@@ -0,0 +1,780 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+// DocNet.cs
+// Author: Antonio Cisternino
+// Version: 0.1
+// Last update: 5/12/2001
+// Modified Jan 2004 by kokholm@itu.dk
+
+using System;
+using System.IO;
+using System.Reflection;
+using System.Xml;
+using System.Text;
+using System.Diagnostics;
+
+namespace DocNet
+{
+  class DocNet
+  {
+    private Assembly assembly;
+
+    //private XmlDocument xml;
+
+    private string defaultNamespace;
+
+    private string assemblyName;
+
+    private static C5.HashDictionary<string, string> longtype2short;
+
+    private static C5.HashDictionary<string, XmlNode> cachedDocComments;
+
+    static DocNet()
+    {
+      longtype2short = new C5.HashDictionary<string, string>();
+      cachedDocComments = new C5.HashDictionary<string, XmlNode>();
+      longtype2short.Add("System.Boolean", "bool");
+      longtype2short.Add("System.Byte", "byte");
+      longtype2short.Add("System.Int32", "int");
+      longtype2short.Add("System.Double", "double");
+      longtype2short.Add("System.Void", "void");
+      longtype2short.Add("System.Object", "object");
+      longtype2short.Add("System.String", "string");
+      longtype2short.Add("System.Collections.Generic.IEnumerable{T}", "IEnumerable{T}");
+      longtype2short.Add("System.Collections.Generic.IEnumerable{U}", "IEnumerable{U}");
+      //longtype2short.Add("", "");
+    }
+
+
+    DocNet(string a, string x, string defaultNamespace)
+    {
+      this.defaultNamespace = defaultNamespace;
+      assembly = Assembly.LoadFrom(a, null);
+      XmlDocument xml = new XmlDocument();
+      xml.Load(x);
+      assemblyName = xml.SelectSingleNode("doc/assembly/name").InnerXml;
+
+      if (!assembly.FullName.StartsWith(assemblyName + ","))
+        throw new Exception("Wrong assembly specified!\n>> " + assembly.FullName + "\n>> " + assemblyName);
+
+      foreach (XmlNode node in xml.SelectNodes("doc/members/member"))
+        cachedDocComments.Add(node.SelectNodes("@name").Item(0).Value, node);
+    }
+
+
+    private void CopyCodeDoc(XmlElement p, string xpath, XmlDocument ret)
+    {
+      XmlNode n;
+      //xml.SelectSingleNode(xpath);
+
+      if (cachedDocComments.Find(xpath, out n))
+      {
+        foreach (XmlNode child in n.ChildNodes)
+          p.AppendChild(ret.ImportNode(child, true));
+      }
+      //else
+      //  Console.Error.WriteLine("docNet: {0} not found", xpath);
+    }
+
+    string xmlClean(string s)
+    {
+//            return s.Replace("&", "&amp;").Replace("{", "&lt;").Replace("}", "&gt;").Replace("<", "&lt;").Replace(">", "&gt;");
+      return s.Replace("{", "<").Replace("}", ">");
+    }
+
+    private void AddSignature(XmlElement p, string signtext, XmlDocument ret)
+    {
+      XmlElement sign = CreateElement(ret, "Signature");
+
+      try
+      {
+        sign.InnerXml = signtext.Replace("&", "&amp;").Replace("{", "&lt;").Replace("}", "&gt;").Replace("<", "&lt;").Replace(">", "&gt;");
+      }
+      catch (XmlException)
+      {
+        Console.Error.WriteLine(signtext);
+      }
+      p.AppendChild(sign);
+    }
+
+    private void addImplements(XmlElement p, Type t, XmlDocument ret)
+    {
+      foreach (Type ty in t.GetInterfaces())
+      {
+        XmlElement impl = CreateElement(ret, "Implements");
+
+        if (ty.Assembly == assembly)
+        {
+          impl.SetAttribute("refid", "T:" + canonicalTypeName(ty, null));
+          impl.SetAttribute("C5", "");
+        }
+        AddSignature(impl, prettyTypeName(ty), ret);
+        p.AppendChild(impl);
+      }
+    }
+
+    private void addBases(XmlElement p, Type t, XmlDocument ret)
+    {
+      Type ty = t.BaseType;
+
+      while (ty != null)
+      {
+        XmlElement @base = CreateElement(ret, "Bases");
+
+        if (ty.Assembly == assembly)
+        {
+          @base.SetAttribute("refid", "T:" + canonicalTypeName(ty, null));
+          @base.SetAttribute("C5", "");
+        }
+
+        AddSignature(@base, prettyTypeName(ty), ret);
+        p.PrependChild(@base);
+        ty = ty.BaseType;
+      }
+    }
+
+
+
+    private XmlElement CreateElement(XmlDocument ret, string name)
+    {
+      return ret.CreateElement(null, name, null);
+    }
+
+    private void VisitField(bool inherited, FieldInfo f, XmlElement type, XmlDocument refman)
+    {
+      if (f.Name.Equals("value__"))
+        return;
+      string refid = "F:" + canonicalTypeName(f.DeclaringType, null) + "." + f.Name;
+      //string xpath = "doc/members/member[@name = \"" + refid + "\"]";
+      XmlElement el = CreateElement(refman, "Field");
+
+      el.SetAttribute("Name", f.Name);
+      el.SetAttribute("refid", refid);
+      el.SetAttribute("Static", f.IsStatic.ToString());
+      el.SetAttribute("Declared", xmlClean(prettyTypeName(f.DeclaringType)));
+      el.SetAttribute("CDeclared", canonicalTypeName(f.DeclaringType, null));
+      el.SetAttribute("Type", xmlClean(prettyTypeName(f.FieldType)));
+      el.SetAttribute("Access", f.IsPublic ? "public" : (f.IsPrivate || f.IsAssembly ? "private" : "protected"));
+      if (f.DeclaringType.Assembly == assembly)
+        el.SetAttribute("C5", "");
+
+      if (inherited)
+        el.SetAttribute("Inherited", "");
+
+      AddSignature(el, /*prettyTypeName(f.FieldType) + " " +*/ f.Name, refman);
+      CopyCodeDoc(el, refid, refman);
+      //AddSummary(el, xpath + "/summary", ret, doc);
+      type.AppendChild(el);
+    }
+
+    private void VisitEvent(bool inherited, EventInfo e, XmlElement type, XmlDocument ret)
+    {
+      string refid = "E:" + canonicalTypeName(e.DeclaringType, null) + "." + e.Name;
+      //string xpath = "doc/members/member[@name = \"" + refid + "\"]";
+      XmlElement el = CreateElement(ret, "Event");
+
+      el.SetAttribute("Name", e.Name);
+      el.SetAttribute("refid", refid);
+      //el.SetAttribute("Static", f.IsStatic.ToString());
+      //TODO: check virtual and final values on adders/removers
+      //el.SetAttribute("Virtual", e..IsVirtual.ToString());
+      //el.SetAttribute("Final", e.IsFinal.ToString());
+      el.SetAttribute("Declared", xmlClean(prettyTypeName(e.DeclaringType)));
+      el.SetAttribute("CDeclared", canonicalTypeName(e.DeclaringType, null));
+      el.SetAttribute("Type", xmlClean(prettyTypeName(e.EventHandlerType)));
+      MethodInfo addMethod = e.GetAddMethod(true);
+      el.SetAttribute("Access", addMethod.IsPublic ? "public" : addMethod.IsFamily ? "protected" : "private");//NBNBNB! e.IsPublic ? "public" : (e.IsPrivate || e.IsAssembly ? "private" : "protected"));
+      if (e.DeclaringType.Assembly == assembly)
+        el.SetAttribute("C5", "");
+
+      if (inherited)
+        el.SetAttribute("Inherited", "");
+
+      AddSignature(el, /*prettyTypeName(e.EventHandlerType) + " " +*/ e.Name, ret);
+      CopyCodeDoc(el, refid, ret);
+      //AddSummary(el, xpath + "/summary", ret, doc);
+      type.AppendChild(el);
+    }
+
+
+    private void VisitProperty(bool inherited, PropertyInfo p, XmlElement type, XmlDocument ret)
+    {
+      string refid = "P:" + canonicalPropertyName(p);
+      string xpath = "doc/members/member[@name = \"" + refid + "\"]";
+      XmlElement el = CreateElement(ret, "Property");
+
+      el.SetAttribute("Name", p.Name);
+      el.SetAttribute("refid", refid);
+      el.SetAttribute("Access", "public");//TODO: check if reasonable
+      MethodInfo m = p.CanRead ? p.GetGetMethod() : p.GetSetMethod();
+      if (m != null)
+      {
+        el.SetAttribute("Static", m.IsStatic.ToString());
+        el.SetAttribute("Abstract", m.IsAbstract.ToString());
+        el.SetAttribute("Virtual", m.IsVirtual.ToString());
+        el.SetAttribute("Final", m.IsFinal.ToString());
+      }
+      //else
+      //Console.Error.WriteLine("%%%%% {0} | {1}", p, p.DeclaringType);
+      el.SetAttribute("Declared", xmlClean(prettyTypeName(p.DeclaringType)));
+      el.SetAttribute("CDeclared", canonicalTypeName(p.DeclaringType, null));
+      el.SetAttribute("Get", p.CanRead.ToString());
+      el.SetAttribute("Set", p.CanWrite.ToString());
+      el.SetAttribute("Type", xmlClean(prettyTypeName(p.PropertyType)));
+
+      if (p.DeclaringType.Assembly == assembly)
+        el.SetAttribute("C5", "");
+
+      if (inherited)
+        el.SetAttribute("Inherited", "");
+
+      if (p.Name.Equals("Item"))
+        AddSignature(el, prettyIndexerSignature(p), ret);
+      else
+        AddSignature(el, /*prettyTypeName(p.PropertyType) + " " +*/ p.Name, ret);
+
+      //AddSummary(el, xpath + "/summary", ret, doc);
+      CopyCodeDoc(el, refid, ret);
+      //AddValue(el, xpath + "/value", ret, doc);
+      VisitParameters(p.GetIndexParameters(), el, ret, xpath);
+      type.AppendChild(el);
+    }
+
+
+    private void VisitParameters(ParameterInfo[] pars, XmlElement n, XmlDocument ret, string xpath)
+    {
+      foreach (ParameterInfo p in pars)
+      {
+        XmlElement el = CreateElement(ret, "Parameter");
+
+        el.SetAttribute("Name", p.Name);
+        el.SetAttribute("Type", prettyTypeName(p.ParameterType));
+        //AddSummary(el, xpath + "/param[@name = \"" + p.Name + "\"]", ret, doc);
+        CopyCodeDoc(el, xpath + "/param[@name = \"" + p.Name + "\"]", ret);
+
+        n.AppendChild(el);
+      }
+    }
+
+
+    private void VisitConstructor(Type t, ConstructorInfo c, XmlElement type, XmlDocument ret)
+    {
+      Type declaringType = c.DeclaringType;
+      string refid = "M:" + canonicalTypeName(c.DeclaringType, null) + "." + "#ctor";
+
+      refid += canonicalParameters(c.GetParameters(), new string[]{});
+
+      string xpath = "doc/members/member[@name = \"" + refid + "\"]";
+      XmlElement el = CreateElement(ret, "Constructor");
+      el.SetAttribute("Foo", c.IsConstructor ? "Con" : "San");
+      el.SetAttribute("refid", refid);
+      el.SetAttribute("Declared", prettyTypeName(declaringType));
+      el.SetAttribute("CDeclared", canonicalTypeName(declaringType, null));
+      el.SetAttribute("Access", c.IsPublic ? "public" : (c.IsPrivate ? "private" : "protected"));
+      //el.SetAttribute("Access", c.IsPublic ? "public" : (c.IsPrivate || c.IsAssembly ? "private" : "protected"));
+      if (declaringType.Assembly == assembly)
+        el.SetAttribute("C5", "");
+      if (declaringType != t)
+        el.SetAttribute("Inherited", "");
+      AddSignature(el, prettyConstructorSignature(c), ret);
+      CopyCodeDoc(el, refid, ret);
+      //AddSummary(el, xpath + "/summary", ret, doc);
+      VisitParameters(c.GetParameters(), el, ret, xpath);
+      type.AppendChild(el);
+    }
+
+
+    private void VisitMethod(bool inherited, MethodInfo m, XmlElement type, XmlDocument ret)
+    {
+      if (m.Name.StartsWith("get_") || m.Name.StartsWith("set_") || m.Name.StartsWith("add_") || m.Name.StartsWith("remove_"))
+        return;
+      bool isOperator = m.Name.StartsWith("op_");
+
+      string refid = "M:" + canonicalMethodName(m);
+
+      string xpath = "doc/members/member[@name = \"" + refid + "\"]";
+      XmlElement el = CreateElement(ret, isOperator ? "Operator" : "Method");
+
+      string mangledName = m.Name;
+      if (isOperator)
+      {
+        switch (mangledName)
+        {
+          case "op_Equality": mangledName = "operator =="; break;
+          case "op_Inequality": mangledName = "operator !="; break;
+          default: throw new ApplicationException("unknown operatorname, " + mangledName);
+        }
+      }
+      el.SetAttribute("Name", mangledName);
+      el.SetAttribute("refid", refid);
+      el.SetAttribute("Static", m.IsStatic.ToString());
+      el.SetAttribute("Abstract", m.IsAbstract.ToString());
+      el.SetAttribute("Virtual", m.IsVirtual.ToString());
+      el.SetAttribute("Final", m.IsFinal.ToString());
+      el.SetAttribute("Declared", xmlClean(prettyTypeName(m.DeclaringType)));
+      el.SetAttribute("CDeclared", canonicalTypeName(m.DeclaringType, null));
+      el.SetAttribute("ReturnType", xmlClean(prettyTypeName(m.ReturnType)));
+      if (m.DeclaringType.Assembly == assembly)
+        el.SetAttribute("C5", "");
+      if (inherited)
+        el.SetAttribute("Inherited", "");
+      el.SetAttribute("Access", m.IsPublic ? "public" : (m.IsPrivate || m.IsAssembly ? "private" : "protected"));
+      el.SetAttribute("Sealed", m.IsFinal.ToString());
+      AddSignature(el, prettyMethodSignature(mangledName, m), ret);
+      CopyCodeDoc(el, refid, ret);
+      VisitParameters(m.GetParameters(), el, ret, xpath);
+
+      foreach (Type gp in m.GetGenericArguments())
+        foreach (Type gc in gp.GetGenericParameterConstraints())
+          if (gc != typeof(object))
+          {
+            XmlElement constraint = CreateElement(ret, "constraint");
+            constraint.SetAttribute("Value", prettyTypeName(gp) + " : " + xmlClean(prettyTypeName(gc)));
+            el.AppendChild(constraint);
+          }
+      type.AppendChild(el);
+    }
+
+    public XmlDocument GenerateDoc()
+    {
+      BindingFlags flags = BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.NonPublic;
+
+      XmlDocument ret = new XmlDocument();
+      XmlElement root = CreateElement(ret, "Assembly");
+
+      root.SetAttribute("Name", assemblyName);
+
+      ret.AppendChild(root);
+
+      XmlElement type = null;
+      //string xpath = null;
+
+      foreach (Type t in assembly.GetTypes())
+      {
+        if (t.Name.StartsWith("DocNet"))
+          continue;
+
+        if (t.IsInterface)
+        {
+          type = CreateElement(ret, "Interface");
+          foreach (EventInfo e in t.GetEvents(flags))
+            VisitEvent(e.DeclaringType != t, e, type, ret);
+
+          foreach (PropertyInfo p in t.GetProperties(flags))
+            VisitProperty(false, p, type, ret);
+
+          foreach (MethodInfo m in t.GetMethods(flags))
+            VisitMethod(false, m, type, ret);
+        }
+        else if (t.IsValueType)
+        {
+          type = CreateElement(ret, "Struct");
+          foreach (FieldInfo f in t.GetFields(flags))
+            VisitField(f.DeclaringType != t, f, type, ret);
+
+          foreach (EventInfo e in t.GetEvents(flags))
+            VisitEvent(e.DeclaringType != t, e, type, ret);
+
+          foreach (PropertyInfo p in t.GetProperties(flags))
+            VisitProperty(p.DeclaringType != t, p, type, ret);
+
+          foreach (ConstructorInfo c in t.GetConstructors(flags))
+            VisitConstructor(t, c, type, ret);
+
+          foreach (MethodInfo m in t.GetMethods(flags))
+            VisitMethod(m.DeclaringType != t, m, type, ret);
+        }
+        else if (t.IsSubclassOf(typeof(Delegate)))
+        {
+          type = CreateElement(ret, "Delegate");
+          VisitMethod(false, t.GetMethod("Invoke"), type, ret);
+        }
+        else
+        { // Class
+          type = CreateElement(ret, "Class");
+          foreach (FieldInfo f in t.GetFields(flags))
+            VisitField(f.DeclaringType != t, f, type, ret);
+
+          foreach (EventInfo e in t.GetEvents(flags))
+            VisitEvent(e.DeclaringType != t, e, type, ret);
+
+          foreach (PropertyInfo p in t.GetProperties(flags))
+            VisitProperty(p.DeclaringType != t, p, type, ret);
+
+          foreach (ConstructorInfo c in t.GetConstructors(flags))
+            VisitConstructor(t, c, type, ret);
+
+          foreach (MethodInfo m in t.GetMethods(flags))
+            VisitMethod(m.DeclaringType != t, m, type, ret);
+        }
+
+        type.SetAttribute("Name", xmlClean(prettyTypeName(t)));
+        type.SetAttribute("Access", t.IsPublic || t.IsNestedPublic ? "public" : t.IsNestedFamily ? "protected" : "private");
+
+        string refid = "T:" + canonicalTypeName(t, null);
+
+        type.SetAttribute("refid", refid);
+        type.SetAttribute("C5", "");
+        AddSignature(type, prettyTypeName(t), ret);
+        addImplements(type, t, ret);
+        addBases(type, t, ret);
+
+        foreach (Type gp in t.GetGenericArguments())
+        {
+          if (gp.GenericParameterAttributes != GenericParameterAttributes.None)
+          {
+            XmlElement constraint = CreateElement(ret, "constraint");
+            string constraintText = null;
+            switch (gp.GenericParameterAttributes)
+            {
+              case GenericParameterAttributes.Contravariant:
+                break;
+              case GenericParameterAttributes.Covariant:
+                break;
+              case GenericParameterAttributes.DefaultConstructorConstraint:
+                constraintText = "new()";
+                break;
+              case GenericParameterAttributes.None:
+                break;
+              case GenericParameterAttributes.ReferenceTypeConstraint:
+                constraintText = "class";
+                break;
+              case GenericParameterAttributes.SpecialConstraintMask:
+                break;
+              case GenericParameterAttributes.NotNullableValueTypeConstraint:
+                constraintText = "struct";
+                break;
+              case GenericParameterAttributes.VarianceMask:
+                break;
+            }
+            constraint.SetAttribute("Value", String.Format("{0} : {1}", gp, constraintText));
+            type.AppendChild(constraint);
+          }
+          foreach (Type gc in gp.GetGenericParameterConstraints())
+          {
+            if (gc != typeof(object))
+            {
+              XmlElement constraint = CreateElement(ret, "constraint");
+              constraint.SetAttribute("Value", String.Format("{0} : {1}", prettyTypeName(gp), xmlClean(prettyTypeName(gc))));
+              type.AppendChild(constraint);
+            }
+          }
+        }
+
+        CopyCodeDoc(type, refid, ret);
+        root.AppendChild(type);
+      }
+
+      return ret;
+    }
+
+    C5.HashDictionary<Type, string> t2ptn = new C5.HashDictionary<Type, string>();
+    private string prettyTypeName(Type t)
+    {
+      string retval;
+      //if (!t2ptn.Find(t, out retval))
+      //{
+      int consumed = 0;
+      retval = prettyTypeName(t, ref consumed);
+      //    t2ptn.Add(t, retval);
+      //}
+      return retval;
+    }
+
+    private string prettyTypeName(Type t, ref int consumed)
+    {
+      StringBuilder ret = new StringBuilder();
+
+      if (t.IsGenericParameter)
+        ret.Append(t.Name);
+      else if (t.IsArray)
+        ret.Append(prettyTypeName(t.GetElementType()) + "[]");
+      else if (t.IsByRef)
+        ret.Append("ref ").Append(prettyTypeName(t.GetElementType()));
+      else if (!t.IsGenericType)
+        ret.Append(t.IsNested ? prettyTypeName(t.DeclaringType, ref consumed) + "." + t.Name : t.FullName);
+      else
+      {
+        bool first = true;
+        StringBuilder gps = new StringBuilder();
+        Type[] gp = t.GetGenericArguments();
+
+        ret.Append(t.IsNested ? prettyTypeName(t.DeclaringType, ref consumed) : t.Namespace).Append(".").Append(t.Name);
+        if (consumed < gp.Length)
+        {
+          //TODO: fix this ugly hack to remove `n 
+          ret.Remove(ret.Length - 2, 2);
+          //ret = ret.Substring(0, ret.Length - 2);
+          for (int i = consumed, length = gp.Length; i < length; i++)
+          {
+            Type ty = gp[i];
+
+            if (first) first = false;
+            else
+              gps.Append(",");
+
+            gps.Append(prettyTypeName(ty));
+          }
+
+          consumed = gp.Length;
+          ret.Append("{").Append(gps.ToString()).Append("}");
+        }
+      }
+
+      string retval = ret.ToString();
+
+      if (retval.StartsWith(defaultNamespace + "."))
+        retval = retval.Substring(defaultNamespace.Length + 1);
+
+      if (longtype2short.Contains(retval))
+        retval = longtype2short[retval];
+
+      return retval;
+    }
+
+    private string prettyParameters(ParameterInfo[] pars)
+    {
+      string ret = "";
+      bool first = true;
+
+      foreach (ParameterInfo p in pars)
+      {
+        if (first) first = false;
+        else
+          ret += ", ";
+        Type pt = p.ParameterType;
+        if (p.IsOut)
+        {
+          ret += "out ";
+          pt = pt.GetElementType();
+        }
+
+        ret += prettyTypeName(pt) + " " + p.Name;
+      }
+
+      return ret;
+    }
+
+    private string prettyMethodSignature(string name, MethodInfo m)
+    {
+      string gp = "";
+      if (m.IsGenericMethod)
+      {
+        Type[] gps = m.GetGenericArguments();
+        gp = "<";
+
+        for (int i = 0; i < gps.Length; i++)
+          gp += (i == 0 ? "" : ",") + gps[i].Name;
+
+        gp += ">";
+      }
+
+      return name + gp + "(" + prettyParameters(m.GetParameters()) + ")";
+    }
+
+    private string prettyConstructorSignature(ConstructorInfo c)
+    {
+      Type t = c.DeclaringType;
+
+      return prettyTypeName(t) + "(" + prettyParameters(c.GetParameters()) + ")";
+    }
+
+    private string prettyIndexerSignature(PropertyInfo p)
+    {
+      return /*prettyTypeName(p.PropertyType) + " " + */ "this[" + prettyParameters(p.GetIndexParameters()) + "]";
+    }
+
+
+    private string simpleTypeName(Type t)
+    {
+      return (t.IsNested ? simpleTypeName(t.DeclaringType) : t.Namespace) + "." + t.Name;
+    }
+
+
+    private string canonicalTypeName(Type t, string[] mgps)
+    {
+      string ret;
+
+      if (t.IsGenericParameter)
+        ret = "`" + t.GenericParameterPosition;
+      else if (t.IsArray)
+        ret = canonicalTypeName(t.GetElementType(), mgps) + "[]";
+      else if (t.IsByRef)
+        ret = canonicalTypeName(t.GetElementType(), mgps) + "@";
+      else
+      {
+        ret = simpleTypeName(t);
+        if (!t.IsGenericType)
+          ret += "";
+        else if (mgps == null)
+          ret += "";//"`" + t.GetGenericArguments().Length;
+        else
+        {
+          //TODO: fix this ugly hack to remove `n 
+          ret = ret.Substring(0, ret.Length - 2);
+
+          bool first = true;
+          string gps = "";
+          Type[] gp = t.GetGenericArguments();
+
+          foreach (Type ty in gp)
+          {
+            if (first) first = false;
+            else
+              gps += ",";
+
+            if (ty.IsGenericParameter)
+            {
+              bool ismgp = false;
+
+              foreach (string s in mgps) if (s.Equals(ty.Name)) ismgp = true;
+
+              gps += (ismgp ? "``" : "`") + ty.GenericParameterPosition;
+            }
+            else
+              gps += canonicalTypeName(ty, mgps);
+          }
+
+          ret += "{" + gps + "}";
+        }
+      }
+
+      return ret;
+    }
+
+    private string canonicalMethodName(MethodInfo m)
+    {
+      string ret = canonicalTypeName(m.DeclaringType, null) + "." + m.Name;
+
+      string[] gmps;
+
+      if (m.IsGenericMethod)
+      {
+        Type[] gps = m.GetGenericArguments();
+
+        ret += "``" + gps.Length;
+        gmps = new string[gps.Length];
+        for (int i = 0; i < gps.Length; i++)
+          gmps[i] = gps[i].Name;
+      }
+      else
+        gmps = new string[]{};
+
+      ret += canonicalParameters(m.GetParameters(), gmps);
+      return ret;
+    }
+
+    private string canonicalPropertyName(PropertyInfo p)
+    {
+      string pname = canonicalTypeName(p.DeclaringType, null) + "." + p.Name;
+      ParameterInfo[] pars = p.GetIndexParameters();
+
+      if (pars.Length > 0)
+        pname += canonicalParameters(pars, new string[]{});
+
+      return pname;
+    }
+
+    private string canonicalParameters(ParameterInfo[] pars, string[] gmps)
+    {
+      if (pars.Length == 0) return "";
+
+      string ret = "";
+      bool first = true;
+
+      foreach (ParameterInfo p in pars)
+      {
+        if (first) first = false;
+        else
+          ret += ",";
+
+        ret += canonicalTypeName(p.ParameterType, gmps); ;
+      }
+
+      return "(" + ret + ")";
+    }
+
+
+
+    static void Main(string[] args)
+    {
+      if (args.Length != 2)
+      {
+        args = new string[] { @"C5.dll", @"C5.xml" };
+
+      }
+      {
+        Timer timer = new Timer();
+        timer.snap();
+        DocNet doc = new DocNet(args[0], args[1], "C5");
+        XmlDocument merged = doc.GenerateDoc();
+        if (true)
+        {
+          XmlWriterSettings s = new XmlWriterSettings();
+          s.Indent = true;
+          XmlWriter w = XmlWriter.Create("merged.xml", s);
+          merged.WriteTo(w);
+          w.Close();
+        }
+        Console.Error.WriteLine("Time merge: {0} ms", timer.snap());
+
+        System.Xml.Xsl.XslCompiledTransform overview = new System.Xml.Xsl.XslCompiledTransform();
+        overview.Load(@"overview.xslt");
+        overview.Transform(merged, new XmlTextWriter(new StreamWriter(@"docbuild\contents.htm")));
+        Console.Error.WriteLine("Time, overview: {0} ms", timer.snap());
+
+        StringBuilder megaDoc = new StringBuilder();
+        using (XmlWriter writer = XmlWriter.Create(megaDoc))
+        {
+          writer.WriteStartElement("hack");
+          System.Xml.Xsl.XslCompiledTransform trans = new System.Xml.Xsl.XslCompiledTransform();
+          trans.Load(@"trans.xslt");
+          trans.Transform(merged, writer);
+          writer.WriteEndElement();
+          writer.Close();
+        }
+        Console.Error.WriteLine("Time trans: {0} ms", timer.snap());
+        System.Xml.XPath.XPathDocument megaXml =
+          new System.Xml.XPath.XPathDocument(XmlReader.Create(new StringReader(megaDoc.ToString())));
+        System.Xml.XPath.XPathNodeIterator nodes = megaXml.CreateNavigator().Select("/hack/*");
+        string docfn = null;
+        foreach (System.Xml.XPath.XPathNavigator var in nodes)
+        {
+          if (var.Name == "filestart")
+            docfn = var.GetAttribute("name", "");
+          if (var.Name == "html")
+          {
+            Console.Error.Write(".");
+            XmlWriter w = new XmlTextWriter(new StreamWriter(@"docbuild\types\" + docfn));
+            var.WriteSubtree(w);
+            w.Close();
+          }
+        }
+        Console.Error.WriteLine();
+        Console.Error.WriteLine("Time split: {0} ms", timer.snap());
+      }
+      Console.Write("? ");
+      Console.Read();
+    }
+  }
+}
+
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/dodoc.cmd
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/dodoc.cmd	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/dodoc.cmd	(revision 3)
@@ -0,0 +1,3 @@
+md docbuild\types
+del docbuild\types\*.htm
+bin\Debug\docNet.exe ..\C5\bin\Debug\C5.dll ..\C5\c5.xml
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/mkcurrent.cmd
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/mkcurrent.cmd	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/mkcurrent.cmd	(revision 3)
@@ -0,0 +1,10 @@
+cd c:\src\c5\src\C5\docNet\docbuild
+
+copy ..\..\C5\bin\Debug\C5.dll W:\research\c5\current
+copy ..\..\C5\bin\Debug\C5.pdb W:\research\c5\current
+
+rem del "W:\research\c5\current\types\*.htm"
+
+xcopy /Q *.htm W:\research\c5\current /S/Y
+copy docnet.css W:\research\c5\current
+pause
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/overview.xslt
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/overview.xslt	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/overview.xslt	(revision 3)
@@ -0,0 +1,65 @@
+<?xml version="1.0" ?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+<xsl:output encoding = "ISO-8859-1"/>
+    <xsl:template match="/">
+        <html>
+            <head>
+                <title>
+                    <xsl:text>DocNet documentation for</xsl:text>
+                    <xsl:value-of select="Assembly/@Name" /></title>
+                <link rel="stylesheet" type="text/css" href="docnet.css" />
+            </head>
+            <body>
+                <h3>Interfaces overview</h3>
+                <xsl:for-each select="/Assembly/Interface[@Access != 'private']">
+                    <xsl:sort select="@Name" />
+                    <xsl:call-template name="htmllink" />
+                    <xsl:if test="position()!=last()">,<br/> </xsl:if>
+                </xsl:for-each>
+                <h3>Classes overview</h3>
+                <xsl:for-each select="/Assembly/Class[@Access != 'private']">
+                    <xsl:sort select="@Name" />
+                    <xsl:call-template name="htmllink" />
+                    <xsl:if test="position()!=last()">,<br/> </xsl:if>
+                </xsl:for-each>
+                <h3>Value Types overview</h3>
+                <xsl:for-each select="/Assembly/Struct[@Access != 'private']">
+                    <xsl:sort select="@Name" />
+                    <xsl:call-template name="htmllink" />
+                    <xsl:if test="position()!=last()">,<br/> </xsl:if>
+                </xsl:for-each>
+                <h3>Delegates overview</h3>
+                <xsl:for-each select="/Assembly/Delegate[@Access != 'private']">
+                    <xsl:sort select="@Name" />
+                    <xsl:call-template name="htmllink" />
+                    <xsl:if test="position()!=last()">,<br/> </xsl:if>
+                </xsl:for-each>
+            </body>
+        </html>
+    </xsl:template>
+    <xsl:template match="Signature">
+        <code>
+            <xsl:value-of select="." />
+        </code>
+    </xsl:template>
+    <xsl:template name="htmllink">
+        <xsl:choose>
+            <xsl:when test="@refid">
+                <xsl:element name="a">
+                    <xsl:attribute name="href">
+                        <!--xsl:text>main.htm#</xsl:text>
+                        <xsl:value-of select="@refid" /-->
+                        <xsl:text>types/</xsl:text><xsl:value-of select="translate(substring(@refid,3),'`','_')" /><xsl:text>.htm</xsl:text>
+                    </xsl:attribute>
+                    <xsl:attribute name="target">
+                        <xsl:text>main</xsl:text>
+                    </xsl:attribute>
+                    <xsl:apply-templates select="Signature" />
+                </xsl:element>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:apply-templates select="Signature" />
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+</xsl:stylesheet>
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/tolatex.xslt
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/tolatex.xslt	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/tolatex.xslt	(revision 3)
@@ -0,0 +1,43 @@
+<?xml version="1.0" ?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+    <xsl:output encoding = "ISO-8859-1" omit-xml-declaration="yes" indent="no"/>
+    <xsl:strip-space elements="*"/>
+    <xsl:template match="table">
+        <xsl:text>\begin{tabular}{lc|*{15}{c}}\hline\hline&#10;</xsl:text>
+        <xsl:apply-templates></xsl:apply-templates>
+        <xsl:text>\hline\hline&#10;\end{tabular}&#10;</xsl:text>
+    </xsl:template>
+    <xsl:template match="tr">
+        <xsl:choose>
+            <xsl:when test="td/i">
+                <xsl:text>\hline&#10;%</xsl:text><xsl:value-of select="td/i/font"/><xsl:text>&#10;</xsl:text>
+            </xsl:when>
+            <xsl:otherwise>
+                <xsl:for-each select="th">
+                    <xsl:if test="position()!=1">\turned{</xsl:if>
+                    <xsl:apply-templates/>
+                    <xsl:if test="position()!=1">}</xsl:if>
+                    <xsl:if test="position()!=last()"><xsl:text disable-output-escaping="yes" >&#10;&amp;&#32;</xsl:text></xsl:if>
+                </xsl:for-each>
+                <xsl:for-each select="td">
+                    <xsl:if test="position()=1">\texttt{</xsl:if>
+                    <xsl:if test="position()!=1">$</xsl:if>
+                    <xsl:apply-templates/>
+                    <xsl:if test="position()=1">}</xsl:if>
+                    <xsl:if test="position()!=1">$</xsl:if>
+                    <xsl:if test="position()!=last()"><xsl:text disable-output-escaping="yes" >&#32;&amp;&#32;</xsl:text></xsl:if>
+                </xsl:for-each>
+                <!---->\\&#10;<!---->
+            </xsl:otherwise>
+        </xsl:choose>
+    </xsl:template>
+    <xsl:template match ="th">
+        <xsl:apply-templates/>
+    </xsl:template>
+    <xsl:template match ="td">
+        <xsl:apply-templates/>
+    </xsl:template>
+    <xsl:template match="font">
+        <xsl:apply-templates/>
+    </xsl:template>
+</xsl:stylesheet>
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/trans.xslt
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/trans.xslt	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/docNet/trans.xslt	(revision 3)
@@ -0,0 +1,592 @@
+<?xml version="1.0" ?>
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+  <xsl:output encoding = "ISO-8859-1"/>
+  <xsl:template match="/">
+    <xsl:apply-templates select="/Assembly/Interface" />
+    <xsl:apply-templates select="/Assembly/Class" />
+    <xsl:apply-templates select="/Assembly/Struct" />
+    <xsl:apply-templates select="/Assembly/Delegate" />
+  </xsl:template>
+  <xsl:template match="/Assembly/Interface">
+    <xsl:call-template name="file"/>
+  </xsl:template>
+  <xsl:template match="/Assembly/Class">
+    <xsl:call-template name="file"/>
+  </xsl:template>
+  <xsl:template match="/Assembly/Struct">
+    <xsl:call-template name="file"/>
+  </xsl:template>
+  <xsl:template match="/Assembly/Delegate">
+    <xsl:call-template name="file"/>
+  </xsl:template>
+  <xsl:template name="file">
+    <xsl:if test="@Access[.!='private']">
+      <xsl:text>&#13;&#10;</xsl:text>
+      <xsl:element name="filestart">
+        <xsl:attribute name="name">
+          <xsl:value-of select="translate(substring(@refid,3),'`','_')"/>
+          <xsl:text>.htm</xsl:text>
+        </xsl:attribute>
+      </xsl:element>
+      <xsl:text>&#13;&#10;</xsl:text>
+      <html >
+        <head>
+          <title>
+            <xsl:text>C5 doc: </xsl:text>
+            <xsl:value-of select="@Name" />
+          </title>
+          <link rel="stylesheet" type="text/css" href="../docnet.css" />
+        </head>
+        <xsl:element name="body">
+          <xsl:attribute name="onLoad">
+            <xsl:text>parent.document.title ='C5 doc: </xsl:text>
+            <xsl:value-of select="@Name" />
+            <xsl:text>'</xsl:text>
+          </xsl:attribute>
+          <h2>
+            <xsl:value-of select="name()"/>
+            <xsl:text>&#32;</xsl:text>
+            <xsl:call-template name="htmlname" />
+          </h2>
+          <xsl:apply-templates select="summary" />
+          <xsl:call-template name="typeparams" />
+          <xsl:call-template name="implements" />
+          <xsl:call-template name="implementedby" />
+          <xsl:call-template name="super" />
+          <xsl:apply-templates select="Bases" />
+          <xsl:call-template name="baseof" />
+          <xsl:call-template name="foverview" />
+          <xsl:call-template name="eoverview" />
+          <xsl:call-template name="poverview" />
+          <xsl:call-template name="coverview" />
+          <xsl:call-template name="moverview" />
+          <xsl:call-template name="ooverview" />
+          <xsl:call-template name="ftable" />
+          <xsl:call-template name="etable" />
+          <xsl:call-template name="ptable" />
+          <xsl:call-template name="ctable" />
+          <xsl:call-template name="mtable" />
+          <xsl:call-template name="otable" />
+        </xsl:element>
+      </html>
+    </xsl:if>
+  </xsl:template>
+  <xsl:template name="implements">
+    <xsl:for-each select="Implements">
+      <xsl:sort select="@refid" />
+      <xsl:if test="position()=1">
+        <h3>Implements</h3>
+      </xsl:if>
+      <xsl:call-template name="htmllink" />
+      <xsl:if test="position()!=last()">, </xsl:if>
+    </xsl:for-each>
+  </xsl:template>
+  <xsl:template name="super">
+    <xsl:variable name="leRefid" select="@refid" />
+    <xsl:for-each select="/Assembly/Interface[Implements[@refid = $leRefid ] and @Access != 'private']">
+      <xsl:sort select="@Name" />
+      <xsl:if test="position()=1">
+        <h3>Super</h3>
+      </xsl:if>
+      <xsl:call-template name="htmllink" />
+      <xsl:if test="position()!=last()">, </xsl:if>
+    </xsl:for-each>
+  </xsl:template>
+  <xsl:template name="implementedby">
+    <xsl:variable name="leRefid" select="@refid" />
+    <xsl:for-each select="/Assembly/Class[Implements[@refid = $leRefid ] and @Access != 'private']">
+      <xsl:sort select="@Name" />
+      <xsl:if test="position()=1">
+        <h3>Implemented by</h3>
+      </xsl:if>
+      <xsl:call-template name="htmllink" />
+      <xsl:if test="position()!=last()">, </xsl:if>
+    </xsl:for-each>
+  </xsl:template>
+  <xsl:template match="Bases">
+    <xsl:if test="position()=1">
+      <h3>Bases</h3>
+    </xsl:if>
+    <xsl:call-template name="htmllink" />
+    <xsl:if test="position()!=last()">, </xsl:if>
+  </xsl:template>
+  <xsl:template name="baseof">
+    <xsl:variable name="leRefid" select="@refid" />
+    <xsl:for-each select="/Assembly/Class[Bases[@refid = $leRefid ] and @Access != 'private']">
+      <xsl:sort select="@Name" />
+      <xsl:if test="position()=1">
+        <h3>Base of</h3>
+      </xsl:if>
+      <xsl:call-template name="htmllink" />
+      <xsl:if test="position()!=last()">, </xsl:if>
+    </xsl:for-each>
+  </xsl:template>
+  <xsl:template match="param">
+    <tr>
+      <td valign="top">
+        <!--code-->
+        <xsl:value-of select="@name" />
+        <!--/code-->
+        <xsl:text>:</xsl:text>
+      </td>
+      <td valign="top">
+        <xsl:apply-templates/>
+      </td>
+    </tr>
+  </xsl:template>
+  <xsl:template match="returns">
+    <xsl:if test="current()[../@ReturnType!='void']">
+      <tr>
+        <td valign="top">
+          <b>Returns:</b>
+        </td>
+        <td valign="top">
+          <xsl:apply-templates/>
+        </td>
+      </tr>
+    </xsl:if>
+  </xsl:template>
+  <xsl:template match="Signature">
+    <code>
+      <xsl:value-of select="." />
+    </code>
+  </xsl:template>
+  <xsl:template match="summary">
+    <xsl:apply-templates />
+  </xsl:template>
+  <xsl:template match="value">
+    <p>
+      <b>Value:</b>
+      <xsl:apply-templates />
+    </p>
+  </xsl:template>
+  <!-- templates for VS 2005 doc tags-->
+  <xsl:template match="exception">
+    <xsl:choose>
+      <xsl:when test="current()[name(..)='summary']">
+        <b>/Throws</b>
+        <xsl:value-of select="substring(@cref,3)" />
+        <xsl:apply-templates />
+      </xsl:when>
+      <xsl:otherwise>
+        <tr>
+          <td valign="top">
+            <xsl:variable name="leRefid" select="@cref" />
+            <xsl:variable name="leExcNode" select="/Assembly/Class[@refid = $leRefid  and @Access != 'private']"/>
+            <xsl:choose>
+              <xsl:when test="$leExcNode">
+                <xsl:for-each select="$leExcNode">
+                  <xsl:call-template name="htmllink" />
+                </xsl:for-each>
+              </xsl:when>
+              <xsl:otherwise>
+                <xsl:value-of select="substring(@cref,3)" />
+              </xsl:otherwise>
+            </xsl:choose>
+          </td>
+          <td valign="top">
+            <xsl:apply-templates />
+          </td>
+        </tr>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  <!--xsl:template match="code">
+        <code>
+            <xsl:apply-templates select="@* | node()" />
+        </code>
+    </xsl:template-->
+  <xsl:template match="item">
+    <li>
+      <xsl:apply-templates select="@* | node()" />
+    </li>
+  </xsl:template>
+  <!-- also do description and term tags, and other list types?-->
+  <xsl:template match="list">
+    <xsl:choose>
+      <xsl:when test="@type='ordered'">
+        <ol>
+          <xsl:apply-templates select="@* | node()" />
+        </ol>
+      </xsl:when>
+      <xsl:otherwise>
+        <ul>
+          <xsl:apply-templates select="@* | node()" />
+        </ul>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  <xsl:template match="para">
+    <p>
+      <xsl:apply-templates select="@* | node()" />
+    </p>
+  </xsl:template>
+  <xsl:template match="seealso">
+    <xsl:text>See also</xsl:text>
+    <xsl:variable name="leRefid" select="@cref" />
+    <xsl:variable name="leNode" select="//*[@refid=$leRefid]" />
+    <xsl:variable name="leFile" select="substring(ancestor::*[@refid and not(@Declared)]/@refid,3)" />
+    <xsl:choose>
+      <xsl:when test ="substring(@cref,1,2) = 'T:'">
+        <xsl:element name="a">
+          <xsl:attribute name="href">
+            <xsl:value-of select="substring(@cref,3)" />
+            <xsl:text>.htm</xsl:text>
+          </xsl:attribute>
+          <xsl:value-of select="$leNode/Signature" />
+        </xsl:element>
+      </xsl:when>
+      <xsl:when test="$leNode/@CDeclared=$leFile">
+        <xsl:element name="a">
+          <xsl:attribute name="href">
+            #<xsl:value-of select="@cref" />
+          </xsl:attribute>
+          <xsl:value-of select="$leNode/Signature" />
+        </xsl:element>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:element name="a">
+          <xsl:attribute name="href">
+            <xsl:value-of select="translate($leNode/@CDeclared,'`','_')" />.htm#<xsl:value-of select="@cref" />
+          </xsl:attribute>
+          <xsl:value-of select="$leNode/@Declared" />.<xsl:value-of select="$leNode/Signature" />
+        </xsl:element>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  <xsl:template match="see">
+    <!--xsl:text>See </xsl:text-->
+    <xsl:variable name="leRefid" select="@cref" />
+    <xsl:variable name="leNode" select="//*[@refid=$leRefid]" />
+    <xsl:variable name="leFile" select="substring(ancestor::*[@refid and not(@Declared)]/@refid,3)" />
+    <xsl:choose>
+      <xsl:when test ="substring(@cref,1,2) = 'T:'">
+        <xsl:element name="a">
+          <xsl:attribute name="href">
+            <xsl:value-of select="substring(@cref,3)" />
+            <xsl:text>.htm</xsl:text>
+          </xsl:attribute>
+          <xsl:value-of select="$leNode/Signature" />
+        </xsl:element>
+      </xsl:when>
+      <xsl:when test="$leNode/@CDeclared=$leFile">
+        <xsl:element name="a">
+          <xsl:attribute name="href">
+            <xsl:text>#</xsl:text>
+            <xsl:value-of select="@cref" />
+          </xsl:attribute>
+          <xsl:value-of select="$leNode/Signature" />
+        </xsl:element>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:element name="a">
+          <xsl:attribute name="href">
+            <xsl:value-of select="translate($leNode/@CDeclared,'`','_')" />.htm#<xsl:value-of select="@cref" />
+          </xsl:attribute>
+          <xsl:value-of select="$leNode/@Declared" />.<xsl:value-of select="$leNode/Signature" />
+        </xsl:element>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  <xsl:template match="typeparam">
+    <tr>
+      <td valign="top">
+        <xsl:value-of select="@name" />
+      </td>
+      <td valign="top">
+        <xsl:apply-templates />
+      </td>
+    </tr>
+  </xsl:template>
+  <xsl:template match="constraint">
+    <tr>
+      <td valign="top"></td>
+      <td valign="top">
+        <xsl:value-of select="@Value" />
+      </td>
+    </tr>
+  </xsl:template>
+  <xsl:template match="@* | node()">
+    <xsl:copy>
+      <xsl:apply-templates select="@* | node()" />
+    </xsl:copy>
+  </xsl:template>
+  <!-- end templates for VS 2005 doc tags -->
+  <xsl:template name="typeparams">
+    <xsl:if test="typeparam">
+      <table>
+        <tr>
+          <td>
+            <b>Type parameters:</b>
+          </td>
+          <td></td>
+        </tr>
+        <xsl:apply-templates select="typeparam"/>
+        <xsl:if test="constraint">
+          <tr>
+            <td>
+              <b>Constraints:</b>
+            </td>
+            <td></td>
+          </tr>
+          <xsl:apply-templates select="constraint"/>
+        </xsl:if>
+      </table>
+    </xsl:if>
+  </xsl:template>
+  <xsl:template name="htmllink">
+    <xsl:choose>
+      <xsl:when test="@C5">
+        <xsl:element name="a">
+          <xsl:attribute name="href">
+            <xsl:choose>
+              <xsl:when test ="substring(@refid,1,2) = 'T:'">
+                <xsl:value-of select="translate(substring(@refid,3),'`','_')" />
+                <xsl:text>.htm</xsl:text>
+              </xsl:when>
+              <xsl:otherwise>
+                <xsl:value-of select="translate(@CDeclared,'`','_')"/>.htm#<xsl:value-of select="@refid" />
+              </xsl:otherwise>
+            </xsl:choose>
+          </xsl:attribute>
+          <xsl:apply-templates select="Signature" />
+        </xsl:element>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:apply-templates select="Signature" />
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  <xsl:template name="locallink">
+    <xsl:choose>
+      <xsl:when test="@refid">
+        <xsl:element name="a">
+          <xsl:attribute name="href">
+            <xsl:text>#</xsl:text>
+            <xsl:value-of select="concat(../@refid , '|',@refid)" />
+          </xsl:attribute>
+          <xsl:apply-templates select="Signature" />
+        </xsl:element>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:apply-templates select="Signature" />
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  <xsl:template name="htmlname">
+    <xsl:choose>
+      <xsl:when test="@refid">
+        <xsl:choose>
+          <xsl:when test ="not(@Declared)">
+            <!-- i.e. a type -->
+            <xsl:element name="a">
+              <xsl:attribute name="name">
+                <xsl:value-of select="@refid" />
+              </xsl:attribute>
+              <xsl:apply-templates select="Signature" />
+            </xsl:element>
+          </xsl:when>
+          <xsl:otherwise>
+            <!-- i.e. a member -->
+            <xsl:element name="a">
+              <xsl:attribute name="name">
+                <xsl:value-of select="concat(../@refid , '|',@refid)" />
+              </xsl:attribute>
+              <xsl:apply-templates select="Signature" />
+            </xsl:element>
+            <xsl:if test ="not(@Inherited)">
+              <!-- the canonical description -->
+              <xsl:element name="a">
+                <xsl:attribute name="name">
+                  <xsl:value-of select="@refid" />
+                </xsl:attribute>
+              </xsl:element>
+            </xsl:if>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:apply-templates select="Signature" />
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  <xsl:template name="ftable">
+    <xsl:call-template name="table">
+      <xsl:with-param name="type">Field</xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+  <xsl:template name="etable">
+    <xsl:call-template name="table">
+      <xsl:with-param name="type">Event</xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+  <xsl:template name="ptable">
+    <xsl:call-template name="table">
+      <xsl:with-param name="type">Property</xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+  <xsl:template name="ctable">
+    <xsl:call-template name="table">
+      <xsl:with-param name="type">Constructor</xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+  <xsl:template name="mtable">
+    <xsl:call-template name="table">
+      <xsl:with-param name="type" select="'Method'"/>
+    </xsl:call-template>
+  </xsl:template>
+  <xsl:template name="otable">
+    <xsl:call-template name="table">
+      <xsl:with-param name="type" select="'Operator'"/>
+    </xsl:call-template>
+  </xsl:template>
+  <xsl:template name="table">
+    <xsl:param name="type" />
+    <xsl:param name="protection" />
+    <xsl:variable name="thenodes" select="*[name() = $type and @Access != 'private' and not(@Inherited)]" />
+    <xsl:if test="$thenodes">
+      <h3>
+        <xsl:value-of select="$type" />
+        <xsl:text> details</xsl:text>
+      </h3>
+      <table border="1">
+        <xsl:for-each select="$thenodes">
+          <xsl:sort select="@Name" />
+          <tr>
+            <td valign="top">
+              <xsl:if test="current()[@Virtual != 'True' and @Static != 'True']">
+                <code class="greenbg">N</code>
+              </xsl:if>
+              <xsl:if test="current()[@Final = 'True' and @Static != 'True']">
+                <code class="greenbg">F</code>
+              </xsl:if>
+              <xsl:if test="current()[@Abstract = 'True']">
+                <code class="greenbg">A</code>
+              </xsl:if>
+              <xsl:if test="current()[@Static = 'True']">
+                <code class="greenbg">S</code>
+              </xsl:if>
+              <xsl:if test="current()[@Access = 'protected']">
+                <code class="greenbg">P</code>
+              </xsl:if>
+              <code>
+                <xsl:text>&#32;</xsl:text>
+                <xsl:choose>
+                  <xsl:when test="@ReturnType">
+                    <xsl:value-of select="@ReturnType"/>
+                  </xsl:when>
+                  <xsl:otherwise>
+                    <xsl:value-of select="@Type"/>
+                  </xsl:otherwise>
+                </xsl:choose>
+                <xsl:text>&#32;</xsl:text>
+              </code>
+              <xsl:call-template name="htmlname" />
+            </td>
+            <td>
+              <!--xsl:if test="@Inherited">
+                                <xsl:text>Inherited from </xsl:text>
+                                <xsl:value-of select="@Declared"/>
+                                <xsl:text>: </xsl:text>
+                                <xsl:call-template name="htmllink" />
+                            </xsl:if-->
+              <xsl:if test="not(@Inherited)">
+                <xsl:if test="@Get">
+                  <b>Access: </b>
+                  <xsl:if test="@Get='True' and @Set='True'">Read-Write</xsl:if>
+                  <xsl:if test="@Get='True' and @Set='False'">Read-Only</xsl:if>
+                  <xsl:if test="@Get='False' and @Set='True'">Write-Only</xsl:if>
+                  <br/>
+                </xsl:if>
+                <xsl:apply-templates select="value" />
+                <xsl:apply-templates select="summary" />
+                <xsl:if test="exception">
+                  <table>
+                    <tr>
+                      <td>
+                        <b>Throws</b>
+                      </td>
+                      <td></td>
+                    </tr>
+                    <xsl:apply-templates select="exception" />
+                  </table>
+                </xsl:if>
+                <xsl:call-template name="typeparams"/>
+                <!--xsl:if test="current()[@ReturnType != 'void'] or param"-->
+                  <xsl:if test="returns or param">
+                  <table>
+                    <xsl:apply-templates select="returns" />
+                    <xsl:if test="param">
+                      <tr>
+                        <td>
+                          <b>Parameters:</b>
+                        </td>
+                      </tr>
+                      <xsl:apply-templates select="param" />
+                    </xsl:if>
+                  </table>
+                </xsl:if>
+              </xsl:if>
+            </td>
+          </tr>
+        </xsl:for-each>
+      </table>
+    </xsl:if>
+  </xsl:template>
+  <xsl:template name="foverview">
+    <xsl:call-template name="overview">
+      <xsl:with-param name="type">Field</xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+  <xsl:template name="eoverview">
+    <xsl:call-template name="overview">
+      <xsl:with-param name="type">Event</xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+  <xsl:template name="poverview">
+    <xsl:call-template name="overview">
+      <xsl:with-param name="type">Property</xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+  <xsl:template name="coverview">
+    <xsl:call-template name="overview">
+      <xsl:with-param name="type">Constructor</xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+  <xsl:template name="moverview">
+    <xsl:call-template name="overview">
+      <xsl:with-param name="type">Method</xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+  <xsl:template name="ooverview">
+    <xsl:call-template name="overview">
+      <xsl:with-param name="type">Operator</xsl:with-param>
+    </xsl:call-template>
+  </xsl:template>
+  <xsl:template name="overview">
+    <xsl:param name="type" select="'[Unknown Locale]'" />
+    <xsl:for-each select="*[name() = $type and @Access != 'private']">
+      <xsl:sort select="@Name" />
+      <xsl:if test="position() = 1">
+        <h3>
+          <xsl:value-of select="$type" />
+          <xsl:text> overview</xsl:text>
+        </h3>
+      </xsl:if>
+      <xsl:choose>
+        <xsl:when test="@Inherited">
+          <xsl:call-template name="htmllink" />
+          <xsl:text>, </xsl:text>
+          <xsl:text>Inherited from </xsl:text>
+          <xsl:value-of select="@Declared"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:call-template name="locallink" />
+        </xsl:otherwise>
+      </xsl:choose>
+      <xsl:if test="position()!=last()">
+        ,<br/>
+      </xsl:if>
+    </xsl:for-each>
+  </xsl:template>
+</xsl:stylesheet>
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/arrays/ArrayListTest.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/arrays/ArrayListTest.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/arrays/ArrayListTest.cs	(revision 3)
@@ -0,0 +1,3840 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+namespace C5UnitTests.arrays.list
+{
+  using CollectionOfInt = ArrayList<int>;
+
+  [TestFixture]
+  public class GenericTesters
+  {
+    [Test]
+    public void TestEvents()
+    {
+      Fun<CollectionOfInt> factory = delegate() { return new CollectionOfInt(TenEqualityComparer.Default); };
+      new C5UnitTests.Templates.Events.ListTester<CollectionOfInt>().Test(factory);
+      new C5UnitTests.Templates.Events.QueueTester<CollectionOfInt>().Test(factory);
+      new C5UnitTests.Templates.Events.StackTester<CollectionOfInt>().Test(factory);
+    }
+
+    [Test]
+    public void Extensible()
+    {
+      C5UnitTests.Templates.Extensible.Clone.Tester<CollectionOfInt>();
+      C5UnitTests.Templates.Extensible.Clone.ViewTester<CollectionOfInt>();
+      C5UnitTests.Templates.Extensible.Serialization.Tester<CollectionOfInt>();
+      C5UnitTests.Templates.Extensible.Serialization.ViewTester<CollectionOfInt>();
+    }
+
+    [Test]
+    public void List()
+    {
+      C5UnitTests.Templates.List.Dispose.Tester<CollectionOfInt>();
+      C5UnitTests.Templates.List.SCG_IList.Tester<CollectionOfInt>();
+    }
+  }
+
+  static class Factory
+  {
+    public static ICollection<T> New<T>() { return new ArrayList<T>(); }
+  }
+
+  namespace Events
+  {
+    [TestFixture]
+    public class IList_
+    {
+      private ArrayList<int> list;
+      CollectionEventList<int> seen;
+
+      [SetUp]
+      public void Init()
+      {
+        list = new ArrayList<int>(TenEqualityComparer.Default);
+        seen = new CollectionEventList<int>(IntEqualityComparer.Default);
+      }
+
+      private void listen() { seen.Listen(list, EventTypeEnum.Added); }
+
+      [Test]
+      public void Listenable()
+      {
+        Assert.AreEqual(EventTypeEnum.All, list.ListenableEvents);
+        Assert.AreEqual(EventTypeEnum.None, list.ActiveEvents);
+        listen();
+        Assert.AreEqual(EventTypeEnum.Added, list.ActiveEvents);
+      }
+
+      [Test]
+      public void SetThis()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list[1] = 45;
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(56,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(45,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+          });
+      }
+
+      [Test]
+      public void Insert()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.Insert(1, 45);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(45,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+          });
+      }
+
+      [Test]
+      public void InsertAll()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.InsertAll<int>(1, new int[] { 666, 777, 888 });
+        //seen.Print(Console.Error);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(666,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(666, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(777,2), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(777, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(888,3), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(888, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+          });
+        list.InsertAll<int>(1, new int[] {});
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void InsertFirstLast()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.InsertFirst(45);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(45,0), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+          });
+        list.InsertLast(88);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(88,4), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(88, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+          });
+      }
+
+      [Test]
+      public void Remove()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.Remove();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(8, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+      }
+
+      [Test]
+      public void RemoveFirst()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.RemoveFirst();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(4,0), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(4, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+      }
+
+      [Test]
+      public void RemoveLast()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.RemoveLast();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(8,2), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(8, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+      }
+
+      [Test]
+      public void Reverse()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.Reverse();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        list.View(1, 0).Reverse();
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+
+      [Test]
+      public void Sort()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.Sort();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        list.View(1, 0).Sort();
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void Shuffle()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.Shuffle();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        list.View(1, 0).Shuffle();
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void RemoveAt()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.RemoveAt(1);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(56,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+      }
+
+      [Test]
+      public void RemoveInterval()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.RemoveInterval(1, 2);
+        seen.Check(new CollectionEvent<int>[] {
+           new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(false,2,1), list),
+         new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        list.RemoveInterval(1, 0);
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void Update()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.Update(53);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(53, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+          });
+        list.Update(67);
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void FindOrAdd()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        int val = 53;
+        list.FindOrAdd(ref val);
+        seen.Check(new CollectionEvent<int>[] {});
+        val = 67;
+        list.FindOrAdd(ref val);
+        seen.Check(new CollectionEvent<int>[] { 
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+      }
+
+      [Test]
+      public void UpdateOrAdd()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        int val = 53;
+        list.UpdateOrAdd(val);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(53, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        val = 67;
+        list.UpdateOrAdd(val);
+        seen.Check(new CollectionEvent<int>[] { 
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        list.UpdateOrAdd(51, out val);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(53, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(51, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        val = 67;
+        list.UpdateOrAdd(81, out val);
+        seen.Check(new CollectionEvent<int>[] { 
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(81, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+      }
+
+      [Test]
+      public void RemoveItem()
+      {
+        list.Add(4); list.Add(56); list.Add(18);
+        listen();
+        list.Remove(53);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.Remove(11);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(18, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+      }
+
+      [Test]
+      public void RemoveAll()
+      {
+        for (int i = 0; i < 10; i++)
+        {
+          list.Add(10 * i + 5);
+        }
+        listen();
+        list.RemoveAll<int>(new int[] { 32, 187, 45 });
+        //TODO: the order depends on internals of the HashSet
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(35, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(45, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.RemoveAll<int>(new int[] { 200, 300 });
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void Clear()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.View(1, 1).Clear();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(false,1,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        list.Clear();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(true,2,0), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        list.Clear();
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void ListDispose()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.View(1, 1).Dispose();
+        seen.Check(new CollectionEvent<int>[] {});
+        list.Dispose();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(true,3,0), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        list.Dispose();
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+
+      [Test]
+      public void RetainAll()
+      {
+        for (int i = 0; i < 10; i++)
+        {
+          list.Add(10 * i + 5);
+        }
+        listen();
+        list.RetainAll<int>(new int[] { 32, 187, 45, 62, 82, 95, 2 });
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(15, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(25, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(55, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(75, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.RetainAll<int>(new int[] { 32, 187, 45, 62, 82, 95, 2 });
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void RemoveAllCopies()
+      {
+        for (int i = 0; i < 10; i++)
+        {
+          list.Add(3 * i + 5);
+        }
+        listen();
+        list.RemoveAllCopies(14);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(11, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(14, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(17, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.RemoveAllCopies(14);
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void Add()
+      {
+        listen();
+        seen.Check(new CollectionEvent<int>[0]);
+        list.Add(23);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(23, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+      }
+
+      [Test]
+      public void AddAll()
+      {
+        for (int i = 0; i < 10; i++)
+        {
+          list.Add(10 * i + 5);
+        }
+        listen();
+        list.AddAll<int>(new int[] { 45, 56, 67 });
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(56, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.AddAll<int>(new int[] { });
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [TearDown]
+      public void Dispose() { list = null; seen = null; }
+
+      [Test]
+      [ExpectedException(typeof(UnlistenableEventException))]
+      public void ViewChanged()
+      {
+        IList<int> w = list.View(0, 0);
+        w.CollectionChanged += new CollectionChangedHandler<int>(w_CollectionChanged);
+      }
+
+      [Test]
+      [ExpectedException(typeof(UnlistenableEventException))]
+      public void ViewCleared()
+      {
+        IList<int> w = list.View(0, 0);
+        w.CollectionCleared += new CollectionClearedHandler<int>(w_CollectionCleared);
+      }
+
+      [Test]
+      [ExpectedException(typeof(UnlistenableEventException))]
+      public void ViewAdded()
+      {
+        IList<int> w = list.View(0, 0);
+        w.ItemsAdded += new ItemsAddedHandler<int>(w_ItemAdded);
+      }
+
+      [Test]
+      [ExpectedException(typeof(UnlistenableEventException))]
+      public void ViewInserted()
+      {
+        IList<int> w = list.View(0, 0);
+        w.ItemInserted += new ItemInsertedHandler<int>(w_ItemInserted);
+      }
+
+      [Test]
+      [ExpectedException(typeof(UnlistenableEventException))]
+      public void ViewRemoved()
+      {
+        IList<int> w = list.View(0, 0);
+        w.ItemsRemoved += new ItemsRemovedHandler<int>(w_ItemRemoved);
+      }
+
+      [Test]
+      [ExpectedException(typeof(UnlistenableEventException))]
+      public void ViewRemovedAt()
+      {
+        IList<int> w = list.View(0, 0);
+        w.ItemRemovedAt += new ItemRemovedAtHandler<int>(w_ItemRemovedAt);
+      }
+
+      void w_CollectionChanged(object sender)
+      {
+        throw new NotImplementedException();
+      }
+
+      void w_CollectionCleared(object sender, ClearedEventArgs eventArgs)
+      {
+        throw new NotImplementedException();
+      }
+
+      void w_ItemAdded(object sender, ItemCountEventArgs<int> eventArgs)
+      {
+        throw new NotImplementedException();
+      }
+
+      void w_ItemInserted(object sender, ItemAtEventArgs<int> eventArgs)
+      {
+        throw new NotImplementedException();
+      }
+
+      void w_ItemRemoved(object sender, ItemCountEventArgs<int> eventArgs)
+      {
+        throw new NotImplementedException();
+      }
+
+      void w_ItemRemovedAt(object sender, ItemAtEventArgs<int> eventArgs)
+      {
+        throw new NotImplementedException();
+      }
+    }
+
+    [TestFixture]
+    public class StackQueue
+    {
+
+      private ArrayList<int> list;
+      CollectionEventList<int> seen;
+
+      [SetUp]
+      public void Init()
+      {
+        list = new ArrayList<int>(TenEqualityComparer.Default);
+        seen = new CollectionEventList<int>(IntEqualityComparer.Default);
+      }
+
+      private void listen() { seen.Listen(list, EventTypeEnum.All); }
+
+      [Test]
+      public void EnqueueDequeue()
+      {
+        listen();
+        list.Enqueue(67);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(67,0), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.Enqueue(2);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(2,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(2, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.Dequeue();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(67,0), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(67, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.Dequeue();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(2,0), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(2, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+      }
+
+      [Test]
+      public void PushPop()
+      {
+        listen();
+        seen.Check(new CollectionEvent<int>[0]);
+        list.Push(23);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(23,0), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(23, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.Push(-12);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(-12,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(-12, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.Pop();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(-12,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(-12, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.Pop();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(23,0), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(23, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+      }
+
+      [TearDown]
+      public void Dispose() { list = null; seen = null; }
+    }
+  }
+
+  namespace Safety
+  {
+    /// <summary>
+    /// Tests to see if the collection classes are robust for enumerable arguments that throw exceptions.
+    /// </summary>
+    [TestFixture]
+    public class BadEnumerable
+    {
+      private ArrayList<int> list;
+
+      [SetUp]
+      public void Init()
+      {
+        list = new ArrayList<int>();
+      }
+
+      [Test]
+      public void InsertAll()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        try
+        {
+          list.InsertAll<int>(1, new BadEnumerable<int>(new BadEnumerableException(), 9, 8, 7));
+          Assert.Fail("Should not get here");
+        }
+        catch (BadEnumerableException) { }
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 9, 8, 7, 56, 8));
+
+      }
+
+      [Test]
+      public void AddAll()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        try
+        {
+          list.View(0, 1).AddAll<int>(new BadEnumerable<int>(new BadEnumerableException(), 9, 8, 7));
+          Assert.Fail("Should not get here");
+        }
+        catch (BadEnumerableException) { }
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 9, 8, 7, 56, 8));
+      }
+
+      [Test]
+      public void RemoveAll()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        try
+        {
+          list.RemoveAll(new BadEnumerable<int>(new BadEnumerableException(), 9, 8, 7));
+          Assert.Fail("Should not get here");
+        }
+        catch (BadEnumerableException) { }
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 56, 8));
+      }
+
+      [Test]
+      public void RetainAll()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        try
+        {
+          list.RetainAll(new BadEnumerable<int>(new BadEnumerableException(), 9, 8, 7));
+          Assert.Fail("Should not get here");
+        }
+        catch (BadEnumerableException) { }
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 56, 8));
+      }
+
+
+      [Test]
+      public void ContainsAll()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        try
+        {
+          list.ContainsAll(new BadEnumerable<int>(new BadEnumerableException(), 4, 18));
+          Assert.Fail("Should not get here");
+        }
+        catch (BadEnumerableException) { }
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 56, 8));
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+
+    /// <summary>
+    /// Tests to see if the collection classes are robust for delegate arguments that throw exceptions.
+    /// </summary>
+    [TestFixture]
+    public class BadFun
+    {
+      private ArrayList<int> list;
+
+      [SetUp]
+      public void Init()
+      {
+        list = new ArrayList<int>();
+      }
+
+      [Test]
+      public void NoTests() { }
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+  }
+
+  namespace Enumerable
+  {
+    [TestFixture]
+    public class Multiops
+    {
+      private ArrayList<int> list;
+
+      private Fun<int, bool> always, never, even;
+
+
+      [SetUp]
+      public void Init()
+      {
+        list = new ArrayList<int>();
+        always = delegate { return true; };
+        never = delegate { return false; };
+        even = delegate(int i) { return i % 2 == 0; };
+      }
+
+
+      [Test]
+      public void All()
+      {
+        Assert.IsTrue(list.All(always));
+        Assert.IsTrue(list.All(never));
+        Assert.IsTrue(list.All(even));
+        list.Add(8);
+        Assert.IsTrue(list.All(always));
+        Assert.IsFalse(list.All(never));
+        Assert.IsTrue(list.All(even));
+        list.Add(5);
+        Assert.IsTrue(list.All(always));
+        Assert.IsFalse(list.All(never));
+        Assert.IsFalse(list.All(even));
+      }
+
+
+      [Test]
+      public void Exists()
+      {
+        Assert.IsFalse(list.Exists(always));
+        Assert.IsFalse(list.Exists(never));
+        Assert.IsFalse(list.Exists(even));
+        list.Add(5);
+        Assert.IsTrue(list.Exists(always));
+        Assert.IsFalse(list.Exists(never));
+        Assert.IsFalse(list.Exists(even));
+        list.Add(8);
+        Assert.IsTrue(list.Exists(always));
+        Assert.IsFalse(list.Exists(never));
+        Assert.IsTrue(list.Exists(even));
+      }
+
+
+      [Test]
+      public void Apply()
+      {
+        int sum = 0;
+        Act<int> a = delegate(int i) { sum = i + 10 * sum; };
+
+        list.Apply(a);
+        Assert.AreEqual(0, sum);
+        sum = 0;
+        list.Add(5); list.Add(8); list.Add(7); list.Add(5);
+        list.Apply(a);
+        Assert.AreEqual(5875, sum);
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+
+
+
+    [TestFixture]
+    public class GetEnumerator
+    {
+      private ArrayList<int> list;
+
+
+      [SetUp]
+      public void Init() { list = new ArrayList<int>(); }
+
+
+      [Test]
+      public void Empty()
+      {
+        SCG.IEnumerator<int> e = list.GetEnumerator();
+
+        Assert.IsFalse(e.MoveNext());
+      }
+
+
+      [Test]
+      public void Normal()
+      {
+        list.Add(5);
+        list.Add(8);
+        list.Add(5);
+        list.Add(5);
+        list.Add(10);
+        list.Add(1);
+
+        SCG.IEnumerator<int> e = list.GetEnumerator();
+
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(5, e.Current);
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(8, e.Current);
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(5, e.Current);
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(5, e.Current);
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(10, e.Current);
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(1, e.Current);
+        Assert.IsFalse(e.MoveNext());
+      }
+
+
+      [Test]
+      public void DoDispose()
+      {
+        list.Add(5);
+        list.Add(8);
+        list.Add(5);
+
+        SCG.IEnumerator<int> e = list.GetEnumerator();
+
+        e.MoveNext();
+        e.MoveNext();
+        e.Dispose();
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterUpdate()
+      {
+        list.Add(5);
+        list.Add(8);
+        list.Add(5);
+
+        SCG.IEnumerator<int> e = list.GetEnumerator();
+
+        e.MoveNext();
+        list.Add(99);
+        e.MoveNext();
+      }
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+  }
+
+  namespace CollectionOrSink
+  {
+    [TestFixture]
+    public class Formatting
+    {
+      ICollection<int> coll;
+      IFormatProvider rad16;
+      [SetUp]
+      public void Init() { coll = Factory.New<int>(); rad16 = new RadixFormatProvider(16); }
+      [TearDown]
+      public void Dispose() { coll = null; rad16 = null; }
+      [Test]
+      public void Format()
+      {
+        Assert.AreEqual("[  ]", coll.ToString());
+        coll.AddAll<int>(new int[] { -4, 28, 129, 65530 });
+        Assert.AreEqual("[ 0:-4, 1:28, 2:129, 3:65530 ]", coll.ToString());
+        Assert.AreEqual("[ 0:-4, 1:1C, 2:81, 3:FFFA ]", coll.ToString(null, rad16));
+        Assert.AreEqual("[ 0:-4, 1:28... ]", coll.ToString("L14", null));
+        Assert.AreEqual("[ 0:-4, 1:1C... ]", coll.ToString("L14", rad16));
+      }
+    }
+
+    [TestFixture]
+    public class CollectionOrSink
+    {
+      private ArrayList<int> list;
+
+
+      [SetUp]
+      public void Init() { list = new ArrayList<int>(); }
+
+      [Test]
+      public void Choose()
+      {
+        list.Add(7);
+        Assert.AreEqual(7, list.Choose());
+      }
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void BadChoose()
+      {
+        list.Choose();
+      }
+
+      [Test]
+      public void CountEtAl()
+      {
+        Assert.AreEqual(0, list.Count);
+        Assert.IsTrue(list.IsEmpty);
+        Assert.IsTrue(list.AllowsDuplicates);
+        list.Add(5);
+        Assert.AreEqual(1, list.Count);
+        Assert.IsFalse(list.IsEmpty);
+        list.Add(5);
+        Assert.AreEqual(2, list.Count);
+        Assert.IsFalse(list.IsEmpty);
+        list.Add(8);
+        Assert.AreEqual(3, list.Count);
+      }
+
+
+      [Test]
+      public void AddAll()
+      {
+        list.Add(3); list.Add(4); list.Add(5);
+
+        ArrayList<int> list2 = new ArrayList<int>();
+
+        list2.AddAll(list);
+        Assert.IsTrue(IC.eq(list2, 3, 4, 5));
+        list.AddAll(list2);
+        Assert.IsTrue(IC.eq(list2, 3, 4, 5));
+        Assert.IsTrue(IC.eq(list, 3, 4, 5, 3, 4, 5));
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+
+    [TestFixture]
+    public class FindPredicate
+    {
+      private ArrayList<int> list;
+      Fun<int, bool> pred;
+
+      [SetUp]
+      public void Init()
+      {
+        list = new ArrayList<int>(TenEqualityComparer.Default);
+        pred = delegate(int i) { return i % 5 == 0; };
+      }
+
+      [TearDown]
+      public void Dispose() { list = null; }
+
+      [Test]
+      public void Find()
+      {
+        int i;
+        Assert.IsFalse(list.Find(pred, out i));
+        list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+        Assert.IsFalse(list.Find(pred, out i));
+        list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+        Assert.IsTrue(list.Find(pred, out i));
+        Assert.AreEqual(45, i);
+      }
+
+      [Test]
+      public void FindLast()
+      {
+        int i;
+        Assert.IsFalse(list.FindLast(pred, out i));
+        list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+        Assert.IsFalse(list.FindLast(pred, out i));
+        list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+        Assert.IsTrue(list.FindLast(pred, out i));
+        Assert.AreEqual(675, i);
+      }
+
+      [Test]
+      public void FindIndex()
+      {
+        Assert.IsFalse(0 <= list.FindIndex(pred));
+        list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+        Assert.IsFalse(0 <= list.FindIndex(pred));
+        list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+        Assert.AreEqual(4, list.FindIndex(pred));
+      }
+
+      [Test]
+      public void FindLastIndex()
+      {
+        Assert.IsFalse(0 <= list.FindLastIndex(pred));
+        list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+        Assert.IsFalse(0 <= list.FindLastIndex(pred));
+        list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+        Assert.AreEqual(6, list.FindLastIndex(pred));
+      }
+    }
+
+    [TestFixture]
+    public class UniqueItems
+    {
+      private ArrayList<int> list;
+
+      [SetUp]
+      public void Init() { list = new ArrayList<int>(); }
+
+      [TearDown]
+      public void Dispose() { list = null; }
+
+      [Test]
+      public void Test()
+      {
+        Assert.IsTrue(IC.seteq(list.UniqueItems()));
+        Assert.IsTrue(IC.seteq(list.ItemMultiplicities()));
+        list.AddAll<int>(new int[] { 7, 9, 7 });
+        Assert.IsTrue(IC.seteq(list.UniqueItems(), 7, 9));
+        Assert.IsTrue(IC.seteq(list.ItemMultiplicities(), 7, 2, 9, 1));
+      }
+    }
+
+    [TestFixture]
+    public class ArrayTest
+    {
+      private ArrayList<int> list;
+
+      int[] a;
+
+
+      [SetUp]
+      public void Init()
+      {
+        list = new ArrayList<int>();
+        a = new int[10];
+        for (int i = 0; i < 10; i++)
+          a[i] = 1000 + i;
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+
+
+      private string aeq(int[] a, params int[] b)
+      {
+        if (a.Length != b.Length)
+          return "Lengths differ: " + a.Length + " != " + b.Length;
+
+        for (int i = 0; i < a.Length; i++)
+          if (a[i] != b[i])
+            return String.Format("{0}'th elements differ: {1} != {2}", i, a[i], b[i]);
+
+        return "Alles klar";
+      }
+
+
+      [Test]
+      public void ToArray()
+      {
+        Assert.AreEqual("Alles klar", aeq(list.ToArray()));
+        list.Add(7);
+        list.Add(7);
+        Assert.AreEqual("Alles klar", aeq(list.ToArray(), 7, 7));
+      }
+
+
+      [Test]
+      public void CopyTo()
+      {
+        list.CopyTo(a, 1);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+        list.Add(6);
+        list.CopyTo(a, 2);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+        list.Add(4);
+        list.Add(4);
+        list.Add(9);
+        list.CopyTo(a, 4);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 4, 4, 9, 1008, 1009));
+        list.Clear();
+        list.Add(7);
+        list.CopyTo(a, 9);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 4, 4, 9, 1008, 7));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void CopyToBad()
+      {
+        list.CopyTo(a, 11);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void CopyToBad2()
+      {
+        list.CopyTo(a, -1);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void CopyToTooFar()
+      {
+        list.Add(3);
+        list.Add(3);
+        list.CopyTo(a, 9);
+      }
+    }
+
+    [TestFixture]
+    public class Sync
+    {
+      private ArrayList<int> list;
+
+
+      [SetUp]
+      public void Init()
+      {
+        list = new ArrayList<int>();
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+
+
+      [Test]
+      public void Get()
+      {
+        Assert.IsNotNull(((System.Collections.IList)list).SyncRoot);
+      }
+    }
+  }
+
+
+
+
+  namespace EditableCollection
+  {
+    [TestFixture]
+    public class Searching
+    {
+      private ArrayList<int> list;
+
+
+      [SetUp]
+      public void Init() { list = new ArrayList<int>(); }
+
+      [Test]
+      [ExpectedException(typeof(NullReferenceException))]
+      public void NullEqualityComparerinConstructor1()
+      {
+        new ArrayList<int>(null);
+      }
+
+      [Test]
+      [ExpectedException(typeof(NullReferenceException))]
+      public void NullEqualityComparerinConstructor2()
+      {
+        new ArrayList<int>(5, null);
+      }
+
+      [Test]
+      public void Contains()
+      {
+        Assert.IsFalse(list.Contains(5));
+        list.Add(5);
+        Assert.IsTrue(list.Contains(5));
+        Assert.IsFalse(list.Contains(7));
+        list.Add(8);
+        list.Add(10);
+        Assert.IsTrue(list.Contains(5));
+        Assert.IsFalse(list.Contains(7));
+        Assert.IsTrue(list.Contains(8));
+        Assert.IsTrue(list.Contains(10));
+        list.Remove(8);
+        Assert.IsTrue(list.Contains(5));
+        Assert.IsFalse(list.Contains(7));
+        Assert.IsFalse(list.Contains(8));
+        Assert.IsTrue(list.Contains(10));
+      }
+
+
+      [Test]
+      public void ContainsCount()
+      {
+        Assert.AreEqual(0, list.ContainsCount(5));
+        list.Add(5);
+        Assert.AreEqual(1, list.ContainsCount(5));
+        Assert.AreEqual(0, list.ContainsCount(7));
+        list.Add(8);
+        Assert.AreEqual(1, list.ContainsCount(5));
+        Assert.AreEqual(0, list.ContainsCount(7));
+        Assert.AreEqual(1, list.ContainsCount(8));
+        list.Add(5);
+        Assert.AreEqual(2, list.ContainsCount(5));
+        Assert.AreEqual(0, list.ContainsCount(7));
+        Assert.AreEqual(1, list.ContainsCount(8));
+      }
+
+
+      [Test]
+      public void RemoveAllCopies()
+      {
+        list.Add(5); list.Add(7); list.Add(5);
+        Assert.AreEqual(2, list.ContainsCount(5));
+        Assert.AreEqual(1, list.ContainsCount(7));
+        list.RemoveAllCopies(5);
+        Assert.AreEqual(0, list.ContainsCount(5));
+        Assert.AreEqual(1, list.ContainsCount(7));
+        list.Add(5); list.Add(8); list.Add(5);
+        list.RemoveAllCopies(8);
+        Assert.IsTrue(IC.eq(list, 7, 5, 5));
+      }
+
+
+      [Test]
+      public void FindAll()
+      {
+        Fun<int, bool> f = delegate(int i) { return i % 2 == 0; };
+
+        Assert.IsTrue(list.FindAll(f).IsEmpty);
+        list.Add(5); list.Add(8); list.Add(5); list.Add(10); list.Add(8);
+        Assert.IsTrue(((ArrayList<int>)list.FindAll(f)).Check());
+        Assert.IsTrue(IC.eq(list.FindAll(f), 8, 10, 8));
+      }
+
+
+      [Test]
+      public void ContainsAll()
+      {
+        ArrayList<int> list2 = new ArrayList<int>();
+
+        Assert.IsTrue(list.ContainsAll(list2));
+        list2.Add(4);
+        Assert.IsFalse(list.ContainsAll(list2));
+        list.Add(4);
+        Assert.IsTrue(list.ContainsAll(list2));
+        list.Add(5);
+        Assert.IsTrue(list.ContainsAll(list2));
+        list2.Add(4);
+        Assert.IsFalse(list.ContainsAll(list2));
+        list.Add(4);
+        Assert.IsTrue(list.ContainsAll(list2));
+      }
+
+
+      [Test]
+      public void RetainAll()
+      {
+        ArrayList<int> list2 = new ArrayList<int>();
+
+        list.Add(4); list.Add(4); list.Add(5); list.Add(4); list.Add(6);
+        list2.Add(5); list2.Add(4); list2.Add(7); list2.Add(7); list2.Add(4);
+        list.RetainAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 4, 5));
+        list.Add(5); list.Add(4); list.Add(6);
+        list2.Clear();
+        list2.Add(5); list2.Add(5); list2.Add(6);
+        list.RetainAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 5, 5, 6));
+        list2.Clear();
+        list2.Add(7); list2.Add(8); list2.Add(9);
+        list.RetainAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list));
+      }
+
+
+      [Test]
+      public void RemoveAll()
+      {
+        ArrayList<int> list2 = new ArrayList<int>();
+
+        list.Add(4); list.Add(4); list.Add(5); list.Add(4); list.Add(6);
+        list2.Add(5); list2.Add(4); list2.Add(7); list2.Add(7); list2.Add(4);
+        list.RemoveAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 6));
+        list.Add(5); list.Add(4); list.Add(6);
+        list2.Clear();
+        list2.Add(6); list2.Add(5); list2.Add(5); list2.Add(6);
+        list.RemoveAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 4));
+        list2.Clear();
+        list2.Add(7); list2.Add(8); list2.Add(9);
+        list.RemoveAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 4));
+      }
+
+
+      [Test]
+      public void Remove()
+      {
+        Assert.IsFalse(list.FIFO);
+        list.Add(4); list.Add(4); list.Add(5); list.Add(4); list.Add(6);
+        Assert.IsFalse(list.Remove(2));
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(list.Remove(4));
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 4, 5, 6));
+        Assert.AreEqual(6, list.RemoveLast());
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 4, 5));
+        list.Add(7);
+        Assert.AreEqual(4, list.RemoveFirst());
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 5, 7));
+
+        list.FIFO = true;
+        list.Clear();
+        list.Add(4); list.Add(4); list.Add(5); list.Add(4); list.Add(6);
+        Assert.IsFalse(list.Remove(2));
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(list.Remove(4));
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 5, 4, 6));
+        Assert.AreEqual(6, list.RemoveLast());
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 5, 4));
+        list.Add(7);
+        Assert.AreEqual(4, list.RemoveFirst());
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 5, 4, 7));
+      }
+
+
+      [Test]
+      public void Clear()
+      {
+        list.Add(7); list.Add(7);
+        list.Clear();
+        Assert.IsTrue(list.IsEmpty);
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+  }
+
+
+
+
+  namespace Indexed
+  {
+    [TestFixture]
+    public class Searching
+    {
+      private IIndexed<int> dit;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new ArrayList<int>();
+      }
+
+
+      [Test]
+      public void IndexOf()
+      {
+        Assert.AreEqual(~0, dit.IndexOf(6));
+        dit.Add(7);
+        Assert.AreEqual(~1, dit.IndexOf(6));
+        Assert.AreEqual(~1, dit.LastIndexOf(6));
+        Assert.AreEqual(0, dit.IndexOf(7));
+        dit.Add(5); dit.Add(7); dit.Add(8); dit.Add(7);
+        Assert.AreEqual(~5, dit.IndexOf(6));
+        Assert.AreEqual(0, dit.IndexOf(7));
+        Assert.AreEqual(4, dit.LastIndexOf(7));
+        Assert.AreEqual(3, dit.IndexOf(8));
+        Assert.AreEqual(1, dit.LastIndexOf(5));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class Removing
+    {
+      private IIndexed<int> dit;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new ArrayList<int>();
+      }
+
+
+      [Test]
+      public void RemoveAt()
+      {
+        dit.Add(5); dit.Add(7); dit.Add(9); dit.Add(1); dit.Add(2);
+        Assert.AreEqual(7, dit.RemoveAt(1));
+        Assert.IsTrue(((ArrayList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 5, 9, 1, 2));
+        Assert.AreEqual(5, dit.RemoveAt(0));
+        Assert.IsTrue(((ArrayList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 9, 1, 2));
+        Assert.AreEqual(2, dit.RemoveAt(2));
+        Assert.IsTrue(((ArrayList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 9, 1));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void RemoveAtBad0()
+      {
+        dit.RemoveAt(0);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void RemoveAtBadM1()
+      {
+        dit.RemoveAt(-1);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void RemoveAtBad1()
+      {
+        dit.Add(8);
+        dit.RemoveAt(1);
+      }
+
+
+      [Test]
+      public void RemoveInterval()
+      {
+        dit.RemoveInterval(0, 0);
+        dit.Add(10); dit.Add(20); dit.Add(30); dit.Add(40); dit.Add(50); dit.Add(60);
+        dit.RemoveInterval(3, 0);
+        Assert.IsTrue(((ArrayList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 10, 20, 30, 40, 50, 60));
+        dit.RemoveInterval(3, 1);
+        Assert.IsTrue(((ArrayList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 10, 20, 30, 50, 60));
+        dit.RemoveInterval(1, 3);
+        Assert.IsTrue(((ArrayList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 10, 60));
+        dit.RemoveInterval(0, 2);
+        Assert.IsTrue(((ArrayList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit));
+        dit.Add(10); dit.Add(20); dit.Add(30); dit.Add(40); dit.Add(50); dit.Add(60);
+        dit.RemoveInterval(0, 2);
+        Assert.IsTrue(((ArrayList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 30, 40, 50, 60));
+        dit.RemoveInterval(2, 2);
+        Assert.IsTrue(((ArrayList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 30, 40));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+      }
+    }
+  }
+
+
+
+
+  namespace List
+  {
+    [TestFixture]
+    public class Searching
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new ArrayList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void FirstBad()
+      {
+        int f = lst.First;
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void LastBad()
+      {
+        int f = lst.Last;
+      }
+
+
+      [Test]
+      public void FirstLast()
+      {
+        lst.Add(19);
+        Assert.AreEqual(19, lst.First);
+        Assert.AreEqual(19, lst.Last);
+        lst.Add(34); lst.InsertFirst(12);
+        Assert.AreEqual(12, lst.First);
+        Assert.AreEqual(34, lst.Last);
+      }
+
+
+      [Test]
+      public void This()
+      {
+        lst.Add(34);
+        Assert.AreEqual(34, lst[0]);
+        lst[0] = 56;
+        Assert.AreEqual(56, lst.First);
+        lst.Add(7); lst.Add(7); lst.Add(7); lst.Add(7);
+        lst[0] = 45; lst[2] = 78; lst[4] = 101;
+        Assert.IsTrue(IC.eq(lst, 45, 7, 78, 7, 101));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadEmptyGet()
+      {
+        int f = lst[0];
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadLowGet()
+      {
+        lst.Add(7);
+
+        int f = lst[-1];
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadHiGet()
+      {
+        lst.Add(6);
+
+        int f = lst[1];
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadEmptySet()
+      {
+        lst[0] = 4;
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadLowSet()
+      {
+        lst.Add(7);
+        lst[-1] = 9;
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadHiSet()
+      {
+        lst.Add(6);
+        lst[1] = 11;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class Inserting
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new ArrayList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void Insert()
+      {
+        lst.Insert(0, 5);
+        Assert.IsTrue(IC.eq(lst, 5));
+        lst.Insert(0, 7);
+        Assert.IsTrue(IC.eq(lst, 7, 5));
+        lst.Insert(1, 4);
+        Assert.IsTrue(IC.eq(lst, 7, 4, 5));
+        lst.Insert(3, 2);
+        Assert.IsTrue(IC.eq(lst, 7, 4, 5, 2));
+      }
+
+      [Test]
+      public void InsertDuplicate()
+      {
+        lst.Insert(0, 5);
+        Assert.IsTrue(IC.eq(lst, 5));
+        lst.Insert(0, 7);
+        Assert.IsTrue(IC.eq(lst, 7, 5));
+        lst.Insert(1, 5);
+        Assert.IsTrue(IC.eq(lst, 7, 5, 5));
+      }
+
+
+      [Test]
+      public void InsertAllDuplicate1()
+      {
+        lst.Insert(0, 3);
+        Assert.IsTrue(IC.eq(lst, 3));
+        lst.Insert(0, 7);
+        Assert.IsTrue(IC.eq(lst, 7, 3));
+        lst.InsertAll<int>(1, new int[] { 1, 2, 3, 4 });
+        Assert.IsTrue(IC.eq(lst, 7, 1, 2, 3, 4, 3));
+        Assert.IsTrue(lst.Check());
+      }
+      [Test]
+      public void InsertAllDuplicate2()
+      {
+        lst.Insert(0, 3);
+        Assert.IsTrue(IC.eq(lst, 3));
+        lst.Insert(0, 7);
+        Assert.IsTrue(IC.eq(lst, 7, 3));
+        lst.InsertAll<int>(1, new int[] { 5, 6, 5, 8 });
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 5, 6, 5, 8, 3));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void BadInsertLow()
+      {
+        lst.Add(7);
+        lst.Insert(-1, 9);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void BadInsertHi()
+      {
+        lst.Add(6);
+        lst.Insert(2, 11);
+      }
+
+
+      [Test]
+      public void FIFO()
+      {
+        for (int i = 0; i < 7; i++)
+          lst.Add(2 * i);
+
+        Assert.IsFalse(lst.FIFO);
+        Assert.AreEqual(12, lst.Remove());
+        Assert.AreEqual(10, lst.Remove());
+        lst.FIFO = true;
+        Assert.AreEqual(0, lst.Remove());
+        Assert.AreEqual(2, lst.Remove());
+        lst.FIFO = false;
+        Assert.AreEqual(8, lst.Remove());
+        Assert.AreEqual(6, lst.Remove());
+      }
+
+
+      [Test]
+      public void InsertFirstLast()
+      {
+        lst.InsertFirst(4);
+        lst.InsertLast(5);
+        lst.InsertFirst(14);
+        lst.InsertLast(15);
+        lst.InsertFirst(24);
+        lst.InsertLast(25);
+        lst.InsertFirst(34);
+        lst.InsertLast(55);
+        Assert.IsTrue(IC.eq(lst, 34, 24, 14, 4, 5, 15, 25, 55));
+      }
+
+
+      [Test]
+      public void InsertFirst()
+      {
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(2);
+        lst.Add(5);
+        lst.ViewOf(2).InsertFirst(7);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 2, 3, 2, 5));
+        lst.ViewOf(3).InsertFirst(8);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 2, 8, 3, 2, 5));
+        lst.ViewOf(5).InsertFirst(9);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 2, 8, 3, 2, 9, 5));
+      }
+
+      [Test]
+      public void InsertAfter()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(2);
+        lst.Add(5);
+        lst.LastViewOf(2).InsertLast(7);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 1, 2, 3, 2, 7, 5));
+        lst.LastViewOf(1).InsertLast(8);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 1, 8, 2, 3, 2, 7, 5));
+        lst.LastViewOf(5).InsertLast(9);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 1, 8, 2, 3, 2, 7, 5, 9));
+      }
+
+      [Test]
+      public void InsertAll()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(4);
+
+        IList<int> lst2 = new ArrayList<int>();
+
+        lst2.Add(7); lst2.Add(8); lst2.Add(9);
+        lst.InsertAll(0, lst2);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 1, 2, 3, 4));
+        lst.InsertAll(7, lst2);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 1, 2, 3, 4, 7, 8, 9));
+        lst.InsertAll(5, lst2);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 1, 2, 7, 8, 9, 3, 4, 7, 8, 9));
+      }
+
+
+      [Test]
+      public void Map()
+      {
+        Fun<int, string> m = delegate(int i) { return "<<" + i + ">>"; };
+        IList<string> r = lst.Map(m);
+
+        Assert.IsTrue(r.Check());
+        Assert.IsTrue(r.IsEmpty);
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(4);
+        r = lst.Map(m);
+        Assert.IsTrue(r.Check());
+        Assert.AreEqual(4, r.Count);
+        for (int i = 0; i < 4; i++)
+          Assert.AreEqual("<<" + (i + 1) + ">>", r[i]);
+      }
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void BadMapper()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        Fun<int, bool> m = delegate(int i) { if (i == 2) lst.Add(7); return true; };
+        lst.Map(m);
+      }
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void ModifyingFindAll()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        Fun<int, bool> m = delegate(int i) { if (i == 2) lst.Add(7); return true; };
+        lst.FindAll(m);
+      }
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void BadMapperView()
+      {
+        lst = lst.View(0, 0);
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        Fun<int, bool> m = delegate(int i) { if (i == 2) lst.Add(7); return true; };
+        lst.Map(m);
+      }
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void ModifyingFindAllView()
+      {
+        lst = lst.View(0, 0);
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        Fun<int, bool> m = delegate(int i) { if (i == 2) lst.Add(7); return true; };
+        lst.FindAll(m);
+      }
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void BadRemove() { lst.Remove(); }
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void BadRemoveFirst() { lst.RemoveFirst(); }
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void BadRemoveLast() { lst.RemoveLast(); }
+
+
+      [Test]
+      public void RemoveFirstLast()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(4);
+        Assert.AreEqual(1, lst.RemoveFirst());
+        Assert.AreEqual(4, lst.RemoveLast());
+        Assert.AreEqual(2, lst.RemoveFirst());
+        Assert.AreEqual(3, lst.RemoveLast());
+        Assert.IsTrue(lst.IsEmpty);
+      }
+
+
+      [Test]
+      public void Reverse()
+      {
+        for (int i = 0; i < 10; i++)
+          lst.Add(i);
+
+        lst.Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0));
+        lst.View(0, 3).Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0));
+        lst.View(7, 0).Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0));
+        lst.View(7, 3).Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2));
+        lst.View(5, 1).Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void BadReverse()
+      {
+        for (int i = 0; i < 10; i++)
+          lst.Add(i);
+
+        lst.View(8, 3).Reverse();
+      }
+    }
+
+    [TestFixture]
+    public class Combined
+    {
+      private IList<KeyValuePair<int, int>> lst;
+
+
+      [SetUp]
+      public void Init()
+      {
+        lst = new ArrayList<KeyValuePair<int, int>>(new KeyValuePairEqualityComparer<int, int>());
+        for (int i = 0; i < 10; i++)
+          lst.Add(new KeyValuePair<int, int>(i, i + 30));
+      }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void Find()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+        Assert.IsTrue(lst.Find(ref p));
+        Assert.AreEqual(3, p.Key);
+        Assert.AreEqual(33, p.Value);
+        p = new KeyValuePair<int, int>(13, 78);
+        Assert.IsFalse(lst.Find(ref p));
+      }
+
+
+      [Test]
+      public void FindOrAdd()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.FindOrAdd(ref p));
+        Assert.AreEqual(3, p.Key);
+        Assert.AreEqual(33, p.Value);
+        p = new KeyValuePair<int, int>(13, 79);
+        Assert.IsFalse(lst.FindOrAdd(ref p));
+        Assert.AreEqual(13, lst[10].Key);
+        Assert.AreEqual(79, lst[10].Value);
+      }
+
+
+      [Test]
+      public void Update()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.Update(p));
+        Assert.AreEqual(3, lst[3].Key);
+        Assert.AreEqual(78, lst[3].Value);
+        p = new KeyValuePair<int, int>(13, 78);
+        Assert.IsFalse(lst.Update(p));
+      }
+
+
+      [Test]
+      public void UpdateOrAdd1()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.UpdateOrAdd(p));
+        Assert.AreEqual(3, lst[3].Key);
+        Assert.AreEqual(78, lst[3].Value);
+        p = new KeyValuePair<int, int>(13, 79);
+        Assert.IsFalse(lst.UpdateOrAdd(p));
+        Assert.AreEqual(13, lst[10].Key);
+        Assert.AreEqual(79, lst[10].Value);
+      }
+
+      [Test]
+      public void UpdateOrAdd2()
+      {
+          ICollection<String> coll = new ArrayList<String>();
+          // s1 and s2 are distinct objects but contain the same text:
+          String old, s1 = "abc", s2 = ("def" + s1).Substring(3);
+          Assert.IsFalse(coll.UpdateOrAdd(s1, out old));
+          Assert.AreEqual(null, old);
+          Assert.IsTrue(coll.UpdateOrAdd(s2, out old));
+          Assert.IsTrue(Object.ReferenceEquals(s1, old));
+          Assert.IsFalse(Object.ReferenceEquals(s2, old));
+      }
+
+      [Test]
+      public void RemoveWithReturn()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.Remove(p, out p));
+        Assert.AreEqual(3, p.Key);
+        Assert.AreEqual(33, p.Value);
+        Assert.AreEqual(4, lst[3].Key);
+        Assert.AreEqual(34, lst[3].Value);
+        p = new KeyValuePair<int, int>(13, 78);
+        Assert.IsFalse(lst.Remove(p, out p));
+      }
+    }
+
+
+    [TestFixture]
+    public class SortingTests
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new ArrayList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void Sort()
+      {
+        lst.Add(5); lst.Add(6); lst.Add(5); lst.Add(7); lst.Add(3);
+        Assert.IsFalse(lst.IsSorted(new IC()));
+        lst.Sort(new IC());
+        Assert.IsTrue(lst.IsSorted());
+        Assert.IsTrue(lst.IsSorted(new IC()));
+        Assert.IsTrue(IC.eq(lst, 3, 5, 5, 6, 7));
+      }
+
+
+      [Test]
+      public void Stability()
+      {
+        IList<KeyValuePair<int, string>> lst2 = new ArrayList<KeyValuePair<int, string>>();
+        SCG.IComparer<KeyValuePair<int, string>> c = new KeyValuePairComparer<int, string>(new IC());
+
+        lst2.Add(new KeyValuePair<int, string>(5, "a"));
+        lst2.Add(new KeyValuePair<int, string>(5, "b"));
+        lst2.Add(new KeyValuePair<int, string>(6, "c"));
+        lst2.Add(new KeyValuePair<int, string>(4, "d"));
+        lst2.Add(new KeyValuePair<int, string>(3, "e"));
+        lst2.Add(new KeyValuePair<int, string>(4, "f"));
+        lst2.Add(new KeyValuePair<int, string>(5, "handle"));
+        Assert.IsFalse(lst2.IsSorted(c));
+        lst2.Sort(c);
+        Assert.IsTrue(lst2.IsSorted(c));
+
+        KeyValuePair<int, string> p = lst2.RemoveFirst();
+
+        Assert.AreEqual(3, p.Key);
+        Assert.AreEqual("e", p.Value);
+        p = lst2.RemoveFirst();
+        Assert.AreEqual(4, p.Key);
+        Assert.AreEqual("d", p.Value);
+        p = lst2.RemoveFirst();
+        Assert.AreEqual(4, p.Key);
+        Assert.AreEqual("f", p.Value);
+        p = lst2.RemoveFirst();
+        Assert.AreEqual(5, p.Key);
+        Assert.AreEqual("a", p.Value);
+        p = lst2.RemoveFirst();
+        Assert.AreEqual(5, p.Key);
+        Assert.AreEqual("b", p.Value);
+        p = lst2.RemoveFirst();
+        Assert.AreEqual(5, p.Key);
+        Assert.AreEqual("handle", p.Value);
+        p = lst2.RemoveFirst();
+        Assert.AreEqual(6, p.Key);
+        Assert.AreEqual("c", p.Value);
+        Assert.IsTrue(lst2.IsEmpty);
+      }
+    }
+
+    [TestFixture]
+    public class ShuffleTests
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new ArrayList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void Shuffle()
+      {
+        lst.Add(5); lst.Add(6); lst.Add(5); lst.Add(7); lst.Add(3);
+        for (int i = 0; i < 100; i++)
+        {
+          lst.Shuffle(new C5Random(i + 1));
+          Assert.IsTrue(lst.Check(), "Check " + i);
+          int[] lst2 = lst.ToArray();
+          Sorting.IntroSort<int>(lst2);
+          Assert.IsTrue(IC.eq(lst2, 3, 5, 5, 6, 7), "Contents " + i);
+        }
+      }
+    }
+
+  }
+
+
+  namespace IStackQueue
+  {
+    [TestFixture]
+    public class Stack
+    {
+      private IStack<int> list;
+
+
+      [SetUp]
+      public void Init() { list = new ArrayList<int>(); }
+
+
+      [Test]
+      public void Normal()
+      {
+        list.Push(7);
+        list.Push(5);
+        list.Push(7);
+        list.Push(8);
+        list.Push(9);
+        Assert.AreEqual(9, list.Pop());
+        Assert.AreEqual(8, list.Pop());
+        Assert.AreEqual(7, list.Pop());
+        Assert.AreEqual(5, list.Pop());
+        Assert.AreEqual(7, list.Pop());
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void PopEmpty()
+      {
+        list.Push(5);
+        Assert.AreEqual(5, list.Pop());
+        list.Pop();
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+    [TestFixture]
+    public class Queue
+    {
+      private IQueue<int> list;
+
+
+      [SetUp]
+      public void Init() { list = new ArrayList<int>(); }
+
+
+      [Test]
+      public void Normal()
+      {
+        list.Enqueue(7);
+        list.Enqueue(5);
+        list.Enqueue(7);
+        list.Enqueue(8);
+        list.Enqueue(9);
+        Assert.AreEqual(7, list.Dequeue());
+        Assert.AreEqual(5, list.Dequeue());
+        Assert.AreEqual(7, list.Dequeue());
+        Assert.AreEqual(8, list.Dequeue());
+        Assert.AreEqual(9, list.Dequeue());
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void DeQueueEmpty()
+      {
+        list.Enqueue(5);
+        Assert.AreEqual(5, list.Dequeue());
+        list.Dequeue();
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+  }
+
+
+  namespace Range
+  {
+    [TestFixture]
+    public class Range
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new ArrayList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void GetRange()
+      {
+        //Assert.IsTrue(IC.eq(lst[0, 0)));
+        for (int i = 0; i < 10; i++) lst.Add(i);
+
+        Assert.IsTrue(IC.eq(lst[0, 3], 0, 1, 2));
+        Assert.IsTrue(IC.eq(lst[3, 4], 3, 4, 5, 6));
+        Assert.IsTrue(IC.eq(lst[6, 4], 6, 7, 8, 9));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void BadGetRange()
+      {
+        object foo = lst[0, 11];
+      }
+
+
+      [Test]
+      public void Backwards()
+      {
+        for (int i = 0; i < 10; i++) lst.Add(i);
+
+        Assert.IsTrue(IC.eq(lst.Backwards(), 9, 8, 7, 6, 5, 4, 3, 2, 1, 0));
+        Assert.IsTrue(IC.eq(lst[0, 4].Backwards(), 3, 2, 1, 0));
+        Assert.IsTrue(IC.eq(lst[3, 4].Backwards(), 6, 5, 4, 3));
+        Assert.IsTrue(IC.eq(lst[6, 4].Backwards(), 9, 8, 7, 6));
+      }
+
+
+      [Test]
+      public void DirectionAndCount()
+      {
+        for (int i = 0; i < 10; i++) lst.Add(i);
+
+        Assert.AreEqual(EnumerationDirection.Forwards, lst.Direction);
+        Assert.AreEqual(EnumerationDirection.Forwards, lst[3, 4].Direction);
+        Assert.AreEqual(EnumerationDirection.Backwards, lst[3, 4].Backwards().Direction);
+        Assert.AreEqual(EnumerationDirection.Backwards, lst.Backwards().Direction);
+        Assert.AreEqual(4, lst[3, 4].Count);
+        Assert.AreEqual(4, lst[3, 4].Backwards().Count);
+        Assert.AreEqual(10, lst.Backwards().Count);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterUpdate()
+      {
+        for (int i = 0; i < 10; i++) lst.Add(i);
+
+        foreach (int i in lst)
+        {
+          lst.Add(45 + i);
+        }
+      }
+    }
+  }
+
+
+
+
+  namespace View
+  {
+    [TestFixture]
+    public class Simple
+    {
+      ArrayList<int> list, view;
+
+
+      [SetUp]
+      public void Init()
+      {
+        list = new ArrayList<int>();
+        list.Add(0); list.Add(1); list.Add(2); list.Add(3);
+        view = (ArrayList<int>)list.View(1, 2);
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        list = view = null;
+      }
+
+
+      void check()
+      {
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(view.Check());
+      }
+
+
+      //static void pint(IEnumerable<int> l) { foreach (int cell in l) Console.WriteLine(cell); }
+
+      [Test]
+      public void InsertPointer()
+      {
+        IList<int> view2 = list.View(2, 0);
+        list.Insert(view2, 7);
+        check();
+        list.Insert(list, 8);
+        check();
+        view.Insert(view2, 9);
+        check();
+        view.Insert(list.View(3, 2), 10);
+        check();
+        view.Insert(list.ViewOf(0), 11);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 11, 1, 9, 7, 2, 10, 3, 8));
+        Assert.IsTrue(IC.eq(view, 11, 1, 9, 7, 2, 10));
+      }
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void InsertPointerBad1()
+      {
+        view.Insert(list.View(0, 0), 7);
+      }
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void InsertPointerBad2()
+      {
+        view.Insert(list, 7);
+      }
+
+      [Test]
+      [ExpectedException(typeof(IncompatibleViewException))]
+      public void InsertPointerBad3()
+      {
+        list.Insert(new ArrayList<int>(), 7);
+      }
+
+      [Test]
+      [ExpectedException(typeof(IncompatibleViewException))]
+      public void InsertPointerBad4()
+      {
+        list.Insert(new ArrayList<int>().View(0, 0), 7);
+      }
+
+
+      [Test]
+      public void Span()
+      {
+        IList<int> span = list.View(1, 0).Span(list.View(2, 0));
+        Assert.IsTrue(span.Check());
+        Assert.AreEqual(1, span.Offset);
+        Assert.AreEqual(1, span.Count);
+        span = list.View(0, 2).Span(list.View(2, 2));
+        Assert.IsTrue(span.Check());
+        Assert.AreEqual(0, span.Offset);
+        Assert.AreEqual(4, span.Count);
+        span = list.View(3, 1).Span(list.View(1, 1));
+        Assert.IsNull(span);
+      }
+
+      [Test]
+      public void ViewOf()
+      {
+        for (int i = 0; i < 4; i++)
+          list.Add(i);
+        IList<int> v = view.ViewOf(2);
+        Assert.IsTrue(v.Check());
+        Assert.IsTrue(IC.eq(v, 2));
+        Assert.AreEqual(2, v.Offset);
+        v = list.ViewOf(2);
+        Assert.IsTrue(v.Check());
+        Assert.IsTrue(IC.eq(v, 2));
+        Assert.AreEqual(2, v.Offset);
+        v = list.LastViewOf(2);
+        Assert.IsTrue(v.Check());
+        Assert.IsTrue(IC.eq(v, 2));
+        Assert.AreEqual(6, v.Offset);
+      }
+
+      [Test]
+      public void ArrayStuff()
+      {
+        Assert.IsTrue(IC.eq(view.ToArray(), 1, 2));
+        int[] extarray = new int[5];
+        view.CopyTo(extarray, 2);
+        Assert.IsTrue(IC.eq(extarray, 0, 0, 1, 2, 0));
+      }
+
+      [Test]
+      public void BadViewOf()
+      {
+        Assert.IsNull(view.ViewOf(5));
+        Assert.IsNull(view.LastViewOf(5));
+        Assert.IsNull(view.ViewOf(3));
+        Assert.IsNull(view.LastViewOf(3));
+        Assert.IsNull(view.ViewOf(0));
+        Assert.IsNull(view.LastViewOf(0));
+      }
+
+      [Test]
+      public void Add()
+      {
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 1, 2, 3));
+        Assert.IsTrue(IC.eq(view, 1, 2));
+        view.InsertFirst(10);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 10, 1, 2, 3));
+        Assert.IsTrue(IC.eq(view, 10, 1, 2));
+        view.Clear();
+        Assert.IsFalse(view.IsReadOnly);
+        Assert.IsTrue(view.AllowsDuplicates);
+        Assert.IsTrue(view.IsEmpty);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 3));
+        Assert.IsTrue(IC.eq(view));
+        view.Add(8);
+        Assert.IsFalse(view.IsEmpty);
+        Assert.IsTrue(view.AllowsDuplicates);
+        Assert.IsFalse(view.IsReadOnly);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 3));
+        Assert.IsTrue(IC.eq(view, 8));
+        view.Add(12);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 12, 3));
+        Assert.IsTrue(IC.eq(view, 8, 12));
+        view./*ViewOf(12)*/InsertLast(15);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 12, 15, 3));
+        Assert.IsTrue(IC.eq(view, 8, 12, 15));
+        view.ViewOf(12).InsertFirst(18);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 18, 12, 15, 3));
+        Assert.IsTrue(IC.eq(view, 8, 18, 12, 15));
+
+        ArrayList<int> lst2 = new ArrayList<int>();
+
+        lst2.Add(90); lst2.Add(92);
+        view.AddAll(lst2);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 18, 12, 15, 90, 92, 3));
+        Assert.IsTrue(IC.eq(view, 8, 18, 12, 15, 90, 92));
+        view.InsertLast(66);
+        check();
+
+        Assert.IsTrue(IC.eq(list, 0, 8, 18, 12, 15, 90, 92, 66, 3));
+        Assert.IsTrue(IC.eq(view, 8, 18, 12, 15, 90, 92, 66));
+      }
+
+
+      [Test]
+      public void Bxxx()
+      {
+        Assert.IsTrue(IC.eq(view.Backwards(), 2, 1));
+        Assert.AreSame(list, view.Underlying);
+        Assert.IsNull(list.Underlying);
+        Assert.AreEqual(EnumerationDirection.Forwards, view.Direction);
+        Assert.AreEqual(EnumerationDirection.Backwards, view.Backwards().Direction);
+        Assert.AreEqual(0, list.Offset);
+        Assert.AreEqual(1, view.Offset);
+      }
+
+
+      [Test]
+      public void Contains()
+      {
+        Assert.IsTrue(view.Contains(1));
+        Assert.IsFalse(view.Contains(0));
+
+        ArrayList<int> lst2 = new ArrayList<int>();
+
+        lst2.Add(2);
+        Assert.IsTrue(view.ContainsAll(lst2));
+        lst2.Add(3);
+        Assert.IsFalse(view.ContainsAll(lst2));
+        Assert.AreEqual(Speed.Linear, view.ContainsSpeed);
+        Assert.AreEqual(2, view.Count);
+        view.Add(1);
+        Assert.AreEqual(1, view.ContainsCount(2));
+        Assert.AreEqual(2, view.ContainsCount(1));
+        Assert.AreEqual(3, view.Count);
+      }
+
+
+      [Test]
+      public void CreateView()
+      {
+        ArrayList<int> view2 = (ArrayList<int>)view.View(1, 0);
+
+        Assert.AreSame(list, view2.Underlying);
+      }
+
+
+      [Test]
+      public void FIFO()
+      {
+        Assert.IsFalse(view.FIFO);
+        view.FIFO = true;
+        view.Add(23); view.Add(24); view.Add(25);
+        check();
+        Assert.IsTrue(IC.eq(view, 1, 2, 23, 24, 25));
+        Assert.AreEqual(1, view.Remove());
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 23, 24, 25));
+        view.FIFO = false;
+        Assert.IsFalse(view.FIFO);
+        Assert.AreEqual(25, view.Remove());
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 23, 24));
+      }
+
+
+      [Test]
+      public void MapEtc()
+      {
+        ArrayList<double> dbl = (ArrayList<double>)view.Map(new Fun<int, double>(delegate(int i) { return i / 10.0; }));
+
+        Assert.IsTrue(dbl.Check());
+        Assert.AreEqual(0.1, dbl[0]);
+        Assert.AreEqual(0.2, dbl[1]);
+        for (int i = 0; i < 10; i++) view.Add(i);
+
+        list = (ArrayList<int>)view.FindAll(new Fun<int, bool>(delegate(int i) { return i % 4 == 1; }));
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 1, 1, 5, 9));
+      }
+
+
+      [Test]
+      public void FL()
+      {
+        Assert.AreEqual(1, view.First);
+        Assert.AreEqual(2, view.Last);
+      }
+
+
+      [Test]
+      public void Indexing()
+      {
+        list.Clear();
+        for (int i = 0; i < 20; i++) list.Add(i);
+
+        view = (ArrayList<int>)list.View(5, 7);
+        for (int i = 0; i < 7; i++) Assert.AreEqual(i + 5, view[i]);
+
+        for (int i = 0; i < 7; i++) Assert.AreEqual(i, view.IndexOf(i + 5));
+
+        for (int i = 0; i < 7; i++) Assert.AreEqual(i, view.LastIndexOf(i + 5));
+      }
+
+
+      [Test]
+      public void Insert()
+      {
+        view.Insert(0, 34);
+        view.Insert(1, 35);
+        view.Insert(4, 36);
+        Assert.IsTrue(view.Check());
+        Assert.IsTrue(IC.eq(view, 34, 35, 1, 2, 36));
+
+        IList<int> list2 = new ArrayList<int>();
+
+        list2.AddAll(view);
+        view.InsertAll(3, list2);
+        Assert.IsTrue(view.Check());
+        Assert.IsTrue(IC.eq(view, 34, 35, 1, 34, 35, 1, 2, 36, 2, 36));
+      }
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void RangeCheck1()
+      {
+        IList<int> lst = new ArrayList<int>();
+        lst.Add(2);
+        lst = lst.View(1, 1);
+      }
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void RangeCheck2()
+      {
+        IList<int> lst = new ArrayList<int>();
+        lst.Add(2);
+        lst = lst.View(1, -1);
+      }
+
+
+      [Test]
+      public void Sort()
+      {
+        view.Add(45); view.Add(47); view.Add(46); view.Add(48);
+        Assert.IsFalse(view.IsSorted(new IC()));
+        view.Sort(new IC());
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 1, 2, 45, 46, 47, 48, 3));
+        Assert.IsTrue(IC.eq(view, 1, 2, 45, 46, 47, 48));
+      }
+
+
+      [Test]
+      public void Remove()
+      {
+        view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0);
+        Assert.IsTrue(IC.eq(view, 1, 2, 1, 5, 3, 1, 3, 0));
+        Assert.IsTrue(view.Remove(1));
+        check();
+        Assert.IsTrue(IC.eq(view, 1, 2, 1, 5, 3, 3, 0));
+        Assert.IsTrue(view.Remove(1));
+        check();
+        Assert.IsTrue(IC.eq(view, 1, 2, 5, 3, 3, 0));
+        Assert.IsTrue(view.Remove(0));
+        check();
+        Assert.IsTrue(IC.eq(view, 1, 2, 5, 3, 3));
+        view.RemoveAllCopies(3);
+        check();
+        Assert.IsTrue(IC.eq(view, 1, 2, 5));
+        Assert.IsTrue(IC.eq(list, 0, 1, 2, 5, 3));
+        view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0);
+        Assert.IsTrue(IC.eq(view, 1, 2, 5, 1, 5, 3, 1, 3, 0));
+
+        view.FIFO = true;
+        view.Clear(); view.Add(1); view.Add(2);
+
+        view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0);
+        Assert.IsTrue(IC.eq(view, 1, 2, 1, 5, 3, 1, 3, 0));
+        Assert.IsTrue(view.Remove(1));
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 1, 5, 3, 1, 3, 0));
+        Assert.IsTrue(view.Remove(1));
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 5, 3, 1, 3, 0));
+        Assert.IsTrue(view.Remove(0));
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 5, 3, 1, 3));
+        view.RemoveAllCopies(3);
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 5, 1));
+        Assert.IsTrue(IC.eq(list, 0, 2, 5, 1, 3));
+        view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0);
+        Assert.IsTrue(IC.eq(view, 2, 5, 1, 1, 5, 3, 1, 3, 0));
+
+        view.FIFO = false;
+
+        ArrayList<int> l2 = new ArrayList<int>();
+
+        l2.Add(1); l2.Add(2); l2.Add(2); l2.Add(3); l2.Add(1);
+        view.RemoveAll(l2);
+        check();
+        Assert.IsTrue(IC.eq(view, 5, 5, 1, 3, 0));
+        view.RetainAll(l2);
+        check();
+        Assert.IsTrue(IC.eq(view, 1, 3));
+        view.Add(2); view.Add(4); view.Add(5);
+        Assert.AreEqual(1, view.RemoveAt(0));
+        Assert.AreEqual(5, view.RemoveAt(3));
+        Assert.AreEqual(2, view.RemoveAt(1));
+        check();
+        Assert.IsTrue(IC.eq(view, 3, 4));
+        view.Add(8);
+        Assert.AreEqual(3, view.RemoveFirst());
+        Assert.AreEqual(8, view.RemoveLast());
+        view.Add(2); view.Add(5); view.Add(3); view.Add(1);
+        view.RemoveInterval(1, 2);
+        check();
+        Assert.IsTrue(IC.eq(view, 4, 3, 1));
+      }
+
+
+      [Test]
+      public void Reverse()
+      {
+        view.Clear();
+        for (int i = 0; i < 10; i++) view.Add(10 + i);
+
+        view.View(3, 4).Reverse();
+        check();
+        Assert.IsTrue(IC.eq(view, 10, 11, 12, 16, 15, 14, 13, 17, 18, 19));
+        view.Reverse();
+        Assert.IsTrue(IC.eq(view, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10));
+        Assert.IsTrue(IC.eq(list, 0, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10, 3));
+      }
+
+
+      [Test]
+      public void Slide()
+      {
+        view.Slide(1);
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 3));
+        view.Slide(-2);
+        check();
+        Assert.IsTrue(IC.eq(view, 0, 1));
+        view.Slide(0, 3);
+        check();
+        Assert.IsTrue(IC.eq(view, 0, 1, 2));
+        view.Slide(2, 1);
+        check();
+        Assert.IsTrue(IC.eq(view, 2));
+        Assert.AreEqual(view, view.Slide(-1, 0));
+        check();
+        Assert.IsTrue(IC.eq(view));
+        view.Add(28);
+        Assert.IsTrue(IC.eq(list, 0, 28, 1, 2, 3));
+      }
+      [Test]
+      public void Iterate()
+      {
+        list.Clear();
+        view = null;
+        foreach (int i in new int[] { 2, 4, 8, 13, 6, 1, 2, 7 }) list.Add(i);
+
+        view = (ArrayList<int>)list.View(list.Count - 2, 2);
+        while (true)
+        {
+          if ((view.Last - view.First) % 2 == 1)
+            view.Insert(1, 666);
+          check();
+          if (view.Offset == 0)
+            break;
+          else
+            view.Slide(-1, 2);
+        }
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 2, 4, 8, 666, 13, 6, 1, 666, 2, 666, 7));
+      }
+
+
+      [Test]
+      public void SyncRoot()
+      {
+        Assert.AreSame(((System.Collections.IList)view).SyncRoot, ((System.Collections.IList)list).SyncRoot);
+      }
+    }
+    [TestFixture]
+    public class MulipleViews
+    {
+      IList<int> list;
+      IList<int>[][] views;
+      [SetUp]
+      public void Init()
+      {
+        list = new ArrayList<int>();
+        for (int i = 0; i < 6; i++)
+          list.Add(i);
+        views = new IList<int>[7][];
+        for (int i = 0; i < 7; i++)
+        {
+          views[i] = new IList<int>[7 - i];
+          for (int j = 0; j < 7 - i; j++)
+            views[i][j] = list.View(i, j);
+        }
+      }
+      [TearDown]
+      public void Dispose()
+      {
+        list = null;
+        views = null;
+      }
+      [Test]
+      public void Insert()
+      {
+        Assert.IsTrue(list.Check(), "list check before insert");
+        list.Insert(3, 777);
+        Assert.IsTrue(list.Check(), "list check after insert");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i < 3 && i + j > 3 ? j + 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void RemoveAt()
+      {
+        Assert.IsTrue(list.Check(), "list check before remove");
+        list.RemoveAt(3);
+        Assert.IsTrue(list.Check(), "list check after remove");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i <= 3 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i <= 3 && i + j > 3 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+      [Test]
+      public void RemoveInterval()
+      {
+        Assert.IsTrue(list.Check(), "list check before remove");
+        list.RemoveInterval(3, 2);
+        Assert.IsTrue(list.Check(), "list check after remove");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i <= 3 ? i : i <= 5 ? 3 : i - 2, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(j == 0 ? 0 : i <= 3 && i + j > 4 ? j - 2 : i > 4 || i + j <= 3 ? j : j - 1, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+
+      [Test]
+      public void InsertAtEnd()
+      {
+        Assert.IsTrue(list.Check(), "list check before insert");
+        list.InsertLast(777);
+        Assert.IsTrue(list.Check(), "list check after insert");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void RemoveAtEnd()
+      {
+        Assert.IsTrue(list.Check(), "list check before remove");
+        list.RemoveAt(5);
+        Assert.IsTrue(list.Check(), "list check after remove");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i <= 5 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i <= 5 && i + j > 5 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void InsertAtStart()
+      {
+        Assert.IsTrue(list.Check(), "list check before insert");
+        list.Insert(0, 777);
+        Assert.IsTrue(list.Check(), "list check after insert");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i == 0 && j == 0 ? 0 : i + 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void RemoveAtStart()
+      {
+        Assert.IsTrue(list.Check(), "list check before remove");
+        list.RemoveAt(0);
+        Assert.IsTrue(list.Check(), "list check after remove");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i == 0 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i == 0 && j > 0 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void Clear()
+      {
+        Assert.IsTrue(list.Check(), "list check before clear");
+        views[2][3].Clear();
+        Assert.IsTrue(list.Check(), "list check after clear");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i < 2 ? i : i < 6 ? 2 : i - 3, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(s(i, j), views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+      private int s(int i, int j)
+      {
+        if (j == 0) return 0;
+        int k = i + j - 1; //end
+        if (i > 4 || k <= 1) return j;
+        if (i >= 2) return k > 4 ? k - 4 : 0;
+        if (i <= 2) return k >= 4 ? j - 3 : 2 - i;
+        return -1;
+      }
+      [Test]
+      public void InsertAll()
+      {
+        ArrayList<int> list2 = new ArrayList<int>();
+        for (int i = 0; i < 5; i++) { list2.Add(100 + i); }
+        Assert.IsTrue(list.Check(), "list check before insertAll");
+        list.InsertAll(3, list2);
+        Assert.IsTrue(list.Check(), "list check after insertAll");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 5, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i < 3 && i + j > 3 ? j + 5 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+      [Test]
+      public void AddAll()
+      {
+        ArrayList<int> list2 = new ArrayList<int>();
+        for (int i = 0; i < 5; i++) { list2.Add(100 + i); }
+        Assert.IsTrue(list.Check(), "list check before AddAll");
+        list.View(1, 2).AddAll(list2);
+        Assert.IsTrue(list.Check(), "list check after AddAll");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 5, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i < 3 && i + j > 3 ? j + 5 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+      [Test]
+      public void RemoveAll1()
+      {
+        ArrayList<int> list2 = new ArrayList<int>();
+        list2.Add(1); list2.Add(3); list2.Add(4);
+
+        for (int i = 0; i < 7; i++)
+        {
+          for (int j = 0; j < 7 - i; j++)
+          {
+            list = new ArrayList<int>();
+            for (int k = 0; k < 6; k++) list.Add(k);
+            ArrayList<int> v = (ArrayList<int>)list.View(i, j);
+            list.RemoveAll(list2);
+            Assert.IsTrue(list.Check(), "list check after RemoveAll, i=" + i + ", j=" + j);
+          }
+        }
+      }
+      [Test]
+      public void RemoveAll2()
+      {
+        ArrayList<int> list2 = new ArrayList<int>();
+        list2.Add(1); list2.Add(3); list2.Add(4);
+        Assert.IsTrue(list.Check(), "list check before RemoveAll");
+        list.RemoveAll(list2);
+
+        Assert.AreEqual(0, views[0][0].Offset, "view [0][0] offset");
+        Assert.AreEqual(0, views[0][1].Offset, "view [0][1] offset");
+        Assert.AreEqual(0, views[0][2].Offset, "view [0][2] offset");
+        Assert.AreEqual(0, views[0][3].Offset, "view [0][3] offset");
+        Assert.AreEqual(0, views[0][4].Offset, "view [0][4] offset");
+        Assert.AreEqual(0, views[0][5].Offset, "view [0][5] offset");
+        Assert.AreEqual(0, views[0][6].Offset, "view [0][6] offset");
+        Assert.AreEqual(1, views[1][0].Offset, "view [1][0] offset");
+        Assert.AreEqual(1, views[1][1].Offset, "view [1][1] offset");
+        Assert.AreEqual(1, views[1][2].Offset, "view [1][2] offset");
+        Assert.AreEqual(1, views[1][3].Offset, "view [1][3] offset");
+        Assert.AreEqual(1, views[1][4].Offset, "view [1][4] offset");
+        Assert.AreEqual(1, views[1][5].Offset, "view [1][5] offset");
+        Assert.AreEqual(1, views[2][0].Offset, "view [2][0] offset");
+        Assert.AreEqual(1, views[2][1].Offset, "view [2][1] offset");
+        Assert.AreEqual(1, views[2][2].Offset, "view [2][2] offset");
+        Assert.AreEqual(1, views[2][3].Offset, "view [2][3] offset");
+        Assert.AreEqual(1, views[2][4].Offset, "view [2][4] offset");
+        Assert.AreEqual(2, views[3][0].Offset, "view [3][0] offset");
+        Assert.AreEqual(2, views[3][1].Offset, "view [3][1] offset");
+        Assert.AreEqual(2, views[3][2].Offset, "view [3][2] offset");
+        Assert.AreEqual(2, views[3][3].Offset, "view [3][3] offset");
+        Assert.AreEqual(2, views[4][0].Offset, "view [4][0] offset");
+        Assert.AreEqual(2, views[4][1].Offset, "view [4][1] offset");
+        Assert.AreEqual(2, views[4][2].Offset, "view [4][2] offset");
+        Assert.AreEqual(2, views[5][0].Offset, "view [5][0] offset");
+        Assert.AreEqual(2, views[5][1].Offset, "view [5][1] offset");
+        Assert.AreEqual(3, views[6][0].Offset, "view [6][0] offset");
+
+        Assert.AreEqual(0, views[0][0].Count, "view [0][0] count");
+        Assert.AreEqual(1, views[0][1].Count, "view [0][1] count");
+        Assert.AreEqual(1, views[0][2].Count, "view [0][2] count");
+        Assert.AreEqual(2, views[0][3].Count, "view [0][3] count");
+        Assert.AreEqual(2, views[0][4].Count, "view [0][4] count");
+        Assert.AreEqual(2, views[0][5].Count, "view [0][5] count");
+        Assert.AreEqual(3, views[0][6].Count, "view [0][6] count");
+        Assert.AreEqual(0, views[1][0].Count, "view [1][0] count");
+        Assert.AreEqual(0, views[1][1].Count, "view [1][1] count");
+        Assert.AreEqual(1, views[1][2].Count, "view [1][2] count");
+        Assert.AreEqual(1, views[1][3].Count, "view [1][3] count");
+        Assert.AreEqual(1, views[1][4].Count, "view [1][4] count");
+        Assert.AreEqual(2, views[1][5].Count, "view [1][5] count");
+        Assert.AreEqual(0, views[2][0].Count, "view [2][0] count");
+        Assert.AreEqual(1, views[2][1].Count, "view [2][1] count");
+        Assert.AreEqual(1, views[2][2].Count, "view [2][2] count");
+        Assert.AreEqual(1, views[2][3].Count, "view [2][3] count");
+        Assert.AreEqual(2, views[2][4].Count, "view [2][4] count");
+        Assert.AreEqual(0, views[3][0].Count, "view [3][0] count");
+        Assert.AreEqual(0, views[3][1].Count, "view [3][1] count");
+        Assert.AreEqual(0, views[3][2].Count, "view [3][2] count");
+        Assert.AreEqual(1, views[3][3].Count, "view [3][3] count");
+        Assert.AreEqual(0, views[4][0].Count, "view [4][0] count");
+        Assert.AreEqual(0, views[4][1].Count, "view [4][1] count");
+        Assert.AreEqual(1, views[4][2].Count, "view [4][2] count");
+        Assert.AreEqual(0, views[5][0].Count, "view [5][0] count");
+        Assert.AreEqual(1, views[5][1].Count, "view [5][1] count");
+        Assert.AreEqual(0, views[6][0].Count, "view [6][0] count");
+
+        Assert.IsTrue(list.Check(), "list check after RemoveAll");
+      }
+
+      [Test]
+      public void RetainAll()
+      {
+        ArrayList<int> list2 = new ArrayList<int>();
+        list2.Add(2); list2.Add(4); list2.Add(5);
+        Assert.IsTrue(list.Check(), "list check before RetainAll");
+        list.RetainAll(list2);
+
+        Assert.AreEqual(0, views[0][0].Offset, "view [0][0] offset");
+        Assert.AreEqual(0, views[0][1].Offset, "view [0][1] offset");
+        Assert.AreEqual(0, views[0][2].Offset, "view [0][2] offset");
+        Assert.AreEqual(0, views[0][3].Offset, "view [0][3] offset");
+        Assert.AreEqual(0, views[0][4].Offset, "view [0][4] offset");
+        Assert.AreEqual(0, views[0][5].Offset, "view [0][5] offset");
+        Assert.AreEqual(0, views[0][6].Offset, "view [0][6] offset");
+        Assert.AreEqual(0, views[1][0].Offset, "view [1][0] offset");
+        Assert.AreEqual(0, views[1][1].Offset, "view [1][1] offset");
+        Assert.AreEqual(0, views[1][2].Offset, "view [1][2] offset");
+        Assert.AreEqual(0, views[1][3].Offset, "view [1][3] offset");
+        Assert.AreEqual(0, views[1][4].Offset, "view [1][4] offset");
+        Assert.AreEqual(0, views[1][5].Offset, "view [1][5] offset");
+        Assert.AreEqual(0, views[2][0].Offset, "view [2][0] offset");
+        Assert.AreEqual(0, views[2][1].Offset, "view [2][1] offset");
+        Assert.AreEqual(0, views[2][2].Offset, "view [2][2] offset");
+        Assert.AreEqual(0, views[2][3].Offset, "view [2][3] offset");
+        Assert.AreEqual(0, views[2][4].Offset, "view [2][4] offset");
+        Assert.AreEqual(1, views[3][0].Offset, "view [3][0] offset");
+        Assert.AreEqual(1, views[3][1].Offset, "view [3][1] offset");
+        Assert.AreEqual(1, views[3][2].Offset, "view [3][2] offset");
+        Assert.AreEqual(1, views[3][3].Offset, "view [3][3] offset");
+        Assert.AreEqual(1, views[4][0].Offset, "view [4][0] offset");
+        Assert.AreEqual(1, views[4][1].Offset, "view [4][1] offset");
+        Assert.AreEqual(1, views[4][2].Offset, "view [4][2] offset");
+        Assert.AreEqual(2, views[5][0].Offset, "view [5][0] offset");
+        Assert.AreEqual(2, views[5][1].Offset, "view [5][1] offset");
+        Assert.AreEqual(3, views[6][0].Offset, "view [6][0] offset");
+
+        Assert.AreEqual(0, views[0][0].Count, "view [0][0] count");
+        Assert.AreEqual(0, views[0][1].Count, "view [0][1] count");
+        Assert.AreEqual(0, views[0][2].Count, "view [0][2] count");
+        Assert.AreEqual(1, views[0][3].Count, "view [0][3] count");
+        Assert.AreEqual(1, views[0][4].Count, "view [0][4] count");
+        Assert.AreEqual(2, views[0][5].Count, "view [0][5] count");
+        Assert.AreEqual(3, views[0][6].Count, "view [0][6] count");
+        Assert.AreEqual(0, views[1][0].Count, "view [1][0] count");
+        Assert.AreEqual(0, views[1][1].Count, "view [1][1] count");
+        Assert.AreEqual(1, views[1][2].Count, "view [1][2] count");
+        Assert.AreEqual(1, views[1][3].Count, "view [1][3] count");
+        Assert.AreEqual(2, views[1][4].Count, "view [1][4] count");
+        Assert.AreEqual(3, views[1][5].Count, "view [1][5] count");
+        Assert.AreEqual(0, views[2][0].Count, "view [2][0] count");
+        Assert.AreEqual(1, views[2][1].Count, "view [2][1] count");
+        Assert.AreEqual(1, views[2][2].Count, "view [2][2] count");
+        Assert.AreEqual(2, views[2][3].Count, "view [2][3] count");
+        Assert.AreEqual(3, views[2][4].Count, "view [2][4] count");
+        Assert.AreEqual(0, views[3][0].Count, "view [3][0] count");
+        Assert.AreEqual(0, views[3][1].Count, "view [3][1] count");
+        Assert.AreEqual(1, views[3][2].Count, "view [3][2] count");
+        Assert.AreEqual(2, views[3][3].Count, "view [3][3] count");
+        Assert.AreEqual(0, views[4][0].Count, "view [4][0] count");
+        Assert.AreEqual(1, views[4][1].Count, "view [4][1] count");
+        Assert.AreEqual(2, views[4][2].Count, "view [4][2] count");
+        Assert.AreEqual(0, views[5][0].Count, "view [5][0] count");
+        Assert.AreEqual(1, views[5][1].Count, "view [5][1] count");
+        Assert.AreEqual(0, views[6][0].Count, "view [6][0] count");
+
+        Assert.IsTrue(list.Check(), "list check after RetainAll");
+      }
+
+      [Test]
+      public void RemoveAllCopies()
+      {
+        ArrayList<int> list2 = new ArrayList<int>();
+        list2.Add(0); list2.Add(2); list2.Add(2); list2.Add(2); list2.Add(5); list2.Add(2); list2.Add(1);
+        for (int i = 0; i < 7; i++)
+        {
+          for (int j = 0; j < 7 - i; j++)
+          {
+            list = new ArrayList<int>();
+            list.AddAll(list2);
+            ArrayList<int> v = (ArrayList<int>)list.View(i, j);
+            list.RemoveAllCopies(2);
+            Assert.AreEqual((i == 0 && j > 0 ? 1 : 0) + (i <= 4 && i + j > 4 ? 1 : 0) + (i <= 6 && i + j > 6 ? 1 : 0), v.Count, "v.Count, i=" + i + ", j=" + j);
+            Assert.AreEqual(i == 0 ? 0 : i <= 4 ? 1 : i <= 6 ? 2 : 3, v.Offset, "v.Offset, i=" + i + ", j=" + j);
+            Assert.IsTrue(list.Check(), "list check after RemoveAllCopies, i=" + i + ", j=" + j);
+          }
+        }
+      }
+
+      private void checkDisposed(bool reverse, int start, int count)
+      {
+        int k = 0;
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            if (i + j <= start || i >= start + count || (i <= start && i + j >= start + count) || (reverse && start <= i && start + count >= i + j))
+            {
+              try
+              {
+                k = views[i][j].Count;
+              }
+              catch (ViewDisposedException)
+              {
+                Assert.Fail("view[" + i + "][" + j + "] threw");
+              }
+              Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] size");
+              if (reverse && ((j > 0 && start <= i && start + count >= i + j) || (j == 0 && start < i && start + count > i)))
+                Assert.AreEqual(start + (start + count - i - j), views[i][j].Offset, "view[" + i + "][" + j + "] offset (mirrored)");
+              else
+                Assert.AreEqual(i, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            }
+            else
+            {
+              try
+              {
+                k = views[i][j].Count;
+                Assert.Fail("view[" + i + "][" + j + "] no throw");
+              }
+              catch (ViewDisposedException) { }
+            }
+          }
+      }
+
+      [Test]
+      public void Reverse()
+      {
+        int start = 2, count = 3;
+        IList<int> list2 = list.View(start, count);
+        Assert.IsTrue(list.Check(), "list check before Reverse");
+        list2.Reverse();
+        Assert.IsTrue(list.Check(), "list check after Reverse");
+        checkDisposed(true, start, count);
+      }
+      [Test]
+      public void Sort()
+      {
+        int start = 2, count = 3;
+        IList<int> list2 = list.View(start, count);
+        Assert.IsTrue(list.Check(), "list check before Sort");
+        list2.Sort();
+        Assert.IsTrue(list.Check(), "list check after Sort");
+        checkDisposed(false, start, count);
+      }
+      [Test]
+      public void Shuffle()
+      {
+        int start = 2, count = 3;
+        IList<int> list2 = list.View(start, count);
+        Assert.IsTrue(list.Check(), "list check before Shuffle");
+        list2.Shuffle();
+        Assert.IsTrue(list.Check(), "list check after Shuffle");
+        checkDisposed(false, start, count);
+      }
+
+
+    }
+  }
+
+
+
+
+  namespace ArrayListOfTreesORLists
+  {
+    [TestFixture]
+    public class MultiLevelUnorderedOfUnOrdered
+    {
+      private ICollection<int> dit, dat, dut;
+
+      private ICollection<ICollection<int>> Dit, Dat, Dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new ArrayList<int>();
+        dat = new TreeSet<int>(Comparer<int>.Default, EqualityComparer<int>.Default);
+        dut = new ArrayList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        Dit = new ArrayList<ICollection<int>>();
+        Dat = new ArrayList<ICollection<int>>();
+        Dut = new ArrayList<ICollection<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dit.UnsequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Assert.IsTrue(Dit.UnsequencedEquals(Dat));
+        Assert.IsFalse(Dit.UnsequencedEquals(Dut));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = null;
+        Dit = Dat = Dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelOrderedOfUnOrdered
+    {
+      private ICollection<int> dit, dat, dut;
+
+      private ISequenced<ICollection<int>> Dit, Dat, Dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new ArrayList<int>();
+        dat = new TreeSet<int>(Comparer<int>.Default, EqualityComparer<int>.Default);
+        dut = new ArrayList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        Dit = new ArrayList<ICollection<int>>();
+        Dat = new ArrayList<ICollection<int>>();
+        Dut = new ArrayList<ICollection<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dit.UnsequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Dut.Add(dit); Dut.Add(dut); Dut.Add(dat);
+        Assert.IsFalse(Dit.SequencedEquals(Dat));
+        Assert.IsTrue(Dit.SequencedEquals(Dut));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = null;
+        Dit = Dat = Dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelUnOrderedOfOrdered
+    {
+      private ISequenced<int> dit, dat, dut, dot;
+
+      private ICollection<ISequenced<int>> Dit, Dat, Dut, Dot;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new TreeSet<int>(Comparer<int>.Default, EqualityComparer<int>.Default);
+        dat = new ArrayList<int>();
+        dut = new ArrayList<int>();
+        dot = new ArrayList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(2); dat.Add(1);
+        dut.Add(3);
+        dot.Add(1); dot.Add(2);
+        Dit = new ArrayList<ISequenced<int>>();
+        Dat = new ArrayList<ISequenced<int>>();
+        Dut = new ArrayList<ISequenced<int>>();
+        Dot = new ArrayList<ISequenced<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsTrue(dit.SequencedEquals(dot));
+        Assert.IsFalse(dit.SequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Dut.Add(dot); Dut.Add(dut); Dut.Add(dit);
+        Dot.Add(dit); Dot.Add(dit); Dot.Add(dut);
+        Assert.IsTrue(Dit.UnsequencedEquals(Dut));
+        Assert.IsFalse(Dit.UnsequencedEquals(Dat));
+        Assert.IsTrue(Dit.UnsequencedEquals(Dot));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = dot = null;
+        Dit = Dat = Dut = Dot = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelOrderedOfOrdered
+    {
+      private ISequenced<int> dit, dat, dut, dot;
+
+      private ISequenced<ISequenced<int>> Dit, Dat, Dut, Dot;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new TreeSet<int>(Comparer<int>.Default, EqualityComparer<int>.Default);
+        dat = new ArrayList<int>();
+        dut = new ArrayList<int>();
+        dot = new ArrayList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(2); dat.Add(1);
+        dut.Add(3);
+        dot.Add(1); dot.Add(2);
+        Dit = new ArrayList<ISequenced<int>>();
+        Dat = new ArrayList<ISequenced<int>>();
+        Dut = new ArrayList<ISequenced<int>>();
+        Dot = new ArrayList<ISequenced<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsTrue(dit.SequencedEquals(dot));
+        Assert.IsFalse(dit.SequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Dut.Add(dot); Dut.Add(dut); Dut.Add(dit);
+        Dot.Add(dit); Dot.Add(dit); Dot.Add(dut);
+        Assert.IsTrue(Dit.SequencedEquals(Dut));
+        Assert.IsFalse(Dit.SequencedEquals(Dat));
+        Assert.IsFalse(Dit.SequencedEquals(Dot));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = dot = null;
+        Dit = Dat = Dut = Dot = null;
+      }
+    }
+  }
+
+
+
+
+  namespace HashingAndEquals
+  {
+    [TestFixture]
+    public class ISequenced
+    {
+      private ISequenced<int> dit, dat, dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new ArrayList<int>();
+        dat = new ArrayList<int>();
+        dut = new ArrayList<int>();
+      }
+
+
+      [Test]
+      public void EmptyEmpty()
+      {
+        Assert.IsTrue(dit.SequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void EmptyNonEmpty()
+      {
+        dit.Add(3);
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsFalse(dat.SequencedEquals(dit));
+      }
+
+      [Test]
+      public void HashVal()
+      {
+        Assert.AreEqual(CHC.sequencedhashcode(), dit.GetSequencedHashCode());
+        dit.Add(3);
+        Assert.AreEqual(CHC.sequencedhashcode(3), dit.GetSequencedHashCode());
+        dit.Add(7);
+        Assert.AreEqual(CHC.sequencedhashcode(3, 7), dit.GetSequencedHashCode());
+        Assert.AreEqual(CHC.sequencedhashcode(), dut.GetSequencedHashCode());
+        dut.Add(7);
+        Assert.AreEqual(CHC.sequencedhashcode(7), dut.GetSequencedHashCode());
+        dut.Add(3);
+        Assert.AreEqual(CHC.sequencedhashcode(7, 3), dut.GetSequencedHashCode());
+      }
+
+
+      [Test]
+      public void EqualHashButDifferent()
+      {
+        dit.Add(0); dit.Add(31);
+        dat.Add(1); dat.Add(0);
+        Assert.AreEqual(dit.GetSequencedHashCode(), dat.GetSequencedHashCode());
+        Assert.IsFalse(dit.SequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void Normal()
+      {
+        dit.Add(3);
+        dit.Add(7);
+        dat.Add(3);
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsFalse(dat.SequencedEquals(dit));
+        dat.Add(7);
+        Assert.IsTrue(dit.SequencedEquals(dat));
+        Assert.IsTrue(dat.SequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void WrongOrder()
+      {
+        dit.Add(3);
+        dut.Add(3);
+        Assert.IsTrue(dit.SequencedEquals(dut));
+        Assert.IsTrue(dut.SequencedEquals(dit));
+        dit.Add(7);
+        ((ArrayList<int>)dut).InsertFirst(7);
+        Assert.IsFalse(dit.SequencedEquals(dut));
+        Assert.IsFalse(dut.SequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void Reflexive()
+      {
+        Assert.IsTrue(dit.SequencedEquals(dit));
+        dit.Add(3);
+        Assert.IsTrue(dit.SequencedEquals(dit));
+        dit.Add(7);
+        Assert.IsTrue(dit.SequencedEquals(dit));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+        dat = null;
+        dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class IEditableCollection
+    {
+      private ICollection<int> dit, dat, dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new ArrayList<int>();
+        dat = new ArrayList<int>();
+        dut = new ArrayList<int>();
+      }
+
+
+      [Test]
+      public void EmptyEmpty()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void EmptyNonEmpty()
+      {
+        dit.Add(3);
+        Assert.IsFalse(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dat.UnsequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void HashVal()
+      {
+        Assert.AreEqual(CHC.unsequencedhashcode(), dit.GetUnsequencedHashCode());
+        dit.Add(3);
+        Assert.AreEqual(CHC.unsequencedhashcode(3), dit.GetUnsequencedHashCode());
+        dit.Add(7);
+        Assert.AreEqual(CHC.unsequencedhashcode(3, 7), dit.GetUnsequencedHashCode());
+        Assert.AreEqual(CHC.unsequencedhashcode(), dut.GetUnsequencedHashCode());
+        dut.Add(3);
+        Assert.AreEqual(CHC.unsequencedhashcode(3), dut.GetUnsequencedHashCode());
+        dut.Add(7);
+        Assert.AreEqual(CHC.unsequencedhashcode(7, 3), dut.GetUnsequencedHashCode());
+      }
+
+
+      [Test]
+      public void EqualHashButDifferent()
+      {
+        dit.Add(-1657792980); dit.Add(-1570288808);
+        dat.Add(1862883298); dat.Add(-272461342);
+        Assert.AreEqual(dit.GetUnsequencedHashCode(), dat.GetUnsequencedHashCode());
+        Assert.IsFalse(dit.UnsequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void Normal()
+      {
+        dit.Add(3);
+        dit.Add(7);
+        dat.Add(3);
+        Assert.IsFalse(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dat.UnsequencedEquals(dit));
+        dat.Add(7);
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsTrue(dat.UnsequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void WrongOrder()
+      {
+        dit.Add(3);
+        dut.Add(3);
+        Assert.IsTrue(dit.UnsequencedEquals(dut));
+        Assert.IsTrue(dut.UnsequencedEquals(dit));
+        dit.Add(7);
+        dut.Add(7);
+        Assert.IsTrue(dit.UnsequencedEquals(dut));
+        Assert.IsTrue(dut.UnsequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void Reflexive()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dit));
+        dit.Add(3);
+        Assert.IsTrue(dit.UnsequencedEquals(dit));
+        dit.Add(7);
+        Assert.IsTrue(dit.UnsequencedEquals(dit));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+        dat = null;
+        dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelUnorderedOfUnOrdered
+    {
+      private ICollection<int> dit, dat, dut;
+
+      private ICollection<ICollection<int>> Dit, Dat, Dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new ArrayList<int>();
+        dat = new ArrayList<int>();
+        dut = new ArrayList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        Dit = new ArrayList<ICollection<int>>();
+        Dat = new ArrayList<ICollection<int>>();
+        Dut = new ArrayList<ICollection<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dit.UnsequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Assert.IsTrue(Dit.UnsequencedEquals(Dat));
+        Assert.IsFalse(Dit.UnsequencedEquals(Dut));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = null;
+        Dit = Dat = Dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelOrderedOfUnOrdered
+    {
+      private ICollection<int> dit, dat, dut;
+
+      private ISequenced<ICollection<int>> Dit, Dat, Dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new ArrayList<int>();
+        dat = new ArrayList<int>();
+        dut = new ArrayList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        Dit = new ArrayList<ICollection<int>>();
+        Dat = new ArrayList<ICollection<int>>();
+        Dut = new ArrayList<ICollection<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dit.UnsequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Dut.Add(dit); Dut.Add(dut); Dut.Add(dat);
+        Assert.IsFalse(Dit.SequencedEquals(Dat));
+        Assert.IsTrue(Dit.SequencedEquals(Dut));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = null;
+        Dit = Dat = Dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelUnOrderedOfOrdered
+    {
+      private ISequenced<int> dit, dat, dut, dot;
+
+      private ICollection<ISequenced<int>> Dit, Dat, Dut, Dot;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new ArrayList<int>();
+        dat = new ArrayList<int>();
+        dut = new ArrayList<int>();
+        dot = new ArrayList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        dot.Add(2); dot.Add(1);
+        Dit = new ArrayList<ISequenced<int>>();
+        Dat = new ArrayList<ISequenced<int>>();
+        Dut = new ArrayList<ISequenced<int>>();
+        Dot = new ArrayList<ISequenced<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsTrue(dit.SequencedEquals(dot));
+        Assert.IsFalse(dit.SequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Dut.Add(dot); Dut.Add(dut); Dut.Add(dit);
+        Dot.Add(dit); Dot.Add(dit); Dot.Add(dut);
+        Assert.IsTrue(Dit.UnsequencedEquals(Dut));
+        Assert.IsFalse(Dit.UnsequencedEquals(Dat));
+        Assert.IsTrue(Dit.UnsequencedEquals(Dot));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = dot = null;
+        Dit = Dat = Dut = Dot = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelOrderedOfOrdered
+    {
+      private ISequenced<int> dit, dat, dut, dot;
+
+      private ISequenced<ISequenced<int>> Dit, Dat, Dut, Dot;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new ArrayList<int>();
+        dat = new ArrayList<int>();
+        dut = new ArrayList<int>();
+        dot = new ArrayList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        dot.Add(2); dot.Add(1);
+        Dit = new ArrayList<ISequenced<int>>();
+        Dat = new ArrayList<ISequenced<int>>();
+        Dut = new ArrayList<ISequenced<int>>();
+        Dot = new ArrayList<ISequenced<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsTrue(dit.SequencedEquals(dot));
+        Assert.IsFalse(dit.SequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Dut.Add(dot); Dut.Add(dut); Dut.Add(dit);
+        Dot.Add(dit); Dot.Add(dit); Dot.Add(dut);
+        Assert.IsTrue(Dit.SequencedEquals(Dut));
+        Assert.IsFalse(Dit.SequencedEquals(Dat));
+        Assert.IsFalse(Dit.SequencedEquals(Dot));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = dot = null;
+        Dit = Dat = Dut = Dot = null;
+      }
+    }
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/arrays/CircularQueueTest.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/arrays/CircularQueueTest.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/arrays/CircularQueueTest.cs	(revision 3)
@@ -0,0 +1,231 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+namespace C5UnitTests.arrays.circularqueue
+{
+  using CollectionOfInt = CircularQueue<int>;
+
+  [TestFixture]
+  public class GenericTesters
+  {
+    [Test]
+    public void TestEvents()
+    {
+      Fun<CollectionOfInt> factory = delegate() { return new CollectionOfInt(); };
+      new C5UnitTests.Templates.Events.QueueTester<CollectionOfInt>().Test(factory);
+      new C5UnitTests.Templates.Events.StackTester<CollectionOfInt>().Test(factory);
+    }
+
+    [Test]
+    public void Extensible()
+    {
+      //TODO: Test Circular Queue for Clone(?) and Serializable 
+      //C5UnitTests.Templates.Extensible.Clone.Tester<CollectionOfInt>();
+      //C5UnitTests.Templates.Extensible.Serialization.Tester<CollectionOfInt>();
+    }
+  }
+
+  //[TestFixture]
+  public class Template
+  {
+    private CircularQueue<int> queue;
+
+    [SetUp]
+    public void Init()
+    {
+      queue = new CircularQueue<int>();
+    }
+
+    [Test]
+    public void LeTest()
+    {
+    }
+
+    [TearDown]
+    public void Dispose() { queue = null; }
+
+  }
+
+  [TestFixture]
+  public class Formatting
+  {
+    CircularQueue<int> coll;
+    IFormatProvider rad16;
+    [SetUp]
+    public void Init() { coll = new CircularQueue<int>(); rad16 = new RadixFormatProvider(16); }
+    [TearDown]
+    public void Dispose() { coll = null; rad16 = null; }
+    [Test]
+    public void Format()
+    {
+      Assert.AreEqual("{  }", coll.ToString());
+      foreach (int i in new int[] { -4, 28, 129, 65530 })
+        coll.Enqueue(i);
+      Assert.AreEqual("{ -4, 28, 129, 65530 }", coll.ToString());
+      Assert.AreEqual("{ -4, 1C, 81, FFFA }", coll.ToString(null, rad16));
+      Assert.AreEqual("{ -4, 28, 129... }", coll.ToString("L14", null));
+      Assert.AreEqual("{ -4, 1C, 81... }", coll.ToString("L14", rad16));
+    }
+  }
+
+  [TestFixture]
+  public class CircularQueue
+  {
+    private CircularQueue<int> queue;
+
+    [SetUp]
+    public void Init()
+    {
+      queue = new CircularQueue<int>();
+    }
+
+    void loadup1()
+    {
+      queue.Enqueue(11);
+      queue.Enqueue(12);
+      queue.Enqueue(13);
+      queue.Dequeue();
+      queue.Enqueue(103);
+      queue.Enqueue(14);
+      queue.Enqueue(15);
+    }
+
+    void loadup2()
+    {
+      loadup1();
+      for (int i = 0; i < 4; i++)
+      {
+        queue.Dequeue();
+        queue.Enqueue(1000 + i);
+      }
+    }
+
+    void loadup3()
+    {
+      for (int i = 0; i < 18; i++)
+      {
+        queue.Enqueue(i);
+        Assert.IsTrue(queue.Check());
+      }
+      for (int i = 0; i < 14; i++)
+      {
+        Assert.IsTrue(queue.Check());
+        queue.Dequeue();
+      }
+    }
+
+    [Test]
+    public void Expand()
+    {
+      Assert.IsTrue(queue.Check());
+      loadup3();
+      Assert.IsTrue(IC.eq(queue, 14, 15, 16, 17));
+    }
+
+    [Test]
+    public void Simple()
+    {
+      loadup1();
+      Assert.IsTrue(queue.Check());
+      Assert.AreEqual(5, queue.Count);
+      Assert.IsTrue(IC.eq(queue, 12, 13, 103, 14, 15));
+      Assert.AreEqual(12, queue.Choose());
+    }
+
+    [Test]
+    public void Stack()
+    {
+      queue.Push(1);
+      Assert.IsTrue(queue.Check());
+      queue.Push(2);
+      Assert.IsTrue(queue.Check());
+      queue.Push(3);
+      Assert.IsTrue(queue.Check());
+      Assert.AreEqual(3, queue.Pop());
+      Assert.IsTrue(queue.Check());
+      Assert.AreEqual(2, queue.Pop());
+      Assert.IsTrue(queue.Check());
+      Assert.AreEqual(1, queue.Pop());
+      Assert.IsTrue(queue.Check());
+    }
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void BadChoose()
+    {
+      queue.Choose();
+    }
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void BadDequeue()
+    {
+      queue.Dequeue();
+    }
+
+    [Test]
+    public void Simple2()
+    {
+      loadup2();
+      Assert.IsTrue(queue.Check());
+      Assert.AreEqual(5, queue.Count);
+      Assert.IsTrue(IC.eq(queue, 15, 1000, 1001, 1002, 1003));
+      Assert.AreEqual(15, queue.Choose());
+    }
+
+    [Test]
+    public void Counting()
+    {
+      Assert.IsTrue(queue.IsEmpty);
+      Assert.AreEqual(0, queue.Count);
+      Assert.AreEqual(Speed.Constant, queue.CountSpeed);
+      queue.Enqueue(11);
+      Assert.IsFalse(queue.IsEmpty);
+      queue.Enqueue(12);
+      Assert.AreEqual(2, queue.Count);
+    }
+
+    //This test by Steve Wallace uncovered a bug in the indexing.
+    [Test]
+    public void SW200602()
+    {
+      C5.CircularQueue<int> list = new C5.CircularQueue<int>(8);
+      for (int count = 0; count <= 7; count++)
+      {
+        list.Enqueue(count);
+      }
+      int end = list.Count;
+      for (int index = 0; index < end; index++)
+      {
+        Assert.AreEqual(index, list[0]);
+        list.Dequeue();
+      }
+    }
+
+    [TearDown]
+    public void Dispose() { queue = null; }
+
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/arrays/HashedArrayListTest.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/arrays/HashedArrayListTest.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/arrays/HashedArrayListTest.cs	(revision 3)
@@ -0,0 +1,3424 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+
+namespace C5UnitTests.arrays.hashed
+{
+  using CollectionOfInt = HashedArrayList<int>;
+
+  [TestFixture]
+  public class GenericTesters
+  {
+    [Test]
+    public void TestEvents()
+    {
+      Fun<CollectionOfInt> factory = delegate() { return new CollectionOfInt(TenEqualityComparer.Default); };
+      new C5UnitTests.Templates.Events.ListTester<CollectionOfInt>().Test(factory);
+    }
+
+    [Test]
+    public void Extensible()
+    {
+      C5UnitTests.Templates.Extensible.Clone.Tester<CollectionOfInt>();
+      C5UnitTests.Templates.Extensible.Clone.ViewTester<CollectionOfInt>();
+      C5UnitTests.Templates.Extensible.Serialization.Tester<CollectionOfInt>();
+      C5UnitTests.Templates.Extensible.Serialization.ViewTester<CollectionOfInt>();
+    }
+
+    [Test]
+    public void List()
+    {
+      C5UnitTests.Templates.List.Dispose.Tester<CollectionOfInt>();
+      C5UnitTests.Templates.List.SCG_IList.Tester<CollectionOfInt>();
+    }
+  }
+
+  static class Factory
+  {
+    public static ICollection<T> New<T>() { return new HashedArrayList<T>(); }
+  }
+
+  namespace Events
+  {
+    class TenEqualityComparer : SCG.IEqualityComparer<int>
+    {
+      TenEqualityComparer() { }
+      public static TenEqualityComparer Default { get { return new TenEqualityComparer(); } }
+      public int GetHashCode(int item) { return (item / 10).GetHashCode(); }
+      public bool Equals(int item1, int item2) { return item1 / 10 == item2 / 10; }
+    }
+
+    [TestFixture]
+    public class IList_
+    {
+      private HashedArrayList<int> list;
+      CollectionEventList<int> seen;
+
+      [SetUp]
+      public void Init()
+      {
+        list = new HashedArrayList<int>(TenEqualityComparer.Default);
+        seen = new CollectionEventList<int>(IntEqualityComparer.Default);
+      }
+
+      private void listen() { seen.Listen(list, EventTypeEnum.All); }
+
+      [Test]
+      public void SetThis()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list[1] = 45;
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(56,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(45,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+          });
+      }
+
+      [Test]
+      public void Insert()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.Insert(1, 45);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(45,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+          });
+      }
+
+      [Test]
+      public void InsertAll()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.InsertAll<int>(1, new int[] { 666, 777, 888 });
+        //seen.Print(Console.Error);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(666,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(666, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(777,2), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(777, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(888,3), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(888, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+          });
+        list.InsertAll<int>(1, new int[] {});
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void InsertFirstLast()
+      {
+        list.Add(4); list.Add(56); list.Add(18);
+        listen();
+        list.InsertFirst(45);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(45,0), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+          });
+        list.InsertLast(88);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(88,4), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(88, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+          });
+      }
+
+      [Test]
+      public void Remove()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.Remove();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+      }
+
+      [Test]
+      public void RemoveFirst()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.RemoveFirst();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(4,0), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(4, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+      }
+
+      [Test]
+      public void RemoveLast()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.RemoveLast();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(56,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+      }
+
+      [Test]
+      public void Reverse()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.Reverse();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        list.View(1, 0).Reverse();
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+
+      [Test]
+      public void Sort()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.Sort();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        list.View(1, 0).Sort();
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void Shuffle()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.Shuffle();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        list.View(1, 0).Shuffle();
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void RemoveAt()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.RemoveAt(1);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(56,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+      }
+
+      [Test]
+      public void RemoveInterval()
+      {
+        list.Add(4); list.Add(56); list.Add(18);
+        listen();
+        list.RemoveInterval(1, 2);
+        seen.Check(new CollectionEvent<int>[] {
+           new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(false,2,1), list),
+         new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        list.RemoveInterval(1, 0);
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void Update()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.Update(53);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(53, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+          });
+        list.Update(67);
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void FindOrAdd()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        int val = 53;
+        list.FindOrAdd(ref val);
+        seen.Check(new CollectionEvent<int>[] {});
+        val = 67;
+        list.FindOrAdd(ref val);
+        seen.Check(new CollectionEvent<int>[] { 
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+      }
+
+      [Test]
+      public void UpdateOrAdd()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        int val = 53;
+        list.UpdateOrAdd(val);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(53, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        val = 67;
+        list.UpdateOrAdd(val);
+        seen.Check(new CollectionEvent<int>[] { 
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        list.UpdateOrAdd(51, out val);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(53, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(51, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        val = 67;
+        list.UpdateOrAdd(81, out val);
+        seen.Check(new CollectionEvent<int>[] { 
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(81, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+      }
+
+      [Test]
+      public void RemoveItem()
+      {
+        list.Add(4); list.Add(56); list.Add(18);
+        listen();
+        list.Remove(53);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.Remove(11);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(18, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+      }
+
+      [Test]
+      public void RemoveAll()
+      {
+        for (int i = 0; i < 10; i++)
+        {
+          list.Add(10 * i + 5);
+        }
+        listen();
+        list.RemoveAll<int>(new int[] { 32, 187, 45 });
+        //TODO: the order depends on internals of the HashSet
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(35, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(45, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.RemoveAll<int>(new int[] { 200, 300 });
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void Clear()
+      {
+        list.Add(4); list.Add(56); list.Add(18);
+        listen();
+        list.View(1, 1).Clear();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(false,1,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        list.Clear();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(true,2,0), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        list.Clear();
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void ListDispose()
+      {
+        list.Add(4); list.Add(56); list.Add(18);
+        listen();
+        list.View(1, 1).Dispose();
+        seen.Check(new CollectionEvent<int>[] {});
+        list.Dispose();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(true,3,0), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)
+        });
+        list.Dispose();
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+
+      [Test]
+      public void RetainAll()
+      {
+        for (int i = 0; i < 10; i++)
+        {
+          list.Add(10 * i + 5);
+        }
+        listen();
+        list.RetainAll<int>(new int[] { 32, 187, 45, 62, 82, 95, 2 });
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(15, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(25, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(55, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(75, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.RetainAll<int>(new int[] { 32, 187, 45, 62, 82, 95, 2 });
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void RemoveAllCopies()
+      {
+        for (int i = 0; i < 10; i++)
+        {
+          list.Add(3 * i + 5);
+        }
+        listen();
+        list.RemoveAllCopies(14);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(11, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.RemoveAllCopies(14);
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void Add()
+      {
+        listen();
+        seen.Check(new CollectionEvent<int>[0]);
+        list.Add(23);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(23, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+      }
+
+      [Test]
+      public void AddAll()
+      {
+        for (int i = 0; i < 10; i++)
+        {
+          list.Add(10 * i + 5);
+        }
+        listen();
+        list.AddAll<int>(new int[] { 145, 56, 167 });
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(145, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(167, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.AddAll<int>(new int[] { });
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [TearDown]
+      public void Dispose() { list = null; seen = null; }
+    }
+
+    [TestFixture]
+    public class StackQueue
+    {
+
+      private ArrayList<int> list;
+      CollectionEventList<int> seen;
+
+      [SetUp]
+      public void Init()
+      {
+        list = new ArrayList<int>(TenEqualityComparer.Default);
+        seen = new CollectionEventList<int>(IntEqualityComparer.Default);
+      }
+
+      private void listen() { seen.Listen(list, EventTypeEnum.All); }
+
+      [Test]
+      public void EnqueueDequeue()
+      {
+        listen();
+        list.Enqueue(67);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(67,0), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.Enqueue(2);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(2,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(2, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.Dequeue();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(67,0), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(67, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.Dequeue();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(2,0), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(2, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+      }
+
+      [Test]
+      public void PushPop()
+      {
+        listen();
+        seen.Check(new CollectionEvent<int>[0]);
+        list.Push(23);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(23,0), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(23, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.Push(-12);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(-12,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(-12, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.Pop();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(-12,1), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(-12, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+        list.Pop();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(23,0), list),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(23, 1), list),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), list)});
+      }
+
+      [TearDown]
+      public void Dispose() { list = null; seen = null; }
+    }
+
+
+  }
+
+  namespace Safety
+  {
+    /// <summary>
+    /// Tests to see if the collection classes are robust for enumerable arguments that throw exceptions.
+    /// </summary>
+    [TestFixture]
+    public class BadEnumerable
+    {
+      private HashedArrayList<int> list;
+
+      [SetUp]
+      public void Init()
+      {
+        list = new HashedArrayList<int>();
+      }
+
+      [Test]
+      public void InsertAll()
+      {
+        list.Add(4); list.Add(56); list.Add(18);
+        try
+        {
+          list.InsertAll<int>(1, new BadEnumerable<int>(new BadEnumerableException(), 91, 81, 71));
+          Assert.Fail("Should not get here");
+        }
+        catch (BadEnumerableException) { }
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 91, 81, 71, 56, 18));
+      }
+
+      [Test]
+      public void AddAll()
+      {
+        list.Add(4); list.Add(56); list.Add(18);
+        try
+        {
+          list.View(0, 1).AddAll<int>(new BadEnumerable<int>(new BadEnumerableException(), 91, 81, 71));
+          Assert.Fail("Should not get here");
+        }
+        catch (BadEnumerableException) { }
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 91, 81, 71, 56, 18));
+      }
+
+      [Test]
+      public void RemoveAll()
+      {
+        list.Add(4); list.Add(56); list.Add(18);
+        try
+        {
+          list.RemoveAll(new BadEnumerable<int>(new BadEnumerableException(), 9, 8, 7));
+          Assert.Fail("Should not get here");
+        }
+        catch (BadEnumerableException) { }
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 56, 18));
+      }
+
+      [Test]
+      public void RetainAll()
+      {
+        list.Add(4); list.Add(56); list.Add(18);
+        try
+        {
+          list.RetainAll(new BadEnumerable<int>(new BadEnumerableException(), 9, 8, 7));
+          Assert.Fail("Should not get here");
+        }
+        catch (BadEnumerableException) { }
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 56, 18));
+      }
+
+
+      [Test]
+      public void ContainsAll()
+      {
+        list.Add(4); list.Add(56); list.Add(18);
+        try
+        {
+          list.ContainsAll(new BadEnumerable<int>(new BadEnumerableException(), 4, 18));
+          Assert.Fail("Should not get here");
+        }
+        catch (BadEnumerableException) { }
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 56, 18));
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+
+    /// <summary>
+    /// Tests to see if the collection classes are robust for delegate arguments that throw exceptions.
+    /// </summary>
+    [TestFixture]
+    public class BadFun
+    {
+      private HashedArrayList<int> list;
+
+      [SetUp]
+      public void Init()
+      {
+        list = new HashedArrayList<int>();
+      }
+
+      [Test]
+      public void NoTests() { }
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+  }
+
+
+  namespace Enumerable
+  {
+    [TestFixture]
+    public class Multiops
+    {
+      private HashedArrayList<int> list;
+
+      private Fun<int, bool> always, never, even;
+
+
+      [SetUp]
+      public void Init()
+      {
+        list = new HashedArrayList<int>();
+        always = delegate { return true; };
+        never = delegate { return false; };
+        even = delegate(int i) { return i % 2 == 0; };
+      }
+
+
+      [Test]
+      public void All()
+      {
+        Assert.IsTrue(list.All(always));
+        Assert.IsTrue(list.All(never));
+        Assert.IsTrue(list.All(even));
+        list.Add(8);
+        Assert.IsTrue(list.All(always));
+        Assert.IsFalse(list.All(never));
+        Assert.IsTrue(list.All(even));
+        list.Add(5);
+        Assert.IsTrue(list.All(always));
+        Assert.IsFalse(list.All(never));
+        Assert.IsFalse(list.All(even));
+      }
+
+
+      [Test]
+      public void Exists()
+      {
+        Assert.IsFalse(list.Exists(always));
+        Assert.IsFalse(list.Exists(never));
+        Assert.IsFalse(list.Exists(even));
+        list.Add(5);
+        Assert.IsTrue(list.Exists(always));
+        Assert.IsFalse(list.Exists(never));
+        Assert.IsFalse(list.Exists(even));
+        list.Add(8);
+        Assert.IsTrue(list.Exists(always));
+        Assert.IsFalse(list.Exists(never));
+        Assert.IsTrue(list.Exists(even));
+      }
+
+
+      [Test]
+      public void Apply()
+      {
+        int sum = 0;
+        Act<int> a = delegate(int i) { sum = i + 10 * sum; };
+
+        list.Apply(a);
+        Assert.AreEqual(0, sum);
+        sum = 0;
+        list.Add(5); list.Add(8); list.Add(7); list.Add(5);
+        list.Apply(a);
+        Assert.AreEqual(587, sum);
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+
+
+
+    [TestFixture]
+    public class GetEnumerator
+    {
+      private HashedArrayList<int> list;
+
+
+      [SetUp]
+      public void Init() { list = new HashedArrayList<int>(); }
+
+
+      [Test]
+      public void Empty()
+      {
+        SCG.IEnumerator<int> e = list.GetEnumerator();
+
+        Assert.IsFalse(e.MoveNext());
+      }
+
+
+      [Test]
+      public void Normal()
+      {
+        list.Add(5);
+        list.Add(8);
+        list.Add(5);
+        list.Add(5);
+        list.Add(10);
+        list.Add(1);
+
+        SCG.IEnumerator<int> e = list.GetEnumerator();
+
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(5, e.Current);
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(8, e.Current);
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(10, e.Current);
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(1, e.Current);
+        Assert.IsFalse(e.MoveNext());
+      }
+
+
+      [Test]
+      public void DoDispose()
+      {
+        list.Add(5);
+        list.Add(8);
+        list.Add(5);
+
+        SCG.IEnumerator<int> e = list.GetEnumerator();
+
+        e.MoveNext();
+        e.MoveNext();
+        e.Dispose();
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterUpdate()
+      {
+        list.Add(5);
+        list.Add(8);
+        list.Add(5);
+
+        SCG.IEnumerator<int> e = list.GetEnumerator();
+
+        e.MoveNext();
+        list.Add(99);
+        e.MoveNext();
+      }
+
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+  }
+
+  namespace CollectionOrSink
+  {
+    [TestFixture]
+    public class Formatting
+    {
+      ICollection<int> coll;
+      IFormatProvider rad16;
+      [SetUp]
+      public void Init() { coll = Factory.New<int>(); rad16 = new RadixFormatProvider(16); }
+      [TearDown]
+      public void Dispose() { coll = null; rad16 = null; }
+      [Test]
+      public void Format()
+      {
+        Assert.AreEqual("[  ]", coll.ToString());
+        coll.AddAll<int>(new int[] { -4, 28, 129, 65530 });
+        Assert.AreEqual("[ 0:-4, 1:28, 2:129, 3:65530 ]", coll.ToString());
+        Assert.AreEqual("[ 0:-4, 1:1C, 2:81, 3:FFFA ]", coll.ToString(null, rad16));
+        Assert.AreEqual("[ 0:-4, 1:28... ]", coll.ToString("L14", null));
+        Assert.AreEqual("[ 0:-4, 1:1C... ]", coll.ToString("L14", rad16));
+      }
+    }
+
+    [TestFixture]
+    public class CollectionOrSink
+    {
+      private HashedArrayList<int> list;
+
+
+      [SetUp]
+      public void Init() { list = new HashedArrayList<int>(); }
+
+      [Test]
+      public void Choose()
+      {
+        list.Add(7);
+        Assert.AreEqual(7, list.Choose());
+      }
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void BadChoose()
+      {
+        list.Choose();
+      }
+
+
+      [Test]
+      public void CountEtAl()
+      {
+        Assert.AreEqual(0, list.Count);
+        Assert.IsTrue(list.IsEmpty);
+        Assert.IsFalse(list.AllowsDuplicates);
+        Assert.IsTrue(list.Add(5));
+        Assert.AreEqual(1, list.Count);
+        Assert.IsFalse(list.IsEmpty);
+        Assert.IsFalse(list.Add(5));
+        Assert.AreEqual(1, list.Count);
+        Assert.IsFalse(list.IsEmpty);
+        Assert.IsTrue(list.Add(8));
+        Assert.AreEqual(2, list.Count);
+      }
+
+
+      [Test]
+      public void AddAll()
+      {
+        list.Add(3); list.Add(4); list.Add(5);
+
+        HashedArrayList<int> list2 = new HashedArrayList<int>();
+
+        list2.AddAll(list);
+        Assert.IsTrue(IC.eq(list2, 3, 4, 5));
+        list.AddAll(list2);
+        Assert.IsTrue(IC.eq(list2, 3, 4, 5));
+        Assert.IsTrue(IC.eq(list, 3, 4, 5));
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+
+    [TestFixture]
+    public class FindPredicate
+    {
+      private HashedArrayList<int> list;
+      Fun<int, bool> pred;
+
+      [SetUp]
+      public void Init()
+      {
+        list = new HashedArrayList<int>(TenEqualityComparer.Default);
+        pred = delegate(int i) { return i % 5 == 0; };
+      }
+
+      [TearDown]
+      public void Dispose() { list = null; }
+
+      [Test]
+      public void Find()
+      {
+        int i;
+        Assert.IsFalse(list.Find(pred, out i));
+        list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+        Assert.IsFalse(list.Find(pred, out i));
+        list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+        Assert.IsTrue(list.Find(pred, out i));
+        Assert.AreEqual(45, i);
+      }
+
+      [Test]
+      public void FindLast()
+      {
+        int i;
+        Assert.IsFalse(list.FindLast(pred, out i));
+        list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+        Assert.IsFalse(list.FindLast(pred, out i));
+        list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+        Assert.IsTrue(list.FindLast(pred, out i));
+        Assert.AreEqual(675, i);
+      }
+
+      [Test]
+      public void FindIndex()
+      {
+        Assert.IsFalse(0 <= list.FindIndex(pred));
+        list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+        Assert.IsFalse(0 <= list.FindIndex(pred));
+        list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+        Assert.AreEqual(4, list.FindIndex(pred));
+      }
+
+      [Test]
+      public void FindLastIndex()
+      {
+        Assert.IsFalse(0 <= list.FindLastIndex(pred));
+        list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+        Assert.IsFalse(0 <= list.FindLastIndex(pred));
+        list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+        Assert.AreEqual(6, list.FindLastIndex(pred));
+      }
+    }
+
+    [TestFixture]
+    public class UniqueItems
+    {
+      private HashedArrayList<int> list;
+
+      [SetUp]
+      public void Init() { list = new HashedArrayList<int>(); }
+
+      [TearDown]
+      public void Dispose() { list = null; }
+
+      [Test]
+      public void Test()
+      {
+        Assert.IsTrue(IC.seteq(list.UniqueItems()));
+        Assert.IsTrue(IC.seteq(list.ItemMultiplicities()));
+        list.AddAll<int>(new int[] { 7, 9, 7 });
+        Assert.IsTrue(IC.seteq(list.UniqueItems(), 7, 9));
+        Assert.IsTrue(IC.seteq(list.ItemMultiplicities(), 7, 1, 9, 1));
+      }
+    }
+
+    [TestFixture]
+    public class ArrayTest
+    {
+      private HashedArrayList<int> list;
+
+      int[] a;
+
+
+      [SetUp]
+      public void Init()
+      {
+        list = new HashedArrayList<int>();
+        a = new int[10];
+        for (int i = 0; i < 10; i++)
+          a[i] = 1000 + i;
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+
+
+      private string aeq(int[] a, params int[] b)
+      {
+        if (a.Length != b.Length)
+          return "Lengths differ: " + a.Length + " != " + b.Length;
+
+        for (int i = 0; i < a.Length; i++)
+          if (a[i] != b[i])
+            return String.Format("{0}'th elements differ: {1} != {2}", i, a[i], b[i]);
+
+        return "Alles klar";
+      }
+
+
+      [Test]
+      public void ToArray()
+      {
+        Assert.AreEqual("Alles klar", aeq(list.ToArray()));
+        list.Add(7);
+        list.Add(8);
+        Assert.AreEqual("Alles klar", aeq(list.ToArray(), 7, 8));
+      }
+
+
+      [Test]
+      public void CopyTo()
+      {
+        list.CopyTo(a, 1);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+        list.Add(6);
+        list.CopyTo(a, 2);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+        list.Add(4);
+        list.Add(5);
+        list.Add(9);
+        list.CopyTo(a, 4);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 4, 5, 9, 1008, 1009));
+        list.Clear();
+        list.Add(7);
+        list.CopyTo(a, 9);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 4, 5, 9, 1008, 7));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void CopyToBad()
+      {
+        list.CopyTo(a, 11);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void CopyToBad2()
+      {
+        list.CopyTo(a, -1);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void CopyToTooFar()
+      {
+        list.Add(3);
+        list.Add(4);
+        list.CopyTo(a, 9);
+      }
+    }
+
+
+
+    [TestFixture]
+    public class Sync
+    {
+      private HashedArrayList<int> list;
+
+
+      [SetUp]
+      public void Init()
+      {
+        list = new HashedArrayList<int>();
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+
+
+      [Test]
+      public void Get()
+      {
+        Assert.IsNotNull(((System.Collections.IList)list).SyncRoot);
+      }
+    }
+  }
+
+
+
+
+  namespace EditableCollection
+  {
+    [TestFixture]
+    public class Searching
+    {
+      private HashedArrayList<int> list;
+
+
+      [SetUp]
+      public void Init() { list = new HashedArrayList<int>(); }
+
+
+      [Test]
+      [ExpectedException(typeof(NullReferenceException))]
+      public void NullEqualityComparerinConstructor1()
+      {
+        new HashedArrayList<int>(null);
+      }
+
+      [Test]
+      [ExpectedException(typeof(NullReferenceException))]
+      public void NullEqualityComparerinConstructor2()
+      {
+        new HashedArrayList<int>(5, null);
+      }
+
+      [Test]
+      public void Contains()
+      {
+        Assert.IsFalse(list.Contains(5));
+        list.Add(5);
+        Assert.IsTrue(list.Contains(5));
+        Assert.IsFalse(list.Contains(7));
+        list.Add(8);
+        list.Add(10);
+        Assert.IsTrue(list.Contains(5));
+        Assert.IsFalse(list.Contains(7));
+        Assert.IsTrue(list.Contains(8));
+        Assert.IsTrue(list.Contains(10));
+        list.Remove(8);
+        Assert.IsTrue(list.Contains(5));
+        Assert.IsFalse(list.Contains(7));
+        Assert.IsFalse(list.Contains(8));
+        Assert.IsTrue(list.Contains(10));
+      }
+
+      [Test]
+      public void BadAdd()
+      {
+        Assert.IsTrue(list.Add(5));
+        Assert.IsTrue(list.Add(8));
+        Assert.IsFalse(list.Add(5));
+      }
+
+
+      [Test]
+      public void ContainsCount()
+      {
+        Assert.AreEqual(0, list.ContainsCount(5));
+        list.Add(5);
+        Assert.AreEqual(1, list.ContainsCount(5));
+        Assert.AreEqual(0, list.ContainsCount(7));
+        list.Add(8);
+        Assert.AreEqual(1, list.ContainsCount(5));
+        Assert.AreEqual(0, list.ContainsCount(7));
+        Assert.AreEqual(1, list.ContainsCount(8));
+      }
+
+
+      [Test]
+      public void RemoveAllCopies()
+      {
+        list.Add(5); list.Add(7);
+        Assert.AreEqual(1, list.ContainsCount(5));
+        Assert.AreEqual(1, list.ContainsCount(7));
+        list.RemoveAllCopies(5);
+        Assert.AreEqual(0, list.ContainsCount(5));
+        Assert.AreEqual(1, list.ContainsCount(7));
+        list.Add(5); list.Add(8);
+        list.RemoveAllCopies(8);
+        Assert.IsTrue(IC.eq(list, 7, 5));
+      }
+
+
+      [Test]
+      public void FindAll()
+      {
+        Fun<int, bool> f = delegate(int i) { return i % 2 == 0; };
+
+        Assert.IsTrue(list.FindAll(f).IsEmpty);
+        list.Add(5); list.Add(8); list.Add(10);
+        Assert.IsTrue(((HashedArrayList<int>)list.FindAll(f)).Check());
+        Assert.IsTrue(IC.eq(list.FindAll(f), 8, 10));
+      }
+
+
+      [Test]
+      public void ContainsAll()
+      {
+        HashedArrayList<int> list2 = new HashedArrayList<int>();
+
+        Assert.IsTrue(list.ContainsAll(list2));
+        list2.Add(4);
+        Assert.IsFalse(list.ContainsAll(list2));
+        list.Add(4);
+        Assert.IsTrue(list.ContainsAll(list2));
+        list.Add(5);
+        Assert.IsTrue(list.ContainsAll(list2));
+      }
+
+
+      [Test]
+      public void RetainAll()
+      {
+        HashedArrayList<int> list2 = new HashedArrayList<int>();
+
+        list.Add(4); list.Add(5); list.Add(6);
+        list2.Add(5); list2.Add(4); list2.Add(7);
+        list.RetainAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 5));
+        list.Add(5); list.Add(4); list.Add(6);
+        list2.Clear();
+        list2.Add(5); list2.Add(5); list2.Add(6);
+        list.RetainAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 5, 6));
+        list2.Clear();
+        list2.Add(7); list2.Add(8); list2.Add(9);
+        list.RetainAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list));
+      }
+
+
+      [Test]
+      public void RemoveAll()
+      {
+        HashedArrayList<int> list2 = new HashedArrayList<int>();
+
+        list.Add(4); list.Add(5); list.Add(6);
+        list2.Add(5); list2.Add(4); list2.Add(7);
+        list.RemoveAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 6));
+        list.Add(5); list.Add(4); list.Add(6);
+        list2.Clear();
+        list2.Add(6); list2.Add(5);
+        list.RemoveAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4));
+        list2.Clear();
+        list2.Add(7); list2.Add(8); list2.Add(9);
+        list.RemoveAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4));
+      }
+
+
+      [Test]
+      public void Remove()
+      {
+        list.Add(4); list.Add(5); list.Add(6);
+        Assert.IsFalse(list.Remove(2));
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(list.Remove(4));
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 5, 6));
+        Assert.AreEqual(6, list.RemoveLast());
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 5));
+        list.Add(7);
+        Assert.AreEqual(5, list.RemoveFirst());
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 7));
+      }
+
+
+      [Test]
+      public void Clear()
+      {
+        list.Add(7); list.Add(6);
+        list.Clear();
+        Assert.IsTrue(list.IsEmpty);
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+  }
+
+
+
+
+  namespace IIndexed
+  {
+    [TestFixture]
+    public class Searching
+    {
+      private IIndexed<int> dit;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashedArrayList<int>();
+      }
+
+
+      [Test]
+      public void IndexOf()
+      {
+        Assert.AreEqual(~0, dit.IndexOf(6));
+        dit.Add(7);
+        Assert.AreEqual(~1, dit.IndexOf(6));
+        Assert.AreEqual(~1, dit.LastIndexOf(6));
+        Assert.AreEqual(0, dit.IndexOf(7));
+        dit.Add(5); dit.Add(7); dit.Add(8); dit.Add(7);
+        Assert.AreEqual(~3, dit.IndexOf(6));
+        Assert.AreEqual(0, dit.IndexOf(7));
+        Assert.AreEqual(0, dit.LastIndexOf(7));
+        Assert.AreEqual(2, dit.IndexOf(8));
+        Assert.AreEqual(1, dit.LastIndexOf(5));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class Removing
+    {
+      private IIndexed<int> dit;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashedArrayList<int>();
+      }
+
+
+      [Test]
+      public void RemoveAt()
+      {
+        dit.Add(5); dit.Add(7); dit.Add(9); dit.Add(1); dit.Add(2);
+        Assert.AreEqual(7, dit.RemoveAt(1));
+        Assert.IsTrue(((HashedArrayList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 5, 9, 1, 2));
+        Assert.AreEqual(5, dit.RemoveAt(0));
+        Assert.IsTrue(((HashedArrayList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 9, 1, 2));
+        Assert.AreEqual(2, dit.RemoveAt(2));
+        Assert.IsTrue(((HashedArrayList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 9, 1));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void RemoveAtBad0()
+      {
+        dit.RemoveAt(0);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void RemoveAtBadM1()
+      {
+        dit.RemoveAt(-1);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void RemoveAtBad1()
+      {
+        dit.Add(8);
+        dit.RemoveAt(1);
+      }
+
+
+      [Test]
+      public void RemoveInterval()
+      {
+        dit.RemoveInterval(0, 0);
+        dit.Add(10); dit.Add(20); dit.Add(30); dit.Add(40); dit.Add(50); dit.Add(60);
+        dit.RemoveInterval(3, 0);
+        Assert.IsTrue(((HashedArrayList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 10, 20, 30, 40, 50, 60));
+        dit.RemoveInterval(3, 1);
+        Assert.IsTrue(((HashedArrayList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 10, 20, 30, 50, 60));
+        dit.RemoveInterval(1, 3);
+        Assert.IsTrue(((HashedArrayList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 10, 60));
+        dit.RemoveInterval(0, 2);
+        Assert.IsTrue(((HashedArrayList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit));
+        dit.Add(10); dit.Add(20); dit.Add(30); dit.Add(40); dit.Add(50); dit.Add(60);
+        dit.RemoveInterval(0, 2);
+        Assert.IsTrue(((HashedArrayList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 30, 40, 50, 60));
+        dit.RemoveInterval(2, 2);
+        Assert.IsTrue(((HashedArrayList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 30, 40));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+      }
+    }
+  }
+
+
+
+
+  namespace IList
+  {
+    [TestFixture]
+    public class Searching
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new HashedArrayList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void FirstBad()
+      {
+        int f = lst.First;
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void LastBad()
+      {
+        int f = lst.Last;
+      }
+
+
+      [Test]
+      public void FirstLast()
+      {
+        lst.Add(19);
+        Assert.AreEqual(19, lst.First);
+        Assert.AreEqual(19, lst.Last);
+        lst.Add(34); lst.InsertFirst(12);
+        Assert.AreEqual(12, lst.First);
+        Assert.AreEqual(34, lst.Last);
+      }
+
+
+      [Test]
+      public void This()
+      {
+        lst.Add(34);
+        Assert.AreEqual(34, lst[0]);
+        lst[0] = 56;
+        Assert.AreEqual(56, lst.First);
+        lst.Add(7); lst.Add(77); lst.Add(777); lst.Add(7777);
+        lst[0] = 45; lst[2] = 78; lst[4] = 101;
+        Assert.IsTrue(IC.eq(lst, 45, 7, 78, 777, 101));
+      }
+
+      [Test]
+      public void ThisWithUpdates()
+      {
+        HashedArrayList<KeyValuePair<int, int>> pairlist = new HashedArrayList<KeyValuePair<int, int>>(new KeyValuePairEqualityComparer<int, int>());
+        pairlist.Add(new KeyValuePair<int, int>(10, 50));
+        pairlist.Add(new KeyValuePair<int, int>(11, 51));
+        pairlist.Add(new KeyValuePair<int, int>(12, 52));
+        pairlist.Add(new KeyValuePair<int, int>(13, 53));
+        pairlist[2] = new KeyValuePair<int, int>(12, 102);
+        Assert.IsTrue(pairlist.Check());
+        Assert.AreEqual(new KeyValuePair<int, int>(12, 102), pairlist[2]);
+        pairlist[2] = new KeyValuePair<int, int>(22, 202);
+        Assert.IsTrue(pairlist.Check());
+        Assert.AreEqual(new KeyValuePair<int, int>(22, 202), pairlist[2]);
+        pairlist[1] = new KeyValuePair<int, int>(12, 303);
+        Assert.IsTrue(pairlist.Check());
+        Assert.AreEqual(new KeyValuePair<int, int>(12, 303), pairlist[1]);
+        Assert.AreEqual(new KeyValuePair<int, int>(22, 202), pairlist[2]);
+      }
+
+      [Test]
+      [ExpectedException(typeof(DuplicateNotAllowedException))]
+      public void ThisWithUpdatesBad()
+      {
+        HashedArrayList<KeyValuePair<int, int>> pairlist = new HashedArrayList<KeyValuePair<int, int>>(new KeyValuePairEqualityComparer<int, int>());
+        pairlist.Add(new KeyValuePair<int, int>(10, 50));
+        pairlist.Add(new KeyValuePair<int, int>(11, 51));
+        pairlist.Add(new KeyValuePair<int, int>(12, 52));
+        pairlist.Add(new KeyValuePair<int, int>(13, 53));
+        pairlist[2] = new KeyValuePair<int, int>(11, 102);
+      }
+
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadEmptyGet()
+      {
+        int f = lst[0];
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadLowGet()
+      {
+        lst.Add(7);
+
+        int f = lst[-1];
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadHiGet()
+      {
+        lst.Add(6);
+
+        int f = lst[1];
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadEmptySet()
+      {
+        lst[0] = 4;
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadLowSet()
+      {
+        lst.Add(7);
+        lst[-1] = 9;
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadHiSet()
+      {
+        lst.Add(6);
+        lst[1] = 11;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class Inserting
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new HashedArrayList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void Insert()
+      {
+        lst.Insert(0, 5);
+        Assert.IsTrue(IC.eq(lst, 5));
+        lst.Insert(0, 7);
+        Assert.IsTrue(IC.eq(lst, 7, 5));
+        lst.Insert(1, 4);
+        Assert.IsTrue(IC.eq(lst, 7, 4, 5));
+        lst.Insert(3, 2);
+        Assert.IsTrue(IC.eq(lst, 7, 4, 5, 2));
+      }
+
+      [Test]
+      [ExpectedException(typeof(DuplicateNotAllowedException))]
+      public void InsertDuplicate()
+      {
+        lst.Insert(0, 5);
+        Assert.IsTrue(IC.eq(lst, 5));
+        lst.Insert(0, 7);
+        Assert.IsTrue(IC.eq(lst, 7, 5));
+        lst.Insert(1, 5);
+      }
+
+      [Test]
+      public void InsertAllDuplicate1()
+      {
+        lst.Insert(0, 3);
+        Assert.IsTrue(IC.eq(lst, 3));
+        lst.Insert(0, 7);
+        Assert.IsTrue(IC.eq(lst, 7, 3));
+        try
+        {
+          lst.InsertAll<int>(1, new int[] { 1, 2, 3, 4 });
+        }
+        catch (DuplicateNotAllowedException)
+        {
+        }
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 1, 2, 3));
+      }
+
+      [Test]
+      public void InsertAllDuplicate2()
+      {
+        lst.Insert(0, 3);
+        Assert.IsTrue(IC.eq(lst, 3));
+        lst.Insert(0, 7);
+        Assert.IsTrue(IC.eq(lst, 7, 3));
+        try
+        {
+          lst.InsertAll<int>(1, new int[] { 5, 6, 5, 8 });
+        }
+        catch (DuplicateNotAllowedException)
+        {
+        }
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 5, 6, 3));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void BadInsertLow()
+      {
+        lst.Add(7);
+        lst.Insert(-1, 9);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void BadInsertHi()
+      {
+        lst.Add(6);
+        lst.Insert(2, 11);
+      }
+
+
+      [Test]
+      public void FIFO()
+      {
+        for (int i = 0; i < 7; i++)
+          lst.Add(2 * i);
+
+        Assert.IsFalse(lst.FIFO);
+        Assert.AreEqual(12, lst.Remove());
+        Assert.AreEqual(10, lst.Remove());
+        lst.FIFO = true;
+        Assert.AreEqual(0, lst.Remove());
+        Assert.AreEqual(2, lst.Remove());
+        lst.FIFO = false;
+        Assert.AreEqual(8, lst.Remove());
+        Assert.AreEqual(6, lst.Remove());
+      }
+
+
+      [Test]
+      public void InsertFirstLast()
+      {
+        lst.InsertFirst(4);
+        lst.InsertLast(5);
+        lst.InsertFirst(14);
+        lst.InsertLast(15);
+        lst.InsertFirst(24);
+        lst.InsertLast(25);
+        lst.InsertFirst(34);
+        lst.InsertLast(55);
+        Assert.IsTrue(IC.eq(lst, 34, 24, 14, 4, 5, 15, 25, 55));
+      }
+
+
+      [Test]
+      public void InsertFirst()
+      {
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(4);
+        lst.Add(5);
+        lst.ViewOf(2).InsertFirst(7);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 2, 3, 4, 5));
+        lst.ViewOf(3).InsertFirst(8);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 2, 8, 3, 4, 5));
+        lst.ViewOf(5).InsertFirst(9);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 2, 8, 3, 4, 9, 5));
+      }
+
+
+      [Test]
+      public void BadFirst()
+      {
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(2);
+        lst.Add(5);
+        Assert.IsNull(lst.ViewOf(4));
+      }
+
+
+      [Test]
+      public void InsertAfter()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(4);
+        lst.Add(5);
+        lst.LastViewOf(2).InsertLast(7);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 1, 2, 7, 3, 4, 5));
+        lst.LastViewOf(1).InsertLast(8);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 1, 8, 2, 7, 3, 4, 5));
+        lst.LastViewOf(5).InsertLast(9);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 1, 8, 2, 7, 3, 4, 5, 9));
+      }
+
+
+      [Test]
+      public void BadInsertAfter()
+      {
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(6);
+        lst.Add(5);
+        Assert.IsNull(lst.ViewOf(4));
+      }
+
+
+      [Test]
+      public void InsertAll()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(4);
+
+        IList<int> lst2 = new HashedArrayList<int>();
+
+        lst2.Add(7); lst2.Add(8); lst2.Add(9);
+        lst.InsertAll(0, lst2);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 1, 2, 3, 4));
+        lst.RemoveAll(lst2);
+        lst.InsertAll(4, lst2);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 1, 2, 3, 4, 7, 8, 9));
+        lst.RemoveAll(lst2);
+        lst.InsertAll(2, lst2);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 1, 2, 7, 8, 9, 3, 4));
+      }
+
+      [Test]
+      [ExpectedException(typeof(DuplicateNotAllowedException))]
+      public void InsertAllBad()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(4);
+
+        IList<int> lst2 = new HashedArrayList<int>();
+
+        lst2.Add(5); lst2.Add(2); lst2.Add(9);
+        lst.InsertAll(0, lst2);
+      }
+
+
+      [Test]
+      public void Map()
+      {
+        Fun<int, string> m = delegate(int i) { return "<<" + i + ">>"; };
+        IList<string> r = lst.Map(m);
+
+        Assert.IsTrue(((HashedArrayList<string>)r).Check());
+        Assert.IsTrue(r.IsEmpty);
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(4);
+        r = lst.Map(m);
+        Assert.IsTrue(((HashedArrayList<string>)r).Check());
+        Assert.AreEqual(4, r.Count);
+        for (int i = 0; i < 4; i++)
+          Assert.AreEqual("<<" + (i + 1) + ">>", r[i]);
+      }
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void BadMapper()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        Fun<int, bool> m = delegate(int i) { if (i == 2) lst.Add(7); return true; };
+        lst.Map(m);
+      }
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void ModifyingFindAll()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        Fun<int, bool> m = delegate(int i) { if (i == 2) lst.Add(7); return true; };
+        lst.FindAll(m);
+      }
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void BadMapperView()
+      {
+        lst = lst.View(0, 0);
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        Fun<int, bool> m = delegate(int i) { if (i == 2) lst.Add(7); return true; };
+        lst.Map(m);
+      }
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void ModifyingFindAllView()
+      {
+        lst = lst.View(0, 0);
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        Fun<int, bool> m = delegate(int i) { if (i == 2) lst.Add(7); return true; };
+        lst.FindAll(m);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void BadRemove() { lst.Remove(); }
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void BadRemoveFirst() { lst.RemoveFirst(); }
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void BadRemoveLast() { lst.RemoveLast(); }
+
+
+      [Test]
+      public void RemoveFirstLast()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(4);
+        Assert.AreEqual(1, lst.RemoveFirst());
+        Assert.AreEqual(4, lst.RemoveLast());
+        Assert.AreEqual(2, lst.RemoveFirst());
+        Assert.AreEqual(3, lst.RemoveLast());
+        Assert.IsTrue(lst.IsEmpty);
+      }
+
+
+      [Test]
+      public void Reverse()
+      {
+        for (int i = 0; i < 10; i++)
+          lst.Add(i);
+
+        lst.Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0));
+        lst.View(0, 3).Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0));
+        lst.View(7, 0).Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0));
+        lst.View(7, 3).Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2));
+        lst.View(5, 1).Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void BadReverse()
+      {
+        for (int i = 0; i < 10; i++)
+          lst.Add(i);
+
+        lst.View(8, 3).Reverse();
+      }
+    }
+
+
+    [TestFixture]
+    public class Combined
+    {
+      private IList<KeyValuePair<int, int>> lst;
+
+
+      [SetUp]
+      public void Init()
+      {
+        lst = new HashedArrayList<KeyValuePair<int, int>>(new KeyValuePairEqualityComparer<int, int>());
+        for (int i = 0; i < 10; i++)
+          lst.Add(new KeyValuePair<int, int>(i, i + 30));
+      }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void Find()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.Find(ref p));
+        Assert.AreEqual(3, p.Key);
+        Assert.AreEqual(33, p.Value);
+        p = new KeyValuePair<int, int>(13, 78);
+        Assert.IsFalse(lst.Find(ref p));
+      }
+
+
+      [Test]
+      public void FindOrAdd()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.FindOrAdd(ref p));
+        Assert.AreEqual(3, p.Key);
+        Assert.AreEqual(33, p.Value);
+        p = new KeyValuePair<int, int>(13, 79);
+        Assert.IsFalse(lst.FindOrAdd(ref p));
+        Assert.AreEqual(13, lst[10].Key);
+        Assert.AreEqual(79, lst[10].Value);
+      }
+
+
+      [Test]
+      public void Update()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.Update(p));
+        Assert.AreEqual(3, lst[3].Key);
+        Assert.AreEqual(78, lst[3].Value);
+        p = new KeyValuePair<int, int>(13, 78);
+        Assert.IsFalse(lst.Update(p));
+      }
+
+
+      [Test]
+      public void UpdateOrAdd1()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.UpdateOrAdd(p));
+        Assert.AreEqual(3, lst[3].Key);
+        Assert.AreEqual(78, lst[3].Value);
+        p = new KeyValuePair<int, int>(13, 79);
+        Assert.IsFalse(lst.UpdateOrAdd(p));
+        Assert.AreEqual(13, lst[10].Key);
+        Assert.AreEqual(79, lst[10].Value);
+      }
+
+      [Test]
+      public void UpdateOrAdd2()
+      {
+          ICollection<String> coll = new HashedArrayList<String>();
+          // s1 and s2 are distinct objects but contain the same text:
+          String old, s1 = "abc", s2 = ("def" + s1).Substring(3);
+          Assert.IsFalse(coll.UpdateOrAdd(s1, out old));
+          Assert.AreEqual(null, old);
+          Assert.IsTrue(coll.UpdateOrAdd(s2, out old));
+          Assert.IsTrue(Object.ReferenceEquals(s1, old));
+          Assert.IsFalse(Object.ReferenceEquals(s2, old));
+      }
+
+      [Test]
+      public void RemoveWithReturn()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.Remove(p, out p));
+        Assert.AreEqual(3, p.Key);
+        Assert.AreEqual(33, p.Value);
+        Assert.AreEqual(4, lst[3].Key);
+        Assert.AreEqual(34, lst[3].Value);
+        p = new KeyValuePair<int, int>(13, 78);
+        Assert.IsFalse(lst.Remove(p, out p));
+      }
+    }
+
+
+    [TestFixture]
+    public class Sorting
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new HashedArrayList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void Sort()
+      {
+        lst.Add(5); lst.Add(6); lst.Add(55); lst.Add(7); lst.Add(3);
+        Assert.IsFalse(lst.IsSorted(new IC()));
+        lst.Sort(new IC());
+        Assert.IsTrue(lst.IsSorted());
+        Assert.IsTrue(lst.IsSorted(new IC()));
+        Assert.IsTrue(IC.eq(lst, 3, 5, 6, 7, 55));
+      }
+    }
+  }
+
+
+
+
+  namespace Range
+  {
+    [TestFixture]
+    public class Range
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new HashedArrayList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void GetRange()
+      {
+        //Assert.IsTrue(IC.eq(lst[0, 0)));
+        for (int i = 0; i < 10; i++) lst.Add(i);
+
+        Assert.IsTrue(IC.eq(lst[0, 3], 0, 1, 2));
+        Assert.IsTrue(IC.eq(lst[3, 3], 3, 4, 5));
+        Assert.IsTrue(IC.eq(lst[6, 3], 6, 7, 8));
+        Assert.IsTrue(IC.eq(lst[6, 4], 6, 7, 8, 9));
+      }
+
+
+      [Test]
+      public void Backwards()
+      {
+        for (int i = 0; i < 10; i++) lst.Add(i);
+
+        Assert.IsTrue(IC.eq(lst.Backwards(), 9, 8, 7, 6, 5, 4, 3, 2, 1, 0));
+        Assert.IsTrue(IC.eq(lst[0, 3].Backwards(), 2, 1, 0));
+        Assert.IsTrue(IC.eq(lst[3, 3].Backwards(), 5, 4, 3));
+        Assert.IsTrue(IC.eq(lst[6, 4].Backwards(), 9, 8, 7, 6));
+      }
+
+
+      [Test]
+      public void DirectionAndCount()
+      {
+        for (int i = 0; i < 10; i++) lst.Add(i);
+
+        Assert.AreEqual(EnumerationDirection.Forwards, lst.Direction);
+        Assert.AreEqual(EnumerationDirection.Forwards, lst[3, 4].Direction);
+        Assert.AreEqual(EnumerationDirection.Backwards, lst[3, 4].Backwards().Direction);
+        Assert.AreEqual(EnumerationDirection.Backwards, lst.Backwards().Direction);
+        Assert.AreEqual(4, lst[3, 4].Count);
+        Assert.AreEqual(4, lst[3, 4].Backwards().Count);
+        Assert.AreEqual(10, lst.Backwards().Count);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterUpdate()
+      {
+        for (int i = 0; i < 10; i++) lst.Add(i);
+
+        foreach (int i in lst)
+        {
+          lst.Add(45 + i);
+        }
+      }
+    }
+  }
+
+
+
+
+  namespace View
+  {
+    [TestFixture]
+    public class Simple
+    {
+      HashedArrayList<int> list;
+      HashedArrayList<int> view;
+
+
+      [SetUp]
+      public void Init()
+      {
+        list = new HashedArrayList<int>();
+        list.Add(0); list.Add(1); list.Add(2); list.Add(3);
+        view = (HashedArrayList<int>)list.View(1, 2);
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        list = null;
+        view = null;
+      }
+
+
+      void check()
+      {
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(view.Check());
+      }
+
+      [Test]
+      public void InsertPointer()
+      {
+        IList<int> view2 = list.View(2, 0);
+        list.Insert(view2, 7);
+        check();
+        list.Insert(list, 8);
+        check();
+        view.Insert(view2, 9);
+        check();
+        view.Insert(list.View(3, 2), 10);
+        check();
+        view.Insert(list.ViewOf(0), 11);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 11, 1, 9, 7, 2, 10, 3, 8));
+        Assert.IsTrue(IC.eq(view, 11, 1, 9, 7, 2, 10));
+      }
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void InsertPointerBad1()
+      {
+        view.Insert(list.View(0, 0), 7);
+      }
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void InsertPointerBad2()
+      {
+        view.Insert(list, 7);
+      }
+
+      [Test]
+      [ExpectedException(typeof(IncompatibleViewException))]
+      public void InsertPointerBad3()
+      {
+        list.Insert(new ArrayList<int>(), 7);
+      }
+
+      [Test]
+      [ExpectedException(typeof(IncompatibleViewException))]
+      public void InsertPointerBad4()
+      {
+        list.Insert(new ArrayList<int>().View(0, 0), 7);
+      }
+
+
+      [Test]
+      public void Span()
+      {
+        IList<int> span = list.View(1, 0).Span(list.View(2, 0));
+        Assert.IsTrue(span.Check());
+        Assert.AreEqual(1, span.Offset);
+        Assert.AreEqual(1, span.Count);
+        span = list.View(0, 2).Span(list.View(2, 2));
+        Assert.IsTrue(span.Check());
+        Assert.AreEqual(0, span.Offset);
+        Assert.AreEqual(4, span.Count);
+        span = list.View(3, 1).Span(list.View(1, 1));
+        Assert.IsNull(span);
+      }
+
+      [Test]
+      public void ViewOf()
+      {
+        for (int i = 0; i < 4; i++)
+          list.Add(i);
+        IList<int> v = view.ViewOf(2);
+        Assert.IsTrue(v.Check());
+        Assert.IsTrue(IC.eq(v, 2));
+        Assert.AreEqual(2, v.Offset);
+        v = list.ViewOf(2);
+        Assert.IsTrue(v.Check());
+        Assert.IsTrue(IC.eq(v, 2));
+        Assert.AreEqual(2, v.Offset);
+        v = list.LastViewOf(2);
+        Assert.IsTrue(v.Check());
+        Assert.IsTrue(IC.eq(v, 2));
+        Assert.AreEqual(2, v.Offset);
+      }
+
+      [Test]
+      public void BadViewOf()
+      {
+        Assert.IsNull(view.ViewOf(5));
+        Assert.IsNull(view.LastViewOf(5));
+        Assert.IsNull(view.ViewOf(3));
+        Assert.IsNull(view.LastViewOf(3));
+        Assert.IsNull(view.ViewOf(0));
+        Assert.IsNull(view.LastViewOf(0));
+      }
+
+
+      [Test]
+      public void ArrayStuff()
+      {
+        Assert.IsTrue(IC.eq(view.ToArray(), 1, 2));
+        int[] extarray = new int[5];
+        view.CopyTo(extarray, 2);
+        Assert.IsTrue(IC.eq(extarray, 0, 0, 1, 2, 0));
+      }
+
+
+      [Test]
+      public void Add()
+      {
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 1, 2, 3));
+        Assert.IsTrue(IC.eq(view, 1, 2));
+        view.InsertFirst(10);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 10, 1, 2, 3));
+        Assert.IsTrue(IC.eq(view, 10, 1, 2));
+        view.Clear();
+        Assert.IsFalse(view.IsReadOnly);
+        Assert.IsFalse(view.AllowsDuplicates);
+        Assert.IsTrue(view.IsEmpty);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 3));
+        Assert.IsTrue(IC.eq(view));
+        view.Add(8);
+        Assert.IsFalse(view.IsEmpty);
+        Assert.IsFalse(view.AllowsDuplicates);
+        Assert.IsFalse(view.IsReadOnly);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 3));
+        Assert.IsTrue(IC.eq(view, 8));
+        view.Add(12);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 12, 3));
+        Assert.IsTrue(IC.eq(view, 8, 12));
+        view./*ViewOf(12).*/InsertLast(15);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 12, 15, 3));
+        Assert.IsTrue(IC.eq(view, 8, 12, 15));
+        view.ViewOf(12).InsertFirst(18);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 18, 12, 15, 3));
+        Assert.IsTrue(IC.eq(view, 8, 18, 12, 15));
+
+        HashedArrayList<int> lst2 = new HashedArrayList<int>();
+
+        lst2.Add(90); lst2.Add(92);
+        view.AddAll(lst2);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 18, 12, 15, 90, 92, 3));
+        Assert.IsTrue(IC.eq(view, 8, 18, 12, 15, 90, 92));
+        view.InsertLast(66);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 18, 12, 15, 90, 92, 66, 3));
+        Assert.IsTrue(IC.eq(view, 8, 18, 12, 15, 90, 92, 66));
+      }
+
+
+      [Test]
+      public void Bxxx()
+      {
+        Assert.IsTrue(IC.eq(view.Backwards(), 2, 1));
+        Assert.AreSame(list, view.Underlying);
+        Assert.IsNull(list.Underlying);
+        Assert.AreEqual(EnumerationDirection.Forwards, view.Direction);
+        Assert.AreEqual(EnumerationDirection.Backwards, view.Backwards().Direction);
+        Assert.AreEqual(0, list.Offset);
+        Assert.AreEqual(1, view.Offset);
+      }
+
+
+      [Test]
+      public void Contains()
+      {
+        Assert.IsTrue(view.Contains(1));
+        Assert.IsFalse(view.Contains(0));
+
+        HashedArrayList<int> lst2 = new HashedArrayList<int>();
+
+        lst2.Add(2);
+        Assert.IsTrue(view.ContainsAll(lst2));
+        lst2.Add(3);
+        Assert.IsFalse(view.ContainsAll(lst2));
+        Assert.AreEqual(Speed.Constant, view.ContainsSpeed);
+        Assert.AreEqual(2, view.Count);
+        view.Add(1);
+        Assert.AreEqual(1, view.ContainsCount(2));
+        Assert.AreEqual(1, view.ContainsCount(1));
+        Assert.AreEqual(2, view.Count);
+      }
+
+
+      [Test]
+      public void CreateView()
+      {
+        HashedArrayList<int> view2 = (HashedArrayList<int>)view.View(1, 0);
+
+        Assert.AreSame(list, view2.Underlying);
+      }
+
+
+      [Test]
+      public void FIFO()
+      {
+        Assert.IsFalse(view.FIFO);
+        view.FIFO = true;
+        view.Add(23); view.Add(24); view.Add(25);
+        check();
+        Assert.IsTrue(IC.eq(view, 1, 2, 23, 24, 25));
+        Assert.AreEqual(1, view.Remove());
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 23, 24, 25));
+        view.FIFO = false;
+        Assert.IsFalse(view.FIFO);
+        Assert.AreEqual(25, view.Remove());
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 23, 24));
+      }
+
+
+      [Test]
+      public void MapEtc()
+      {
+        HashedArrayList<double> dbl = (HashedArrayList<double>)view.Map(new Fun<int, double>(delegate(int i) { return i / 10.0; }));
+
+        Assert.IsTrue(dbl.Check());
+        Assert.AreEqual(0.1, dbl[0]);
+        Assert.AreEqual(0.2, dbl[1]);
+        for (int i = 0; i < 10; i++) view.Add(i);
+
+        HashedArrayList<int> list2 = (HashedArrayList<int>)view.FindAll(new Fun<int, bool>(delegate(int i) { return i % 4 == 1; }));
+
+        Assert.IsTrue(list2.Check());
+        Assert.IsTrue(IC.eq(list2, 1, 5, 9));
+      }
+
+
+      [Test]
+      public void FL()
+      {
+        Assert.AreEqual(1, view.First);
+        Assert.AreEqual(2, view.Last);
+      }
+
+
+      [Test]
+      public void Indexing()
+      {
+        list.Clear();
+        for (int i = 0; i < 20; i++) list.Add(i);
+
+        view = (HashedArrayList<int>)list.View(5, 7);
+        for (int i = 0; i < 7; i++) Assert.AreEqual(i + 5, view[i]);
+
+        for (int i = 0; i < 7; i++) Assert.AreEqual(i, view.IndexOf(i + 5));
+
+        for (int i = 0; i < 7; i++) Assert.AreEqual(i, view.LastIndexOf(i + 5));
+      }
+
+
+      [Test]
+      public void Insert()
+      {
+        view.Insert(0, 34);
+        view.Insert(1, 35);
+        view.Insert(4, 36);
+        Assert.IsTrue(view.Check());
+        Assert.IsTrue(IC.eq(view, 34, 35, 1, 2, 36));
+
+        IList<int> list2 = new HashedArrayList<int>();
+
+        list2.Add(40); list2.Add(41);
+        view.InsertAll(3, list2);
+        Assert.IsTrue(view.Check());
+        Assert.IsTrue(IC.eq(view, 34, 35, 1, 40, 41, 2, 36));
+      }
+
+
+      [Test]
+      public void Sort()
+      {
+        view.Add(45); view.Add(47); view.Add(46); view.Add(48);
+        Assert.IsFalse(view.IsSorted(new IC()));
+        view.Sort(new IC());
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 1, 2, 45, 46, 47, 48, 3));
+        Assert.IsTrue(IC.eq(view, 1, 2, 45, 46, 47, 48));
+      }
+
+
+      [Test]
+      public void Remove()
+      {
+        view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0);
+        Assert.IsTrue(IC.eq(view, 1, 2, 5));
+        Assert.IsTrue(view.Remove(1));
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 5));
+        Assert.IsFalse(view.Remove(1));
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 5));
+        Assert.IsFalse(view.Remove(0));
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 5));
+        view.RemoveAllCopies(3);
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 5));
+        Assert.IsTrue(IC.eq(list, 0, 2, 5, 3));
+        view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0);
+        Assert.IsTrue(IC.eq(view, 2, 5, 1));
+
+        HashedArrayList<int> l2 = new HashedArrayList<int>();
+
+        l2.Add(1); l2.Add(2); l2.Add(2); l2.Add(3); l2.Add(1);
+        view.RemoveAll(l2);
+        check();
+        Assert.IsTrue(IC.eq(view, 5));
+        view.RetainAll(l2);
+        check();
+        Assert.IsTrue(IC.eq(view));
+        view.Add(2); view.Add(4); view.Add(5);
+        Assert.AreEqual(2, view.RemoveAt(0));
+        Assert.AreEqual(5, view.RemoveAt(1));
+        Assert.AreEqual(4, view.RemoveAt(0));
+        check();
+        Assert.IsTrue(IC.eq(view));
+        view.Add(8); view.Add(6); view.Add(78);
+        Assert.AreEqual(8, view.RemoveFirst());
+        Assert.AreEqual(78, view.RemoveLast());
+        view.Add(2); view.Add(5); view.Add(3); view.Add(1);
+        view.RemoveInterval(1, 2);
+        check();
+        Assert.IsTrue(IC.eq(view, 6, 1));
+      }
+
+
+      [Test]
+      public void Reverse()
+      {
+        view.Clear();
+        for (int i = 0; i < 10; i++) view.Add(10 + i);
+
+        view.View(3, 4).Reverse();
+        check();
+        Assert.IsTrue(IC.eq(view, 10, 11, 12, 16, 15, 14, 13, 17, 18, 19));
+        view.Reverse();
+        Assert.IsTrue(IC.eq(view, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10));
+        Assert.IsTrue(IC.eq(list, 0, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10, 3));
+      }
+
+
+      [Test]
+      public void Slide()
+      {
+        view.Slide(1);
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 3));
+        view.Slide(-2);
+        check();
+        Assert.IsTrue(IC.eq(view, 0, 1));
+        view.Slide(0, 3);
+        check();
+        Assert.IsTrue(IC.eq(view, 0, 1, 2));
+        view.Slide(2, 1);
+        check();
+        Assert.IsTrue(IC.eq(view, 2));
+        view.Slide(-1, 0);
+        check();
+        Assert.IsTrue(IC.eq(view));
+        view.Add(28);
+        Assert.IsTrue(IC.eq(list, 0, 28, 1, 2, 3));
+      }
+      [Test]
+      public void Iterate()
+      {
+        list.Clear();
+        view = null;
+        foreach (int i in new int[] { 2, 4, 8, 13, 6, 1, 10, 11 }) list.Add(i);
+
+        view = (HashedArrayList<int>)list.View(list.Count - 2, 2);
+        int j = 666;
+        while (true)
+        {
+          //Console.WriteLine("View: {0}:  {1} --> {2}", view.Count, view.First, view.Last);
+          if ((view.Last - view.First) % 2 == 1)
+            view.Insert(1, j++);
+          check();
+          if (view.Offset == 0)
+            break;
+          else
+            view.Slide(-1, 2);
+        }
+        //foreach (int cell in list) Console.Write(" " + cell);
+        //Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 2, 4, 8, 668, 13, 6, 1, 667, 10, 666, 11));
+      }
+
+
+      [Test]
+      public void SyncRoot()
+      {
+        Assert.AreSame(((System.Collections.IList)view).SyncRoot, ((System.Collections.IList)list).SyncRoot);
+      }
+    }
+
+    [TestFixture]
+    public class MulipleViews
+    {
+      IList<int> list;
+      IList<int>[][] views;
+      [SetUp]
+      public void Init()
+      {
+        list = new HashedArrayList<int>();
+        for (int i = 0; i < 6; i++)
+          list.Add(i);
+        views = new IList<int>[7][];
+        for (int i = 0; i < 7; i++)
+        {
+          views[i] = new IList<int>[7 - i];
+          for (int j = 0; j < 7 - i; j++)
+            views[i][j] = list.View(i, j);
+        }
+      }
+      [TearDown]
+      public void Dispose()
+      {
+        list = null;
+        views = null;
+      }
+      [Test]
+      public void Insert()
+      {
+        Assert.IsTrue(list.Check(), "list check before insert");
+        list.Insert(3, 777);
+        Assert.IsTrue(list.Check(), "list check after insert");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i < 3 && i + j > 3 ? j + 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void RemoveAt()
+      {
+        Assert.IsTrue(list.Check(), "list check before remove");
+        list.RemoveAt(3);
+        Assert.IsTrue(list.Check(), "list check after remove");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i <= 3 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i <= 3 && i + j > 3 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+      [Test]
+      public void RemoveInterval()
+      {
+        Assert.IsTrue(list.Check(), "list check before remove");
+        list.RemoveInterval(3, 2);
+        Assert.IsTrue(list.Check(), "list check after remove");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i <= 3 ? i : i <= 5 ? 3 : i - 2, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(j == 0 ? 0 : i <= 3 && i + j > 4 ? j - 2 : i > 4 || i + j <= 3 ? j : j - 1, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+      [Test]
+      public void InsertAtEnd()
+      {
+        Assert.IsTrue(list.Check(), "list check before insert");
+        list.InsertLast(777);
+        Assert.IsTrue(list.Check(), "list check after insert");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void RemoveAtEnd()
+      {
+        Assert.IsTrue(list.Check(), "list check before remove");
+        list.RemoveAt(5);
+        Assert.IsTrue(list.Check(), "list check after remove");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i <= 5 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i <= 5 && i + j > 5 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void InsertAtStart()
+      {
+        Assert.IsTrue(list.Check(), "list check before insert");
+        list.Insert(0, 777);
+        Assert.IsTrue(list.Check(), "list check after insert");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i == 0 && j == 0 ? 0 : i + 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void RemoveAtStart()
+      {
+        Assert.IsTrue(list.Check(), "list check before remove");
+        list.RemoveAt(0);
+        Assert.IsTrue(list.Check(), "list check after remove");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i == 0 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i == 0 && j > 0 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void Clear()
+      {
+        Assert.IsTrue(list.Check(), "list check before clear");
+        //for (int i = 0; i < 7; i++)
+        //for (int j = 0; j < 7 - i; j++)
+        //Console.WriteLine("// view[{0}][{1}] : {2}", i, j, ((HashedArrayList<int>) views[i][j]).GetHashCode());
+        views[2][3].Clear();
+        Assert.IsTrue(list.Check(), "list check after clear");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i < 2 ? i : i < 6 ? 2 : i - 3, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(s(i, j), views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+      private int s(int i, int j)
+      {
+        if (j == 0) return 0;
+        int k = i + j - 1; //end
+        if (i > 4 || k <= 1) return j;
+        if (i >= 2) return k > 4 ? k - 4 : 0;
+        if (i <= 2) return k >= 4 ? j - 3 : 2 - i;
+        return -1;
+      }
+      [Test]
+      public void InsertAll()
+      {
+        IList<int> list2 = new HashedArrayList<int>();
+        for (int i = 0; i < 5; i++) { list2.Add(100 + i); }
+        Assert.IsTrue(list.Check(), "list check before insertAll");
+        list.InsertAll(3, list2);
+        Assert.IsTrue(list.Check(), "list check after insertAll");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 5, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i < 3 && i + j > 3 ? j + 5 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+      [Test]
+      public void AddAll()
+      {
+        IList<int> list2 = new HashedArrayList<int>();
+        for (int i = 0; i < 5; i++) { list2.Add(100 + i); }
+        Assert.IsTrue(list.Check(), "list check before AddAll");
+        list.View(1, 2).AddAll(list2);
+        Assert.IsTrue(list.Check(), "list check after AddAll");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 5, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i < 3 && i + j > 3 ? j + 5 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+      [Test]
+      public void Remove()
+      {
+        for (int i = 0; i < 7; i++)
+        {
+          for (int j = 0; j < 7 - i; j++)
+          {
+            list = new HashedArrayList<int>();
+            for (int k = 0; k < 6; k++) list.Add(k);
+            HashedArrayList<int> v = (HashedArrayList<int>)list.View(i, j);
+            list.Remove(3);
+            Assert.IsTrue(list.Check(), "list check after Remove, i=" + i + ", j=" + j);
+          }
+        }
+      }
+      [Test]
+      public void RemoveAll1()
+      {
+        IList<int> list2 = new HashedArrayList<int>();
+        list2.Add(1); list2.Add(3); list2.Add(4);
+
+        for (int i = 0; i < 7; i++)
+        {
+          for (int j = 0; j < 7 - i; j++)
+          {
+            list = new HashedArrayList<int>();
+            for (int k = 0; k < 6; k++) list.Add(k);
+            HashedArrayList<int> v = (HashedArrayList<int>)list.View(i, j);
+            list.RemoveAll(list2);
+            Assert.IsTrue(list.Check(), "list check after RemoveAll, i=" + i + ", j=" + j);
+          }
+        }
+      }
+      [Test]
+      public void RemoveAll2()
+      {
+        IList<int> list2 = new HashedArrayList<int>();
+        list2.Add(1); list2.Add(3); list2.Add(4);
+        Assert.IsTrue(list.Check(), "list check before RemoveAll");
+        list.RemoveAll(list2);
+
+        Assert.AreEqual(0, views[0][0].Offset, "view [0][0] offset");
+        Assert.AreEqual(0, views[0][1].Offset, "view [0][1] offset");
+        Assert.AreEqual(0, views[0][2].Offset, "view [0][2] offset");
+        Assert.AreEqual(0, views[0][3].Offset, "view [0][3] offset");
+        Assert.AreEqual(0, views[0][4].Offset, "view [0][4] offset");
+        Assert.AreEqual(0, views[0][5].Offset, "view [0][5] offset");
+        Assert.AreEqual(0, views[0][6].Offset, "view [0][6] offset");
+        Assert.AreEqual(1, views[1][0].Offset, "view [1][0] offset");
+        Assert.AreEqual(1, views[1][1].Offset, "view [1][1] offset");
+        Assert.AreEqual(1, views[1][2].Offset, "view [1][2] offset");
+        Assert.AreEqual(1, views[1][3].Offset, "view [1][3] offset");
+        Assert.AreEqual(1, views[1][4].Offset, "view [1][4] offset");
+        Assert.AreEqual(1, views[1][5].Offset, "view [1][5] offset");
+        Assert.AreEqual(1, views[2][0].Offset, "view [2][0] offset");
+        Assert.AreEqual(1, views[2][1].Offset, "view [2][1] offset");
+        Assert.AreEqual(1, views[2][2].Offset, "view [2][2] offset");
+        Assert.AreEqual(1, views[2][3].Offset, "view [2][3] offset");
+        Assert.AreEqual(1, views[2][4].Offset, "view [2][4] offset");
+        Assert.AreEqual(2, views[3][0].Offset, "view [3][0] offset");
+        Assert.AreEqual(2, views[3][1].Offset, "view [3][1] offset");
+        Assert.AreEqual(2, views[3][2].Offset, "view [3][2] offset");
+        Assert.AreEqual(2, views[3][3].Offset, "view [3][3] offset");
+        Assert.AreEqual(2, views[4][0].Offset, "view [4][0] offset");
+        Assert.AreEqual(2, views[4][1].Offset, "view [4][1] offset");
+        Assert.AreEqual(2, views[4][2].Offset, "view [4][2] offset");
+        Assert.AreEqual(2, views[5][0].Offset, "view [5][0] offset");
+        Assert.AreEqual(2, views[5][1].Offset, "view [5][1] offset");
+        Assert.AreEqual(3, views[6][0].Offset, "view [6][0] offset");
+
+        Assert.AreEqual(0, views[0][0].Count, "view [0][0] count");
+        Assert.AreEqual(1, views[0][1].Count, "view [0][1] count");
+        Assert.AreEqual(1, views[0][2].Count, "view [0][2] count");
+        Assert.AreEqual(2, views[0][3].Count, "view [0][3] count");
+        Assert.AreEqual(2, views[0][4].Count, "view [0][4] count");
+        Assert.AreEqual(2, views[0][5].Count, "view [0][5] count");
+        Assert.AreEqual(3, views[0][6].Count, "view [0][6] count");
+        Assert.AreEqual(0, views[1][0].Count, "view [1][0] count");
+        Assert.AreEqual(0, views[1][1].Count, "view [1][1] count");
+        Assert.AreEqual(1, views[1][2].Count, "view [1][2] count");
+        Assert.AreEqual(1, views[1][3].Count, "view [1][3] count");
+        Assert.AreEqual(1, views[1][4].Count, "view [1][4] count");
+        Assert.AreEqual(2, views[1][5].Count, "view [1][5] count");
+        Assert.AreEqual(0, views[2][0].Count, "view [2][0] count");
+        Assert.AreEqual(1, views[2][1].Count, "view [2][1] count");
+        Assert.AreEqual(1, views[2][2].Count, "view [2][2] count");
+        Assert.AreEqual(1, views[2][3].Count, "view [2][3] count");
+        Assert.AreEqual(2, views[2][4].Count, "view [2][4] count");
+        Assert.AreEqual(0, views[3][0].Count, "view [3][0] count");
+        Assert.AreEqual(0, views[3][1].Count, "view [3][1] count");
+        Assert.AreEqual(0, views[3][2].Count, "view [3][2] count");
+        Assert.AreEqual(1, views[3][3].Count, "view [3][3] count");
+        Assert.AreEqual(0, views[4][0].Count, "view [4][0] count");
+        Assert.AreEqual(0, views[4][1].Count, "view [4][1] count");
+        Assert.AreEqual(1, views[4][2].Count, "view [4][2] count");
+        Assert.AreEqual(0, views[5][0].Count, "view [5][0] count");
+        Assert.AreEqual(1, views[5][1].Count, "view [5][1] count");
+        Assert.AreEqual(0, views[6][0].Count, "view [6][0] count");
+
+        Assert.IsTrue(list.Check(), "list check after RemoveAll");
+      }
+
+      [Test]
+      public void RetainAll()
+      {
+        IList<int> list2 = new HashedArrayList<int>();
+        list2.Add(2); list2.Add(4); list2.Add(5);
+        Assert.IsTrue(list.Check(), "list check before RetainAll");
+        list.RetainAll(list2);
+        Assert.AreEqual(0, views[0][0].Offset, "view [0][0] offset");
+        Assert.AreEqual(0, views[0][1].Offset, "view [0][1] offset");
+        Assert.AreEqual(0, views[0][2].Offset, "view [0][2] offset");
+        Assert.AreEqual(0, views[0][3].Offset, "view [0][3] offset");
+        Assert.AreEqual(0, views[0][4].Offset, "view [0][4] offset");
+        Assert.AreEqual(0, views[0][5].Offset, "view [0][5] offset");
+        Assert.AreEqual(0, views[0][6].Offset, "view [0][6] offset");
+        Assert.AreEqual(0, views[1][0].Offset, "view [1][0] offset");
+        Assert.AreEqual(0, views[1][1].Offset, "view [1][1] offset");
+        Assert.AreEqual(0, views[1][2].Offset, "view [1][2] offset");
+        Assert.AreEqual(0, views[1][3].Offset, "view [1][3] offset");
+        Assert.AreEqual(0, views[1][4].Offset, "view [1][4] offset");
+        Assert.AreEqual(0, views[1][5].Offset, "view [1][5] offset");
+        Assert.AreEqual(0, views[2][0].Offset, "view [2][0] offset");
+        Assert.AreEqual(0, views[2][1].Offset, "view [2][1] offset");
+        Assert.AreEqual(0, views[2][2].Offset, "view [2][2] offset");
+        Assert.AreEqual(0, views[2][3].Offset, "view [2][3] offset");
+        Assert.AreEqual(0, views[2][4].Offset, "view [2][4] offset");
+        Assert.AreEqual(1, views[3][0].Offset, "view [3][0] offset");
+        Assert.AreEqual(1, views[3][1].Offset, "view [3][1] offset");
+        Assert.AreEqual(1, views[3][2].Offset, "view [3][2] offset");
+        Assert.AreEqual(1, views[3][3].Offset, "view [3][3] offset");
+        Assert.AreEqual(1, views[4][0].Offset, "view [4][0] offset");
+        Assert.AreEqual(1, views[4][1].Offset, "view [4][1] offset");
+        Assert.AreEqual(1, views[4][2].Offset, "view [4][2] offset");
+        Assert.AreEqual(2, views[5][0].Offset, "view [5][0] offset");
+        Assert.AreEqual(2, views[5][1].Offset, "view [5][1] offset");
+        Assert.AreEqual(3, views[6][0].Offset, "view [6][0] offset");
+
+        Assert.AreEqual(0, views[0][0].Count, "view [0][0] count");
+        Assert.AreEqual(0, views[0][1].Count, "view [0][1] count");
+        Assert.AreEqual(0, views[0][2].Count, "view [0][2] count");
+        Assert.AreEqual(1, views[0][3].Count, "view [0][3] count");
+        Assert.AreEqual(1, views[0][4].Count, "view [0][4] count");
+        Assert.AreEqual(2, views[0][5].Count, "view [0][5] count");
+        Assert.AreEqual(3, views[0][6].Count, "view [0][6] count");
+        Assert.AreEqual(0, views[1][0].Count, "view [1][0] count");
+        Assert.AreEqual(0, views[1][1].Count, "view [1][1] count");
+        Assert.AreEqual(1, views[1][2].Count, "view [1][2] count");
+        Assert.AreEqual(1, views[1][3].Count, "view [1][3] count");
+        Assert.AreEqual(2, views[1][4].Count, "view [1][4] count");
+        Assert.AreEqual(3, views[1][5].Count, "view [1][5] count");
+        Assert.AreEqual(0, views[2][0].Count, "view [2][0] count");
+        Assert.AreEqual(1, views[2][1].Count, "view [2][1] count");
+        Assert.AreEqual(1, views[2][2].Count, "view [2][2] count");
+        Assert.AreEqual(2, views[2][3].Count, "view [2][3] count");
+        Assert.AreEqual(3, views[2][4].Count, "view [2][4] count");
+        Assert.AreEqual(0, views[3][0].Count, "view [3][0] count");
+        Assert.AreEqual(0, views[3][1].Count, "view [3][1] count");
+        Assert.AreEqual(1, views[3][2].Count, "view [3][2] count");
+        Assert.AreEqual(2, views[3][3].Count, "view [3][3] count");
+        Assert.AreEqual(0, views[4][0].Count, "view [4][0] count");
+        Assert.AreEqual(1, views[4][1].Count, "view [4][1] count");
+        Assert.AreEqual(2, views[4][2].Count, "view [4][2] count");
+        Assert.AreEqual(0, views[5][0].Count, "view [5][0] count");
+        Assert.AreEqual(1, views[5][1].Count, "view [5][1] count");
+        Assert.AreEqual(0, views[6][0].Count, "view [6][0] count");
+
+        Assert.IsTrue(list.Check(), "list check after RetainAll");
+      }
+
+      [Test]
+      public void RemoveAllCopies()
+      {
+        IList<int> list2 = new HashedArrayList<int>();
+        list2.Add(0); list2.Add(2); list2.Add(82); list2.Add(92); list2.Add(5); list2.Add(2); list2.Add(1);
+        for (int i = 0; i < 7; i++)
+        {
+          for (int j = 0; j < 7 - i; j++)
+          {
+            list = new HashedArrayList<int>();
+            list.AddAll(list2);
+            HashedArrayList<int> v = (HashedArrayList<int>)list.View(i, j);
+            list.RemoveAllCopies(2);
+            Assert.IsTrue(list.Check(), "list check after RemoveAllCopies, i=" + i + ", j=" + j);
+          }
+        }
+      }
+
+      private void checkDisposed(bool reverse, int start, int count)
+      {
+        int k = 0;
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            if (i + j <= start || i >= start + count || (i <= start && i + j >= start + count) || (reverse && start <= i && start + count >= i + j))
+            {
+              try
+              {
+                k = views[i][j].Count;
+              }
+              catch (ViewDisposedException)
+              {
+                Assert.Fail("view[" + i + "][" + j + "] threw");
+              }
+              Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] size");
+              if (reverse && ((j > 0 && start <= i && start + count >= i + j) || (j == 0 && start < i && start + count > i)))
+                Assert.AreEqual(start + (start + count - i - j), views[i][j].Offset, "view[" + i + "][" + j + "] offset (mirrored)");
+              else
+                Assert.AreEqual(i, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            }
+            else
+            {
+              try
+              {
+                k = views[i][j].Count;
+                Assert.Fail("view[" + i + "][" + j + "] no throw");
+              }
+              catch (ViewDisposedException) { }
+            }
+          }
+      }
+
+      [Test]
+      public void Reverse()
+      {
+        int start = 2, count = 3;
+        IList<int> list2 = list.View(start, count);
+        Assert.IsTrue(list.Check(), "list check before Reverse");
+        list2.Reverse();
+        Assert.IsTrue(list.Check(), "list check after Reverse");
+        checkDisposed(true, start, count);
+      }
+
+      [Test]
+      public void Sort()
+      {
+        int start = 2, count = 3;
+        IList<int> list2 = list.View(start, count);
+        Assert.IsTrue(list.Check(), "list check before Sort");
+        list2.Sort();
+        Assert.IsTrue(list.Check(), "list check after Sort");
+        checkDisposed(false, start, count);
+      }
+      [Test]
+      public void Shuffle()
+      {
+        int start = 2, count = 3;
+        IList<int> list2 = list.View(start, count);
+        Assert.IsTrue(list.Check(), "list check before Shuffle");
+        list2.Shuffle();
+        Assert.IsTrue(list.Check(), "list check after Shuffle");
+        checkDisposed(false, start, count);
+      }
+
+
+    }
+
+  }
+
+  namespace HashingAndEquals
+  {
+    [TestFixture]
+    public class IIndexed
+    {
+      private ISequenced<int> dit, dat, dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashedArrayList<int>();
+        dat = new HashedArrayList<int>();
+        dut = new HashedArrayList<int>();
+      }
+
+
+      [Test]
+      public void EmptyEmpty()
+      {
+        Assert.IsTrue(dit.SequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void EmptyNonEmpty()
+      {
+        dit.Add(3);
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsFalse(dat.SequencedEquals(dit));
+      }
+
+      [Test]
+      public void HashVal()
+      {
+        Assert.AreEqual(CHC.sequencedhashcode(), dit.GetSequencedHashCode());
+        dit.Add(3);
+        Assert.AreEqual(CHC.sequencedhashcode(3), dit.GetSequencedHashCode());
+        dit.Add(7);
+        Assert.AreEqual(CHC.sequencedhashcode(3, 7), dit.GetSequencedHashCode());
+        Assert.AreEqual(CHC.sequencedhashcode(), dut.GetSequencedHashCode());
+        dut.Add(7);
+        Assert.AreEqual(CHC.sequencedhashcode(7), dut.GetSequencedHashCode());
+        dut.Add(3);
+        Assert.AreEqual(CHC.sequencedhashcode(7, 3), dut.GetSequencedHashCode());
+      }
+
+
+      [Test]
+      public void EqualHashButDifferent()
+      {
+        dit.Add(0); dit.Add(31);
+        dat.Add(1); dat.Add(0);
+        Assert.AreEqual(dit.GetSequencedHashCode(), dat.GetSequencedHashCode());
+        Assert.IsFalse(dit.SequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void Normal()
+      {
+        dit.Add(3);
+        dit.Add(7);
+        dat.Add(3);
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsFalse(dat.SequencedEquals(dit));
+        dat.Add(7);
+        Assert.IsTrue(dit.SequencedEquals(dat));
+        Assert.IsTrue(dat.SequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void WrongOrder()
+      {
+        dit.Add(3);
+        dut.Add(3);
+        Assert.IsTrue(dit.SequencedEquals(dut));
+        Assert.IsTrue(dut.SequencedEquals(dit));
+        dit.Add(7);
+        ((HashedArrayList<int>)dut).InsertFirst(7);
+        Assert.IsFalse(dit.SequencedEquals(dut));
+        Assert.IsFalse(dut.SequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void Reflexive()
+      {
+        Assert.IsTrue(dit.SequencedEquals(dit));
+        dit.Add(3);
+        Assert.IsTrue(dit.SequencedEquals(dit));
+        dit.Add(7);
+        Assert.IsTrue(dit.SequencedEquals(dit));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+        dat = null;
+        dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class IEditableCollection
+    {
+      private ICollection<int> dit, dat, dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashedArrayList<int>();
+        dat = new HashedArrayList<int>();
+        dut = new HashedArrayList<int>();
+      }
+
+
+      [Test]
+      public void EmptyEmpty()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void EmptyNonEmpty()
+      {
+        dit.Add(3);
+        Assert.IsFalse(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dat.UnsequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void HashVal()
+      {
+        Assert.AreEqual(CHC.unsequencedhashcode(), dit.GetUnsequencedHashCode());
+        dit.Add(3);
+        Assert.AreEqual(CHC.unsequencedhashcode(3), dit.GetUnsequencedHashCode());
+        dit.Add(7);
+        Assert.AreEqual(CHC.unsequencedhashcode(3, 7), dit.GetUnsequencedHashCode());
+        Assert.AreEqual(CHC.unsequencedhashcode(), dut.GetUnsequencedHashCode());
+        dut.Add(3);
+        Assert.AreEqual(CHC.unsequencedhashcode(3), dut.GetUnsequencedHashCode());
+        dut.Add(7);
+        Assert.AreEqual(CHC.unsequencedhashcode(7, 3), dut.GetUnsequencedHashCode());
+      }
+
+
+      [Test]
+      public void EqualHashButDifferent()
+      {
+        dit.Add(-1657792980); dit.Add(-1570288808);
+        dat.Add(1862883298); dat.Add(-272461342);
+        Assert.AreEqual(dit.GetUnsequencedHashCode(), dat.GetUnsequencedHashCode());
+        Assert.IsFalse(dit.UnsequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void Normal()
+      {
+        dit.Add(3);
+        dit.Add(7);
+        dat.Add(3);
+        Assert.IsFalse(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dat.UnsequencedEquals(dit));
+        dat.Add(7);
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsTrue(dat.UnsequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void WrongOrder()
+      {
+        dit.Add(3);
+        dut.Add(3);
+        Assert.IsTrue(dit.UnsequencedEquals(dut));
+        Assert.IsTrue(dut.UnsequencedEquals(dit));
+        dit.Add(7);
+        dut.Add(7);
+        Assert.IsTrue(dit.UnsequencedEquals(dut));
+        Assert.IsTrue(dut.UnsequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void Reflexive()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dit));
+        dit.Add(3);
+        Assert.IsTrue(dit.UnsequencedEquals(dit));
+        dit.Add(7);
+        Assert.IsTrue(dit.UnsequencedEquals(dit));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+        dat = null;
+        dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelUnorderedOfUnOrdered
+    {
+      private ICollection<int> dit, dat, dut;
+
+      private ICollection<ICollection<int>> Dit, Dat, Dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashedArrayList<int>();
+        dat = new HashedArrayList<int>();
+        dut = new HashedArrayList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        Dit = new HashedArrayList<ICollection<int>>();
+        Dat = new HashedArrayList<ICollection<int>>();
+        Dut = new HashedArrayList<ICollection<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dit.UnsequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Assert.IsTrue(Dit.UnsequencedEquals(Dat));
+        Assert.IsFalse(Dit.UnsequencedEquals(Dut));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = null;
+        Dit = Dat = Dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelOrderedOfUnOrdered
+    {
+      private ICollection<int> dit, dat, dut;
+
+      private ISequenced<ICollection<int>> Dit, Dat, Dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashedArrayList<int>();
+        dat = new HashedArrayList<int>();
+        dut = new HashedArrayList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        Dit = new HashedArrayList<ICollection<int>>();
+        Dat = new HashedArrayList<ICollection<int>>();
+        Dut = new HashedArrayList<ICollection<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dit.UnsequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Dut.Add(dit); Dut.Add(dut); Dut.Add(dat);
+        Assert.IsFalse(Dit.SequencedEquals(Dat));
+        Assert.IsTrue(Dit.SequencedEquals(Dut));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = null;
+        Dit = Dat = Dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelUnOrderedOfOrdered
+    {
+      private ISequenced<int> dit, dat, dut, dot;
+
+      private ICollection<ISequenced<int>> Dit, Dat, Dut, Dot;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashedArrayList<int>();
+        dat = new HashedArrayList<int>();
+        dut = new HashedArrayList<int>();
+        dot = new HashedArrayList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        dot.Add(2); dot.Add(1);
+        Dit = new HashedArrayList<ISequenced<int>>();
+        Dat = new HashedArrayList<ISequenced<int>>();
+        Dut = new HashedArrayList<ISequenced<int>>();
+        Dot = new HashedArrayList<ISequenced<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsTrue(dit.SequencedEquals(dot));
+        Assert.IsFalse(dit.SequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Dut.Add(dot); Dut.Add(dut); Dut.Add(dit);
+        Dot.Add(dit); Dot.Add(dit); Dot.Add(dut);
+        Assert.IsTrue(Dit.UnsequencedEquals(Dut));
+        Assert.IsFalse(Dit.UnsequencedEquals(Dat));
+        Assert.IsTrue(Dit.UnsequencedEquals(Dot));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = dot = null;
+        Dit = Dat = Dut = Dot = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelOrderedOfOrdered
+    {
+      private ISequenced<int> dit, dat, dut, dot;
+
+      private ISequenced<ISequenced<int>> Dit, Dat, Dut, Dot;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashedArrayList<int>();
+        dat = new HashedArrayList<int>();
+        dut = new HashedArrayList<int>();
+        dot = new HashedArrayList<int>();
+        dit.Add(2); dit.Add(1); //{2,1}
+        dat.Add(1); dat.Add(2); //{1,2}
+        dut.Add(3);            //{3}
+        dot.Add(2); dot.Add(1); //{2,1}
+        Dit = new HashedArrayList<ISequenced<int>>();
+        Dat = new HashedArrayList<ISequenced<int>>();
+        Dut = new HashedArrayList<ISequenced<int>>();
+        Dot = new HashedArrayList<ISequenced<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsTrue(dit.SequencedEquals(dot));
+        Assert.IsFalse(dit.SequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit); // {{2,1},{3}}
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); // {{3},{2,1},{1,2}}
+        Dut.Add(dot); Dut.Add(dut); Dut.Add(dit); // {{2,1},{3}}
+        Dot.Add(dit); Dot.Add(dit); Dot.Add(dut); // {{2,1},{3}}
+        Assert.IsTrue(Dit.SequencedEquals(Dut));
+        Assert.IsFalse(Dit.SequencedEquals(Dat));
+        Assert.IsTrue(Dit.SequencedEquals(Dot));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = dot = null;
+        Dit = Dat = Dut = Dot = null;
+      }
+    }
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/arrays/SortedArrayTests.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/arrays/SortedArrayTests.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/arrays/SortedArrayTests.cs	(revision 3)
@@ -0,0 +1,2492 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+namespace C5UnitTests.arrays.sorted
+{
+  using CollectionOfInt = SortedArray<int>;
+
+  [TestFixture]
+  public class GenericTesters
+  {
+    [Test]
+    public void TestEvents()
+    {
+      Fun<CollectionOfInt> factory = delegate() { return new CollectionOfInt(TenEqualityComparer.Default); };
+      new C5UnitTests.Templates.Events.SortedIndexedTester<CollectionOfInt>().Test(factory);
+    }
+
+    [Test]
+    public void Extensible()
+    {
+      C5UnitTests.Templates.Extensible.Clone.Tester<CollectionOfInt>();
+      C5UnitTests.Templates.Extensible.Serialization.Tester<CollectionOfInt>();
+    }
+  }
+
+  static class Factory
+  {
+    public static ICollection<T> New<T>() { return new SortedArray<T>(); }
+  }
+
+
+  [TestFixture]
+  public class Formatting
+  {
+    ICollection<int> coll;
+    IFormatProvider rad16;
+    [SetUp]
+    public void Init() { coll = Factory.New<int>(); rad16 = new RadixFormatProvider(16); }
+    [TearDown]
+    public void Dispose() { coll = null; rad16 = null; }
+    [Test]
+    public void Format()
+    {
+      Assert.AreEqual("{  }", coll.ToString());
+      coll.AddAll<int>(new int[] { -4, 28, 129, 65530 });
+      Assert.AreEqual("{ -4, 28, 129, 65530 }", coll.ToString());
+      Assert.AreEqual("{ -4, 1C, 81, FFFA }", coll.ToString(null, rad16));
+      Assert.AreEqual("{ -4, 28, 129... }", coll.ToString("L14", null));
+      Assert.AreEqual("{ -4, 1C, 81... }", coll.ToString("L14", rad16));
+    }
+  }
+
+  [TestFixture]
+  public class Ranges
+	{
+		private SortedArray<int> array;
+
+		private SCG.IComparer<int> c;
+
+
+		[SetUp]
+		public void Init()
+		{
+			c = new IC();
+			array = new SortedArray<int>(c);
+			for (int i = 1; i <= 10; i++)
+			{
+				array.Add(i * 2);
+			}
+		}
+
+
+		[Test]
+		public void Enumerator()
+		{
+			SCG.IEnumerator<int> e = array.RangeFromTo(5, 17).GetEnumerator();
+			int i = 3;
+
+			while (e.MoveNext())
+			{
+				Assert.AreEqual(2 * i++, e.Current);
+			}
+
+			Assert.AreEqual(9, i);
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(CollectionModifiedException))]
+		public void Enumerator3()
+		{
+			SCG.IEnumerator<int> e = array.RangeFromTo(5, 17).GetEnumerator();
+
+			e.MoveNext();
+			array.Add(67);
+			e.MoveNext();
+		}
+
+
+		[Test]
+		public void Remove()
+		{
+			int[] all = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
+
+			array.RemoveRangeFrom(18);
+			Assert.IsTrue(IC.eq(array, new int[] { 2, 4, 6, 8, 10, 12, 14, 16 }));
+			array.RemoveRangeFrom(28);
+			Assert.IsTrue(IC.eq(array, new int[] { 2, 4, 6, 8, 10, 12, 14, 16 }));
+			array.RemoveRangeFrom(13);
+			Assert.IsTrue(IC.eq(array, new int[] { 2, 4, 6, 8, 10, 12 }));
+			array.RemoveRangeFrom(2);
+			Assert.IsTrue(IC.eq(array));
+			foreach (int i in all) array.Add(i);
+
+			array.RemoveRangeTo(10);
+			Assert.IsTrue(IC.eq(array, new int[] { 10, 12, 14, 16, 18, 20 }));
+			array.RemoveRangeTo(2);
+			Assert.IsTrue(IC.eq(array, new int[] { 10, 12, 14, 16, 18, 20 }));
+			array.RemoveRangeTo(21);
+			Assert.IsTrue(IC.eq(array));
+			foreach (int i in all) array.Add(i);
+
+			array.RemoveRangeFromTo(4, 8);
+			Assert.IsTrue(IC.eq(array, 2, 8, 10, 12, 14, 16, 18, 20));
+			array.RemoveRangeFromTo(14, 28);
+			Assert.IsTrue(IC.eq(array, 2, 8, 10, 12));
+			array.RemoveRangeFromTo(0, 9);
+			Assert.IsTrue(IC.eq(array, 10, 12));
+			array.RemoveRangeFromTo(0, 81);
+			Assert.IsTrue(IC.eq(array));
+		}
+
+		[Test]
+		public void Normal()
+		{
+			int[] all = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
+
+			Assert.IsTrue(IC.eq(array, all));
+			Assert.IsTrue(IC.eq(array.RangeAll(), all));
+			Assert.AreEqual(10, array.RangeAll().Count);
+			Assert.IsTrue(IC.eq(array.RangeFrom(11), new int[] { 12, 14, 16, 18, 20 }));
+			Assert.AreEqual(5, array.RangeFrom(11).Count);
+			Assert.IsTrue(IC.eq(array.RangeFrom(12), new int[] { 12, 14, 16, 18, 20 }));
+			Assert.IsTrue(IC.eq(array.RangeFrom(2), all));
+			Assert.IsTrue(IC.eq(array.RangeFrom(1), all));
+			Assert.IsTrue(IC.eq(array.RangeFrom(21), new int[] { }));
+			Assert.IsTrue(IC.eq(array.RangeFrom(20), new int[] { 20 }));
+			Assert.IsTrue(IC.eq(array.RangeTo(8), new int[] { 2, 4, 6 }));
+			Assert.IsTrue(IC.eq(array.RangeTo(7), new int[] { 2, 4, 6 }));
+			Assert.AreEqual(3, array.RangeTo(7).Count);
+			Assert.IsTrue(IC.eq(array.RangeTo(2), new int[] { }));
+			Assert.IsTrue(IC.eq(array.RangeTo(1), new int[] {  }));
+			Assert.IsTrue(IC.eq(array.RangeTo(3), new int[] { 2 }));
+			Assert.IsTrue(IC.eq(array.RangeTo(20), new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18 }));
+			Assert.IsTrue(IC.eq(array.RangeTo(21), all));
+			Assert.IsTrue(IC.eq(array.RangeFromTo(7, 12), new int[] { 8, 10 }));
+			Assert.IsTrue(IC.eq(array.RangeFromTo(6, 11), new int[] { 6, 8, 10 }));
+			Assert.IsTrue(IC.eq(array.RangeFromTo(1, 12), new int[] { 2, 4, 6, 8, 10 }));
+			Assert.AreEqual(5, array.RangeFromTo(1, 12).Count);
+			Assert.IsTrue(IC.eq(array.RangeFromTo(2, 12), new int[] { 2, 4, 6, 8, 10 }));
+			Assert.IsTrue(IC.eq(array.RangeFromTo(6, 21), new int[] { 6, 8, 10, 12, 14, 16, 18, 20 }));
+			Assert.IsTrue(IC.eq(array.RangeFromTo(6, 20), new int[] { 6, 8, 10, 12, 14, 16, 18 }));
+		}
+
+
+		[Test]
+		public void Backwards()
+		{
+			int[] all = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
+			int[] lla = new int[] { 20, 18, 16, 14, 12, 10, 8, 6, 4, 2 };
+
+			Assert.IsTrue(IC.eq(array, all));
+			Assert.IsTrue(IC.eq(array.RangeAll().Backwards(), lla));
+			Assert.IsTrue(IC.eq(array.RangeFrom(11).Backwards(), new int[] { 20, 18, 16, 14, 12 }));
+            Assert.IsTrue(IC.eq(array.RangeFrom(12).Backwards(), new int[] { 20, 18, 16, 14, 12 }));
+			Assert.IsTrue(IC.eq(array.RangeFrom(2).Backwards(), lla));
+			Assert.IsTrue(IC.eq(array.RangeFrom(1).Backwards(), lla));
+			Assert.IsTrue(IC.eq(array.RangeFrom(21).Backwards(), new int[] { }));
+			Assert.IsTrue(IC.eq(array.RangeFrom(20).Backwards(), new int[] { 20 }));
+			Assert.IsTrue(IC.eq(array.RangeTo(8).Backwards(), new int[] { 6, 4, 2 }));
+			Assert.IsTrue(IC.eq(array.RangeTo(7).Backwards(), new int[] { 6, 4, 2 }));
+			Assert.IsTrue(IC.eq(array.RangeTo(2).Backwards(), new int[] { }));
+			Assert.IsTrue(IC.eq(array.RangeTo(1).Backwards(), new int[] {  }));
+			Assert.IsTrue(IC.eq(array.RangeTo(3).Backwards(), new int[] { 2 }));
+			Assert.IsTrue(IC.eq(array.RangeTo(20).Backwards(), new int[] { 18, 16, 14, 12, 10, 8, 6, 4, 2}));
+			Assert.IsTrue(IC.eq(array.RangeTo(21).Backwards(), lla));
+			Assert.IsTrue(IC.eq(array.RangeFromTo(7, 12).Backwards(), new int[] { 10, 8 }));
+			Assert.IsTrue(IC.eq(array.RangeFromTo(6, 11).Backwards(), new int[] { 10, 8, 6 }));
+			Assert.IsTrue(IC.eq(array.RangeFromTo(1, 12).Backwards(), new int[] { 10, 8, 6, 4, 2 }));
+			Assert.IsTrue(IC.eq(array.RangeFromTo(2, 12).Backwards(), new int[] { 10, 8, 6, 4, 2 }));
+			Assert.IsTrue(IC.eq(array.RangeFromTo(6, 21).Backwards(), new int[] { 20, 18, 16, 14, 12, 10, 8, 6 }));
+			Assert.IsTrue(IC.eq(array.RangeFromTo(6, 20).Backwards(), new int[] { 18, 16, 14, 12, 10, 8, 6 }));
+		}
+
+		[Test]
+		public void Direction()
+		{
+			Assert.AreEqual(EnumerationDirection.Forwards, array.Direction);
+			Assert.AreEqual(EnumerationDirection.Forwards, array.RangeFrom(20).Direction);
+			Assert.AreEqual(EnumerationDirection.Forwards, array.RangeTo(7).Direction);
+			Assert.AreEqual(EnumerationDirection.Forwards, array.RangeFromTo(1, 12).Direction);
+			Assert.AreEqual(EnumerationDirection.Forwards, array.RangeAll().Direction);
+			Assert.AreEqual(EnumerationDirection.Backwards, array.Backwards().Direction);
+			Assert.AreEqual(EnumerationDirection.Backwards, array.RangeFrom(20).Backwards().Direction);
+			Assert.AreEqual(EnumerationDirection.Backwards, array.RangeTo(7).Backwards().Direction);
+			Assert.AreEqual(EnumerationDirection.Backwards, array.RangeFromTo(1, 12).Backwards().Direction);
+			Assert.AreEqual(EnumerationDirection.Backwards, array.RangeAll().Backwards().Direction);
+		}
+
+
+		[TearDown]
+		public void Dispose()
+		{
+			array = null;
+			c = null;
+		}
+	}
+
+	[TestFixture]
+	public class BagItf
+	{
+		private SortedArray<int> array;
+
+
+		[SetUp]
+		public void Init()
+		{
+			array = new SortedArray<int>(new IC());
+			for (int i = 10; i < 20; i++)
+			{
+				array.Add(i);
+				array.Add(i + 10);
+			}
+		}
+
+
+		[Test]
+		public void Both()
+		{
+			Assert.AreEqual(0, array.ContainsCount(7));
+			Assert.AreEqual(1, array.ContainsCount(10));
+			array.RemoveAllCopies(10);
+			Assert.AreEqual(0, array.ContainsCount(10));
+			array.RemoveAllCopies(7);
+		}
+
+
+		[TearDown]
+		public void Dispose()
+		{
+			array = null;
+		}
+	}
+
+
+	[TestFixture]
+	public class Div
+	{
+		private SortedArray<int> array;
+
+
+		[SetUp]
+		public void Init()
+		{
+			array = new SortedArray<int>(new IC());
+		}
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor1()
+    {
+      new SortedArray<int>(null);
+    }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor2()
+    {
+      new SortedArray<int>(5, null);
+    }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor3()
+    {
+      new SortedArray<int>(5, null, EqualityComparer<int>.Default);
+    }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor4()
+    {
+      new SortedArray<int>(5, Comparer<int>.Default, null);
+    }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor5()
+    {
+      new SortedArray<int>(5, null, null);
+    }
+
+    [Test]
+    public void Choose()
+    {
+      array.Add(7);
+      Assert.AreEqual(7, array.Choose());
+    }
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void BadChoose()
+    {
+      array.Choose();
+    }
+
+
+
+    private void loadup()
+		{
+			for (int i = 10; i < 20; i++)
+			{
+				array.Add(i);
+				array.Add(i + 10);
+			}
+		}
+
+
+		[Test]
+		public void NoDuplicatesEtc()
+		{
+			Assert.IsFalse(array.AllowsDuplicates);
+			loadup();
+			Assert.IsFalse(array.AllowsDuplicates);
+			Assert.AreEqual(Speed.Log, array.ContainsSpeed);
+			Assert.IsTrue(array.Comparer.Compare(2, 3) < 0);
+            Assert.IsTrue(array.Comparer.Compare(4, 3) > 0);
+            Assert.IsTrue(array.Comparer.Compare(3, 3) == 0);
+        }
+
+		[Test]
+		public void Add()
+		{
+			Assert.IsTrue(array.Add(17));
+			Assert.IsFalse(array.Add(17));
+			Assert.IsTrue(array.Add(18));
+			Assert.IsFalse(array.Add(18));
+			Assert.AreEqual(2, array.Count);
+		}
+
+
+		[TearDown]
+		public void Dispose()
+		{
+			array = null;
+		}
+	}
+
+
+	[TestFixture]
+	public class FindOrAdd
+	{
+		private SortedArray<KeyValuePair<int,string>> bag;
+
+
+		[SetUp]
+		public void Init()
+		{
+			bag = new SortedArray<KeyValuePair<int,string>>(new KeyValuePairComparer<int,string>(new IC()));
+		}
+
+
+		[TearDown]
+		public void Dispose()
+		{
+			bag = null;
+		}
+
+
+		[Test]
+		public void Test()
+		{
+			KeyValuePair<int,string> p = new KeyValuePair<int,string>(3, "tre");
+
+			Assert.IsFalse(bag.FindOrAdd(ref p));
+			p.Value = "drei";
+			Assert.IsTrue(bag.FindOrAdd(ref p));
+			Assert.AreEqual("tre", p.Value);
+			p.Value = "three";
+			Assert.AreEqual(1, bag.ContainsCount(p));
+			Assert.AreEqual("tre", bag[0].Value);
+		}
+	}
+
+  [TestFixture]
+  public class FindPredicate
+  {
+    private SortedArray<int> list;
+    Fun<int, bool> pred;
+
+    [SetUp]
+    public void Init()
+    {
+      list = new SortedArray<int>(TenEqualityComparer.Default);
+      pred = delegate(int i) { return i % 5 == 0; };
+    }
+
+    [TearDown]
+    public void Dispose() { list = null; }
+
+    [Test]
+    public void Find()
+    {
+      int i;
+      Assert.IsFalse(list.Find(pred, out i));
+      list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+      Assert.IsFalse(list.Find(pred, out i));
+      list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+      Assert.IsTrue(list.Find(pred, out i));
+      Assert.AreEqual(45, i);
+    }
+
+    [Test]
+    public void FindLast()
+    {
+      int i;
+      Assert.IsFalse(list.FindLast(pred, out i));
+      list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+      Assert.IsFalse(list.FindLast(pred, out i));
+      list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+      Assert.IsTrue(list.FindLast(pred, out i));
+      Assert.AreEqual(675, i);
+    }
+
+    [Test]
+    public void FindIndex()
+    {
+      Assert.IsFalse(0 <= list.FindIndex(pred));
+      list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+      Assert.IsFalse(0 <= list.FindIndex(pred));
+      list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+      Assert.AreEqual(3, list.FindIndex(pred));
+    }
+
+    [Test]
+    public void FindLastIndex()
+    {
+      Assert.IsFalse(0 <= list.FindLastIndex(pred));
+      list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+      Assert.IsFalse(0 <= list.FindLastIndex(pred));
+      list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+      Assert.AreEqual(7, list.FindLastIndex(pred));
+    }
+  }
+
+  [TestFixture]
+  public class UniqueItems
+  {
+    private SortedArray<int> list;
+
+    [SetUp]
+    public void Init() { list = new SortedArray<int>(); }
+
+    [TearDown]
+    public void Dispose() { list = null; }
+
+    [Test]
+    public void Test()
+    {
+      Assert.IsTrue(IC.seteq(list.UniqueItems()));
+      Assert.IsTrue(IC.seteq(list.ItemMultiplicities()));
+      list.AddAll<int>(new int[] { 7, 9, 7 });
+      Assert.IsTrue(IC.seteq(list.UniqueItems(), 7, 9));
+      Assert.IsTrue(IC.seteq(list.ItemMultiplicities(), 7, 1, 9, 1));
+    }
+  }
+
+  [TestFixture]
+  public class ArrayTest
+	{
+		private SortedArray<int> tree;
+
+		int[] a;
+
+
+		[SetUp]
+		public void Init()
+		{
+			tree = new SortedArray<int>(new IC());
+			a = new int[10];
+			for (int i = 0; i < 10; i++)
+				a[i] = 1000 + i;
+		}
+
+
+		[TearDown]
+		public void Dispose() { tree = null; }
+
+
+		private string aeq(int[] a, params int[] b)
+		{
+			if (a.Length != b.Length)
+				return "Lengths differ: " + a.Length + " != " + b.Length;
+
+			for (int i = 0; i < a.Length; i++)
+				if (a[i] != b[i])
+					return String.Format("{0}'th elements differ: {1} != {2}", i, a[i], b[i]);
+
+			return "Alles klar";
+		}
+
+
+		[Test]
+		public void ToArray()
+		{
+			Assert.AreEqual("Alles klar", aeq(tree.ToArray()));
+			tree.Add(7);
+			tree.Add(4);
+			Assert.AreEqual("Alles klar", aeq(tree.ToArray(), 4, 7));
+		}
+
+
+		[Test]
+		public void CopyTo()
+		{
+			tree.CopyTo(a, 1);
+			Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+			tree.Add(6);
+			tree.CopyTo(a, 2);
+			Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+			tree.Add(4);
+			tree.Add(9);
+			tree.CopyTo(a, 4);
+			Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 4, 6, 9, 1007, 1008, 1009));
+			tree.Clear();
+			tree.Add(7);
+			tree.CopyTo(a, 9);
+			Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 4, 6, 9, 1007, 1008, 7));
+		}
+
+
+		[Test]
+    [ExpectedException(typeof(ArgumentOutOfRangeException))]
+    public void CopyToBad()
+		{
+			tree.CopyTo(a, 11);
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(ArgumentOutOfRangeException))]
+		public void CopyToBad2()
+		{
+			tree.CopyTo(a, -1);
+		}
+
+
+		[Test]
+    [ExpectedException(typeof(ArgumentOutOfRangeException))]
+    public void CopyToTooFar()
+		{
+			tree.Add(3);
+			tree.Add(4);
+			tree.CopyTo(a, 9);
+		}
+	}
+
+
+	[TestFixture]
+	public class Combined
+	{
+		private IIndexedSorted<KeyValuePair<int,int>> lst;
+
+
+		[SetUp]
+		public void Init()
+		{
+			lst = new SortedArray<KeyValuePair<int,int>>(new KeyValuePairComparer<int,int>(new IC()));
+			for (int i = 0; i < 10; i++)
+				lst.Add(new KeyValuePair<int,int>(i, i + 30));
+		}
+
+
+		[TearDown]
+		public void Dispose() { lst = null; }
+
+
+		[Test]
+		public void Find()
+		{
+			KeyValuePair<int,int> p = new KeyValuePair<int,int>(3, 78);
+
+			Assert.IsTrue(lst.Find(ref p));
+			Assert.AreEqual(3, p.Key);
+			Assert.AreEqual(33, p.Value);
+			p = new KeyValuePair<int,int>(13, 78);
+			Assert.IsFalse(lst.Find(ref p));
+		}
+
+
+		[Test]
+		public void FindOrAdd()
+		{
+			KeyValuePair<int,int> p = new KeyValuePair<int,int>(3, 78);
+
+			Assert.IsTrue(lst.FindOrAdd(ref p));
+			Assert.AreEqual(3, p.Key);
+			Assert.AreEqual(33, p.Value);
+			p = new KeyValuePair<int,int>(13, 79);
+			Assert.IsFalse(lst.FindOrAdd(ref p));
+			Assert.AreEqual(13, lst[10].Key);
+			Assert.AreEqual(79, lst[10].Value);
+		}
+
+
+		[Test]
+		public void Update()
+		{
+			KeyValuePair<int,int> p = new KeyValuePair<int,int>(3, 78);
+
+			Assert.IsTrue(lst.Update(p));
+			Assert.AreEqual(3, lst[3].Key);
+			Assert.AreEqual(78, lst[3].Value);
+			p = new KeyValuePair<int,int>(13, 78);
+			Assert.IsFalse(lst.Update(p));
+		}
+
+
+		[Test]
+		public void UpdateOrAdd1()
+		{
+			KeyValuePair<int,int> p = new KeyValuePair<int,int>(3, 78);
+
+			Assert.IsTrue(lst.UpdateOrAdd(p));
+			Assert.AreEqual(3, lst[3].Key);
+			Assert.AreEqual(78, lst[3].Value);
+			p = new KeyValuePair<int,int>(13, 79);
+			Assert.IsFalse(lst.UpdateOrAdd(p));
+			Assert.AreEqual(13, lst[10].Key);
+			Assert.AreEqual(79, lst[10].Value);
+		}
+
+        [Test]
+        public void UpdateOrAdd2()
+        {
+            ICollection<String> coll = new SortedArray<String>();
+            // s1 and s2 are distinct objects but contain the same text:
+            String old, s1 = "abc", s2 = ("def" + s1).Substring(3);
+            Assert.IsFalse(coll.UpdateOrAdd(s1, out old));
+            Assert.AreEqual(null, old);
+            Assert.IsTrue(coll.UpdateOrAdd(s2, out old));
+            Assert.IsTrue(Object.ReferenceEquals(s1, old));
+            Assert.IsFalse(Object.ReferenceEquals(s2, old));
+        }
+
+        [Test]
+        public void UpdateOrAddWithExpand()
+        {
+            // bug20071217
+            SortedArray<double> arr = new SortedArray<double>();
+            for (int i = 0; i < 50; i++)
+            {
+                arr.UpdateOrAdd(i + 0.1);
+                arr.Add(i + 0.2);
+            }
+            Assert.IsTrue(arr.Count == 100);
+        }
+
+        [Test]
+        public void FindOrAddWithExpand()
+        {
+            // bug20071217
+            SortedArray<double> arr = new SortedArray<double>();
+            for (int i = 0; i < 50; i++)
+            {
+                double iVar = i + 0.1;
+                arr.FindOrAdd(ref iVar);
+                arr.Add(i * 0.2);
+            }
+            Assert.IsTrue(arr.Count == 100);
+        }
+
+		[Test]
+		public void RemoveWithReturn()
+		{
+			KeyValuePair<int,int> p = new KeyValuePair<int,int>(3, 78);
+
+            Assert.IsTrue(lst.Remove(p, out p));
+            Assert.AreEqual(3, p.Key);
+			Assert.AreEqual(33, p.Value);
+			Assert.AreEqual(4, lst[3].Key);
+			Assert.AreEqual(34, lst[3].Value);
+			p = new KeyValuePair<int,int>(13, 78);
+            Assert.IsFalse(lst.Remove(p, out p));
+        }
+	}
+
+
+	[TestFixture]
+	public class Remove
+	{
+		private SortedArray<int> array;
+
+
+		[SetUp]
+		public void Init()
+		{
+			array = new SortedArray<int>(new IC());
+			for (int i = 10; i < 20; i++)
+			{
+				array.Add(i);
+				array.Add(i + 10);
+			}
+		}
+
+
+		[Test]
+		public void SmallTrees()
+		{
+			array.Clear();
+			array.Add(7);
+			array.Add(9);
+			Assert.IsTrue(array.Remove(7));
+			Assert.IsTrue(array.Check());
+		}
+
+
+		[Test]
+		public void ByIndex()
+		{
+			//Remove root!
+			int n = array.Count;
+			int i = array[10];
+
+			array.RemoveAt(10);
+			Assert.IsTrue(array.Check());
+			Assert.IsFalse(array.Contains(i));
+			Assert.AreEqual(n - 1, array.Count);
+
+			//Low end
+			i = array.FindMin();
+			array.RemoveAt(0);
+			Assert.IsTrue(array.Check());
+			Assert.IsFalse(array.Contains(i));
+			Assert.AreEqual(n - 2, array.Count);
+
+			//high end
+			i = array.FindMax();
+			array.RemoveAt(array.Count - 1);
+			Assert.IsTrue(array.Check());
+			Assert.IsFalse(array.Contains(i));
+			Assert.AreEqual(n - 3, array.Count);
+
+			//Some leaf
+			i = 18;
+			array.RemoveAt(7);
+			Assert.IsTrue(array.Check());
+			Assert.IsFalse(array.Contains(i));
+			Assert.AreEqual(n - 4, array.Count);
+		}
+
+
+		[Test]
+		public void AlmostEmpty()
+		{
+			//Almost empty
+			array.Clear();
+			array.Add(3);
+			array.RemoveAt(0);
+			Assert.IsTrue(array.Check());
+			Assert.IsFalse(array.Contains(3));
+			Assert.AreEqual(0, array.Count);
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(IndexOutOfRangeException), "Index out of range for sequenced collectionvalue")]
+		public void Empty()
+		{
+			array.Clear();
+			array.RemoveAt(0);
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(IndexOutOfRangeException), "Index out of range for sequenced collectionvalue")]
+		public void HighIndex()
+		{
+			array.RemoveAt(array.Count);
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(IndexOutOfRangeException), "Index out of range for sequenced collectionvalue")]
+		public void LowIndex()
+		{
+			array.RemoveAt(-1);
+		}
+
+
+		[Test]
+		public void Normal()
+		{
+			Assert.IsFalse(array.Remove(-20));
+
+			//No demote case, with move_item
+			Assert.IsTrue(array.Remove(20));
+			Assert.IsTrue(array.Check());
+			Assert.IsFalse(array.Remove(20));
+
+			//plain case 2
+			Assert.IsTrue(array.Remove(14));
+			Assert.IsTrue(array.Check(), "Bad tree");
+
+			//case 1b
+			Assert.IsTrue(array.Remove(25));
+			Assert.IsTrue(array.Check(), "Bad tree");
+
+			//case 1c
+			Assert.IsTrue(array.Remove(29));
+			Assert.IsTrue(array.Check(), "Bad tree");
+
+			//1a (terminating)
+			Assert.IsTrue(array.Remove(10));
+			Assert.IsTrue(array.Check(), "Bad tree");
+
+			//2+1b
+			Assert.IsTrue(array.Remove(12));
+			Assert.IsTrue(array.Remove(11));
+
+			//1a+1b
+			Assert.IsTrue(array.Remove(18));
+			Assert.IsTrue(array.Remove(13));
+			Assert.IsTrue(array.Remove(15));
+
+			//2+1c
+			for (int i = 0; i < 10; i++)
+				array.Add(50 - 2 * i);
+
+			Assert.IsTrue(array.Remove(42));
+			Assert.IsTrue(array.Remove(38));
+			Assert.IsTrue(array.Remove(28));
+			Assert.IsTrue(array.Remove(40));
+
+			//
+			Assert.IsTrue(array.Remove(16));
+			Assert.IsTrue(array.Remove(23));
+			Assert.IsTrue(array.Remove(17));
+			Assert.IsTrue(array.Remove(19));
+			Assert.IsTrue(array.Remove(50));
+			Assert.IsTrue(array.Remove(26));
+			Assert.IsTrue(array.Remove(21));
+			Assert.IsTrue(array.Remove(22));
+			Assert.IsTrue(array.Remove(24));
+			for (int i = 0; i < 48; i++)
+				array.Remove(i);
+
+			//Almost empty tree:
+			Assert.IsFalse(array.Remove(26));
+			Assert.IsTrue(array.Remove(48));
+			Assert.IsTrue(array.Check(), "Bad tree");
+
+			//Empty tree:
+			Assert.IsFalse(array.Remove(26));
+			Assert.IsTrue(array.Check(), "Bad tree");
+		}
+
+
+		[TearDown]
+		public void Dispose()
+		{
+			array = null;
+		}
+	}
+
+
+
+	[TestFixture]
+	public class PredecessorStructure
+	{
+		private SortedArray<int> tree;
+
+
+		[SetUp]
+		public void Init()
+		{
+			tree = new SortedArray<int>(new IC());
+		}
+
+
+		private void loadup()
+		{
+			for (int i = 0; i < 20; i++)
+				tree.Add(2 * i);
+		}
+
+        [Test]
+        public void FindPredecessor()
+        {
+            loadup();
+            int res;
+            Assert.IsTrue(tree.TryPredecessor(7, out res) && res == 6);
+            Assert.IsTrue(tree.TryPredecessor(8, out res) && res == 6);
+
+            //The bottom
+            Assert.IsTrue(tree.TryPredecessor(1, out res) && res == 0);
+
+            //The top
+            Assert.IsTrue(tree.TryPredecessor(39, out res) && res == 38);
+        }
+
+        [Test]
+        public void FindPredecessorTooLow1()
+        {
+            int res;
+            Assert.IsFalse(tree.TryPredecessor(-2, out res));
+            Assert.AreEqual(0, res);
+            Assert.IsFalse(tree.TryPredecessor(0, out res));
+            Assert.AreEqual(0, res);
+        }
+
+        [Test]
+        public void FindWeakPredecessor()
+        {
+            loadup();
+            int res;
+            Assert.IsTrue(tree.TryWeakPredecessor(7, out res) && res == 6);
+            Assert.IsTrue(tree.TryWeakPredecessor(8, out res) && res == 8);
+
+            //The bottom
+            Assert.IsTrue(tree.TryWeakPredecessor(1, out res) && res == 0);
+            Assert.IsTrue(tree.TryWeakPredecessor(0, out res) && res == 0);
+
+            //The top
+            Assert.IsTrue(tree.TryWeakPredecessor(39, out res) && res == 38);
+            Assert.IsTrue(tree.TryWeakPredecessor(38, out res) && res == 38);
+        }
+
+        [Test]
+        public void FindWeakPredecessorTooLow1()
+        {
+            int res;
+            Assert.IsFalse(tree.TryWeakPredecessor(-1, out res));
+            Assert.AreEqual(0, res);
+        }
+
+        [Test]
+        public void FindSuccessor()
+        {
+            loadup();
+            int res;
+            Assert.IsTrue(tree.TrySuccessor(7, out res) && res == 8);
+            Assert.IsTrue(tree.TrySuccessor(8, out res) && res == 10);
+
+            //The bottom
+            Assert.IsTrue(tree.TrySuccessor(0, out res) && res == 2);
+            Assert.IsTrue(tree.TrySuccessor(-1, out res) && res == 0);
+
+            //The top
+            Assert.IsTrue(tree.TrySuccessor(37, out res) && res == 38);
+        }
+
+        [Test]
+        public void FindSuccessorTooHigh()
+        {
+            int res;
+            Assert.IsFalse(tree.TrySuccessor(38, out res));
+            Assert.AreEqual(0, res);
+            Assert.IsFalse(tree.TrySuccessor(39, out res));
+            Assert.AreEqual(0, res);
+        }
+
+        [Test]
+        public void FindWeakSuccessor()
+        {
+            loadup();
+            int res;
+            Assert.IsTrue(tree.TryWeakSuccessor(6, out res) && res == 6);
+            Assert.IsTrue(tree.TryWeakSuccessor(7, out res) && res == 8);
+
+            //The bottom
+            Assert.IsTrue(tree.TryWeakSuccessor(-1, out res) && res == 0);
+            Assert.IsTrue(tree.TryWeakSuccessor(0, out res) && res == 0);
+
+            //The top
+            Assert.IsTrue(tree.TryWeakSuccessor(37, out res) && res == 38);
+            Assert.IsTrue(tree.TryWeakSuccessor(38, out res) && res == 38);
+        }
+
+        [Test]
+        public void FindWeakSuccessorTooHigh1()
+        {
+            int res;
+            Assert.IsFalse(tree.TryWeakSuccessor(39, out res));
+            Assert.AreEqual(0, res);
+        }
+
+
+		[Test]
+		public void Predecessor()
+		{
+			loadup();
+			Assert.AreEqual(6, tree.Predecessor(7));
+			Assert.AreEqual(6, tree.Predecessor(8));
+
+			//The bottom
+			Assert.AreEqual(0, tree.Predecessor(1));
+
+			//The top
+			Assert.AreEqual(38, tree.Predecessor(39));
+		}
+
+		[Test]
+		[ExpectedException(typeof(NoSuchItemException))]
+		public void PredecessorTooLow1()
+		{
+			tree.Predecessor(-2);
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(NoSuchItemException))]
+		public void PredecessorTooLow2()
+		{
+			tree.Predecessor(0);
+		}
+
+		[Test]
+		public void WeakPredecessor()
+		{
+			loadup();
+			Assert.AreEqual(6, tree.WeakPredecessor(7));
+			Assert.AreEqual(8, tree.WeakPredecessor(8));
+
+			//The bottom
+			Assert.AreEqual(0, tree.WeakPredecessor(1));
+			Assert.AreEqual(0, tree.WeakPredecessor(0));
+
+			//The top
+			Assert.AreEqual(38, tree.WeakPredecessor(39));
+			Assert.AreEqual(38, tree.WeakPredecessor(38));
+		}
+
+		[Test]
+        [ExpectedException(typeof(NoSuchItemException))]
+        public void WeakPredecessorTooLow1()
+		{
+			tree.WeakPredecessor(-1);
+		}
+
+
+		[Test]
+		public void Successor()
+		{
+			loadup();
+			Assert.AreEqual(8, tree.Successor(7));
+			Assert.AreEqual(10, tree.Successor(8));
+
+			//The bottom
+			Assert.AreEqual(2, tree.Successor(0));
+			Assert.AreEqual(0, tree.Successor(-1));
+
+			//The top
+			Assert.AreEqual(38, tree.Successor(37));
+		}
+
+
+		[Test]
+        [ExpectedException(typeof(NoSuchItemException))]
+        public void SuccessorTooHigh1()
+		{
+			tree.Successor(38);
+		}
+
+
+		[Test]
+        [ExpectedException(typeof(NoSuchItemException))]
+        public void SuccessorTooHigh2()
+		{
+			tree.Successor(39);
+		}
+
+
+		[Test]
+		public void WeakSuccessor()
+		{
+			loadup();
+			Assert.AreEqual(6, tree.WeakSuccessor(6));
+			Assert.AreEqual(8, tree.WeakSuccessor(7));
+
+			//The bottom
+			Assert.AreEqual(0, tree.WeakSuccessor(-1));
+			Assert.AreEqual(0, tree.WeakSuccessor(0));
+
+			//The top
+			Assert.AreEqual(38, tree.WeakSuccessor(37));
+			Assert.AreEqual(38, tree.WeakSuccessor(38));
+		}
+
+		[Test]
+        [ExpectedException(typeof(NoSuchItemException))]
+        public void WeakSuccessorTooHigh1()
+		{
+			tree.WeakSuccessor(39);
+		}
+
+
+		[TearDown]
+		public void Dispose()
+		{
+			tree = null;
+		}
+	}
+
+
+
+	[TestFixture]
+	public class PriorityQueue
+	{
+		private SortedArray<int> tree;
+
+
+		[SetUp]
+		public void Init()
+		{
+			tree = new SortedArray<int>(new IC());
+		}
+
+
+		private void loadup()
+		{
+			foreach (int i in new int[] { 1, 2, 3, 4 })
+				tree.Add(i);
+		}
+
+
+		[Test]
+		public void Normal()
+		{
+			loadup();
+			Assert.AreEqual(1, tree.FindMin());
+			Assert.AreEqual(4, tree.FindMax());
+			Assert.AreEqual(1, tree.DeleteMin());
+			Assert.AreEqual(4, tree.DeleteMax());
+			Assert.IsTrue(tree.Check(), "Bad tree");
+			Assert.AreEqual(2, tree.FindMin());
+			Assert.AreEqual(3, tree.FindMax());
+			Assert.AreEqual(2, tree.DeleteMin());
+			Assert.AreEqual(3, tree.DeleteMax());
+			Assert.IsTrue(tree.Check(), "Bad tree");
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(NoSuchItemException))]
+		public void Empty1()
+		{
+			tree.FindMin();
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(NoSuchItemException))]
+		public void Empty2()
+		{
+			tree.FindMax();
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(NoSuchItemException))]
+		public void Empty3()
+		{
+			tree.DeleteMin();
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(NoSuchItemException))]
+		public void Empty4()
+		{
+			tree.DeleteMax();
+		}
+
+
+		[TearDown]
+		public void Dispose()
+		{
+			tree = null;
+		}
+	}
+
+
+
+	[TestFixture]
+	public class IndexingAndCounting
+	{
+		private SortedArray<int> array;
+
+
+		[SetUp]
+		public void Init()
+		{
+			array = new SortedArray<int>(new IC());
+		}
+
+
+		private void populate()
+		{
+			array.Add(30);
+			array.Add(50);
+			array.Add(10);
+			array.Add(70);
+		}
+
+
+		[Test]
+		public void ToArray()
+		{
+			populate();
+
+			int[] a = array.ToArray();
+
+			Assert.AreEqual(4, a.Length);
+			Assert.AreEqual(10, a[0]);
+			Assert.AreEqual(30, a[1]);
+			Assert.AreEqual(50, a[2]);
+			Assert.AreEqual(70, a[3]);
+		}
+
+
+		[Test]
+		public void GoodIndex()
+		{
+			Assert.AreEqual(~0, array.IndexOf(20));
+			Assert.AreEqual(~0, array.LastIndexOf(20));
+			populate();
+			Assert.AreEqual(10, array[0]);
+			Assert.AreEqual(30, array[1]);
+			Assert.AreEqual(50, array[2]);
+			Assert.AreEqual(70, array[3]);
+			Assert.AreEqual(0, array.IndexOf(10));
+			Assert.AreEqual(1, array.IndexOf(30));
+			Assert.AreEqual(2, array.IndexOf(50));
+			Assert.AreEqual(3, array.IndexOf(70));
+			Assert.AreEqual(~1, array.IndexOf(20));
+			Assert.AreEqual(~0, array.IndexOf(0));
+			Assert.AreEqual(~4, array.IndexOf(90));
+			Assert.AreEqual(0, array.LastIndexOf(10));
+			Assert.AreEqual(1, array.LastIndexOf(30));
+			Assert.AreEqual(2, array.LastIndexOf(50));
+			Assert.AreEqual(3, array.LastIndexOf(70));
+			Assert.AreEqual(~1, array.LastIndexOf(20));
+			Assert.AreEqual(~0, array.LastIndexOf(0));
+			Assert.AreEqual(~4, array.LastIndexOf(90));
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(IndexOutOfRangeException))]
+		public void IndexTooLarge()
+		{
+			populate();
+			Console.WriteLine(array[4]);
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(IndexOutOfRangeException))]
+		public void IndexTooSmall()
+		{
+			populate();
+			Console.WriteLine(array[-1]);
+		}
+
+
+		[Test]
+		public void FilledTreeOutsideInput()
+		{
+			populate();
+			Assert.AreEqual(0, array.CountFrom(90));
+			Assert.AreEqual(0, array.CountFromTo(-20, 0));
+			Assert.AreEqual(0, array.CountFromTo(80, 100));
+			Assert.AreEqual(0, array.CountTo(0));
+			Assert.AreEqual(4, array.CountTo(90));
+			Assert.AreEqual(4, array.CountFromTo(-20, 90));
+			Assert.AreEqual(4, array.CountFrom(0));
+		}
+
+
+		[Test]
+		public void FilledTreeIntermediateInput()
+		{
+			populate();
+			Assert.AreEqual(3, array.CountFrom(20));
+			Assert.AreEqual(1, array.CountFromTo(20, 40));
+			Assert.AreEqual(2, array.CountTo(40));
+		}
+
+
+		[Test]
+		public void FilledTreeMatchingInput()
+		{
+			populate();
+			Assert.AreEqual(3, array.CountFrom(30));
+			Assert.AreEqual(2, array.CountFromTo(30, 70));
+			Assert.AreEqual(0, array.CountFromTo(50, 30));
+			Assert.AreEqual(0, array.CountFromTo(50, 50));
+			Assert.AreEqual(0, array.CountTo(10));
+			Assert.AreEqual(2, array.CountTo(50));
+		}
+
+
+		[Test]
+		public void CountEmptyTree()
+		{
+			Assert.AreEqual(0, array.CountFrom(20));
+			Assert.AreEqual(0, array.CountFromTo(20, 40));
+			Assert.AreEqual(0, array.CountTo(40));
+		}
+
+
+		[TearDown]
+		public void Dispose()
+		{
+			array = null;
+		}
+	}
+
+
+
+
+	namespace ModificationCheck
+	{
+		[TestFixture]
+		public class Enumerator
+		{
+			private SortedArray<int> tree;
+
+			private SCG.IEnumerator<int> e;
+
+
+			[SetUp]
+			public void Init()
+			{
+				tree = new SortedArray<int>(new IC());
+				for (int i = 0; i < 10; i++)
+					tree.Add(i);
+
+				e = tree.GetEnumerator();
+			}
+
+
+			[Test]
+			public void CurrentAfterModification()
+			{
+				e.MoveNext();
+				tree.Add(34);
+				Assert.AreEqual(0, e.Current);
+			}
+
+
+			[Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterAdd()
+			{
+				e.MoveNext();
+				tree.Add(34);
+				e.MoveNext();
+			}
+
+
+
+
+			[Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterRemove()
+			{
+				e.MoveNext();
+				tree.Remove(34);
+				e.MoveNext();
+			}
+
+
+			[Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterClear()
+			{
+				e.MoveNext();
+				tree.Clear();
+				e.MoveNext();
+			}
+
+
+			[TearDown]
+			public void Dispose()
+			{
+				tree = null;
+				e = null;
+			}
+		}
+
+
+
+		[TestFixture]
+		public class RangeEnumerator
+		{
+			private SortedArray<int> tree;
+
+			private SCG.IEnumerator<int> e;
+
+
+			[SetUp]
+			public void Init()
+			{
+				tree = new SortedArray<int>(new IC());
+				for (int i = 0; i < 10; i++)
+					tree.Add(i);
+
+				e = tree.RangeFromTo(3, 7).GetEnumerator();
+			}
+
+
+			[Test]
+			public void CurrentAfterModification()
+			{
+				e.MoveNext();
+				tree.Add(34);
+				Assert.AreEqual(3, e.Current);
+			}
+
+
+			[Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterAdd()
+			{
+				tree.Add(34);
+				e.MoveNext();
+			}
+
+
+
+
+			[Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterRemove()
+			{
+				tree.Remove(34);
+				e.MoveNext();
+			}
+
+
+			[Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterClear()
+			{
+				tree.Clear();
+				e.MoveNext();
+			}
+
+
+			[TearDown]
+			public void Dispose()
+			{
+				tree = null;
+				e = null;
+			}
+		}
+	}
+
+	namespace HigherOrder
+	{
+		internal class CubeRoot: IComparable<int>
+		{
+			private int c;
+
+
+			internal CubeRoot(int c) { this.c = c; }
+
+
+			public int CompareTo(int that) { return c - that * that * that; }
+
+            public bool Equals(int that) { return c == that * that * that; }
+
+		}
+
+
+
+		class Interval: IComparable<int>
+		{
+			private int b, t;
+
+
+			internal Interval(int b, int t) { this.b = b; this.t = t; }
+
+
+			public int CompareTo(int that) { return that < b ? 1 : that > t ? -1 : 0; }
+
+            public bool Equals(int that) { return that >= b && that <= t; }
+        }
+
+
+
+		[TestFixture]
+		public class Simple
+		{
+			private SortedArray<int> array;
+
+			private SCG.IComparer<int> ic;
+
+
+			[SetUp]
+			public void Init()
+			{
+				ic = new IC();
+				array = new SortedArray<int>(ic);
+			}
+
+
+			private bool never(int i) { return false; }
+
+
+			private bool always(int i) { return true; }
+
+
+			private bool even(int i) { return i % 2 == 0; }
+
+
+			private string themap(int i) { return String.Format("AA {0,4} BB", i); }
+
+
+			private string badmap(int i) { return String.Format("AA {0} BB", i); }
+
+
+			private int appfield1;
+
+			private int appfield2;
+
+
+			private void apply(int i) { appfield1++; appfield2 += i * i; }
+
+
+			[Test]
+			public void Apply()
+			{
+				Simple simple1 = new Simple();
+
+				array.Apply(new Act<int>(simple1.apply));
+				Assert.AreEqual(0, simple1.appfield1);
+				Assert.AreEqual(0, simple1.appfield2);
+
+				Simple simple2 = new Simple();
+
+				for (int i = 0; i < 10; i++) array.Add(i);
+
+				array.Apply(new Act<int>(simple2.apply));
+				Assert.AreEqual(10, simple2.appfield1);
+				Assert.AreEqual(285, simple2.appfield2);
+			}
+
+
+			[Test]
+			public void All()
+			{
+				Assert.IsTrue(array.All(new Fun<int, bool>(never)));
+				Assert.IsTrue(array.All(new Fun<int, bool>(even)));
+				Assert.IsTrue(array.All(new Fun<int, bool>(always)));
+				for (int i = 0; i < 10; i++)					array.Add(i);
+
+				Assert.IsFalse(array.All(new Fun<int, bool>(never)));
+				Assert.IsFalse(array.All(new Fun<int, bool>(even)));
+				Assert.IsTrue(array.All(new Fun<int, bool>(always)));
+				array.Clear();
+				for (int i = 0; i < 10; i++)					array.Add(i * 2);
+
+				Assert.IsFalse(array.All(new Fun<int, bool>(never)));
+				Assert.IsTrue(array.All(new Fun<int, bool>(even)));
+				Assert.IsTrue(array.All(new Fun<int, bool>(always)));
+				array.Clear();
+				for (int i = 0; i < 10; i++)					array.Add(i * 2 + 1);
+
+				Assert.IsFalse(array.All(new Fun<int, bool>(never)));
+				Assert.IsFalse(array.All(new Fun<int, bool>(even)));
+				Assert.IsTrue(array.All(new Fun<int, bool>(always)));
+			}
+
+
+			[Test]
+			public void Exists()
+			{
+				Assert.IsFalse(array.Exists(new Fun<int, bool>(never)));
+				Assert.IsFalse(array.Exists(new Fun<int, bool>(even)));
+				Assert.IsFalse(array.Exists(new Fun<int, bool>(always)));
+				for (int i = 0; i < 10; i++)					array.Add(i);
+
+				Assert.IsFalse(array.Exists(new Fun<int, bool>(never)));
+				Assert.IsTrue(array.Exists(new Fun<int, bool>(even)));
+				Assert.IsTrue(array.Exists(new Fun<int, bool>(always)));
+				array.Clear();
+				for (int i = 0; i < 10; i++)					array.Add(i * 2);
+
+				Assert.IsFalse(array.Exists(new Fun<int, bool>(never)));
+				Assert.IsTrue(array.Exists(new Fun<int, bool>(even)));
+				Assert.IsTrue(array.Exists(new Fun<int, bool>(always)));
+				array.Clear();
+				for (int i = 0; i < 10; i++)					array.Add(i * 2 + 1);
+
+				Assert.IsFalse(array.Exists(new Fun<int, bool>(never)));
+				Assert.IsFalse(array.Exists(new Fun<int, bool>(even)));
+				Assert.IsTrue(array.Exists(new Fun<int, bool>(always)));
+			}
+
+
+			[Test]
+			public void FindAll()
+			{
+				Assert.AreEqual(0, array.FindAll(new Fun<int, bool>(never)).Count);
+				for (int i = 0; i < 10; i++)
+					array.Add(i);
+
+				Assert.AreEqual(0, array.FindAll(new Fun<int, bool>(never)).Count);
+				Assert.AreEqual(10, array.FindAll(new Fun<int, bool>(always)).Count);
+				Assert.AreEqual(5, array.FindAll(new Fun<int, bool>(even)).Count);
+				Assert.IsTrue(((SortedArray<int>)array.FindAll(new Fun<int, bool>(even))).Check());
+			}
+
+
+			[Test]
+			public void Map()
+			{
+				Assert.AreEqual(0, array.Map(new Fun<int,string>(themap), new SC()).Count);
+				for (int i = 0; i < 11; i++)
+					array.Add(i * i * i);
+
+				IIndexedSorted<string> res = array.Map(new Fun<int,string>(themap), new SC());
+
+				Assert.IsTrue(((SortedArray<string>)res).Check());
+				Assert.AreEqual(11, res.Count);
+				Assert.AreEqual("AA    0 BB", res[0]);
+				Assert.AreEqual("AA   27 BB", res[3]);
+				Assert.AreEqual("AA  125 BB", res[5]);
+				Assert.AreEqual("AA 1000 BB", res[10]);
+			}
+
+
+			[Test]
+			[ExpectedException(typeof(ArgumentException), "mapper not monotonic")]
+			public void BadMap()
+			{
+				for (int i = 0; i < 11; i++)
+					array.Add(i * i * i);
+
+				ISorted<string> res = array.Map(new Fun<int,string>(badmap), new SC());
+			}
+
+
+			[Test]
+			public void Cut()
+			{
+				for (int i = 0; i < 10; i++)
+					array.Add(i);
+
+				int low, high;
+				bool lval, hval;
+
+				Assert.IsTrue(array.Cut(new CubeRoot(27), out low, out lval, out high, out hval));
+				Assert.IsTrue(lval && hval);
+				Assert.AreEqual(4, high);
+				Assert.AreEqual(2, low);
+				Assert.IsFalse(array.Cut(new CubeRoot(30), out low, out lval, out high, out hval));
+				Assert.IsTrue(lval && hval);
+				Assert.AreEqual(4, high);
+				Assert.AreEqual(3, low);
+			}
+
+
+			[Test]
+			public void CutInt()
+			{
+				for (int i = 0; i < 10; i++)
+					array.Add(2 * i);
+
+				int low, high;
+				bool lval, hval;
+
+				Assert.IsFalse(array.Cut(new IC(3), out low, out lval, out high, out hval));
+				Assert.IsTrue(lval && hval);
+				Assert.AreEqual(4, high);
+				Assert.AreEqual(2, low);
+				Assert.IsTrue(array.Cut(new IC(6), out low, out lval, out high, out hval));
+				Assert.IsTrue(lval && hval);
+				Assert.AreEqual(8, high);
+				Assert.AreEqual(4, low);
+			}
+
+
+			[Test]
+			public void CutInterval()
+			{
+				for (int i = 0; i < 10; i++)
+					array.Add(2 * i);
+
+				int lo, hi;
+				bool lv, hv;
+
+				Assert.IsTrue(array.Cut(new Interval(5, 9), out lo, out lv, out hi, out hv));
+				Assert.IsTrue(lv && hv);
+				Assert.AreEqual(10, hi);
+				Assert.AreEqual(4, lo);
+				Assert.IsTrue(array.Cut(new Interval(6, 10), out lo, out lv, out hi, out hv));
+				Assert.IsTrue(lv && hv);
+				Assert.AreEqual(12, hi);
+				Assert.AreEqual(4, lo);
+				for (int i = 0; i < 100; i++)
+					array.Add(2 * i);
+
+				array.Cut(new Interval(77, 105), out lo, out lv, out hi, out hv);
+				Assert.IsTrue(lv && hv);
+				Assert.AreEqual(106, hi);
+				Assert.AreEqual(76, lo);
+				array.Cut(new Interval(5, 7), out lo, out lv, out hi, out hv);
+				Assert.IsTrue(lv && hv);
+				Assert.AreEqual(8, hi);
+				Assert.AreEqual(4, lo);
+				array.Cut(new Interval(80, 110), out lo, out lv, out hi, out hv);
+				Assert.IsTrue(lv && hv);
+				Assert.AreEqual(112, hi);
+				Assert.AreEqual(78, lo);
+			}
+
+
+			[Test]
+			public void UpperCut()
+			{
+				for (int i = 0; i < 10; i++)
+					array.Add(i);
+
+				int l, h;
+				bool lv, hv;
+
+				Assert.IsFalse(array.Cut(new CubeRoot(1000), out l, out lv, out h, out hv));
+				Assert.IsTrue(lv && !hv);
+				Assert.AreEqual(9, l);
+				Assert.IsFalse(array.Cut(new CubeRoot(-50), out l, out lv, out h, out hv));
+				Assert.IsTrue(!lv && hv);
+				Assert.AreEqual(0, h);
+			}
+
+
+			[TearDown]
+			public void Dispose() { ic = null; array = null; }
+		}
+	}
+
+
+
+
+	namespace MultiOps
+	{
+		[TestFixture]
+		public class AddAll
+		{
+			private int sqr(int i) { return i * i; }
+
+
+			SortedArray<int> array;
+
+
+			[SetUp]
+			public void Init() { array = new SortedArray<int>(new IC()); }
+
+
+			[Test]
+			public void EmptyEmpty()
+			{
+				array.AddAll(new FunEnumerable(0, new Fun<int,int>(sqr)));
+				Assert.AreEqual(0, array.Count);
+				Assert.IsTrue(array.Check());
+			}
+
+
+			[Test]
+			public void SomeEmpty()
+			{
+				for (int i = 4; i < 9; i++) array.Add(i);
+
+				array.AddAll(new FunEnumerable(0, new Fun<int,int>(sqr)));
+				Assert.AreEqual(5, array.Count);
+				Assert.IsTrue(array.Check());
+			}
+
+
+			[Test]
+			public void EmptySome()
+			{
+				array.AddAll(new FunEnumerable(4, new Fun<int,int>(sqr)));
+				Assert.AreEqual(4, array.Count);
+				Assert.IsTrue(array.Check());
+				Assert.AreEqual(0, array[0]);
+				Assert.AreEqual(1, array[1]);
+				Assert.AreEqual(4, array[2]);
+				Assert.AreEqual(9, array[3]);
+			}
+
+
+			[Test]
+			public void SomeSome()
+			{
+				for (int i = 3; i < 9; i++) array.Add(i);
+
+				array.AddAll(new FunEnumerable(4, new Fun<int,int>(sqr)));
+				Assert.AreEqual(9, array.Count);
+				Assert.IsTrue(array.Check());
+				Assert.IsTrue(IC.eq(array, 0, 1, 3,4, 5, 6, 7, 8, 9));
+			}
+
+
+			[TearDown]
+			public void Dispose() { array = null; }
+		}
+
+
+
+		[TestFixture]
+		public class AddSorted
+		{
+			private int sqr(int i) { return i * i; }
+
+
+			private int bad(int i) { return i * (5 - i); }
+
+
+			SortedArray<int> array;
+
+
+			[SetUp]
+			public void Init() { array = new SortedArray<int>(new IC()); }
+
+
+			[Test]
+			public void EmptyEmpty()
+			{
+				array.AddSorted(new FunEnumerable(0, new Fun<int,int>(sqr)));
+				Assert.AreEqual(0, array.Count);
+				Assert.IsTrue(array.Check());
+			}
+
+
+
+			[Test]
+			public void SomeEmpty()
+			{
+				for (int i = 4; i < 9; i++) array.Add(i);
+
+				array.AddSorted(new FunEnumerable(0, new Fun<int,int>(sqr)));
+				Assert.AreEqual(5, array.Count);
+				Assert.IsTrue(array.Check());
+			}
+
+
+
+			[Test]
+			public void EmptySome()
+			{
+				array.AddSorted(new FunEnumerable(4, new Fun<int,int>(sqr)));
+				Assert.AreEqual(4, array.Count);
+				Assert.IsTrue(array.Check());
+				Assert.AreEqual(0, array[0]);
+				Assert.AreEqual(1, array[1]);
+				Assert.AreEqual(4, array[2]);
+				Assert.AreEqual(9, array[3]);
+			}
+
+
+
+			[Test]
+			public void SomeSome()
+			{
+				for (int i = 3; i < 9; i++) array.Add(i);
+
+				array.AddSorted(new FunEnumerable(4, new Fun<int,int>(sqr)));
+				Assert.AreEqual(9, array.Count);
+				Assert.IsTrue(array.Check());
+				Assert.IsTrue(IC.eq(array, 0, 1, 3, 4, 5, 6, 7, 8, 9));
+			}
+
+			[Test]
+			[ExpectedException(typeof(ArgumentException), "Argument not sorted")]
+			public void EmptyBad()
+			{
+				array.AddSorted(new FunEnumerable(9, new Fun<int,int>(bad)));
+			}
+
+
+			[TearDown]
+			public void Dispose() { array = null; }
+		}
+
+		[TestFixture]
+		public class Rest
+		{
+			SortedArray<int> array, array2;
+
+
+			[SetUp]
+			public void Init()
+			{
+				array = new SortedArray<int>(new IC());
+				array2 = new SortedArray<int>(new IC());
+				for (int i = 0; i < 10; i++)
+					array.Add(i);
+
+				for (int i = 0; i < 10; i++)
+					array2.Add(2 * i);
+			}
+
+
+			[Test]
+			public void RemoveAll()
+			{
+				array.RemoveAll(array2.RangeFromTo(3, 7));
+				Assert.AreEqual(8, array.Count);
+				Assert.IsTrue(array.Check());
+				Assert.IsTrue(IC.eq(array, 0, 1, 2, 3, 5, 7, 8, 9));
+				array.RemoveAll(array2.RangeFromTo(3, 7));
+				Assert.AreEqual(8, array.Count);
+				Assert.IsTrue(array.Check());
+				Assert.IsTrue(IC.eq(array, 0, 1, 2, 3, 5, 7, 8, 9));
+				array.RemoveAll(array2.RangeFromTo(13, 17));
+				Assert.AreEqual(8, array.Count);
+				Assert.IsTrue(array.Check());
+				Assert.IsTrue(IC.eq(array, 0, 1, 2, 3, 5, 7, 8, 9));
+				array.RemoveAll(array2.RangeFromTo(3, 17));
+				Assert.AreEqual(7, array.Count);
+				Assert.IsTrue(array.Check());
+				Assert.IsTrue(IC.eq(array, 0, 1, 2, 3, 5, 7, 9));
+				for (int i = 0; i < 10; i++) array2.Add(i);
+
+				array.RemoveAll(array2.RangeFromTo(-1, 10));
+				Assert.AreEqual(0, array.Count);
+				Assert.IsTrue(array.Check());
+				Assert.IsTrue(IC.eq(array));
+			}
+
+
+			[Test]
+			public void RetainAll()
+			{
+				array.RetainAll(array2.RangeFromTo(3, 17));
+				Assert.AreEqual(3, array.Count);
+				Assert.IsTrue(array.Check());
+				Assert.IsTrue(IC.eq(array, 4, 6, 8));
+				array.RetainAll(array2.RangeFromTo(1, 17));
+				Assert.AreEqual(3, array.Count);
+				Assert.IsTrue(array.Check());
+				Assert.IsTrue(IC.eq(array, 4, 6, 8));
+				array.RetainAll(array2.RangeFromTo(3, 5));
+				Assert.AreEqual(1, array.Count);
+				Assert.IsTrue(array.Check());
+				Assert.IsTrue(IC.eq(array, 4));
+				array.RetainAll(array2.RangeFromTo(7, 17));
+				Assert.AreEqual(0, array.Count);
+				Assert.IsTrue(array.Check());
+				Assert.IsTrue(IC.eq(array));
+				for (int i = 0; i < 10; i++) array.Add(i);
+
+				array.RetainAll(array2.RangeFromTo(5, 5));
+				Assert.AreEqual(0, array.Count);
+				Assert.IsTrue(array.Check());
+				Assert.IsTrue(IC.eq(array));
+				for (int i = 0; i < 10; i++) array.Add(i);
+
+				array.RetainAll(array2.RangeFromTo(15, 25));
+				Assert.AreEqual(0, array.Count);
+				Assert.IsTrue(array.Check());
+				Assert.IsTrue(IC.eq(array));
+			}
+
+
+			[Test]
+			public void ContainsAll()
+			{
+				Assert.IsFalse(array.ContainsAll(array2));
+				Assert.IsTrue(array.ContainsAll(array));
+				array2.Clear();
+				Assert.IsTrue(array.ContainsAll(array2));
+				array.Clear();
+				Assert.IsTrue(array.ContainsAll(array2));
+				array2.Add(8);
+				Assert.IsFalse(array.ContainsAll(array2));
+			}
+
+
+			[Test]
+			public void RemoveInterval()
+			{
+				array.RemoveInterval(3, 4);
+				Assert.IsTrue(array.Check());
+				Assert.AreEqual(6, array.Count);
+				Assert.IsTrue(IC.eq(array, 0, 1, 2, 7, 8, 9));
+				array.RemoveInterval(2, 3);
+				Assert.IsTrue(array.Check());
+				Assert.AreEqual(3, array.Count);
+				Assert.IsTrue(IC.eq(array, 0, 1, 9));
+				array.RemoveInterval(0, 3);
+				Assert.IsTrue(array.Check());
+				Assert.AreEqual(0, array.Count);
+				Assert.IsTrue(IC.eq(array));
+			}
+
+
+			[Test]
+			[ExpectedException(typeof(ArgumentOutOfRangeException))]
+			public void RemoveRangeBad1()
+			{
+				array.RemoveInterval(-3, 8);
+			}
+
+
+			[Test]
+			[ExpectedException(typeof(ArgumentOutOfRangeException))]
+			public void RemoveRangeBad2()
+			{
+				array.RemoveInterval(3, -8);
+			}
+
+
+			[Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void RemoveRangeBad3()
+			{
+				array.RemoveInterval(3, 8);
+			}
+
+
+			[Test]
+			public void GetRange()
+			{
+				SCG.IEnumerable<int> e = array[3, 3];
+
+				Assert.IsTrue(IC.eq(e, 3, 4, 5));
+				e = array[3, 0];
+				Assert.IsTrue(IC.eq(e));
+			}
+
+
+			[Test]
+			[ExpectedException(typeof(ArgumentOutOfRangeException))]
+			public void GetRangeBad1()
+			{
+				object foo = array[-3, 0];
+			}
+
+
+			[Test]
+			[ExpectedException(typeof(ArgumentOutOfRangeException))]
+			public void GetRangeBad2()
+			{
+				object foo = array[3, -1];
+			}
+
+
+			[Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void GetRangeBad3()
+			{
+				object foo = array[3, 8];
+			}
+
+
+			[TearDown]
+			public void Dispose() { array = null; array2 = null; }
+		}
+	}
+
+
+
+
+	namespace Sync
+	{
+		[TestFixture]
+		public class SyncRoot
+		{
+			private SortedArray<int> tree;
+      private readonly Object mySyncRoot = new Object();
+			int sz = 5000;
+
+
+			[Test]
+			public void Safe()
+			{
+				System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ThreadStart(safe1));
+				System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ThreadStart(safe2));
+
+				t1.Start();
+				t2.Start();
+				t1.Join();
+				t2.Join();
+				Assert.AreEqual(2 * sz + 1, tree.Count);
+				Assert.IsTrue(tree.Check());
+			}
+
+
+			//[Test]
+			public void UnSafe()
+			{
+				bool bad = false;
+
+				for (int i = 0; i < 10; i++)
+				{
+					System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe1));
+					System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe2));
+
+					t1.Start();
+					t2.Start();
+					t1.Join();
+					t2.Join();
+					if (bad = 2 * sz + 1 != tree.Count)
+					{
+						Console.WriteLine("{0}::Unsafe(): bad at {1}", GetType(), i);
+						break;
+					}
+				}
+
+				Assert.IsTrue(bad, "No sync problems!");
+			}
+
+
+			[Test]
+			public void SafeUnSafe()
+			{
+				System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe1));
+				System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe2));
+
+				t1.Start();
+				t1.Join();
+				t2.Start();
+				t2.Join();
+				Assert.AreEqual(2 * sz + 1, tree.Count);
+			}
+
+
+			[SetUp]
+			public void Init() { tree = new SortedArray<int>(new IC()); }
+
+
+			private void unsafe1()
+			{
+				for (int i = 0; i < 2 * sz; i++)
+					tree.Add(i * 2);
+
+				for (int i = 1; i < sz; i++)
+					tree.Remove(i * 4);
+			}
+
+
+			private void safe1()
+			{
+				for (int i = 0; i < 2 * sz; i++)
+					lock (mySyncRoot)
+						tree.Add(i * 2);
+
+				for (int i = 1; i < sz; i++)
+					lock (mySyncRoot)
+						tree.Remove(i * 4);
+			}
+
+
+			private void unsafe2()
+			{
+				for (int i = 2 * sz; i > 0; i--)
+					tree.Add(i * 2 + 1);
+
+				for (int i = sz; i > 0; i--)
+					tree.Remove(i * 4 + 1);
+			}
+
+
+			private void safe2()
+			{
+				for (int i = 2 * sz; i > 0; i--)
+					lock (mySyncRoot)
+						tree.Add(i * 2 + 1);
+
+				for (int i = sz; i > 0; i--)
+					lock (mySyncRoot)
+						tree.Remove(i * 4 + 1);
+			}
+
+
+			[TearDown]
+			public void Dispose() { tree = null; }
+		}
+
+
+
+		//[TestFixture]
+		public class ConcurrentQueries
+		{
+			private SortedArray<int> tree;
+
+			int sz = 500000;
+
+
+			[SetUp]
+			public void Init()
+			{
+				tree = new SortedArray<int>(new IC());
+				for (int i = 0; i < sz; i++)
+				{
+					tree.Add(i);
+				}
+			}
+
+
+
+			class A
+			{
+				public int count = 0;
+
+				SortedArray<int> t;
+
+
+				public A(SortedArray<int> t) { this.t = t; }
+
+
+				public void a(int i) { count++; }
+
+
+				public void traverse() { t.Apply(new Act<int>(a)); }
+			}
+
+
+
+
+			[Test]
+			public void Safe()
+			{
+				A a = new A(tree);
+
+				a.traverse();
+				Assert.AreEqual(sz, a.count);
+			}
+
+
+			[Test]
+			public void RegrettablyUnsafe()
+			{
+				System.Threading.Thread[] t = new System.Threading.Thread[10];
+				A[] a = new A[10];
+				for (int i = 0; i < 10; i++)
+				{
+					a[i] = new A(tree);
+					t[i] = new System.Threading.Thread(new System.Threading.ThreadStart(a[i].traverse));
+				}
+
+				for (int i = 0; i < 10; i++)
+					t[i].Start();
+				for (int i = 0; i < 10; i++)
+					t[i].Join();
+				for (int i = 0; i < 10; i++)
+					Assert.AreEqual(sz,a[i].count);
+
+			}
+
+
+			[TearDown]
+			public void Dispose() { tree = null; }
+		}
+	}
+
+
+
+
+	namespace Hashing
+	{
+		[TestFixture]
+		public class ISequenced
+		{
+			private ISequenced<int> dit, dat, dut;
+
+
+			[SetUp]
+			public void Init()
+			{
+                dit = new SortedArray<int>(8,Comparer<int>.Default, EqualityComparer<int>.Default);
+                dat = new SortedArray<int>(8,Comparer<int>.Default, EqualityComparer<int>.Default);
+                dut = new SortedArray<int>(8,new RevIC(), EqualityComparer<int>.Default);
+			}
+
+
+			[Test]
+			public void EmptyEmpty()
+			{
+				Assert.IsTrue(dit.SequencedEquals(dat));
+			}
+
+
+			[Test]
+			public void EmptyNonEmpty()
+			{
+				dit.Add(3);
+				Assert.IsFalse(dit.SequencedEquals(dat));
+				Assert.IsFalse(dat.SequencedEquals(dit));
+			}
+
+			[Test]
+			public void HashVal()
+			{
+				Assert.AreEqual(CHC.sequencedhashcode(), dit.GetSequencedHashCode());
+				dit.Add(3);
+				Assert.AreEqual(CHC.sequencedhashcode(3), dit.GetSequencedHashCode());
+				dit.Add(7);
+				Assert.AreEqual(CHC.sequencedhashcode(3, 7), dit.GetSequencedHashCode());
+				Assert.AreEqual(CHC.sequencedhashcode(), dut.GetSequencedHashCode());
+				dut.Add(3);
+				Assert.AreEqual(CHC.sequencedhashcode(3), dut.GetSequencedHashCode());
+				dut.Add(7);
+				Assert.AreEqual(CHC.sequencedhashcode(7, 3), dut.GetSequencedHashCode());
+			}
+
+
+			[Test]
+			public void Normal()
+			{
+				dit.Add(3);
+				dit.Add(7);
+				dat.Add(3);
+				Assert.IsFalse(dit.SequencedEquals(dat));
+				Assert.IsFalse(dat.SequencedEquals(dit));
+				dat.Add(7);
+				Assert.IsTrue(dit.SequencedEquals(dat));
+				Assert.IsTrue(dat.SequencedEquals(dit));
+			}
+
+
+			[Test]
+			public void WrongOrder()
+			{
+				dit.Add(3);
+				dut.Add(3);
+				Assert.IsTrue(dit.SequencedEquals(dut));
+				Assert.IsTrue(dut.SequencedEquals(dit));
+				dit.Add(7);
+				dut.Add(7);
+				Assert.IsFalse(dit.SequencedEquals(dut));
+				Assert.IsFalse(dut.SequencedEquals(dit));
+			}
+
+
+			[Test]
+			public void Reflexive()
+			{
+				Assert.IsTrue(dit.SequencedEquals(dit));
+				dit.Add(3);
+				Assert.IsTrue(dit.SequencedEquals(dit));
+				dit.Add(7);
+				Assert.IsTrue(dit.SequencedEquals(dit));
+			}
+
+
+			[TearDown]
+			public void Dispose()
+			{
+				dit = null;
+				dat = null;
+				dut = null;
+			}
+		}
+
+
+
+		[TestFixture]
+		public class IEditableCollection
+		{
+			private ICollection<int> dit, dat, dut;
+
+
+			[SetUp]
+			public void Init()
+			{
+                dit = new SortedArray<int>(8,Comparer<int>.Default, EqualityComparer<int>.Default);
+                dat = new SortedArray<int>(8,Comparer<int>.Default, EqualityComparer<int>.Default);
+                dut = new SortedArray<int>(8,new RevIC(), EqualityComparer<int>.Default);
+			}
+
+
+			[Test]
+			public void EmptyEmpty()
+			{
+				Assert.IsTrue(dit.UnsequencedEquals(dat));
+			}
+
+
+			[Test]
+			public void EmptyNonEmpty()
+			{
+				dit.Add(3);
+				Assert.IsFalse(dit.UnsequencedEquals(dat));
+				Assert.IsFalse(dat.UnsequencedEquals(dit));
+			}
+
+
+			[Test]
+			public void HashVal()
+			{
+                Assert.AreEqual(CHC.unsequencedhashcode(), dit.GetUnsequencedHashCode());
+                dit.Add(3);
+                Assert.AreEqual(CHC.unsequencedhashcode(3), dit.GetUnsequencedHashCode());
+                dit.Add(7);
+                Assert.AreEqual(CHC.unsequencedhashcode(3, 7), dit.GetUnsequencedHashCode());
+                Assert.AreEqual(CHC.unsequencedhashcode(), dut.GetUnsequencedHashCode());
+                dut.Add(3);
+                Assert.AreEqual(CHC.unsequencedhashcode(3), dut.GetUnsequencedHashCode());
+                dut.Add(7);
+                Assert.AreEqual(CHC.unsequencedhashcode(7, 3), dut.GetUnsequencedHashCode());
+            }
+
+
+			[Test]
+			public void Normal()
+			{
+				dit.Add(3);
+				dit.Add(7);
+				dat.Add(3);
+				Assert.IsFalse(dit.UnsequencedEquals(dat));
+				Assert.IsFalse(dat.UnsequencedEquals(dit));
+				dat.Add(7);
+				Assert.IsTrue(dit.UnsequencedEquals(dat));
+				Assert.IsTrue(dat.UnsequencedEquals(dit));
+			}
+
+
+			[Test]
+			public void WrongOrder()
+			{
+				dit.Add(3);
+				dut.Add(3);
+				Assert.IsTrue(dit.UnsequencedEquals(dut));
+				Assert.IsTrue(dut.UnsequencedEquals(dit));
+				dit.Add(7);
+				dut.Add(7);
+				Assert.IsTrue(dit.UnsequencedEquals(dut));
+				Assert.IsTrue(dut.UnsequencedEquals(dit));
+			}
+
+
+			[Test]
+			public void Reflexive()
+			{
+				Assert.IsTrue(dit.UnsequencedEquals(dit));
+				dit.Add(3);
+				Assert.IsTrue(dit.UnsequencedEquals(dit));
+				dit.Add(7);
+				Assert.IsTrue(dit.UnsequencedEquals(dit));
+			}
+
+
+			[TearDown]
+			public void Dispose()
+			{
+				dit = null;
+				dat = null;
+				dut = null;
+			}
+		}
+
+	}
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/hashing/HashBagTests.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/hashing/HashBagTests.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/hashing/HashBagTests.cs	(revision 3)
@@ -0,0 +1,611 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+namespace C5UnitTests.hashtable.bag
+{
+  using CollectionOfInt = HashBag<int>;
+
+  [TestFixture]
+  public class GenericTesters
+  {
+    [Test]
+    public void TestEvents()
+    {
+      Fun<CollectionOfInt> factory = delegate() { return new CollectionOfInt(TenEqualityComparer.Default); };
+      new C5UnitTests.Templates.Events.CollectionTester<CollectionOfInt>().Test(factory);
+    }
+
+    [Test]
+    public void Extensible()
+    {
+      C5UnitTests.Templates.Extensible.Clone.Tester<CollectionOfInt>();
+      C5UnitTests.Templates.Extensible.Serialization.Tester<CollectionOfInt>();
+    }
+  }
+
+  static class Factory
+  {
+    public static ICollection<T> New<T>() { return new HashBag<T>(); }
+  }
+
+
+  [TestFixture]
+  public class Formatting
+  {
+    ICollection<int> coll;
+    IFormatProvider rad16;
+    [SetUp]
+    public void Init() { coll = Factory.New<int>(); rad16 = new RadixFormatProvider(16); }
+    [TearDown]
+    public void Dispose() { coll = null; rad16 = null; }
+    [Test]
+    public void Format()
+    {
+      Assert.AreEqual("{{  }}", coll.ToString());
+      coll.AddAll<int>(new int[] { -4, 28, 129, 65530, -4, 28 });
+      Assert.AreEqual("{{ 65530(*1), -4(*2), 28(*2), 129(*1) }}", coll.ToString());
+      Assert.AreEqual("{{ FFFA(*1), -4(*2), 1C(*2), 81(*1) }}", coll.ToString(null, rad16));
+      Assert.AreEqual("{{ 65530(*1), -4(*2)... }}", coll.ToString("L18", null));
+      Assert.AreEqual("{{ FFFA(*1), -4(*2)... }}", coll.ToString("L18", rad16));
+    }
+  }
+
+  [TestFixture]
+  public class Combined
+  {
+    private ICollection<KeyValuePair<int, int>> lst;
+
+
+    [SetUp]
+    public void Init()
+    {
+      lst = new HashBag<KeyValuePair<int, int>>(new KeyValuePairEqualityComparer<int, int>());
+      for (int i = 0; i < 10; i++)
+        lst.Add(new KeyValuePair<int, int>(i, i + 30));
+    }
+
+
+    [TearDown]
+    public void Dispose() { lst = null; }
+
+
+    [Test]
+    public void Find()
+    {
+      KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+      Assert.IsTrue(lst.Find(ref p));
+      Assert.AreEqual(3, p.Key);
+      Assert.AreEqual(33, p.Value);
+      p = new KeyValuePair<int, int>(13, 78);
+      Assert.IsFalse(lst.Find(ref p));
+    }
+
+
+    [Test]
+    public void FindOrAdd()
+    {
+      KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+      KeyValuePair<int, int> q = new KeyValuePair<int, int>();
+
+      Assert.IsTrue(lst.FindOrAdd(ref p));
+      Assert.AreEqual(3, p.Key);
+      Assert.AreEqual(33, p.Value);
+      p = new KeyValuePair<int, int>(13, 79);
+      Assert.IsFalse(lst.FindOrAdd(ref p));
+      q.Key = 13;
+      Assert.IsTrue(lst.Find(ref q));
+      Assert.AreEqual(13, q.Key);
+      Assert.AreEqual(79, q.Value);
+    }
+
+
+    [Test]
+    public void Update()
+    {
+      KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+      KeyValuePair<int, int> q = new KeyValuePair<int, int>();
+
+      Assert.IsTrue(lst.Update(p));
+      q.Key = 3;
+      Assert.IsTrue(lst.Find(ref q));
+      Assert.AreEqual(3, q.Key);
+      Assert.AreEqual(78, q.Value);
+      p = new KeyValuePair<int, int>(13, 78);
+      Assert.IsFalse(lst.Update(p));
+    }
+
+
+    [Test]
+    public void UpdateOrAdd1()
+    {
+      KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+      KeyValuePair<int, int> q = new KeyValuePair<int, int>();
+
+      Assert.IsTrue(lst.UpdateOrAdd(p));
+      q.Key = 3;
+      Assert.IsTrue(lst.Find(ref q));
+      Assert.AreEqual(3, q.Key);
+      Assert.AreEqual(78, q.Value);
+      p = new KeyValuePair<int, int>(13, 79);
+      Assert.IsFalse(lst.UpdateOrAdd(p));
+      q.Key = 13;
+      Assert.IsTrue(lst.Find(ref q));
+      Assert.AreEqual(13, q.Key);
+      Assert.AreEqual(79, q.Value);
+    }
+
+    [Test]
+    public void UpdateOrAdd2()
+    {
+        ICollection<String> coll = new HashBag<String>();
+        // s1 and s2 are distinct objects but contain the same text:
+        String old, s1 = "abc", s2 = ("def" + s1).Substring(3);
+        Assert.IsFalse(coll.UpdateOrAdd(s1, out old));
+        Assert.AreEqual(null, old);
+        Assert.IsTrue(coll.UpdateOrAdd(s2, out old));
+        Assert.IsTrue(Object.ReferenceEquals(s1, old));
+        Assert.IsFalse(Object.ReferenceEquals(s2, old));
+    }
+
+    [Test]
+    public void RemoveWithReturn()
+    {
+      KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+      //KeyValuePair<int, int> q = new KeyValuePair<int, int>();
+
+      Assert.IsTrue(lst.Remove(p, out p));
+      Assert.AreEqual(3, p.Key);
+      Assert.AreEqual(33, p.Value);
+      p = new KeyValuePair<int, int>(13, 78);
+      Assert.IsFalse(lst.Remove(p, out p));
+    }
+  }
+
+
+
+  [TestFixture]
+  public class CollectionOrSink
+  {
+    private HashBag<int> hashbag;
+
+
+    [SetUp]
+    public void Init() { hashbag = new HashBag<int>(); }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor1()
+    {
+      new HashBag<int>(null);
+    }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor2()
+    {
+      new HashBag<int>(5, null);
+    }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor3()
+    {
+      new HashBag<int>(5, 0.5, null);
+    }
+
+    [Test]
+    public void Choose()
+    {
+      hashbag.Add(7);
+      Assert.AreEqual(7, hashbag.Choose());
+    }
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void BadChoose()
+    {
+      hashbag.Choose();
+    }
+
+
+    [Test]
+    public void CountEtAl()
+    {
+      Assert.IsFalse(hashbag.IsReadOnly);
+      // Assert.IsFalse(hashbag.SyncRoot == null);
+      Assert.AreEqual(0, hashbag.Count);
+      Assert.IsTrue(hashbag.IsEmpty);
+      Assert.IsTrue(hashbag.AllowsDuplicates);
+      Assert.IsTrue(hashbag.Add(0));
+      Assert.AreEqual(1, hashbag.Count);
+      Assert.IsFalse(hashbag.IsEmpty);
+      Assert.IsTrue(hashbag.Add(5));
+      Assert.AreEqual(2, hashbag.Count);
+      Assert.IsTrue(hashbag.Add(5));
+      Assert.AreEqual(3, hashbag.Count);
+      Assert.IsFalse(hashbag.IsEmpty);
+      Assert.IsTrue(hashbag.Add(8));
+      Assert.AreEqual(4, hashbag.Count);
+      Assert.AreEqual(2, hashbag.ContainsCount(5));
+      Assert.AreEqual(1, hashbag.ContainsCount(8));
+      Assert.AreEqual(1, hashbag.ContainsCount(0));
+    }
+
+
+    [Test]
+    public void AddAll()
+    {
+      hashbag.Add(3); hashbag.Add(4); hashbag.Add(4); hashbag.Add(5); hashbag.Add(4);
+
+      HashBag<int> hashbag2 = new HashBag<int>();
+
+      hashbag2.AddAll(hashbag);
+      Assert.IsTrue(IC.seteq(hashbag2, 3, 4, 4, 4, 5));
+      hashbag.Add(9);
+      hashbag.AddAll(hashbag2);
+      Assert.IsTrue(IC.seteq(hashbag2, 3, 4, 4, 4, 5));
+      Assert.IsTrue(IC.seteq(hashbag, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 9));
+    }
+
+
+    [Test]
+    public void ContainsCount()
+    {
+      Assert.AreEqual(0, hashbag.ContainsCount(5));
+      hashbag.Add(5);
+      Assert.AreEqual(1, hashbag.ContainsCount(5));
+      Assert.AreEqual(0, hashbag.ContainsCount(7));
+      hashbag.Add(8);
+      Assert.AreEqual(1, hashbag.ContainsCount(5));
+      Assert.AreEqual(0, hashbag.ContainsCount(7));
+      Assert.AreEqual(1, hashbag.ContainsCount(8));
+      hashbag.Add(5);
+      Assert.AreEqual(2, hashbag.ContainsCount(5));
+      Assert.AreEqual(0, hashbag.ContainsCount(7));
+      Assert.AreEqual(1, hashbag.ContainsCount(8));
+    }
+
+
+    [Test]
+    public void RemoveAllCopies()
+    {
+      hashbag.Add(5); hashbag.Add(7); hashbag.Add(5);
+      Assert.AreEqual(2, hashbag.ContainsCount(5));
+      Assert.AreEqual(1, hashbag.ContainsCount(7));
+      hashbag.RemoveAllCopies(5);
+      Assert.AreEqual(0, hashbag.ContainsCount(5));
+      Assert.AreEqual(1, hashbag.ContainsCount(7));
+      hashbag.Add(5); hashbag.Add(8); hashbag.Add(5);
+      hashbag.RemoveAllCopies(8);
+      Assert.IsTrue(IC.eq(hashbag, 7, 5, 5));
+    }
+
+
+    [Test]
+    public void ContainsAll()
+    {
+      HashBag<int> list2 = new HashBag<int>();
+
+      Assert.IsTrue(hashbag.ContainsAll(list2));
+      list2.Add(4);
+      Assert.IsFalse(hashbag.ContainsAll(list2));
+      hashbag.Add(4);
+      Assert.IsTrue(hashbag.ContainsAll(list2));
+      hashbag.Add(5);
+      Assert.IsTrue(hashbag.ContainsAll(list2));
+      list2.Add(20);
+      Assert.IsFalse(hashbag.ContainsAll(list2));
+      hashbag.Add(20);
+      Assert.IsTrue(hashbag.ContainsAll(list2));
+      list2.Add(4);
+      Assert.IsFalse(hashbag.ContainsAll(list2));
+      hashbag.Add(4);
+      Assert.IsTrue(hashbag.ContainsAll(list2));
+    }
+
+
+    [Test]
+    public void RetainAll()
+    {
+      HashBag<int> list2 = new HashBag<int>();
+
+      hashbag.Add(4); hashbag.Add(5); hashbag.Add(4); hashbag.Add(6); hashbag.Add(4);
+      list2.Add(5); list2.Add(4); list2.Add(7); list2.Add(4);
+      hashbag.RetainAll(list2);
+      Assert.IsTrue(IC.seteq(hashbag, 4, 4, 5));
+      hashbag.Add(6);
+      list2.Clear();
+      list2.Add(7); list2.Add(8); list2.Add(9);
+      hashbag.RetainAll(list2);
+      Assert.IsTrue(IC.eq(hashbag));
+    }
+
+
+    [Test]
+    public void RemoveAll()
+    {
+      HashBag<int> list2 = new HashBag<int>();
+
+      hashbag.Add(4); hashbag.Add(5); hashbag.Add(6); hashbag.Add(4); hashbag.Add(5);
+      list2.Add(5); list2.Add(4); list2.Add(7); list2.Add(4);
+      hashbag.RemoveAll(list2);
+      Assert.IsTrue(IC.seteq(hashbag, 5, 6));
+      hashbag.Add(5); hashbag.Add(4);
+      list2.Clear();
+      list2.Add(6); list2.Add(5);
+      hashbag.RemoveAll(list2);
+      Assert.IsTrue(IC.seteq(hashbag, 4, 5));
+      list2.Clear();
+      list2.Add(7); list2.Add(8); list2.Add(9);
+      hashbag.RemoveAll(list2);
+      Assert.IsTrue(IC.seteq(hashbag, 4, 5));
+    }
+
+
+    [Test]
+    public void Remove()
+    {
+      hashbag.Add(4); hashbag.Add(4); hashbag.Add(5); hashbag.Add(4); hashbag.Add(6);
+      Assert.IsFalse(hashbag.Remove(2));
+      Assert.IsTrue(hashbag.Remove(4));
+      Assert.IsTrue(IC.seteq(hashbag, 4, 4, 5, 6));
+      hashbag.Add(7);
+      hashbag.Add(21); hashbag.Add(37); hashbag.Add(53); hashbag.Add(69); hashbag.Add(53); hashbag.Add(85);
+      Assert.IsTrue(hashbag.Remove(5));
+      Assert.IsTrue(IC.seteq(hashbag, 4, 4, 6, 7, 21, 37, 53, 53, 69, 85));
+      Assert.IsFalse(hashbag.Remove(165));
+      Assert.IsTrue(hashbag.Check());
+      Assert.IsTrue(IC.seteq(hashbag, 4, 4, 6, 7, 21, 37, 53, 53, 69, 85));
+      Assert.IsTrue(hashbag.Remove(53));
+      Assert.IsTrue(IC.seteq(hashbag, 4, 4, 6, 7, 21, 37, 53, 69, 85));
+      Assert.IsTrue(hashbag.Remove(37));
+      Assert.IsTrue(IC.seteq(hashbag, 4, 4, 6, 7, 21, 53, 69, 85));
+      Assert.IsTrue(hashbag.Remove(85));
+      Assert.IsTrue(IC.seteq(hashbag, 4, 4, 6, 7, 21, 53, 69));
+    }
+
+
+    [TearDown]
+    public void Dispose() { hashbag = null; }
+  }
+
+  [TestFixture]
+  public class FindPredicate
+  {
+    private HashBag<int> list;
+    Fun<int, bool> pred;
+
+    [SetUp]
+    public void Init()
+    {
+      list = new HashBag<int>(TenEqualityComparer.Default);
+      pred = delegate(int i) { return i % 5 == 0; };
+    }
+
+    [TearDown]
+    public void Dispose() { list = null; }
+
+    [Test]
+    public void Find()
+    {
+      int i;
+      Assert.IsFalse(list.Find(pred, out i));
+      list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+      Assert.IsFalse(list.Find(pred, out i));
+      list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+      Assert.IsTrue(list.Find(pred, out i));
+      Assert.AreEqual(45, i);
+    }
+
+  }
+
+  [TestFixture]
+  public class UniqueItems
+  {
+    private HashBag<int> list;
+
+    [SetUp]
+    public void Init() { list = new HashBag<int>(); }
+
+    [TearDown]
+    public void Dispose() { list = null; }
+
+    [Test]
+    public void Test()
+    {
+      Assert.IsTrue(IC.seteq(list.UniqueItems()));
+      Assert.IsTrue(IC.seteq(list.ItemMultiplicities()));
+      list.AddAll<int>(new int[] { 7, 9, 7 });
+      Assert.IsTrue(IC.seteq(list.UniqueItems(), 7, 9));
+      Assert.IsTrue(IC.seteq(list.ItemMultiplicities(), 7, 2, 9, 1));
+    }
+  }
+
+  [TestFixture]
+  public class ArrayTest
+  {
+    private HashBag<int> hashbag;
+
+    int[] a;
+
+
+    [SetUp]
+    public void Init()
+    {
+      hashbag = new HashBag<int>();
+      a = new int[10];
+      for (int i = 0; i < 10; i++)
+        a[i] = 1000 + i;
+    }
+
+
+    [TearDown]
+    public void Dispose() { hashbag = null; }
+
+
+    private string aeq(int[] a, params int[] b)
+    {
+      if (a.Length != b.Length)
+        return "Lengths differ: " + a.Length + " != " + b.Length;
+
+      for (int i = 0; i < a.Length; i++)
+        if (a[i] != b[i])
+          return String.Format("{0}'th elements differ: {1} != {2}", i, a[i], b[i]);
+
+      return "Alles klar";
+    }
+
+
+    [Test]
+    public void ToArray()
+    {
+      Assert.AreEqual("Alles klar", aeq(hashbag.ToArray()));
+      hashbag.Add(7);
+      hashbag.Add(3);
+      hashbag.Add(10);
+      hashbag.Add(3);
+
+      int[] r = hashbag.ToArray();
+
+      Array.Sort(r);
+      Assert.AreEqual("Alles klar", aeq(r, 3, 3, 7, 10));
+    }
+
+
+    [Test]
+    public void CopyTo()
+    {
+      //Note: for small ints the itemequalityComparer is the identity!
+      hashbag.CopyTo(a, 1);
+      Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+      hashbag.Add(6);
+      hashbag.CopyTo(a, 2);
+      Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+      hashbag.Add(4);
+      hashbag.Add(6);
+      hashbag.Add(9);
+      hashbag.CopyTo(a, 4);
+
+      //TODO: make independent of interequalityComparer
+      Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 6, 9, 4, 1008, 1009));
+      hashbag.Clear();
+      hashbag.Add(7);
+      hashbag.CopyTo(a, 9);
+      Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 6, 9, 4, 1008, 7));
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(ArgumentOutOfRangeException))]
+    public void CopyToBad()
+    {
+      hashbag.CopyTo(a, 11);
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(ArgumentOutOfRangeException))]
+    public void CopyToBad2()
+    {
+      hashbag.CopyTo(a, -1);
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(ArgumentOutOfRangeException))]
+    public void CopyToTooFar()
+    {
+      hashbag.Add(3);
+      hashbag.Add(8);
+      hashbag.CopyTo(a, 9);
+    }
+  }
+
+
+
+  [TestFixture]
+  public class HashingEquals
+  {
+    private ICollection<int> h1, h2;
+
+
+    [SetUp]
+    public void Init()
+    {
+      h1 = new HashBag<int>();
+      h2 = new LinkedList<int>();
+    }
+
+
+    [TearDown]
+    public void Dispose()
+    {
+      h1 = h2 = null;
+    }
+
+
+    [Test]
+    public void Hashing()
+    {
+      Assert.AreEqual(h1.GetUnsequencedHashCode(), h2.GetUnsequencedHashCode());
+      h1.Add(7);
+      h2.Add(9);
+      Assert.IsTrue(h1.GetUnsequencedHashCode() != h2.GetUnsequencedHashCode());
+      h2.Add(7);
+      h1.Add(9);
+      Assert.IsTrue(h1.GetUnsequencedHashCode() == h2.GetUnsequencedHashCode());
+    }
+
+
+    [Test]
+    public void Equals()
+    {
+      Assert.IsTrue(h1.UnsequencedEquals(h2));
+//            Code 1550734257, Pair (3 x 1602896434, 2 x 1186320090) number 169185 matched oth
+//er pair (3 x -1615223932, 2 x 1019546595)
+      h1.Add(1602896434);
+      h1.Add(1186320090);
+      h1.Add(1602896434);
+      h1.Add(1186320090);
+      h1.Add(1602896434);
+      h2.Add(-1615223932);
+      h2.Add(1019546595);
+      h2.Add(-1615223932);
+      h2.Add(1019546595);
+      h2.Add(-1615223932);
+      Assert.IsTrue(h1.GetUnsequencedHashCode() == h2.GetUnsequencedHashCode());
+      Assert.IsTrue(!h1.UnsequencedEquals(h2));
+      h1.Clear();
+      h2.Clear();
+      h1.Add(1);
+      h1.Add(2);
+      h2.Add(2);
+      h2.Add(1);
+      Assert.IsTrue(h1.GetUnsequencedHashCode() == h2.GetUnsequencedHashCode());
+      Assert.IsTrue(h1.UnsequencedEquals(h2));
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/hashing/HashDictionaryTests.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/hashing/HashDictionaryTests.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/hashing/HashDictionaryTests.cs	(revision 3)
@@ -0,0 +1,343 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+namespace C5UnitTests.hashtable.dictionary
+{
+  using DictionaryIntToInt = HashDictionary<int, int>;
+
+  [TestFixture]
+  public class GenericTesters
+  {
+    [Test]
+    public void TestEvents()
+    {
+      Fun<DictionaryIntToInt> factory = delegate() { return new DictionaryIntToInt(TenEqualityComparer.Default); };
+      new C5UnitTests.Templates.Events.DictionaryTester<DictionaryIntToInt>().Test(factory);
+    }
+
+    [Test]
+    public void TestSerialize()
+    {
+      C5UnitTests.Templates.Extensible.Serialization.DTester<DictionaryIntToInt>();
+    }
+  }
+
+  static class Factory
+  {
+    public static IDictionary<K, V> New<K, V>() { return new HashDictionary<K, V>(); }
+  }
+
+  [TestFixture]
+  public class Formatting
+  {
+    IDictionary<int, int> coll;
+    IFormatProvider rad16;
+    [SetUp]
+    public void Init() { coll = Factory.New<int, int>(); rad16 = new RadixFormatProvider(16); }
+    [TearDown]
+    public void Dispose() { coll = null; rad16 = null; }
+    [Test]
+    public void Format()
+    {
+      Assert.AreEqual("{  }", coll.ToString());
+      coll.Add(23, 67); coll.Add(45, 89);
+      Assert.AreEqual("{ 45 => 89, 23 => 67 }", coll.ToString());
+      Assert.AreEqual("{ 2D => 59, 17 => 43 }", coll.ToString(null, rad16));
+      Assert.AreEqual("{ 45 => 89, ... }", coll.ToString("L14", null));
+      Assert.AreEqual("{ 2D => 59, ... }", coll.ToString("L14", rad16));
+    }
+  }
+
+  [TestFixture]
+  public class HashDict
+  {
+    private HashDictionary<string, string> dict;
+
+
+    [SetUp]
+    public void Init()
+    {
+      dict = new HashDictionary<string, string>();
+      //dict = TreeDictionary<string,string>.MakeNaturalO<string,string>();
+    }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor1()
+    {
+      new HashDictionary<int, int>(null);
+    }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor2()
+    {
+      new HashDictionary<int, int>(5, 0.5, null);
+    }
+
+    [Test]
+    public void Choose()
+    {
+      dict.Add("ER", "FOO");
+      Assert.AreEqual(new KeyValuePair<string, string>("ER", "FOO"), dict.Choose());
+    }
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void BadChoose()
+    {
+      dict.Choose();
+    }
+
+
+
+    [TearDown]
+    public void Dispose()
+    {
+      dict = null;
+    }
+
+
+    [Test]
+    public void Initial()
+    {
+      bool res;
+
+      Assert.IsFalse(dict.IsReadOnly);
+      Assert.AreEqual(0, dict.Count, "new dict should be empty");
+      dict.Add("A", "B");
+      Assert.AreEqual(1, dict.Count, "bad count");
+      Assert.AreEqual("B", dict["A"], "Wrong value for dict[A]");
+      dict.Add("C", "D");
+      Assert.AreEqual(2, dict.Count, "bad count");
+      Assert.AreEqual("B", dict["A"], "Wrong value");
+      Assert.AreEqual("D", dict["C"], "Wrong value");
+      res = dict.Remove("A");
+      Assert.IsTrue(res, "bad return value from Remove(A)");
+      Assert.AreEqual(1, dict.Count, "bad count");
+      Assert.AreEqual("D", dict["C"], "Wrong value of dict[C]");
+      res = dict.Remove("Z");
+      Assert.IsFalse(res, "bad return value from Remove(Z)");
+      Assert.AreEqual(1, dict.Count, "bad count");
+      Assert.AreEqual("D", dict["C"], "Wrong value of dict[C] (2)");
+    }
+
+
+    [Test]
+    public void Contains()
+    {
+      dict.Add("C", "D");
+      Assert.IsTrue(dict.Contains("C"));
+      Assert.IsFalse(dict.Contains("D"));
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(DuplicateNotAllowedException), "Key being added: 'A'")]
+    public void IllegalAdd()
+    {
+      dict.Add("A", "B");
+      dict.Add("A", "B");
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void GettingNonExisting()
+    {
+      Console.WriteLine(dict["R"]);
+    }
+
+
+    [Test]
+    public void Setter()
+    {
+      dict["R"] = "UYGUY";
+      Assert.AreEqual("UYGUY", dict["R"]);
+      dict["R"] = "UIII";
+      Assert.AreEqual("UIII", dict["R"]);
+      dict["S"] = "VVV";
+      Assert.AreEqual("UIII", dict["R"]);
+      Assert.AreEqual("VVV", dict["S"]);
+      //dict.dump();
+    }
+
+    [Test]
+    public void CombinedOps()
+    {
+      dict["R"] = "UIII";
+      dict["S"] = "VVV";
+      dict["T"] = "XYZ";
+
+      string s;
+
+      Assert.IsTrue(dict.Remove("S", out s));
+      Assert.AreEqual("VVV", s);
+      Assert.IsFalse(dict.Contains("S"));
+      Assert.IsFalse(dict.Remove("A", out s));
+
+      //
+      Assert.IsTrue(dict.Find("T", out s));
+      Assert.AreEqual("XYZ", s);
+      Assert.IsFalse(dict.Find("A", out s));
+
+      //
+      Assert.IsTrue(dict.Update("R", "UHU"));
+      Assert.AreEqual("UHU", dict["R"]);
+      Assert.IsFalse(dict.Update("A", "W"));
+      Assert.IsFalse(dict.Contains("A"));
+
+      //
+      s = "KKK";
+      Assert.IsFalse(dict.FindOrAdd("B", ref s));
+      Assert.AreEqual("KKK", dict["B"]);
+      Assert.IsTrue(dict.FindOrAdd("T", ref s));
+      Assert.AreEqual("XYZ", s);
+
+      //
+      s = "LLL";
+      Assert.IsTrue(dict.UpdateOrAdd("R", s));
+      Assert.AreEqual("LLL", dict["R"]);
+      s = "MMM";
+      Assert.IsFalse(dict.UpdateOrAdd("C", s));
+      Assert.AreEqual("MMM", dict["C"]);
+
+      // bug20071112 fixed 2008-02-03
+      s = "NNN";
+      String old;
+      Assert.IsTrue(dict.UpdateOrAdd("R", s, out old));
+      Assert.AreEqual("NNN", dict["R"]);
+      Assert.AreEqual("LLL", old);
+      s = "OOO";
+      Assert.IsFalse(dict.UpdateOrAdd("D", s, out old));
+      Assert.AreEqual("OOO", dict["D"]);
+      // Unclear which of these is correct:
+      // Assert.AreEqual(null, old);
+      // Assert.AreEqual("OOO", old);
+    }
+
+    [Test]
+    public void DeepBucket()
+    {
+      HashDictionary<int, int> dict2 = new HashDictionary<int, int>();
+
+      for (int i = 0; i < 5; i++)
+        dict2[16 * i] = 5 * i;
+
+      for (int i = 0; i < 5; i++)
+        Assert.AreEqual(5 * i, dict2[16 * i]);
+
+      for (int i = 0; i < 5; i++)
+        dict2[16 * i] = 7 * i + 1;
+
+      for (int i = 0; i < 5; i++)
+        Assert.AreEqual(7 * i + 1, dict2[16 * i]);
+      Assert.IsTrue(dict.Check());
+    }
+  }
+
+
+
+  [TestFixture]
+  public class Enumerators
+  {
+    private HashDictionary<string, string> dict;
+
+    private SCG.IEnumerator<KeyValuePair<string, string>> dictenum;
+
+
+    [SetUp]
+    public void Init()
+    {
+      dict = new HashDictionary<string, string>();
+      dict["S"] = "A";
+      dict["T"] = "B";
+      dict["R"] = "C";
+      dictenum = dict.GetEnumerator();
+    }
+
+
+    [TearDown]
+    public void Dispose()
+    {
+      dictenum = null;
+      dict = null;
+    }
+
+
+    [Test]
+    public void Keys()
+    {
+      SCG.IEnumerator<string> keys = dict.Keys.GetEnumerator();
+
+      Assert.IsTrue(keys.MoveNext());
+      Assert.AreEqual("R", keys.Current);
+      Assert.IsTrue(keys.MoveNext());
+      Assert.AreEqual("T", keys.Current);
+      Assert.IsTrue(keys.MoveNext());
+      Assert.AreEqual("S", keys.Current);
+      Assert.IsFalse(keys.MoveNext());
+    }
+
+
+    [Test]
+    public void Values()
+    {
+      SCG.IEnumerator<string> values = dict.Values.GetEnumerator();
+
+      Assert.IsTrue(values.MoveNext());
+      Assert.AreEqual("C", values.Current);
+      Assert.IsTrue(values.MoveNext());
+      Assert.AreEqual("B", values.Current);
+      Assert.IsTrue(values.MoveNext());
+      Assert.AreEqual("A", values.Current);
+      Assert.IsFalse(values.MoveNext());
+    }
+
+    [Test]
+    public void Fun()
+    {
+      Assert.AreEqual("B", dict.Fun("T"));
+    }
+
+
+    [Test]
+    public void NormalUse()
+    {
+      Assert.IsTrue(dictenum.MoveNext());
+      Assert.AreEqual(dictenum.Current, new KeyValuePair<string, string>("R", "C"));
+      Assert.IsTrue(dictenum.MoveNext());
+      Assert.AreEqual(dictenum.Current, new KeyValuePair<string, string>("T", "B"));
+      Assert.IsTrue(dictenum.MoveNext());
+      Assert.AreEqual(dictenum.Current, new KeyValuePair<string, string>("S", "A"));
+      Assert.IsFalse(dictenum.MoveNext());
+    }
+  }
+}
+
+
+
+
+
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/hashing/HashTableTests.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/hashing/HashTableTests.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/hashing/HashTableTests.cs	(revision 3)
@@ -0,0 +1,1106 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+namespace C5UnitTests.hashtable.set
+{
+  using CollectionOfInt = HashSet<int>;
+
+  [TestFixture]
+  public class GenericTesters
+  {
+    [Test]
+    public void TestEvents()
+    {
+      Fun<CollectionOfInt> factory = delegate() { return new CollectionOfInt(TenEqualityComparer.Default); };
+      new C5UnitTests.Templates.Events.CollectionTester<CollectionOfInt>().Test(factory);
+    }
+
+    [Test]
+    public void Extensible()
+    {
+      C5UnitTests.Templates.Extensible.Clone.Tester<CollectionOfInt>();
+      C5UnitTests.Templates.Extensible.Serialization.Tester<CollectionOfInt>();
+    }
+  }
+
+  static class Factory
+  {
+    public static ICollection<T> New<T>() { return new HashSet<T>(); }
+  }
+
+
+  namespace Enumerable
+  {
+    [TestFixture]
+    public class Multiops
+    {
+      private HashSet<int> list;
+
+      private Fun<int, bool> always, never, even;
+
+
+      [SetUp]
+      public void Init()
+      {
+        list = new HashSet<int>();
+        always = delegate { return true; };
+        never = delegate { return false; };
+        even = delegate(int i) { return i % 2 == 0; };
+      }
+
+
+      [Test]
+      public void All()
+      {
+        Assert.IsTrue(list.All(always));
+        Assert.IsTrue(list.All(never));
+        Assert.IsTrue(list.All(even));
+        list.Add(0);
+        Assert.IsTrue(list.All(always));
+        Assert.IsFalse(list.All(never));
+        Assert.IsTrue(list.All(even));
+        list.Add(5);
+        Assert.IsTrue(list.All(always));
+        Assert.IsFalse(list.All(never));
+        Assert.IsFalse(list.All(even));
+      }
+
+
+      [Test]
+      public void Exists()
+      {
+        Assert.IsFalse(list.Exists(always));
+        Assert.IsFalse(list.Exists(never));
+        Assert.IsFalse(list.Exists(even));
+        list.Add(5);
+        Assert.IsTrue(list.Exists(always));
+        Assert.IsFalse(list.Exists(never));
+        Assert.IsFalse(list.Exists(even));
+        list.Add(8);
+        Assert.IsTrue(list.Exists(always));
+        Assert.IsFalse(list.Exists(never));
+        Assert.IsTrue(list.Exists(even));
+      }
+
+
+      [Test]
+      public void Apply()
+      {
+        int sum = 0;
+        Act<int> a = delegate(int i) { sum = i + 10 * sum; };
+
+        list.Apply(a);
+        Assert.AreEqual(0, sum);
+        sum = 0;
+        list.Add(5); list.Add(8); list.Add(7); list.Add(5);
+        list.Apply(a);
+        Assert.AreEqual(758, sum);
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+
+
+
+    [TestFixture]
+    public class GetEnumerator
+    {
+      private HashSet<int> hashset;
+
+
+      [SetUp]
+      public void Init() { hashset = new HashSet<int>(); }
+
+
+      [Test]
+      public void Empty()
+      {
+        SCG.IEnumerator<int> e = hashset.GetEnumerator();
+
+        Assert.IsFalse(e.MoveNext());
+      }
+
+
+      [Test]
+      public void Normal()
+      {
+        hashset.Add(5);
+        hashset.Add(8);
+        hashset.Add(5);
+        hashset.Add(5);
+        hashset.Add(10);
+        hashset.Add(1);
+        hashset.Add(16);
+        hashset.Add(18);
+        hashset.Add(17);
+        hashset.Add(33);
+        Assert.IsTrue(IC.seteq(hashset, 1, 5, 8, 10, 16, 17, 18, 33));
+      }
+
+      [Test]
+      public void DoDispose()
+      {
+        hashset.Add(5);
+        hashset.Add(8);
+        hashset.Add(5);
+
+        SCG.IEnumerator<int> e = hashset.GetEnumerator();
+
+        e.MoveNext();
+        e.MoveNext();
+        e.Dispose();
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterUpdate()
+      {
+        hashset.Add(5);
+        hashset.Add(8);
+        hashset.Add(5);
+
+        SCG.IEnumerator<int> e = hashset.GetEnumerator();
+
+        e.MoveNext();
+        hashset.Add(99);
+        e.MoveNext();
+      }
+
+
+      [TearDown]
+      public void Dispose() { hashset = null; }
+    }
+  }
+
+  namespace CollectionOrSink
+  {
+    [TestFixture]
+    public class Formatting
+    {
+      ICollection<int> coll;
+      IFormatProvider rad16;
+      [SetUp]
+      public void Init() { coll = Factory.New<int>(); rad16 = new RadixFormatProvider(16); }
+      [TearDown]
+      public void Dispose() { coll = null; rad16 = null; }
+      [Test]
+      public void Format()
+      {
+        Assert.AreEqual("{  }", coll.ToString());
+        coll.AddAll<int>(new int[] { -4, 28, 129, 65530 });
+        Assert.AreEqual("{ 65530, -4, 28, 129 }", coll.ToString());
+        Assert.AreEqual("{ FFFA, -4, 1C, 81 }", coll.ToString(null, rad16));
+        Assert.AreEqual("{ 65530, -4, ... }", coll.ToString("L14", null));
+        Assert.AreEqual("{ FFFA, -4, ... }", coll.ToString("L14", rad16));
+      }
+    }
+
+    [TestFixture]
+    public class CollectionOrSink
+    {
+      private HashSet<int> hashset;
+
+
+      [SetUp]
+      public void Init() { hashset = new HashSet<int>(); }
+
+      [Test]
+      public void Choose()
+      {
+        hashset.Add(7);
+        Assert.AreEqual(7, hashset.Choose());
+      }
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void BadChoose()
+      {
+        hashset.Choose();
+      }
+
+      [Test]
+      public void CountEtAl()
+      {
+        Assert.AreEqual(0, hashset.Count);
+        Assert.IsTrue(hashset.IsEmpty);
+        Assert.IsFalse(hashset.AllowsDuplicates);
+        Assert.IsTrue(hashset.Add(0));
+        Assert.AreEqual(1, hashset.Count);
+        Assert.IsFalse(hashset.IsEmpty);
+        Assert.IsTrue(hashset.Add(5));
+        Assert.AreEqual(2, hashset.Count);
+        Assert.IsFalse(hashset.Add(5));
+        Assert.AreEqual(2, hashset.Count);
+        Assert.IsFalse(hashset.IsEmpty);
+        Assert.IsTrue(hashset.Add(8));
+        Assert.AreEqual(3, hashset.Count);
+      }
+
+
+      [Test]
+      public void AddAll()
+      {
+        hashset.Add(3); hashset.Add(4); hashset.Add(5);
+
+        HashSet<int> hashset2 = new HashSet<int>();
+
+        hashset2.AddAll(hashset);
+        Assert.IsTrue(IC.seteq(hashset2, 3, 4, 5));
+        hashset.Add(9);
+        hashset.AddAll(hashset2);
+        Assert.IsTrue(IC.seteq(hashset2, 3, 4, 5));
+        Assert.IsTrue(IC.seteq(hashset, 3, 4, 5, 9));
+      }
+
+
+      [TearDown]
+      public void Dispose() { hashset = null; }
+    }
+
+    [TestFixture]
+    public class FindPredicate
+    {
+      private HashSet<int> list;
+      Fun<int, bool> pred;
+
+      [SetUp]
+      public void Init()
+      {
+        list = new HashSet<int>(TenEqualityComparer.Default);
+        pred = delegate(int i) { return i % 5 == 0; };
+      }
+
+      [TearDown]
+      public void Dispose() { list = null; }
+
+      [Test]
+      public void Find()
+      {
+        int i;
+        Assert.IsFalse(list.Find(pred, out i));
+        list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+        Assert.IsFalse(list.Find(pred, out i));
+        list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+        Assert.IsTrue(list.Find(pred, out i));
+        Assert.AreEqual(45, i);
+      }
+    }
+
+    [TestFixture]
+    public class UniqueItems
+    {
+      private HashSet<int> list;
+
+      [SetUp]
+      public void Init() { list = new HashSet<int>(); }
+
+      [TearDown]
+      public void Dispose() { list = null; }
+
+      [Test]
+      public void Test()
+      {
+        Assert.IsTrue(IC.seteq(list.UniqueItems()));
+        Assert.IsTrue(IC.seteq(list.ItemMultiplicities()));
+        list.AddAll<int>(new int[] { 7, 9, 7 });
+        Assert.IsTrue(IC.seteq(list.UniqueItems(), 7, 9));
+        Assert.IsTrue(IC.seteq(list.ItemMultiplicities(), 7, 1, 9, 1));
+      }
+    }
+
+    [TestFixture]
+    public class ArrayTest
+    {
+      private HashSet<int> hashset;
+
+      int[] a;
+
+
+      [SetUp]
+      public void Init()
+      {
+        hashset = new HashSet<int>();
+        a = new int[10];
+        for (int i = 0; i < 10; i++)
+          a[i] = 1000 + i;
+      }
+
+
+      [TearDown]
+      public void Dispose() { hashset = null; }
+
+
+      private string aeq(int[] a, params int[] b)
+      {
+        if (a.Length != b.Length)
+          return "Lengths differ: " + a.Length + " != " + b.Length;
+
+        for (int i = 0; i < a.Length; i++)
+          if (a[i] != b[i])
+            return String.Format("{0}'th elements differ: {1} != {2}", i, a[i], b[i]);
+
+        return "Alles klar";
+      }
+
+
+      [Test]
+      public void ToArray()
+      {
+        Assert.AreEqual("Alles klar", aeq(hashset.ToArray()));
+        hashset.Add(7);
+        hashset.Add(3);
+        hashset.Add(10);
+
+        int[] r = hashset.ToArray();
+
+        Array.Sort(r);
+        Assert.AreEqual("Alles klar", aeq(r, 3, 7, 10));
+      }
+
+
+      [Test]
+      public void CopyTo()
+      {
+        //Note: for small ints the itemequalityComparer is the identity!
+        hashset.CopyTo(a, 1);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+        hashset.Add(6);
+        hashset.CopyTo(a, 2);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+        hashset.Add(4);
+        hashset.Add(9);
+        hashset.CopyTo(a, 4);
+
+        //TODO: make test independent on onterequalityComparer
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 9, 4, 1007, 1008, 1009));
+        hashset.Clear();
+        hashset.Add(7);
+        hashset.CopyTo(a, 9);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 9, 4, 1007, 1008, 7));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void CopyToBad()
+      {
+        hashset.CopyTo(a, 11);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void CopyToBad2()
+      {
+        hashset.CopyTo(a, -1);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void CopyToTooFar()
+      {
+        hashset.Add(3);
+        hashset.Add(8);
+        hashset.CopyTo(a, 9);
+      }
+    }
+  }
+
+  namespace EditableCollection
+  {
+    [TestFixture]
+    public class Collision
+    {
+      HashSet<int> hashset;
+
+
+      [SetUp]
+      public void Init()
+      {
+        hashset = new HashSet<int>();
+      }
+
+
+      [Test]
+      public void SingleCollision()
+      {
+        hashset.Add(7);
+        hashset.Add(7 - 1503427877);
+
+        //foreach (int cell in hashset) Console.WriteLine("A: {0}", cell);
+        hashset.Remove(7);
+        Assert.IsTrue(hashset.Contains(7 - 1503427877));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        hashset = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class Searching
+    {
+      private HashSet<int> hashset;
+
+
+      [SetUp]
+      public void Init() { hashset = new HashSet<int>(); }
+
+
+      [Test]
+      [ExpectedException(typeof(NullReferenceException))]
+      public void NullEqualityComparerinConstructor1()
+      {
+        new HashSet<int>(null);
+      }
+
+      [Test]
+      [ExpectedException(typeof(NullReferenceException))]
+      public void NullEqualityComparerinConstructor2()
+      {
+        new HashSet<int>(5, null);
+      }
+
+      [Test]
+      [ExpectedException(typeof(NullReferenceException))]
+      public void NullEqualityComparerinConstructor3()
+      {
+        new HashSet<int>(5, 0.5, null);
+      }
+
+      [Test]
+      public void Contains()
+      {
+        Assert.IsFalse(hashset.Contains(5));
+        hashset.Add(5);
+        Assert.IsTrue(hashset.Contains(5));
+        Assert.IsFalse(hashset.Contains(7));
+        hashset.Add(8);
+        hashset.Add(10);
+        Assert.IsTrue(hashset.Contains(5));
+        Assert.IsFalse(hashset.Contains(7));
+        Assert.IsTrue(hashset.Contains(8));
+        Assert.IsTrue(hashset.Contains(10));
+        hashset.Remove(8);
+        Assert.IsTrue(hashset.Contains(5));
+        Assert.IsFalse(hashset.Contains(7));
+        Assert.IsFalse(hashset.Contains(8));
+        Assert.IsTrue(hashset.Contains(10));
+        hashset.Add(0); hashset.Add(16); hashset.Add(32); hashset.Add(48); hashset.Add(64);
+        Assert.IsTrue(hashset.Contains(0));
+        Assert.IsTrue(hashset.Contains(16));
+        Assert.IsTrue(hashset.Contains(32));
+        Assert.IsTrue(hashset.Contains(48));
+        Assert.IsTrue(hashset.Contains(64));
+        Assert.IsTrue(hashset.Check());
+
+        int i = 0, j = i;
+
+        Assert.IsTrue(hashset.Find(ref i));
+        Assert.AreEqual(j, i);
+        j = i = 16;
+        Assert.IsTrue(hashset.Find(ref i));
+        Assert.AreEqual(j, i);
+        j = i = 32;
+        Assert.IsTrue(hashset.Find(ref i));
+        Assert.AreEqual(j, i);
+        j = i = 48;
+        Assert.IsTrue(hashset.Find(ref i));
+        Assert.AreEqual(j, i);
+        j = i = 64;
+        Assert.IsTrue(hashset.Find(ref i));
+        Assert.AreEqual(j, i);
+        j = i = 80;
+        Assert.IsFalse(hashset.Find(ref i));
+        Assert.AreEqual(j, i);
+      }
+
+
+      [Test]
+      public void Many()
+      {
+        int j = 7373;
+        int[] a = new int[j];
+
+        for (int i = 0; i < j; i++)
+        {
+          hashset.Add(3 * i + 1);
+          a[i] = 3 * i + 1;
+        }
+
+        Assert.IsTrue(IC.seteq(hashset, a));
+      }
+
+
+      [Test]
+      public void ContainsCount()
+      {
+        Assert.AreEqual(0, hashset.ContainsCount(5));
+        hashset.Add(5);
+        Assert.AreEqual(1, hashset.ContainsCount(5));
+        Assert.AreEqual(0, hashset.ContainsCount(7));
+        hashset.Add(8);
+        Assert.AreEqual(1, hashset.ContainsCount(5));
+        Assert.AreEqual(0, hashset.ContainsCount(7));
+        Assert.AreEqual(1, hashset.ContainsCount(8));
+        hashset.Add(5);
+        Assert.AreEqual(1, hashset.ContainsCount(5));
+        Assert.AreEqual(0, hashset.ContainsCount(7));
+        Assert.AreEqual(1, hashset.ContainsCount(8));
+      }
+
+
+      [Test]
+      public void RemoveAllCopies()
+      {
+        hashset.Add(5); hashset.Add(7); hashset.Add(5);
+        Assert.AreEqual(1, hashset.ContainsCount(5));
+        Assert.AreEqual(1, hashset.ContainsCount(7));
+        hashset.RemoveAllCopies(5);
+        Assert.AreEqual(0, hashset.ContainsCount(5));
+        Assert.AreEqual(1, hashset.ContainsCount(7));
+        hashset.Add(5); hashset.Add(8); hashset.Add(5);
+        hashset.RemoveAllCopies(8);
+        Assert.IsTrue(IC.eq(hashset, 7, 5));
+      }
+
+
+      [Test]
+      public void ContainsAll()
+      {
+        HashSet<int> list2 = new HashSet<int>();
+
+        Assert.IsTrue(hashset.ContainsAll(list2));
+        list2.Add(4);
+        Assert.IsFalse(hashset.ContainsAll(list2));
+        hashset.Add(4);
+        Assert.IsTrue(hashset.ContainsAll(list2));
+        hashset.Add(5);
+        Assert.IsTrue(hashset.ContainsAll(list2));
+        list2.Add(20);
+        Assert.IsFalse(hashset.ContainsAll(list2));
+        hashset.Add(20);
+        Assert.IsTrue(hashset.ContainsAll(list2));
+      }
+
+
+      [Test]
+      public void RetainAll()
+      {
+        HashSet<int> list2 = new HashSet<int>();
+
+        hashset.Add(4); hashset.Add(5); hashset.Add(6);
+        list2.Add(5); list2.Add(4); list2.Add(7);
+        hashset.RetainAll(list2);
+        Assert.IsTrue(IC.seteq(hashset, 4, 5));
+        hashset.Add(6);
+        list2.Clear();
+        list2.Add(7); list2.Add(8); list2.Add(9);
+        hashset.RetainAll(list2);
+        Assert.IsTrue(IC.seteq(hashset));
+      }
+
+      //Bug in RetainAll reported by Chris Fesler
+      //The result has different bitsc 
+      [Test]
+      public void RetainAll2()
+      {
+        int LARGE_ARRAY_SIZE = 30;
+        int LARGE_ARRAY_MID = 15;
+        string[] _largeArrayOne = new string[LARGE_ARRAY_SIZE];
+        string[] _largeArrayTwo = new string[LARGE_ARRAY_SIZE];
+        for (int i = 0; i < LARGE_ARRAY_SIZE; i++)
+        {
+          _largeArrayOne[i] = "" + i;
+          _largeArrayTwo[i] = "" + (i + LARGE_ARRAY_MID);
+        }
+
+        HashSet<string> setOne = new HashSet<string>();
+        setOne.AddAll(_largeArrayOne);
+
+        HashSet<string> setTwo = new HashSet<string>();
+        setTwo.AddAll(_largeArrayTwo);
+
+        setOne.RetainAll(setTwo);
+
+        Assert.IsTrue(setOne.Check(),"setOne check fails");
+
+        for (int i = LARGE_ARRAY_MID; i < LARGE_ARRAY_SIZE; i++)
+          Assert.IsTrue(setOne.Contains(_largeArrayOne[i]), "missing " + i);
+      }
+
+      [Test]
+      public void RemoveAll()
+      {
+        HashSet<int> list2 = new HashSet<int>();
+
+        hashset.Add(4); hashset.Add(5); hashset.Add(6);
+        list2.Add(5); list2.Add(7); list2.Add(4);
+        hashset.RemoveAll(list2);
+        Assert.IsTrue(IC.eq(hashset, 6));
+        hashset.Add(5); hashset.Add(4);
+        list2.Clear();
+        list2.Add(6); list2.Add(5);
+        hashset.RemoveAll(list2);
+        Assert.IsTrue(IC.eq(hashset, 4));
+        list2.Clear();
+        list2.Add(7); list2.Add(8); list2.Add(9);
+        hashset.RemoveAll(list2);
+        Assert.IsTrue(IC.eq(hashset, 4));
+      }
+
+
+      [Test]
+      public void Remove()
+      {
+        hashset.Add(4); hashset.Add(4); hashset.Add(5); hashset.Add(4); hashset.Add(6);
+        Assert.IsFalse(hashset.Remove(2));
+        Assert.IsTrue(hashset.Remove(4));
+        Assert.IsTrue(IC.seteq(hashset, 5, 6));
+        hashset.Add(7);
+        hashset.Add(21); hashset.Add(37); hashset.Add(53); hashset.Add(69); hashset.Add(85);
+        Assert.IsTrue(hashset.Remove(5));
+        Assert.IsTrue(IC.seteq(hashset, 6, 7, 21, 37, 53, 69, 85));
+        Assert.IsFalse(hashset.Remove(165));
+        Assert.IsTrue(IC.seteq(hashset, 6, 7, 21, 37, 53, 69, 85));
+        Assert.IsTrue(hashset.Remove(53));
+        Assert.IsTrue(IC.seteq(hashset, 6, 7, 21, 37, 69, 85));
+        Assert.IsTrue(hashset.Remove(37));
+        Assert.IsTrue(IC.seteq(hashset, 6, 7, 21, 69, 85));
+        Assert.IsTrue(hashset.Remove(85));
+        Assert.IsTrue(IC.seteq(hashset, 6, 7, 21, 69));
+      }
+
+
+      [Test]
+      public void Clear()
+      {
+        hashset.Add(7); hashset.Add(7);
+        hashset.Clear();
+        Assert.IsTrue(hashset.IsEmpty);
+      }
+
+
+      [TearDown]
+      public void Dispose() { hashset = null; }
+    }
+
+    [TestFixture]
+    public class Combined
+    {
+      private ICollection<KeyValuePair<int, int>> lst;
+
+
+      [SetUp]
+      public void Init()
+      {
+        lst = new HashSet<KeyValuePair<int, int>>(new KeyValuePairEqualityComparer<int, int>());
+        for (int i = 0; i < 10; i++)
+          lst.Add(new KeyValuePair<int, int>(i, i + 30));
+      }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void Find()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.Find(ref p));
+        Assert.AreEqual(3, p.Key);
+        Assert.AreEqual(33, p.Value);
+        p = new KeyValuePair<int, int>(13, 78);
+        Assert.IsFalse(lst.Find(ref p));
+      }
+
+
+      [Test]
+      public void FindOrAdd()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+        KeyValuePair<int, int> q = new KeyValuePair<int, int>();
+
+        Assert.IsTrue(lst.FindOrAdd(ref p));
+        Assert.AreEqual(3, p.Key);
+        Assert.AreEqual(33, p.Value);
+        p = new KeyValuePair<int, int>(13, 79);
+        Assert.IsFalse(lst.FindOrAdd(ref p));
+        q.Key = 13;
+        Assert.IsTrue(lst.Find(ref q));
+        Assert.AreEqual(13, q.Key);
+        Assert.AreEqual(79, q.Value);
+      }
+
+
+      [Test]
+      public void Update()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+        KeyValuePair<int, int> q = new KeyValuePair<int, int>();
+
+        Assert.IsTrue(lst.Update(p));
+        q.Key = 3;
+        Assert.IsTrue(lst.Find(ref q));
+        Assert.AreEqual(3, q.Key);
+        Assert.AreEqual(78, q.Value);
+        p = new KeyValuePair<int, int>(13, 78);
+        Assert.IsFalse(lst.Update(p));
+      }
+
+
+      [Test]
+      public void UpdateOrAdd1()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+        KeyValuePair<int, int> q = new KeyValuePair<int, int>();
+
+        Assert.IsTrue(lst.UpdateOrAdd(p));
+        q.Key = 3;
+        Assert.IsTrue(lst.Find(ref q));
+        Assert.AreEqual(3, q.Key);
+        Assert.AreEqual(78, q.Value);
+        p = new KeyValuePair<int, int>(13, 79);
+        Assert.IsFalse(lst.UpdateOrAdd(p));
+        q.Key = 13;
+        Assert.IsTrue(lst.Find(ref q));
+        Assert.AreEqual(13, q.Key);
+        Assert.AreEqual(79, q.Value);
+      }
+
+      [Test]
+      public void UpdateOrAdd2()
+      {
+          ICollection<String> coll = new HashSet<String>();
+          // s1 and s2 are distinct objects but contain the same text:
+          String old, s1 = "abc", s2 = ("def" + s1).Substring(3);
+          Assert.IsFalse(coll.UpdateOrAdd(s1, out old));
+          Assert.AreEqual(null, old);
+          Assert.IsTrue(coll.UpdateOrAdd(s2, out old));
+          Assert.IsTrue(Object.ReferenceEquals(s1, old));
+          Assert.IsFalse(Object.ReferenceEquals(s2, old));
+      }
+
+      [Test]
+      public void RemoveWithReturn()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+        //KeyValuePair<int,int> q = new KeyValuePair<int,int>();
+
+        Assert.IsTrue(lst.Remove(p, out p));
+        Assert.AreEqual(3, p.Key);
+        Assert.AreEqual(33, p.Value);
+        p = new KeyValuePair<int, int>(13, 78);
+        Assert.IsFalse(lst.Remove(p, out p));
+      }
+    }
+
+
+  }
+
+
+
+
+  namespace HashingAndEquals
+  {
+    [TestFixture]
+    public class IEditableCollection
+    {
+      private ICollection<int> dit, dat, dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashSet<int>();
+        dat = new HashSet<int>();
+        dut = new HashSet<int>();
+      }
+
+
+      [Test]
+      public void EmptyEmpty()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void EmptyNonEmpty()
+      {
+        dit.Add(3);
+        Assert.IsFalse(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dat.UnsequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void HashVal()
+      {
+        Assert.AreEqual(CHC.unsequencedhashcode(), dit.GetUnsequencedHashCode());
+        dit.Add(3);
+        Assert.AreEqual(CHC.unsequencedhashcode(3), dit.GetUnsequencedHashCode());
+        dit.Add(7);
+        Assert.AreEqual(CHC.unsequencedhashcode(3, 7), dit.GetUnsequencedHashCode());
+        Assert.AreEqual(CHC.unsequencedhashcode(), dut.GetUnsequencedHashCode());
+        dut.Add(3);
+        Assert.AreEqual(CHC.unsequencedhashcode(3), dut.GetUnsequencedHashCode());
+        dut.Add(7);
+        Assert.AreEqual(CHC.unsequencedhashcode(7, 3), dut.GetUnsequencedHashCode());
+      }
+
+
+      [Test]
+      public void EqualHashButDifferent()
+      {
+        dit.Add(-1657792980); dit.Add(-1570288808);
+        dat.Add(1862883298); dat.Add(-272461342);
+        Assert.AreEqual(dit.GetUnsequencedHashCode(), dat.GetUnsequencedHashCode());
+        Assert.IsFalse(dit.UnsequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void Normal()
+      {
+        dit.Add(3);
+        dit.Add(7);
+        dat.Add(3);
+        Assert.IsFalse(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dat.UnsequencedEquals(dit));
+        dat.Add(7);
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsTrue(dat.UnsequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void WrongOrder()
+      {
+        dit.Add(3);
+        dut.Add(3);
+        Assert.IsTrue(dit.UnsequencedEquals(dut));
+        Assert.IsTrue(dut.UnsequencedEquals(dit));
+        dit.Add(7);
+        dut.Add(7);
+        Assert.IsTrue(dit.UnsequencedEquals(dut));
+        Assert.IsTrue(dut.UnsequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void Reflexive()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dit));
+        dit.Add(3);
+        Assert.IsTrue(dit.UnsequencedEquals(dit));
+        dit.Add(7);
+        Assert.IsTrue(dit.UnsequencedEquals(dit));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+        dat = null;
+        dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelUnorderedOfUnOrdered
+    {
+      private ICollection<int> dit, dat, dut;
+
+      private ICollection<ICollection<int>> Dit, Dat, Dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashSet<int>();
+        dat = new HashSet<int>();
+        dut = new HashSet<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        Dit = new HashSet<ICollection<int>>();
+        Dat = new HashSet<ICollection<int>>();
+        Dut = new HashSet<ICollection<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dit.UnsequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Assert.IsTrue(Dit.UnsequencedEquals(Dat));
+        Assert.IsFalse(Dit.UnsequencedEquals(Dut));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = null;
+        Dit = Dat = Dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelOrderedOfUnOrdered
+    {
+      private ICollection<int> dit, dat, dut;
+
+      private ISequenced<ICollection<int>> Dit, Dat, Dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashSet<int>();
+        dat = new HashSet<int>();
+        dut = new HashSet<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        Dit = new LinkedList<ICollection<int>>();
+        Dat = new LinkedList<ICollection<int>>();
+        Dut = new LinkedList<ICollection<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dit.UnsequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Dut.Add(dit); Dut.Add(dut); Dut.Add(dat);
+        Assert.IsFalse(Dit.SequencedEquals(Dat));
+        Assert.IsTrue(Dit.SequencedEquals(Dut));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = null;
+        Dit = Dat = Dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelUnOrderedOfOrdered
+    {
+      private ISequenced<int> dit, dat, dut, dot;
+
+      private ICollection<ISequenced<int>> Dit, Dat, Dut, Dot;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new LinkedList<int>();
+        dat = new LinkedList<int>();
+        dut = new LinkedList<int>();
+        dot = new LinkedList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        dot.Add(2); dot.Add(1);
+        Dit = new HashSet<ISequenced<int>>();
+        Dat = new HashSet<ISequenced<int>>();
+        Dut = new HashSet<ISequenced<int>>();
+        Dot = new HashSet<ISequenced<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsTrue(dit.SequencedEquals(dot));
+        Assert.IsFalse(dit.SequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut);//Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Dut.Add(dot); Dut.Add(dut);//Dut.Add(dit);
+        Dot.Add(dit); Dot.Add(dit); Dot.Add(dut);
+        Assert.IsTrue(Dit.UnsequencedEquals(Dit));
+        Assert.IsTrue(Dit.UnsequencedEquals(Dut));
+        Assert.IsFalse(Dit.UnsequencedEquals(Dat));
+        Assert.IsTrue(Dit.UnsequencedEquals(Dot));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = dot = null;
+        Dit = Dat = Dut = Dot = null;
+      }
+    }
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/heaps/HeapTests.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/heaps/HeapTests.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/heaps/HeapTests.cs	(revision 3)
@@ -0,0 +1,563 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+namespace C5UnitTests.heaps
+{
+  using CollectionOfInt = IntervalHeap<int>;
+
+  [TestFixture]
+  public class GenericTesters
+  {
+    [Test]
+    public void TestEvents()
+    {
+      Fun<CollectionOfInt> factory = delegate() { return new CollectionOfInt(TenEqualityComparer.Default); };
+      new C5UnitTests.Templates.Events.PriorityQueueTester<CollectionOfInt>().Test(factory);
+    }
+
+    [Test]
+    public void Extensible()
+    {
+      C5UnitTests.Templates.Extensible.Clone.Tester<CollectionOfInt>();
+      C5UnitTests.Templates.Extensible.Serialization.Tester<CollectionOfInt>();
+    }
+  }
+
+  [TestFixture]
+  public class Events
+  {
+    IPriorityQueue<int> queue;
+    ArrayList<KeyValuePair<Acts, int>> events;
+
+
+    [SetUp]
+    public void Init()
+    {
+      queue = new IntervalHeap<int>();
+      events = new ArrayList<KeyValuePair<Acts, int>>();
+    }
+
+
+    [TearDown]
+    public void Dispose() { queue = null; events = null; }
+
+    [Test]
+    public void Listenable()
+    {
+      Assert.AreEqual(EventTypeEnum.Basic, queue.ListenableEvents);
+    }
+
+    enum Acts
+    {
+      Add, Remove, Changed
+    }
+
+    [Test]
+    public void Direct()
+    {
+      CollectionChangedHandler<int> cch;
+      ItemsAddedHandler<int> iah;
+      ItemsRemovedHandler<int> irh;
+      Assert.AreEqual(EventTypeEnum.None, queue.ActiveEvents);
+      queue.CollectionChanged += (cch = new CollectionChangedHandler<int>(queue_CollectionChanged));
+      Assert.AreEqual(EventTypeEnum.Changed, queue.ActiveEvents);
+      queue.ItemsAdded += (iah = new ItemsAddedHandler<int>(queue_ItemAdded));
+      Assert.AreEqual(EventTypeEnum.Changed | EventTypeEnum.Added, queue.ActiveEvents);
+      queue.ItemsRemoved += (irh = new ItemsRemovedHandler<int>(queue_ItemRemoved));
+      Assert.AreEqual(EventTypeEnum.Changed | EventTypeEnum.Added | EventTypeEnum.Removed, queue.ActiveEvents);
+      queue.Add(34);
+      queue.Add(56);
+      queue.AddAll<int>(new int[] { });
+      queue.Add(34);
+      queue.Add(12);
+      queue.DeleteMax();
+      queue.DeleteMin();
+      queue.AddAll<int>(new int[] { 4, 5, 6, 2 });
+      Assert.AreEqual(17, events.Count);
+      int[] vals = { 34, 0, 56, 0, 34, 0, 12, 0, 56, 0, 12, 0, 4, 5, 6, 2, 0 };
+      Acts[] acts = { Acts.Add, Acts.Changed, Acts.Add, Acts.Changed, Acts.Add, Acts.Changed, Acts.Add, Acts.Changed, 
+                Acts.Remove, Acts.Changed, Acts.Remove, Acts.Changed, Acts.Add, Acts.Add, Acts.Add, Acts.Add, Acts.Changed };
+      for (int i = 0; i < vals.Length; i++)
+      {
+        //Console.WriteLine("{0}", events[cell]);
+        Assert.AreEqual(acts[i], events[i].Key, "Action " + i);
+        Assert.AreEqual(vals[i], events[i].Value, "Value " + i);
+      }
+      queue.CollectionChanged -= cch;
+      Assert.AreEqual(EventTypeEnum.Added | EventTypeEnum.Removed, queue.ActiveEvents);
+      queue.ItemsAdded -= iah;
+      Assert.AreEqual(EventTypeEnum.Removed, queue.ActiveEvents);
+      queue.ItemsRemoved -= irh;
+      Assert.AreEqual(EventTypeEnum.None, queue.ActiveEvents);
+    }
+
+    [Test]
+    public void Guarded()
+    {
+      ICollectionValue<int> guarded = new GuardedCollectionValue<int>(queue);
+      guarded.CollectionChanged += new CollectionChangedHandler<int>(queue_CollectionChanged);
+      guarded.ItemsAdded += new ItemsAddedHandler<int>(queue_ItemAdded);
+      guarded.ItemsRemoved += new ItemsRemovedHandler<int>(queue_ItemRemoved);
+      queue.Add(34);
+      queue.Add(56);
+      queue.Add(34);
+      queue.Add(12);
+      queue.DeleteMax();
+      queue.DeleteMin();
+      queue.AddAll<int>(new int[] { 4, 5, 6, 2 });
+      Assert.AreEqual(17, events.Count);
+      int[] vals = { 34, 0, 56, 0, 34, 0, 12, 0, 56, 0, 12, 0, 4, 5, 6, 2, 0 };
+      Acts[] acts = { Acts.Add, Acts.Changed, Acts.Add, Acts.Changed, Acts.Add, Acts.Changed, Acts.Add, Acts.Changed, 
+                Acts.Remove, Acts.Changed, Acts.Remove, Acts.Changed, Acts.Add, Acts.Add, Acts.Add, Acts.Add, Acts.Changed };
+      for (int i = 0; i < vals.Length; i++)
+      {
+        //Console.WriteLine("{0}", events[cell]);
+        Assert.AreEqual(vals[i], events[i].Value);
+        Assert.AreEqual(acts[i], events[i].Key);
+      }
+    }
+
+
+    void queue_CollectionChanged(object sender)
+    {
+      events.Add(new KeyValuePair<Acts, int>(Acts.Changed, 0));
+    }
+    void queue_ItemAdded(object sender, ItemCountEventArgs<int> e)
+    {
+      events.Add(new KeyValuePair<Acts, int>(Acts.Add, e.Item));
+    }
+    void queue_ItemRemoved(object sender, ItemCountEventArgs<int> e)
+    {
+      events.Add(new KeyValuePair<Acts, int>(Acts.Remove, e.Item));
+    }
+  }
+
+  [TestFixture]
+  public class Formatting
+  {
+    IntervalHeap<int> coll;
+    IFormatProvider rad16;
+    [SetUp]
+    public void Init() { coll = new IntervalHeap<int>(); rad16 = new RadixFormatProvider(16); }
+    [TearDown]
+    public void Dispose() { coll = null; rad16 = null; }
+    [Test]
+    public void Format()
+    {
+      Assert.AreEqual("{  }", coll.ToString());
+      coll.AddAll<int>(new int[] { -4, 28, 129, 65530 });
+      Assert.AreEqual("{ -4, 65530, 28, 129 }", coll.ToString());
+      Assert.AreEqual("{ -4, FFFA, 1C, 81 }", coll.ToString(null, rad16));
+      Assert.AreEqual("{ -4, 65530, ... }", coll.ToString("L14", null));
+      Assert.AreEqual("{ -4, FFFA, ... }", coll.ToString("L14", rad16));
+    }
+  }
+
+
+  [TestFixture]
+  public class IntervalHeapTests
+  {
+    IPriorityQueue<int> queue;
+
+
+    [SetUp]
+    public void Init() { queue = new IntervalHeap<int>(); }
+
+
+    [TearDown]
+    public void Dispose() { queue = null; }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor1()
+    {
+      new IntervalHeap<int>(null);
+    }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor2()
+    {
+      new IntervalHeap<int>(5, null);
+    }
+
+    [Test]
+    public void Handles()
+    {
+      IPriorityQueueHandle<int>[] handles = new IPriorityQueueHandle<int>[10];
+
+      queue.Add(ref handles[0], 7);
+      Assert.IsTrue(queue.Check());
+      queue.Add(ref handles[1], 72);
+      Assert.IsTrue(queue.Check());
+      queue.Add(ref handles[2], 27);
+      Assert.IsTrue(queue.Check());
+      queue.Add(ref handles[3], 17);
+      Assert.IsTrue(queue.Check());
+      queue.Add(ref handles[4], 70);
+      Assert.IsTrue(queue.Check());
+      queue.Add(ref handles[5], 1);
+      Assert.IsTrue(queue.Check());
+      queue.Add(ref handles[6], 2);
+      Assert.IsTrue(queue.Check());
+      queue.Add(ref handles[7], 7);
+      Assert.IsTrue(queue.Check());
+      queue.Add(ref handles[8], 8);
+      Assert.IsTrue(queue.Check());
+      queue.Add(ref handles[9], 9);
+      Assert.IsTrue(queue.Check());
+      queue.Delete(handles[2]);
+      Assert.IsTrue(queue.Check());
+      queue.Delete(handles[0]);
+      Assert.IsTrue(queue.Check());
+      queue.Delete(handles[8]);
+      Assert.IsTrue(queue.Check());
+      queue.Delete(handles[4]);
+      Assert.IsTrue(queue.Check());
+      queue.Delete(handles[6]);
+      Assert.IsTrue(queue.Check());
+      Assert.AreEqual(5, queue.Count);
+    }
+
+    [Test]
+    public void Replace()
+    {
+      IPriorityQueueHandle<int> handle = null;
+      queue.Add(6);
+      queue.Add(10);
+      queue.Add(ref handle, 7);
+      queue.Add(21);
+      Assert.AreEqual(7, queue.Replace(handle, 12));
+      Assert.AreEqual(21, queue.FindMax());
+      Assert.AreEqual(12, queue.Replace(handle, 34));
+      Assert.AreEqual(34, queue.FindMax());
+      Assert.IsTrue(queue.Check());
+      //replace max
+      Assert.AreEqual(34, queue.Replace(handle, 60));
+      Assert.AreEqual(60, queue.FindMax());
+      Assert.AreEqual(60, queue.Replace(handle, queue[handle] + 80));
+      Assert.AreEqual(140, queue.FindMax());
+      Assert.IsTrue(queue.Check());
+    }
+
+    [Test]
+    public void Replace2()
+    {
+      IPriorityQueueHandle<int> handle = null;
+      queue.Add(6);
+      queue.Add(10);
+      queue.Add(ref handle, 7);
+      //Replace last item in queue with something large
+      Assert.AreEqual(7, queue.Replace(handle, 12));
+      Assert.IsTrue(queue.Check());
+    }
+
+    /// <summary>
+    /// Bug by Viet Yen Nguyen <v.y.nguyen@alumnus.utwente.nl>
+    /// </summary>
+    [Test]
+    public void Replace3()
+    {
+      IPriorityQueueHandle<int> handle = null;
+      queue.Add(ref handle, 10);
+      Assert.AreEqual(10, queue.Replace(handle, 12));
+      Assert.IsTrue(queue.Check());
+    }
+
+    [Test]
+    public void ReuseHandle()
+    {
+      IPriorityQueueHandle<int> handle = null;
+      queue.Add(ref handle, 7);
+      queue.Delete(handle);
+      queue.Add(ref handle, 8);
+    }
+
+    [Test]
+    [ExpectedException(typeof(InvalidPriorityQueueHandleException))]
+    public void ErrorAddValidHandle()
+    {
+      IPriorityQueueHandle<int> handle = null;
+      queue.Add(ref handle, 7);
+      queue.Add(ref handle, 8);
+    }
+
+    [Test]
+    [ExpectedException(typeof(InvalidPriorityQueueHandleException))]
+    public void ErrorDeleteInvalidHandle()
+    {
+      IPriorityQueueHandle<int> handle = null;
+      queue.Add(ref handle, 7);
+      queue.Delete(handle);
+      queue.Delete(handle);
+    }
+
+    [Test]
+    [ExpectedException(typeof(InvalidPriorityQueueHandleException))]
+    public void ErrorReplaceInvalidHandle()
+    {
+      IPriorityQueueHandle<int> handle = null;
+      queue.Add(ref handle, 7);
+      queue.Delete(handle);
+      queue.Replace(handle, 13);
+    }
+
+    [Test]
+    public void Simple()
+    {
+      Assert.IsTrue(queue.AllowsDuplicates);
+      Assert.AreEqual(0, queue.Count);
+      queue.Add(8); queue.Add(18); queue.Add(8); queue.Add(3);
+      Assert.AreEqual(4, queue.Count);
+      Assert.AreEqual(18, queue.DeleteMax());
+      Assert.AreEqual(3, queue.Count);
+      Assert.AreEqual(3, queue.DeleteMin());
+      Assert.AreEqual(2, queue.Count);
+      Assert.AreEqual(8, queue.FindMax());
+      Assert.AreEqual(8, queue.DeleteMax());
+      Assert.AreEqual(8, queue.FindMax());
+      queue.Add(15);
+      Assert.AreEqual(15, queue.FindMax());
+      Assert.AreEqual(8, queue.FindMin());
+      Assert.IsTrue(queue.Comparer.Compare(2, 3) < 0);
+      Assert.IsTrue(queue.Comparer.Compare(4, 3) > 0);
+      Assert.IsTrue(queue.Comparer.Compare(3, 3) == 0);
+
+    }
+
+
+    [Test]
+    public void Enumerate()
+    {
+      int[] a = new int[4];
+      int siz = 0;
+      foreach (int i in queue)
+        siz++;
+      Assert.AreEqual(0, siz);
+
+      queue.Add(8); queue.Add(18); queue.Add(8); queue.Add(3);
+
+      foreach (int i in queue)
+        a[siz++] = i;
+      Assert.AreEqual(4, siz);
+      Array.Sort(a, 0, siz);
+      Assert.AreEqual(3, a[0]);
+      Assert.AreEqual(8, a[1]);
+      Assert.AreEqual(8, a[2]);
+      Assert.AreEqual(18, a[3]);
+
+      siz = 0;
+      Assert.AreEqual(18, queue.DeleteMax());
+      foreach (int i in queue)
+        a[siz++] = i;
+      Assert.AreEqual(3, siz);
+      Array.Sort(a, 0, siz);
+      Assert.AreEqual(3, a[0]);
+      Assert.AreEqual(8, a[1]);
+      Assert.AreEqual(8, a[2]);
+
+      siz = 0;
+      Assert.AreEqual(8, queue.DeleteMax());
+      foreach (int i in queue)
+        a[siz++] = i;
+      Assert.AreEqual(2, siz);
+      Array.Sort(a, 0, siz);
+      Assert.AreEqual(3, a[0]);
+      Assert.AreEqual(8, a[1]);
+
+      siz = 0;
+      Assert.AreEqual(8, queue.DeleteMax());
+      foreach (int i in queue)
+        a[siz++] = i;
+      Assert.AreEqual(1, siz);
+      Assert.AreEqual(3, a[0]);
+    }
+
+    [Test]
+    public void Random()
+    {
+      int length = 1000;
+      int[] a = new int[length];
+      Random ran = new Random(6754);
+
+      for (int i = 0; i < length; i++)
+        queue.Add(a[i] = ran.Next());
+
+      Assert.IsTrue(queue.Check());
+      Array.Sort(a);
+      for (int i = 0; i < length / 2; i++)
+      {
+        Assert.AreEqual(a[length - i - 1], queue.DeleteMax());
+        Assert.IsTrue(queue.Check());
+        Assert.AreEqual(a[i], queue.DeleteMin());
+        Assert.IsTrue(queue.Check());
+      }
+
+      Assert.IsTrue(queue.IsEmpty);
+    }
+
+    [Test]
+    public void RandomWithHandles()
+    {
+      int length = 1000;
+      int[] a = new int[length];
+      Random ran = new Random(6754);
+
+      for (int i = 0; i < length; i++)
+      {
+        IPriorityQueueHandle<int> h = null;
+        queue.Add(ref h, a[i] = ran.Next());
+        Assert.IsTrue(queue.Check());
+      }
+
+      Assert.IsTrue(queue.Check());
+      Array.Sort(a);
+      for (int i = 0; i < length / 2; i++)
+      {
+        Assert.AreEqual(a[length - i - 1], queue.DeleteMax());
+        Assert.IsTrue(queue.Check());
+        Assert.AreEqual(a[i], queue.DeleteMin());
+        Assert.IsTrue(queue.Check());
+      }
+
+      Assert.IsTrue(queue.IsEmpty);
+    }
+
+    [Test]
+    public void RandomWithDeleteHandles()
+    {
+      Random ran = new Random(6754);
+      int length = 1000;
+      int[] a = new int[length];
+      ArrayList<int> shuffle = new ArrayList<int>(length);
+      IPriorityQueueHandle<int>[] h = new IPriorityQueueHandle<int>[length];
+
+      for (int i = 0; i < length; i++)
+      {
+        shuffle.Add(i);
+        queue.Add(ref h[i], a[i] = ran.Next());
+        Assert.IsTrue(queue.Check());
+      }
+
+      Assert.IsTrue(queue.Check());
+      shuffle.Shuffle(ran);
+      for (int i = 0; i < length; i++)
+      {
+        int j = shuffle[i];
+        Assert.AreEqual(a[j], queue.Delete(h[j]));
+        Assert.IsTrue(queue.Check());
+      }
+
+      Assert.IsTrue(queue.IsEmpty);
+    }
+
+    [Test]
+    public void RandomIndexing()
+    {
+      Random ran = new Random(6754);
+      int length = 1000;
+      int[] a = new int[length];
+      int[] b = new int[length];
+      ArrayList<int> shuffle = new ArrayList<int>(length);
+      IPriorityQueueHandle<int>[] h = new IPriorityQueueHandle<int>[length];
+
+      for (int i = 0; i < length; i++)
+      {
+        shuffle.Add(i);
+        queue.Add(ref h[i], a[i] = ran.Next());
+        b[i] = ran.Next();
+        Assert.IsTrue(queue.Check());
+      }
+
+      Assert.IsTrue(queue.Check());
+      shuffle.Shuffle(ran);
+      for (int i = 0; i < length; i++)
+      {
+        int j = shuffle[i];
+        Assert.AreEqual(a[j], queue[h[j]]);
+        queue[h[j]] = b[j];
+        Assert.AreEqual(b[j], queue[h[j]]);
+        Assert.IsTrue(queue.Check());
+      }
+    }
+
+
+
+    [Test]
+    public void RandomDuplicates()
+    {
+      int length = 1000;
+      int s;
+      int[] a = new int[length];
+      Random ran = new Random(6754);
+
+      for (int i = 0; i < length; i++)
+        queue.Add(a[i] = ran.Next(3, 13));
+      Assert.IsTrue(queue.Check());
+
+      Array.Sort(a);
+
+      for (int i = 0; i < length / 2; i++)
+      {
+        Assert.AreEqual(a[i], queue.DeleteMin());
+        Assert.IsTrue(queue.Check());
+        Assert.AreEqual(a[length - i - 1], s = queue.DeleteMax());
+        Assert.IsTrue(queue.Check());
+      }
+
+      Assert.IsTrue(queue.IsEmpty);
+    }
+
+
+    [Test]
+    public void AddAll()
+    {
+      int length = 1000;
+      int[] a = new int[length];
+      Random ran = new Random(6754);
+
+      LinkedList<int> lst = new LinkedList<int>();
+      for (int i = 0; i < length; i++)
+        lst.Add(a[i] = ran.Next());
+
+      queue.AddAll(lst);
+      Assert.IsTrue(queue.Check());
+      Array.Sort(a);
+      for (int i = 0; i < length / 2; i++)
+      {
+        Assert.AreEqual(a[length - i - 1], queue.DeleteMax());
+        Assert.IsTrue(queue.Check());
+        Assert.AreEqual(a[i], queue.DeleteMin());
+        Assert.IsTrue(queue.Check());
+      }
+
+      Assert.IsTrue(queue.IsEmpty);
+    }
+
+  }
+
+
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/linkedlists/HashedLinkedListTest.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/linkedlists/HashedLinkedListTest.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/linkedlists/HashedLinkedListTest.cs	(revision 3)
@@ -0,0 +1,2924 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+
+namespace C5UnitTests.linkedlists.hashed
+{
+  using CollectionOfInt = HashedLinkedList<int>;
+
+  [TestFixture]
+  public class GenericTesters
+  {
+    [Test]
+    public void TestEvents()
+    {
+      Fun<CollectionOfInt> factory = delegate() { return new CollectionOfInt(TenEqualityComparer.Default); };
+      new C5UnitTests.Templates.Events.ListTester<CollectionOfInt>().Test(factory);
+    }
+
+    [Test]
+    public void Extensible()
+    {
+      C5UnitTests.Templates.Extensible.Clone.Tester<CollectionOfInt>();
+      C5UnitTests.Templates.Extensible.Clone.ViewTester<CollectionOfInt>();
+      C5UnitTests.Templates.Extensible.Serialization.Tester<CollectionOfInt>();
+      C5UnitTests.Templates.Extensible.Serialization.ViewTester<CollectionOfInt>();
+    }
+
+    [Test]
+    public void List()
+    {
+      C5UnitTests.Templates.List.Dispose.Tester<CollectionOfInt>();
+      C5UnitTests.Templates.List.SCG_IList.Tester<CollectionOfInt>();
+    }
+  }
+
+  static class Factory
+  {
+    public static ICollection<T> New<T>() { return new HashedLinkedList<T>(); }
+  }
+
+
+  namespace Enumerable
+  {
+    [TestFixture]
+    public class Multiops
+    {
+      private HashedLinkedList<int> list;
+
+      private Fun<int, bool> always, never, even;
+
+
+      [SetUp]
+      public void Init()
+      {
+        list = new HashedLinkedList<int>();
+        always = delegate { return true; };
+        never = delegate { return false; };
+        even = delegate(int i) { return i % 2 == 0; };
+      }
+
+
+      [Test]
+      public void All()
+      {
+        Assert.IsTrue(list.All(always));
+        Assert.IsTrue(list.All(never));
+        Assert.IsTrue(list.All(even));
+        list.Add(8);
+        Assert.IsTrue(list.All(always));
+        Assert.IsFalse(list.All(never));
+        Assert.IsTrue(list.All(even));
+        list.Add(5);
+        Assert.IsTrue(list.All(always));
+        Assert.IsFalse(list.All(never));
+        Assert.IsFalse(list.All(even));
+      }
+
+
+      [Test]
+      public void Exists()
+      {
+        Assert.IsFalse(list.Exists(always));
+        Assert.IsFalse(list.Exists(never));
+        Assert.IsFalse(list.Exists(even));
+        list.Add(5);
+        Assert.IsTrue(list.Exists(always));
+        Assert.IsFalse(list.Exists(never));
+        Assert.IsFalse(list.Exists(even));
+        list.Add(8);
+        Assert.IsTrue(list.Exists(always));
+        Assert.IsFalse(list.Exists(never));
+        Assert.IsTrue(list.Exists(even));
+      }
+
+
+      [Test]
+      public void Apply()
+      {
+        int sum = 0;
+        Act<int> a = delegate(int i) { sum = i + 10 * sum; };
+
+        list.Apply(a);
+        Assert.AreEqual(0, sum);
+        sum = 0;
+        list.Add(5); list.Add(8); list.Add(7); list.Add(5);
+        list.Apply(a);
+        Assert.AreEqual(587, sum);
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+
+
+
+    [TestFixture]
+    public class GetEnumerator
+    {
+      private HashedLinkedList<int> list;
+
+
+      [SetUp]
+      public void Init() { list = new HashedLinkedList<int>(); }
+
+
+      [Test]
+      public void Empty()
+      {
+        SCG.IEnumerator<int> e = list.GetEnumerator();
+
+        Assert.IsFalse(e.MoveNext());
+      }
+
+
+      [Test]
+      public void Normal()
+      {
+        list.Add(5);
+        list.Add(8);
+        list.Add(5);
+        list.Add(5);
+        list.Add(10);
+        list.Add(1);
+
+        SCG.IEnumerator<int> e = list.GetEnumerator();
+
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(5, e.Current);
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(8, e.Current);
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(10, e.Current);
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(1, e.Current);
+        Assert.IsFalse(e.MoveNext());
+      }
+
+
+      [Test]
+      public void DoDispose()
+      {
+        list.Add(5);
+        list.Add(8);
+        list.Add(5);
+
+        SCG.IEnumerator<int> e = list.GetEnumerator();
+
+        e.MoveNext();
+        e.MoveNext();
+        e.Dispose();
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterUpdate()
+      {
+        list.Add(5);
+        list.Add(8);
+        list.Add(5);
+
+        SCG.IEnumerator<int> e = list.GetEnumerator();
+
+        e.MoveNext();
+        list.Add(99);
+        e.MoveNext();
+      }
+
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+  }
+
+  namespace CollectionOrSink
+  {
+    [TestFixture]
+    public class Formatting
+    {
+      ICollection<int> coll;
+      IFormatProvider rad16;
+      [SetUp]
+      public void Init() { coll = Factory.New<int>(); rad16 = new RadixFormatProvider(16); }
+      [TearDown]
+      public void Dispose() { coll = null; rad16 = null; }
+      [Test]
+      public void Format()
+      {
+        Assert.AreEqual("[  ]", coll.ToString());
+        coll.AddAll<int>(new int[] { -4, 28, 129, 65530 });
+        Assert.AreEqual("[ -4, 28, 129, 65530 ]", coll.ToString());
+        Assert.AreEqual("[ -4, 1C, 81, FFFA ]", coll.ToString(null, rad16));
+        Assert.AreEqual("[ -4, 28, 129... ]", coll.ToString("L14", null));
+        Assert.AreEqual("[ -4, 1C, 81... ]", coll.ToString("L14", rad16));
+      }
+    }
+
+    [TestFixture]
+    public class CollectionOrSink
+    {
+      private HashedLinkedList<int> list;
+
+
+      [SetUp]
+      public void Init() { list = new HashedLinkedList<int>(); }
+
+      [Test]
+      [ExpectedException(typeof(NullReferenceException))]
+      public void NullEqualityComparerinConstructor1()
+      {
+        new HashedLinkedList<int>(null);
+      }
+
+      [Test]
+      public void Choose()
+      {
+        list.Add(7);
+        Assert.AreEqual(7, list.Choose());
+      }
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void BadChoose()
+      {
+        list.Choose();
+      }
+
+
+      [Test]
+      public void CountEtAl()
+      {
+        Assert.AreEqual(0, list.Count);
+        Assert.IsTrue(list.IsEmpty);
+        Assert.IsFalse(list.AllowsDuplicates);
+        Assert.IsTrue(list.Add(5));
+        Assert.AreEqual(1, list.Count);
+        Assert.IsFalse(list.IsEmpty);
+        Assert.IsFalse(list.Add(5));
+        Assert.AreEqual(1, list.Count);
+        Assert.IsFalse(list.IsEmpty);
+        Assert.IsTrue(list.Add(8));
+        Assert.AreEqual(2, list.Count);
+      }
+
+
+      [Test]
+      public void AddAll()
+      {
+        list.Add(3); list.Add(4); list.Add(5);
+
+        HashedLinkedList<int> list2 = new HashedLinkedList<int>();
+
+        list2.AddAll(list);
+        Assert.IsTrue(IC.eq(list2, 3, 4, 5));
+        list.AddAll(list2);
+        Assert.IsTrue(IC.eq(list2, 3, 4, 5));
+        Assert.IsTrue(IC.eq(list, 3, 4, 5));
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+
+    [TestFixture]
+    public class FindPredicate
+    {
+      private HashedLinkedList<int> list;
+      Fun<int, bool> pred;
+
+      [SetUp]
+      public void Init()
+      {
+        list = new HashedLinkedList<int>(TenEqualityComparer.Default);
+        pred = delegate(int i) { return i % 5 == 0; };
+      }
+
+      [TearDown]
+      public void Dispose() { list = null; }
+
+      [Test]
+      public void Find()
+      {
+        int i;
+        Assert.IsFalse(list.Find(pred, out i));
+        list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+        Assert.IsFalse(list.Find(pred, out i));
+        list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+        Assert.IsTrue(list.Find(pred, out i));
+        Assert.AreEqual(45, i);
+      }
+
+      [Test]
+      public void FindLast()
+      {
+        int i;
+        Assert.IsFalse(list.FindLast(pred, out i));
+        list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+        Assert.IsFalse(list.FindLast(pred, out i));
+        list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+        Assert.IsTrue(list.FindLast(pred, out i));
+        Assert.AreEqual(675, i);
+      }
+
+      [Test]
+      public void FindIndex()
+      {
+        Assert.IsFalse(0 <= list.FindIndex(pred));
+        list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+        Assert.IsFalse(0 <= list.FindIndex(pred));
+        list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+        Assert.AreEqual(4, list.FindIndex(pred));
+      }
+
+      [Test]
+      public void FindLastIndex()
+      {
+        Assert.IsFalse(0 <= list.FindLastIndex(pred));
+        list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+        Assert.IsFalse(0 <= list.FindLastIndex(pred));
+        list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+        Assert.AreEqual(6, list.FindLastIndex(pred));
+      }
+    }
+
+    [TestFixture]
+    public class UniqueItems
+    {
+      private HashedLinkedList<int> list;
+
+      [SetUp]
+      public void Init() { list = new HashedLinkedList<int>(); }
+
+      [TearDown]
+      public void Dispose() { list = null; }
+
+      [Test]
+      public void Test()
+      {
+        Assert.IsTrue(IC.seteq(list.UniqueItems()));
+        Assert.IsTrue(IC.seteq(list.ItemMultiplicities()));
+        list.AddAll<int>(new int[] { 7, 9, 7 });
+        Assert.IsTrue(IC.seteq(list.UniqueItems(), 7, 9));
+        Assert.IsTrue(IC.seteq(list.ItemMultiplicities(), 7, 1, 9, 1));
+      }
+    }
+
+    [TestFixture]
+    public class ArrayTest
+    {
+      private HashedLinkedList<int> list;
+
+      int[] a;
+
+
+      [SetUp]
+      public void Init()
+      {
+        list = new HashedLinkedList<int>();
+        a = new int[10];
+        for (int i = 0; i < 10; i++)
+          a[i] = 1000 + i;
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+
+
+      private string aeq(int[] a, params int[] b)
+      {
+        if (a.Length != b.Length)
+          return "Lengths differ: " + a.Length + " != " + b.Length;
+
+        for (int i = 0; i < a.Length; i++)
+          if (a[i] != b[i])
+            return String.Format("{0}'th elements differ: {1} != {2}", i, a[i], b[i]);
+
+        return "Alles klar";
+      }
+
+
+      [Test]
+      public void ToArray()
+      {
+        Assert.AreEqual("Alles klar", aeq(list.ToArray()));
+        list.Add(7);
+        list.Add(8);
+        Assert.AreEqual("Alles klar", aeq(list.ToArray(), 7, 8));
+      }
+
+
+      [Test]
+      public void CopyTo()
+      {
+        list.CopyTo(a, 1);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+        list.Add(6);
+        list.CopyTo(a, 2);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+        list.Add(4);
+        list.Add(5);
+        list.Add(9);
+        list.CopyTo(a, 4);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 4, 5, 9, 1008, 1009));
+        list.Clear();
+        list.Add(7);
+        list.CopyTo(a, 9);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 4, 5, 9, 1008, 7));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void CopyToBad()
+      {
+        list.CopyTo(a, 11);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void CopyToBad2()
+      {
+        list.CopyTo(a, -1);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void CopyToTooFar()
+      {
+        list.Add(3);
+        list.Add(4);
+        list.CopyTo(a, 9);
+      }
+    }
+
+
+
+    [TestFixture]
+    public class Sync
+    {
+      private HashedLinkedList<int> list;
+
+
+      [SetUp]
+      public void Init()
+      {
+        list = new HashedLinkedList<int>();
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+
+
+      [Test]
+      public void Get()
+      {
+        Assert.IsNotNull(((System.Collections.IList)list).SyncRoot);
+      }
+    }
+  }
+
+
+
+
+  namespace EditableCollection
+  {
+    [TestFixture]
+    public class Searching
+    {
+      private HashedLinkedList<int> list;
+
+
+      [SetUp]
+      public void Init() { list = new HashedLinkedList<int>(); }
+
+
+      [Test]
+      public void Contains()
+      {
+        Assert.IsFalse(list.Contains(5));
+        list.Add(5);
+        Assert.IsTrue(list.Contains(5));
+        Assert.IsFalse(list.Contains(7));
+        list.Add(8);
+        list.Add(10);
+        Assert.IsTrue(list.Contains(5));
+        Assert.IsFalse(list.Contains(7));
+        Assert.IsTrue(list.Contains(8));
+        Assert.IsTrue(list.Contains(10));
+        list.Remove(8);
+        Assert.IsTrue(list.Contains(5));
+        Assert.IsFalse(list.Contains(7));
+        Assert.IsFalse(list.Contains(8));
+        Assert.IsTrue(list.Contains(10));
+      }
+
+      [Test]
+      public void BadAdd()
+      {
+        Assert.IsTrue(list.Add(5));
+        Assert.IsTrue(list.Add(8));
+        Assert.IsFalse(list.Add(5));
+      }
+
+
+      [Test]
+      public void ContainsCount()
+      {
+        Assert.AreEqual(0, list.ContainsCount(5));
+        list.Add(5);
+        Assert.AreEqual(1, list.ContainsCount(5));
+        Assert.AreEqual(0, list.ContainsCount(7));
+        list.Add(8);
+        Assert.AreEqual(1, list.ContainsCount(5));
+        Assert.AreEqual(0, list.ContainsCount(7));
+        Assert.AreEqual(1, list.ContainsCount(8));
+      }
+
+
+      [Test]
+      public void RemoveAllCopies()
+      {
+        list.Add(5); list.Add(7);
+        Assert.AreEqual(1, list.ContainsCount(5));
+        Assert.AreEqual(1, list.ContainsCount(7));
+        list.RemoveAllCopies(5);
+        Assert.IsTrue(list.Check());
+        Assert.AreEqual(0, list.ContainsCount(5));
+        Assert.AreEqual(1, list.ContainsCount(7));
+        list.Add(5); list.Add(8);
+        list.RemoveAllCopies(8);
+        Assert.IsTrue(IC.eq(list, 7, 5));
+      }
+
+
+      [Test]
+      public void FindAll()
+      {
+        Fun<int, bool> f = delegate(int i) { return i % 2 == 0; };
+
+        Assert.IsTrue(list.FindAll(f).IsEmpty);
+        list.Add(5); list.Add(8); list.Add(10);
+        Assert.IsTrue(((HashedLinkedList<int>)list.FindAll(f)).Check());
+        Assert.IsTrue(IC.eq(list.FindAll(f), 8, 10));
+      }
+
+
+      [Test]
+      public void ContainsAll()
+      {
+        HashedLinkedList<int> list2 = new HashedLinkedList<int>();
+
+        Assert.IsTrue(list.ContainsAll(list2));
+        list2.Add(4);
+        Assert.IsFalse(list.ContainsAll(list2));
+        list.Add(4);
+        Assert.IsTrue(list.ContainsAll(list2));
+        list.Add(5);
+        Assert.IsTrue(list.ContainsAll(list2));
+      }
+
+
+      [Test]
+      public void RetainAll()
+      {
+        HashedLinkedList<int> list2 = new HashedLinkedList<int>();
+
+        list.Add(4); list.Add(5); list.Add(6);
+        list2.Add(5); list2.Add(4); list2.Add(7);
+        list.RetainAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 5));
+        list.Add(5); list.Add(4); list.Add(6);
+        list2.Clear();
+        list2.Add(5); list2.Add(5); list2.Add(6);
+        list.RetainAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 5, 6));
+        list2.Clear();
+        list2.Add(7); list2.Add(8); list2.Add(9);
+        list.RetainAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list));
+      }
+
+
+      [Test]
+      public void RemoveAll()
+      {
+        HashedLinkedList<int> list2 = new HashedLinkedList<int>();
+
+        list.Add(4); list.Add(5); list.Add(6);
+        list2.Add(5); list2.Add(4); list2.Add(7);
+        list.RemoveAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 6));
+        list.Add(5); list.Add(4); list.Add(6);
+        list2.Clear();
+        list2.Add(6); list2.Add(5);
+        list.RemoveAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4));
+        list2.Clear();
+        list2.Add(7); list2.Add(8); list2.Add(9);
+        list.RemoveAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4));
+      }
+
+
+      [Test]
+      public void Remove()
+      {
+        list.Add(4); list.Add(5); list.Add(6);
+        Assert.IsFalse(list.Remove(2));
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(list.Remove(4));
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 5, 6));
+        Assert.AreEqual(6, list.RemoveLast());
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 5));
+        list.Add(7);
+        Assert.AreEqual(5, list.RemoveFirst());
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 7));
+      }
+
+
+      [Test]
+      public void Clear()
+      {
+        list.Add(7); list.Add(6);
+        list.Clear();
+        Assert.IsTrue(list.IsEmpty);
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+  }
+
+
+
+
+  namespace IIndexed
+  {
+    [TestFixture]
+    public class Searching
+    {
+      private IIndexed<int> dit;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashedLinkedList<int>();
+      }
+
+
+      [Test]
+      public void IndexOf()
+      {
+        Assert.AreEqual(~0, dit.IndexOf(6));
+        dit.Add(7);
+        Assert.AreEqual(~1, dit.IndexOf(6));
+        Assert.AreEqual(~1, dit.LastIndexOf(6));
+        Assert.AreEqual(0, dit.IndexOf(7));
+        dit.Add(5); dit.Add(7); dit.Add(8); dit.Add(7);
+        Assert.AreEqual(~3, dit.IndexOf(6));
+        Assert.AreEqual(0, dit.IndexOf(7));
+        Assert.AreEqual(0, dit.LastIndexOf(7));
+        Assert.AreEqual(2, dit.IndexOf(8));
+        Assert.AreEqual(1, dit.LastIndexOf(5));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class Removing
+    {
+      private IIndexed<int> dit;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashedLinkedList<int>();
+      }
+
+
+      [Test]
+      public void RemoveAt()
+      {
+        dit.Add(5); dit.Add(7); dit.Add(9); dit.Add(1); dit.Add(2);
+        Assert.AreEqual(7, dit.RemoveAt(1));
+        Assert.IsTrue(((HashedLinkedList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 5, 9, 1, 2));
+        Assert.AreEqual(5, dit.RemoveAt(0));
+        Assert.IsTrue(((HashedLinkedList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 9, 1, 2));
+        Assert.AreEqual(2, dit.RemoveAt(2));
+        Assert.IsTrue(((HashedLinkedList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 9, 1));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void RemoveAtBad0()
+      {
+        dit.RemoveAt(0);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void RemoveAtBadM1()
+      {
+        dit.RemoveAt(-1);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void RemoveAtBad1()
+      {
+        dit.Add(8);
+        dit.RemoveAt(1);
+      }
+
+
+      [Test]
+      public void RemoveInterval()
+      {
+        dit.RemoveInterval(0, 0);
+        dit.Add(10); dit.Add(20); dit.Add(30); dit.Add(40); dit.Add(50); dit.Add(60);
+        dit.RemoveInterval(3, 0);
+        Assert.IsTrue(((HashedLinkedList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 10, 20, 30, 40, 50, 60));
+        dit.RemoveInterval(3, 1);
+        Assert.IsTrue(((HashedLinkedList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 10, 20, 30, 50, 60));
+        dit.RemoveInterval(1, 3);
+        Assert.IsTrue(((HashedLinkedList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 10, 60));
+        dit.RemoveInterval(0, 2);
+        Assert.IsTrue(((HashedLinkedList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit));
+        dit.Add(10); dit.Add(20); dit.Add(30); dit.Add(40); dit.Add(50); dit.Add(60);
+        dit.RemoveInterval(0, 2);
+        Assert.IsTrue(((HashedLinkedList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 30, 40, 50, 60));
+        dit.RemoveInterval(2, 2);
+        Assert.IsTrue(((HashedLinkedList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 30, 40));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+      }
+    }
+  }
+
+  namespace IList_
+  {
+    [TestFixture]
+    public class Searching
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new HashedLinkedList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void FirstBad()
+      {
+        int f = lst.First;
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void LastBad()
+      {
+        int f = lst.Last;
+      }
+
+
+      [Test]
+      public void FirstLast()
+      {
+        lst.Add(19);
+        Assert.AreEqual(19, lst.First);
+        Assert.AreEqual(19, lst.Last);
+        lst.Add(34); lst.InsertFirst(12);
+        Assert.AreEqual(12, lst.First);
+        Assert.AreEqual(34, lst.Last);
+      }
+
+
+      [Test]
+      public void This()
+      {
+        lst.Add(34);
+        Assert.AreEqual(34, lst[0]);
+        lst[0] = 56;
+        Assert.AreEqual(56, lst.First);
+        lst.Add(7); lst.Add(77); lst.Add(777); lst.Add(7777);
+        lst[0] = 45; lst[2] = 78; lst[4] = 101;
+        Assert.IsTrue(IC.eq(lst, 45, 7, 78, 777, 101));
+      }
+
+      [Test]
+      public void ThisWithUpdates()
+      {
+        HashedLinkedList<KeyValuePair<int, int>> pairlist = new HashedLinkedList<KeyValuePair<int, int>>(new KeyValuePairEqualityComparer<int, int>());
+        pairlist.Add(new KeyValuePair<int, int>(10, 50));
+        pairlist.Add(new KeyValuePair<int, int>(11, 51));
+        pairlist.Add(new KeyValuePair<int, int>(12, 52));
+        pairlist.Add(new KeyValuePair<int, int>(13, 53));
+        pairlist[2] = new KeyValuePair<int, int>(12, 102);
+        Assert.IsTrue(pairlist.Check());
+        Assert.AreEqual(new KeyValuePair<int, int>(12, 102), pairlist[2]);
+        pairlist[2] = new KeyValuePair<int, int>(22, 202);
+        Assert.IsTrue(pairlist.Check());
+        Assert.AreEqual(new KeyValuePair<int, int>(22, 202), pairlist[2]);
+        pairlist[1] = new KeyValuePair<int, int>(12, 303);
+        Assert.IsTrue(pairlist.Check());
+        Assert.AreEqual(new KeyValuePair<int, int>(12, 303), pairlist[1]);
+        Assert.AreEqual(new KeyValuePair<int, int>(22, 202), pairlist[2]);
+      }
+
+      [Test]
+      [ExpectedException(typeof(ArgumentException))]
+      public void ThisWithUpdatesBad()
+      {
+        HashedLinkedList<KeyValuePair<int, int>> pairlist = new HashedLinkedList<KeyValuePair<int, int>>(new KeyValuePairEqualityComparer<int, int>());
+        pairlist.Add(new KeyValuePair<int, int>(10, 50));
+        pairlist.Add(new KeyValuePair<int, int>(11, 51));
+        pairlist.Add(new KeyValuePair<int, int>(12, 52));
+        pairlist.Add(new KeyValuePair<int, int>(13, 53));
+        pairlist[2] = new KeyValuePair<int, int>(11, 102);
+      }
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadEmptyGet()
+      {
+        int f = lst[0];
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadLowGet()
+      {
+        lst.Add(7);
+
+        int f = lst[-1];
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadHiGet()
+      {
+        lst.Add(6);
+
+        int f = lst[1];
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadEmptySet()
+      {
+        lst[0] = 4;
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadLowSet()
+      {
+        lst.Add(7);
+        lst[-1] = 9;
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadHiSet()
+      {
+        lst.Add(6);
+        lst[1] = 11;
+      }
+    }
+
+
+    [TestFixture]
+    public class Combined
+    {
+      private IList<KeyValuePair<int, int>> lst;
+
+
+      [SetUp]
+      public void Init()
+      {
+        lst = new HashedLinkedList<KeyValuePair<int, int>>(new KeyValuePairEqualityComparer<int, int>());
+        for (int i = 0; i < 10; i++)
+          lst.Add(new KeyValuePair<int, int>(i, i + 30));
+      }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void Find()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.Find(ref p));
+        Assert.AreEqual(3, p.Key);
+        Assert.AreEqual(33, p.Value);
+        p = new KeyValuePair<int, int>(13, 78);
+        Assert.IsFalse(lst.Find(ref p));
+      }
+
+
+      [Test]
+      public void FindOrAdd()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.FindOrAdd(ref p));
+        Assert.AreEqual(3, p.Key);
+        Assert.AreEqual(33, p.Value);
+        p = new KeyValuePair<int, int>(13, 79);
+        Assert.IsFalse(lst.FindOrAdd(ref p));
+        Assert.AreEqual(13, lst[10].Key);
+        Assert.AreEqual(79, lst[10].Value);
+      }
+
+
+      [Test]
+      public void Update()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.Update(p));
+        Assert.AreEqual(3, lst[3].Key);
+        Assert.AreEqual(78, lst[3].Value);
+        p = new KeyValuePair<int, int>(13, 78);
+        Assert.IsFalse(lst.Update(p));
+      }
+
+
+      [Test]
+      public void UpdateOrAdd1()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.UpdateOrAdd(p));
+        Assert.AreEqual(3, lst[3].Key);
+        Assert.AreEqual(78, lst[3].Value);
+        p = new KeyValuePair<int, int>(13, 79);
+        Assert.IsFalse(lst.UpdateOrAdd(p));
+        Assert.AreEqual(13, lst[10].Key);
+        Assert.AreEqual(79, lst[10].Value);
+      }
+
+      [Test]
+      public void UpdateOrAdd2()
+      {
+          ICollection<String> coll = new HashedLinkedList<String>();
+          // s1 and s2 are distinct objects but contain the same text:
+          String old, s1 = "abc", s2 = ("def" + s1).Substring(3);
+          Assert.IsFalse(coll.UpdateOrAdd(s1, out old));
+          Assert.AreEqual(null, old);
+          Assert.IsTrue(coll.UpdateOrAdd(s2, out old));
+          Assert.IsTrue(Object.ReferenceEquals(s1, old));
+          Assert.IsFalse(Object.ReferenceEquals(s2, old));
+      }
+
+      [Test]
+      public void RemoveWithReturn()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.Remove(p, out p));
+        Assert.AreEqual(3, p.Key);
+        Assert.AreEqual(33, p.Value);
+        Assert.AreEqual(4, lst[3].Key);
+        Assert.AreEqual(34, lst[3].Value);
+        p = new KeyValuePair<int, int>(13, 78);
+        Assert.IsFalse(lst.Remove(p, out p));
+      }
+    }
+
+
+    [TestFixture]
+    public class Inserting
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new HashedLinkedList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void Insert()
+      {
+        lst.Insert(0, 5);
+        Assert.IsTrue(IC.eq(lst, 5));
+        lst.Insert(0, 7);
+        Assert.IsTrue(IC.eq(lst, 7, 5));
+        lst.Insert(1, 4);
+        Assert.IsTrue(IC.eq(lst, 7, 4, 5));
+        lst.Insert(3, 2);
+        Assert.IsTrue(IC.eq(lst, 7, 4, 5, 2));
+      }
+
+      [Test]
+      [ExpectedException(typeof(DuplicateNotAllowedException))]
+      public void InsertDuplicate()
+      {
+        lst.Insert(0, 5);
+        Assert.IsTrue(IC.eq(lst, 5));
+        lst.Insert(0, 7);
+        Assert.IsTrue(IC.eq(lst, 7, 5));
+        lst.Insert(1, 5);
+      }
+
+      [Test]
+      public void InsertAllDuplicate1()
+      {
+        lst.Insert(0, 3);
+        Assert.IsTrue(IC.eq(lst, 3));
+        lst.Insert(0, 7);
+        Assert.IsTrue(IC.eq(lst, 7, 3));
+        try
+        {
+          lst.InsertAll<int>(1, new int[] { 1, 2, 3, 4 });
+        }
+        catch (DuplicateNotAllowedException)
+        {
+        }
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 1, 2, 3));
+      }
+
+      [Test]
+      public void InsertAllDuplicate2()
+      {
+        lst.Insert(0, 3);
+        Assert.IsTrue(IC.eq(lst, 3));
+        lst.Insert(0, 7);
+        Assert.IsTrue(IC.eq(lst, 7, 3));
+        try
+        {
+          lst.InsertAll<int>(1, new int[] { 5, 6, 5, 8 });
+        }
+        catch (DuplicateNotAllowedException)
+        {
+        }
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 5, 6, 3));
+      }
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void BadInsertLow()
+      {
+        lst.Add(7);
+        lst.Insert(-1, 9);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void BadInsertHi()
+      {
+        lst.Add(6);
+        lst.Insert(2, 11);
+      }
+
+
+      [Test]
+      public void FIFO()
+      {
+        for (int i = 0; i < 7; i++)
+          lst.Add(2 * i);
+
+        Assert.IsTrue(lst.FIFO);
+        Assert.AreEqual(0, lst.Remove());
+        Assert.AreEqual(2, lst.Remove());
+        lst.FIFO = false;
+        Assert.AreEqual(12, lst.Remove());
+        Assert.AreEqual(10, lst.Remove());
+        lst.FIFO = true;
+        Assert.AreEqual(4, lst.Remove());
+        Assert.AreEqual(6, lst.Remove());
+      }
+
+
+      [Test]
+      public void InsertFirstLast()
+      {
+        lst.InsertFirst(4);
+        lst.InsertLast(5);
+        lst.InsertFirst(14);
+        lst.InsertLast(15);
+        lst.InsertFirst(24);
+        lst.InsertLast(25);
+        lst.InsertFirst(34);
+        lst.InsertLast(55);
+        Assert.IsTrue(IC.eq(lst, 34, 24, 14, 4, 5, 15, 25, 55));
+      }
+
+
+      [Test]
+      public void InsertFirst()
+      {
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(4);
+        lst.Add(5);
+        lst.ViewOf(2).InsertFirst(7);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 2, 3, 4, 5));
+        lst.ViewOf(3).InsertFirst(8);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 2, 8, 3, 4, 5));
+        lst.ViewOf(5).InsertFirst(9);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 2, 8, 3, 4, 9, 5));
+      }
+
+
+      [Test]
+      public void BadViewOf()
+      {
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(2);
+        lst.Add(5);
+        Assert.IsNull(lst.ViewOf(4));
+      }
+
+
+      [Test]
+      public void InsertAfter()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(4);
+        lst.Add(5);
+        lst.LastViewOf(2).InsertLast(7);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 1, 2, 7, 3, 4, 5));
+        lst.LastViewOf(1).InsertLast(8);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 1, 8, 2, 7, 3, 4, 5));
+        lst.LastViewOf(5).InsertLast(9);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 1, 8, 2, 7, 3, 4, 5, 9));
+      }
+
+
+      [Test]
+      public void BadInsertAfter()
+      {
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(6);
+        lst.Add(5);
+        Assert.IsNull(lst.ViewOf(4));
+      }
+
+
+      [Test]
+      public void InsertAll()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(4);
+
+        IList<int> lst2 = new HashedLinkedList<int>();
+
+        lst2.Add(7); lst2.Add(8); lst2.Add(9);
+        lst.InsertAll(0, lst2);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 1, 2, 3, 4));
+        lst.RemoveAll(lst2);
+        lst.InsertAll(4, lst2);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 1, 2, 3, 4, 7, 8, 9));
+        lst.RemoveAll(lst2);
+        lst.InsertAll(2, lst2);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 1, 2, 7, 8, 9, 3, 4));
+      }
+
+      [Test]
+      [ExpectedException(typeof(DuplicateNotAllowedException))]
+      public void InsertAllBad()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(4);
+
+        IList<int> lst2 = new HashedLinkedList<int>();
+
+        lst2.Add(5); lst2.Add(2); lst2.Add(9);
+        lst.InsertAll(0, lst2);
+      }
+
+
+      [Test]
+      public void Map()
+      {
+        Fun<int, string> m = delegate(int i) { return "<<" + i + ">>"; };
+        IList<string> r = lst.Map(m);
+
+        Assert.IsTrue(((HashedLinkedList<string>)r).Check());
+        Assert.IsTrue(r.IsEmpty);
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(4);
+        r = lst.Map(m);
+        Assert.IsTrue(((HashedLinkedList<string>)r).Check());
+        Assert.AreEqual(4, r.Count);
+        for (int i = 0; i < 4; i++)
+          Assert.AreEqual("<<" + (i + 1) + ">>", r[i]);
+      }
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void BadMapper()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        Fun<int, bool> m = delegate(int i) { if (i == 2) lst.Add(7); return true; };
+        lst.Map(m);
+      }
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void ModifyingFindAll()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        Fun<int, bool> m = delegate(int i) { if (i == 2) lst.Add(7); return true; };
+        lst.FindAll(m);
+      }
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void BadMapperView()
+      {
+        lst = lst.View(0, 0);
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        Fun<int, bool> m = delegate(int i) { if (i == 2) lst.Add(7); return true; };
+        lst.Map(m);
+      }
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void ModifyingFindAllView()
+      {
+        lst = lst.View(0, 0);
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        Fun<int, bool> m = delegate(int i) { if (i == 2) lst.Add(7); return true; };
+        lst.FindAll(m);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void BadRemove() { lst.Remove(); }
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void BadRemoveFirst() { lst.RemoveFirst(); }
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void BadRemoveLast() { lst.RemoveLast(); }
+
+
+      [Test]
+      public void RemoveFirstLast()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(4);
+        Assert.AreEqual(1, lst.RemoveFirst());
+        Assert.AreEqual(4, lst.RemoveLast());
+        Assert.AreEqual(2, lst.RemoveFirst());
+        Assert.AreEqual(3, lst.RemoveLast());
+        Assert.IsTrue(lst.IsEmpty);
+      }
+
+
+      [Test]
+      public void Reverse()
+      {
+        for (int i = 0; i < 10; i++)
+          lst.Add(i);
+
+        lst.Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0));
+        lst.View(0, 3).Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0));
+        lst.View(7, 0).Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0));
+        lst.View(7, 3).Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2));
+        lst.View(5, 1).Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void BadReverse()
+      {
+        for (int i = 0; i < 10; i++)
+          lst.Add(i);
+
+        lst.View(8, 3).Reverse();
+      }
+    }
+
+
+
+    [TestFixture]
+    public class SortingTest
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new HashedLinkedList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void Sort()
+      {
+        lst.Add(5); lst.Add(6); lst.Add(55); lst.Add(7); lst.Add(3);
+        Assert.IsFalse(lst.IsSorted(new IC()));
+        lst.Sort(new IC());
+        Assert.IsTrue(lst.Check(), "Check ");
+        Assert.IsTrue(lst.IsSorted());
+        Assert.IsTrue(lst.IsSorted(new IC()));
+        Assert.IsTrue(IC.eq(lst, 3, 5, 6, 7, 55));
+      }
+    }
+
+    [TestFixture]
+    public class ShuffleTests
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new HashedLinkedList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void Shuffle()
+      {
+        lst.Add(5); lst.Add(6); lst.Add(5); lst.Add(7); lst.Add(3);
+        for (int i = 0; i < 100; i++)
+        {
+          lst.Shuffle(new C5Random(i + 1));
+          Assert.IsTrue(lst.Check(), "Check " + i);
+          int[] lst2 = lst.ToArray();
+          Sorting.IntroSort<int>(lst2);
+          Assert.IsTrue(IC.eq(lst2, 3, 5, 6, 7), "Contents " + i);
+        }
+      }
+    }
+
+    [TestFixture]
+    public class AddingThenRemoving
+    {
+        [Test]
+        public void AddingThenRemovingTest1()
+        {
+            // bug20070911:
+            HashedLinkedList<int> test = new HashedLinkedList<int>();
+            for (int i = 0; i < 33; i++)
+            {
+                test.Add(i);
+            } // for
+
+            for (int i = 0; i < 33; i++)
+            {
+                test.Remove(i);
+            } // for
+            Assert.IsTrue(test.IsEmpty);
+            for (int count = 0; count < 520; count++)
+            {
+                HashedLinkedList<int> hll = new HashedLinkedList<int>();
+                for (int i = 1; i <= count; i++)
+                {
+                    hll.Add(i);
+                } 
+                Assert.AreEqual(count, hll.Count);
+                for (int i = 1; i <= count; i++)
+                {
+                    hll.Remove(i);
+                } 
+                Assert.IsTrue(hll.IsEmpty);
+            }
+        }
+
+        [Test]
+        public void AddingThenRemovingTest2()
+        {
+            // bug20070911:
+            HashedLinkedList<int> test = new HashedLinkedList<int>();
+            for (int i = 0; i < 33; i++)
+            {
+                test.Add(i);
+            } // for
+
+            for (int i = 32; i >= 0; i--)
+            {
+                test.Remove(i);
+            } // for
+            Assert.IsTrue(test.IsEmpty);
+            for (int count = 0; count < 520; count++)
+            {
+                HashedLinkedList<int> hll = new HashedLinkedList<int>();
+                for (int i = 1; i <= count; i++)
+                {
+                    hll.Add(i);
+                }
+                Assert.AreEqual(count, hll.Count);
+                for (int i = count; i >= 1; i--)
+                {
+                    hll.Remove(i);
+                }
+                Assert.IsTrue(hll.IsEmpty);
+            }
+        }
+    }
+  }
+
+  namespace Range
+  {
+    [TestFixture]
+    public class Range
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new HashedLinkedList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void GetRange()
+      {
+        //Assert.IsTrue(IC.eq(lst[0, 0)));
+        for (int i = 0; i < 10; i++) lst.Add(i);
+
+        Assert.IsTrue(IC.eq(lst[0, 3], 0, 1, 2));
+        Assert.IsTrue(IC.eq(lst[3, 3], 3, 4, 5));
+        Assert.IsTrue(IC.eq(lst[6, 3], 6, 7, 8));
+        Assert.IsTrue(IC.eq(lst[6, 4], 6, 7, 8, 9));
+      }
+
+
+      [Test]
+      public void Backwards()
+      {
+        for (int i = 0; i < 10; i++) lst.Add(i);
+
+        Assert.IsTrue(IC.eq(lst.Backwards(), 9, 8, 7, 6, 5, 4, 3, 2, 1, 0));
+        Assert.IsTrue(IC.eq(lst[0, 3].Backwards(), 2, 1, 0));
+        Assert.IsTrue(IC.eq(lst[3, 3].Backwards(), 5, 4, 3));
+        Assert.IsTrue(IC.eq(lst[6, 4].Backwards(), 9, 8, 7, 6));
+      }
+
+
+      [Test]
+      public void DirectionAndCount()
+      {
+        for (int i = 0; i < 10; i++) lst.Add(i);
+
+        Assert.AreEqual(EnumerationDirection.Forwards, lst.Direction);
+        Assert.AreEqual(EnumerationDirection.Forwards, lst[3, 7].Direction);
+        Assert.AreEqual(EnumerationDirection.Backwards, lst[3, 7].Backwards().Direction);
+        Assert.AreEqual(EnumerationDirection.Backwards, lst.Backwards().Direction);
+        Assert.AreEqual(4, lst[3, 4].Count);
+        Assert.AreEqual(4, lst[3, 4].Backwards().Count);
+        Assert.AreEqual(10, lst.Backwards().Count);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterUpdate()
+      {
+        for (int i = 0; i < 10; i++) lst.Add(i);
+
+        foreach (int i in lst)
+        {
+          lst.Add(45 + i);
+        }
+      }
+    }
+  }
+
+
+
+
+  namespace View
+  {
+    [TestFixture]
+    public class Simple
+    {
+      HashedLinkedList<int> list;
+      HashedLinkedList<int> view;
+
+
+      [SetUp]
+      public void Init()
+      {
+        list = new HashedLinkedList<int>();
+        list.Add(0); list.Add(1); list.Add(2); list.Add(3);
+        view = (HashedLinkedList<int>)list.View(1, 2);
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        list = null;
+        view = null;
+      }
+
+
+      void check()
+      {
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(view.Check());
+      }
+
+      [Test]
+      public void InsertPointer()
+      {
+        IList<int> view2 = list.View(2, 0);
+        list.Insert(view2, 7);
+        check();
+        list.Insert(list, 8);
+        check();
+        view.Insert(view2, 9);
+        check();
+        view.Insert(list.View(3, 2), 10);
+        check();
+        view.Insert(list.ViewOf(0), 11);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 11, 1, 9, 7, 2, 10, 3, 8));
+        Assert.IsTrue(IC.eq(view, 11, 1, 9, 7, 2, 10));
+      }
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void InsertPointerBad1()
+      {
+        view.Insert(list.View(0, 0), 7);
+      }
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void InsertPointerBad2()
+      {
+        view.Insert(list, 7);
+      }
+
+      [Test]
+      [ExpectedException(typeof(IncompatibleViewException))]
+      public void InsertPointerBad3()
+      {
+        list.Insert(new ArrayList<int>(), 7);
+      }
+
+      [Test]
+      [ExpectedException(typeof(IncompatibleViewException))]
+      public void InsertPointerBad4()
+      {
+        list.Insert(new ArrayList<int>().View(0, 0), 7);
+      }
+
+      [Test]
+      public void Span()
+      {
+        IList<int> span = list.View(1, 0).Span(list.View(2, 0));
+        Assert.IsTrue(span.Check());
+        Assert.AreEqual(1, span.Offset);
+        Assert.AreEqual(1, span.Count);
+        span = list.View(0, 2).Span(list.View(2, 2));
+        Assert.IsTrue(span.Check());
+        Assert.AreEqual(0, span.Offset);
+        Assert.AreEqual(4, span.Count);
+        span = list.View(3, 1).Span(list.View(1, 1));
+        Assert.IsNull(span);
+      }
+
+      [Test]
+      public void ViewOf()
+      {
+        for (int i = 0; i < 4; i++)
+          list.Add(i);
+        IList<int> v = view.ViewOf(2);
+        Assert.IsTrue(v.Check());
+        Assert.IsTrue(IC.eq(v, 2));
+        Assert.AreEqual(2, v.Offset);
+        v = list.ViewOf(2);
+        Assert.IsTrue(v.Check());
+        Assert.IsTrue(IC.eq(v, 2));
+        Assert.AreEqual(2, v.Offset);
+        v = list.LastViewOf(2);
+        Assert.IsTrue(v.Check());
+        Assert.IsTrue(IC.eq(v, 2));
+        Assert.AreEqual(2, v.Offset);
+      }
+
+      [Test]
+      public void BadViewOf()
+      {
+        Assert.IsNull(view.ViewOf(5));
+        Assert.IsNull(view.LastViewOf(5));
+        Assert.IsNull(view.ViewOf(3));
+        Assert.IsNull(view.LastViewOf(3));
+        Assert.IsNull(view.ViewOf(0));
+        Assert.IsNull(view.LastViewOf(0));
+      }
+
+
+      [Test]
+      public void ArrayStuff()
+      {
+        Assert.IsTrue(IC.eq(view.ToArray(), 1, 2));
+        int[] extarray = new int[5];
+        view.CopyTo(extarray, 2);
+        Assert.IsTrue(IC.eq(extarray, 0, 0, 1, 2, 0));
+      }
+
+      [Test]
+      public void Add()
+      {
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 1, 2, 3));
+        Assert.IsTrue(IC.eq(view, 1, 2));
+        view.InsertFirst(10);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 10, 1, 2, 3));
+        Assert.IsTrue(IC.eq(view, 10, 1, 2));
+        view.Clear();
+        Assert.IsFalse(view.IsReadOnly);
+        Assert.IsFalse(view.AllowsDuplicates);
+        Assert.IsTrue(view.IsEmpty);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 3));
+        Assert.IsTrue(IC.eq(view));
+        view.Add(8);
+        Assert.IsFalse(view.IsEmpty);
+        Assert.IsFalse(view.AllowsDuplicates);
+        Assert.IsFalse(view.IsReadOnly);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 3));
+        Assert.IsTrue(IC.eq(view, 8));
+        view.Add(12);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 12, 3));
+        Assert.IsTrue(IC.eq(view, 8, 12));
+        view./*ViewOf(12).*/InsertLast(15);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 12, 15, 3));
+        Assert.IsTrue(IC.eq(view, 8, 12, 15));
+        view.ViewOf(12).InsertFirst(18);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 18, 12, 15, 3));
+        Assert.IsTrue(IC.eq(view, 8, 18, 12, 15));
+
+        HashedLinkedList<int> lst2 = new HashedLinkedList<int>();
+
+        lst2.Add(90); lst2.Add(92);
+        view.AddAll(lst2);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 18, 12, 15, 90, 92, 3));
+        Assert.IsTrue(IC.eq(view, 8, 18, 12, 15, 90, 92));
+        view.InsertLast(66);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 18, 12, 15, 90, 92, 66, 3));
+        Assert.IsTrue(IC.eq(view, 8, 18, 12, 15, 90, 92, 66));
+      }
+
+
+      [Test]
+      public void Bxxx()
+      {
+        Assert.IsTrue(IC.eq(view.Backwards(), 2, 1));
+        Assert.AreSame(list, view.Underlying);
+        Assert.IsNull(list.Underlying);
+        Assert.AreEqual(EnumerationDirection.Forwards, view.Direction);
+        Assert.AreEqual(EnumerationDirection.Backwards, view.Backwards().Direction);
+        Assert.AreEqual(0, list.Offset);
+        Assert.AreEqual(1, view.Offset);
+      }
+
+
+      [Test]
+      public void Contains()
+      {
+        Assert.IsTrue(view.Contains(1));
+        Assert.IsFalse(view.Contains(0));
+
+        HashedLinkedList<int> lst2 = new HashedLinkedList<int>();
+
+        lst2.Add(2);
+        Assert.IsTrue(view.ContainsAll(lst2));
+        lst2.Add(3);
+        Assert.IsFalse(view.ContainsAll(lst2));
+        Assert.AreEqual(Speed.Constant, view.ContainsSpeed);
+        Assert.AreEqual(2, view.Count);
+        view.Add(1);
+        Assert.AreEqual(1, view.ContainsCount(2));
+        Assert.AreEqual(1, view.ContainsCount(1));
+        Assert.AreEqual(2, view.Count);
+      }
+
+
+      [Test]
+      public void CreateView()
+      {
+        HashedLinkedList<int> view2 = (HashedLinkedList<int>)view.View(1, 0);
+
+        Assert.AreSame(list, view2.Underlying);
+      }
+
+
+      [Test]
+      public void FIFO()
+      {
+        Assert.IsTrue(view.FIFO);
+        view.Add(23); view.Add(24); view.Add(25);
+        check();
+        Assert.IsTrue(IC.eq(view, 1, 2, 23, 24, 25));
+        Assert.AreEqual(1, view.Remove());
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 23, 24, 25));
+        view.FIFO = false;
+        Assert.IsFalse(view.FIFO);
+        Assert.AreEqual(25, view.Remove());
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 23, 24));
+      }
+
+
+      [Test]
+      public void MapEtc()
+      {
+        HashedLinkedList<double> dbl = (HashedLinkedList<double>)view.Map(new Fun<int, double>(delegate(int i) { return i / 10.0; }));
+
+        Assert.IsTrue(dbl.Check());
+        Assert.AreEqual(0.1, dbl[0]);
+        Assert.AreEqual(0.2, dbl[1]);
+        for (int i = 0; i < 10; i++) view.Add(i);
+
+        HashedLinkedList<int> list2 = (HashedLinkedList<int>)view.FindAll(new Fun<int, bool>(delegate(int i) { return i % 4 == 1; }));
+
+        Assert.IsTrue(list2.Check());
+        Assert.IsTrue(IC.eq(list2, 1, 5, 9));
+      }
+
+
+      [Test]
+      public void FL()
+      {
+        Assert.AreEqual(1, view.First);
+        Assert.AreEqual(2, view.Last);
+      }
+
+
+      [Test]
+      public void Indexing()
+      {
+        list.Clear();
+        for (int i = 0; i < 20; i++) list.Add(i);
+
+        view = (HashedLinkedList<int>)list.View(5, 7);
+        for (int i = 0; i < 7; i++) Assert.AreEqual(i + 5, view[i]);
+
+        for (int i = 0; i < 7; i++) Assert.AreEqual(i, view.IndexOf(i + 5));
+
+        for (int i = 0; i < 7; i++) Assert.AreEqual(i, view.LastIndexOf(i + 5));
+      }
+
+
+      [Test]
+      public void Insert()
+      {
+        view.Insert(0, 34);
+        view.Insert(1, 35);
+        view.Insert(4, 36);
+        Assert.IsTrue(view.Check());
+        Assert.IsTrue(IC.eq(view, 34, 35, 1, 2, 36));
+
+        IList<int> list2 = new HashedLinkedList<int>();
+
+        list2.Add(40); list2.Add(41);
+        view.InsertAll(3, list2);
+        Assert.IsTrue(view.Check());
+        Assert.IsTrue(IC.eq(view, 34, 35, 1, 40, 41, 2, 36));
+      }
+
+
+      [Test]
+      public void Sort()
+      {
+        view.Add(45); view.Add(47); view.Add(46); view.Add(48);
+        Assert.IsFalse(view.IsSorted(new IC()));
+        view.Sort(new IC());
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 1, 2, 45, 46, 47, 48, 3));
+        Assert.IsTrue(IC.eq(view, 1, 2, 45, 46, 47, 48));
+      }
+
+
+      [Test]
+      public void Remove()
+      {
+        view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0);
+        Assert.IsTrue(IC.eq(view, 1, 2, 5));
+        Assert.IsTrue(view.Remove(1));
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 5));
+        Assert.IsFalse(view.Remove(1));
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 5));
+        Assert.IsFalse(view.Remove(0));
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 5));
+        view.RemoveAllCopies(3);
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 5));
+        Assert.IsTrue(IC.eq(list, 0, 2, 5, 3));
+        view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0);
+        Assert.IsTrue(IC.eq(view, 2, 5, 1));
+
+        HashedLinkedList<int> l2 = new HashedLinkedList<int>();
+
+        l2.Add(1); l2.Add(2); l2.Add(2); l2.Add(3); l2.Add(1);
+        view.RemoveAll(l2);
+        check();
+        Assert.IsTrue(IC.eq(view, 5));
+        view.RetainAll(l2);
+        check();
+        Assert.IsTrue(IC.eq(view));
+        view.Add(2); view.Add(4); view.Add(5);
+        Assert.AreEqual(2, view.RemoveAt(0));
+        Assert.AreEqual(5, view.RemoveAt(1));
+        Assert.AreEqual(4, view.RemoveAt(0));
+        check();
+        Assert.IsTrue(IC.eq(view));
+        view.Add(8); view.Add(6); view.Add(78);
+        Assert.AreEqual(8, view.RemoveFirst());
+        Assert.AreEqual(78, view.RemoveLast());
+        view.Add(2); view.Add(5); view.Add(3); view.Add(1);
+        view.RemoveInterval(1, 2);
+        check();
+        Assert.IsTrue(IC.eq(view, 6, 1));
+      }
+
+
+      [Test]
+      public void Reverse()
+      {
+        view.Clear();
+        for (int i = 0; i < 10; i++) view.Add(10 + i);
+
+        view.View(3, 4).Reverse();
+        check();
+        Assert.IsTrue(IC.eq(view, 10, 11, 12, 16, 15, 14, 13, 17, 18, 19));
+        view.Reverse();
+        Assert.IsTrue(IC.eq(view, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10));
+        Assert.IsTrue(IC.eq(list, 0, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10, 3));
+      }
+
+
+      [Test]
+      public void Slide()
+      {
+        view.Slide(1);
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 3));
+        view.Slide(-2);
+        check();
+        Assert.IsTrue(IC.eq(view, 0, 1));
+        view.Slide(0, 3);
+        check();
+        Assert.IsTrue(IC.eq(view, 0, 1, 2));
+        view.Slide(2, 1);
+        check();
+        Assert.IsTrue(IC.eq(view, 2));
+        view.Slide(-1, 0);
+        check();
+        Assert.IsTrue(IC.eq(view));
+        view.Add(28);
+        Assert.IsTrue(IC.eq(list, 0, 28, 1, 2, 3));
+      }
+      [Test]
+      public void Iterate()
+      {
+        list.Clear();
+        check();
+        view = null;
+        foreach (int i in new int[] { 2, 4, 8, 13, 6, 1, 10, 11 }) list.Add(i);
+
+        view = (HashedLinkedList<int>)list.View(list.Count - 2, 2);
+        int j = 666;
+        while (true)
+        {
+          check();
+          //Console.WriteLine("View: {0}:  {1} --> {2}", view.Count, view.First, view.Last);
+          if ((view.Last - view.First) % 2 == 1)
+            view.Insert(1, j++);
+          check();
+          if (view.Offset == 0)
+            break;
+          else
+            view.Slide(-1, 2);
+        }
+        //foreach (int cell in list) Console.Write(" " + cell);
+        //Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 2, 4, 8, 668, 13, 6, 1, 667, 10, 666, 11));
+      }
+
+
+      [Test]
+      public void SyncRoot()
+      {
+        Assert.AreSame(((System.Collections.IList)view).SyncRoot, ((System.Collections.IList)list).SyncRoot);
+      }
+    }
+
+    [TestFixture]
+    public class MultipleViews
+    {
+      IList<int> list;
+      IList<int>[][] views;
+      [SetUp]
+      public void Init()
+      {
+        list = new HashedLinkedList<int>();
+        for (int i = 0; i < 6; i++)
+          list.Add(i);
+        views = new IList<int>[7][];
+        for (int i = 0; i < 7; i++)
+        {
+          views[i] = new IList<int>[7 - i];
+          for (int j = 0; j < 7 - i; j++)
+            views[i][j] = list.View(i, j);
+        }
+      }
+      [TearDown]
+      public void Dispose()
+      {
+        list = null;
+        views = null;
+      }
+      [Test]
+      public void Insert()
+      {
+        Assert.IsTrue(list.Check(), "list check before insert");
+        list.Insert(3, 777);
+        Assert.IsTrue(list.Check(), "list check after insert");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i < 3 && i + j > 3 ? j + 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void RemoveAt()
+      {
+        Assert.IsTrue(list.Check(), "list check before remove");
+        list.RemoveAt(3);
+        Assert.IsTrue(list.Check(), "list check after remove");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i <= 3 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i <= 3 && i + j > 3 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+      [Test]
+      public void RemoveInterval()
+      {
+        Assert.IsTrue(list.Check(), "list check before remove");
+        list.RemoveInterval(3, 2);
+        Assert.IsTrue(list.Check(), "list check after remove");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i <= 3 ? i : i <= 5 ? 3 : i - 2, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(j == 0 ? 0 : i <= 3 && i + j > 4 ? j - 2 : i > 4 || i + j <= 3 ? j : j - 1, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+      [Test]
+      public void InsertAtEnd()
+      {
+        Assert.IsTrue(list.Check(), "list check before insert");
+        list.InsertLast(777);
+        Assert.IsTrue(list.Check(), "list check after insert");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void RemoveAtEnd()
+      {
+        Assert.IsTrue(list.Check(), "list check before remove");
+        list.RemoveAt(5);
+        Assert.IsTrue(list.Check(), "list check after remove");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i <= 5 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i <= 5 && i + j > 5 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void InsertAtStart()
+      {
+        Assert.IsTrue(list.Check(), "list check before insert");
+        list.Insert(0, 777);
+        Assert.IsTrue(list.Check(), "list check after insert");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i == 0 && j == 0 ? 0 : i + 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void RemoveAtStart()
+      {
+        Assert.IsTrue(list.Check(), "list check before remove");
+        list.RemoveAt(0);
+        Assert.IsTrue(list.Check(), "list check after remove");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i == 0 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i == 0 && j > 0 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void Clear()
+      {
+        Assert.IsTrue(list.Check(), "list check before clear");
+        //for (int i = 0; i < 7; i++)
+        //for (int j = 0; j < 7 - i; j++)
+        //Console.WriteLine("// view[{0}][{1}] : {2}", i, j, ((HashedLinkedList<int>) views[i][j]).GetHashCode());
+        views[2][3].Clear();
+        Assert.IsTrue(list.Check(), "list check after clear");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i < 2 ? i : i < 6 ? 2 : i - 3, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(s(i, j), views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+      private int s(int i, int j)
+      {
+        if (j == 0) return 0;
+        int k = i + j - 1; //end
+        if (i > 4 || k <= 1) return j;
+        if (i >= 2) return k > 4 ? k - 4 : 0;
+        if (i <= 2) return k >= 4 ? j - 3 : 2 - i;
+        return -1;
+      }
+      [Test]
+      public void InsertAll()
+      {
+        IList<int> list2 = new HashedLinkedList<int>();
+        for (int i = 0; i < 5; i++) { list2.Add(100 + i); }
+        Assert.IsTrue(list.Check(), "list check before insertAll");
+        list.InsertAll(3, list2);
+        Assert.IsTrue(list.Check(), "list check after insertAll");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 5, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i < 3 && i + j > 3 ? j + 5 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+      [Test]
+      public void AddAll()
+      {
+        IList<int> list2 = new HashedLinkedList<int>();
+        for (int i = 0; i < 5; i++) { list2.Add(100 + i); }
+        Assert.IsTrue(list.Check(), "list check before AddAll");
+        list.View(1, 2).AddAll(list2);
+        Assert.IsTrue(list.Check(), "list check after AddAll");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 5, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i < 3 && i + j > 3 ? j + 5 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+      [Test]
+      public void Remove()
+      {
+        for (int i = 0; i < 7; i++)
+        {
+          for (int j = 0; j < 7 - i; j++)
+          {
+            list = new HashedLinkedList<int>();
+            for (int k = 0; k < 6; k++) list.Add(k);
+            HashedLinkedList<int> v = (HashedLinkedList<int>)list.View(i, j);
+            list.Remove(3);
+            Assert.IsTrue(list.Check(), "list check after Remove, i=" + i + ", j=" + j);
+          }
+        }
+      }
+      [Test]
+      public void RemoveAll1()
+      {
+        IList<int> list2 = new HashedLinkedList<int>();
+        list2.Add(1); list2.Add(3); list2.Add(4);
+
+        for (int i = 0; i < 7; i++)
+        {
+          for (int j = 0; j < 7 - i; j++)
+          {
+            list = new HashedLinkedList<int>();
+            for (int k = 0; k < 6; k++) list.Add(k);
+            HashedLinkedList<int> v = (HashedLinkedList<int>)list.View(i, j);
+            list.RemoveAll(list2);
+            Assert.IsTrue(list.Check(), "list check after RemoveAll, i=" + i + ", j=" + j);
+          }
+        }
+      }
+      [Test]
+      public void RemoveAll2()
+      {
+        IList<int> list2 = new HashedLinkedList<int>();
+        list2.Add(1); list2.Add(3); list2.Add(4);
+        Assert.IsTrue(list.Check(), "list check before RemoveAll");
+        list.RemoveAll(list2);
+
+        Assert.AreEqual(0, views[0][0].Offset, "view [0][0] offset");
+        Assert.AreEqual(0, views[0][1].Offset, "view [0][1] offset");
+        Assert.AreEqual(0, views[0][2].Offset, "view [0][2] offset");
+        Assert.AreEqual(0, views[0][3].Offset, "view [0][3] offset");
+        Assert.AreEqual(0, views[0][4].Offset, "view [0][4] offset");
+        Assert.AreEqual(0, views[0][5].Offset, "view [0][5] offset");
+        Assert.AreEqual(0, views[0][6].Offset, "view [0][6] offset");
+        Assert.AreEqual(1, views[1][0].Offset, "view [1][0] offset");
+        Assert.AreEqual(1, views[1][1].Offset, "view [1][1] offset");
+        Assert.AreEqual(1, views[1][2].Offset, "view [1][2] offset");
+        Assert.AreEqual(1, views[1][3].Offset, "view [1][3] offset");
+        Assert.AreEqual(1, views[1][4].Offset, "view [1][4] offset");
+        Assert.AreEqual(1, views[1][5].Offset, "view [1][5] offset");
+        Assert.AreEqual(1, views[2][0].Offset, "view [2][0] offset");
+        Assert.AreEqual(1, views[2][1].Offset, "view [2][1] offset");
+        Assert.AreEqual(1, views[2][2].Offset, "view [2][2] offset");
+        Assert.AreEqual(1, views[2][3].Offset, "view [2][3] offset");
+        Assert.AreEqual(1, views[2][4].Offset, "view [2][4] offset");
+        Assert.AreEqual(2, views[3][0].Offset, "view [3][0] offset");
+        Assert.AreEqual(2, views[3][1].Offset, "view [3][1] offset");
+        Assert.AreEqual(2, views[3][2].Offset, "view [3][2] offset");
+        Assert.AreEqual(2, views[3][3].Offset, "view [3][3] offset");
+        Assert.AreEqual(2, views[4][0].Offset, "view [4][0] offset");
+        Assert.AreEqual(2, views[4][1].Offset, "view [4][1] offset");
+        Assert.AreEqual(2, views[4][2].Offset, "view [4][2] offset");
+        Assert.AreEqual(2, views[5][0].Offset, "view [5][0] offset");
+        Assert.AreEqual(2, views[5][1].Offset, "view [5][1] offset");
+        Assert.AreEqual(3, views[6][0].Offset, "view [6][0] offset");
+
+        Assert.AreEqual(0, views[0][0].Count, "view [0][0] count");
+        Assert.AreEqual(1, views[0][1].Count, "view [0][1] count");
+        Assert.AreEqual(1, views[0][2].Count, "view [0][2] count");
+        Assert.AreEqual(2, views[0][3].Count, "view [0][3] count");
+        Assert.AreEqual(2, views[0][4].Count, "view [0][4] count");
+        Assert.AreEqual(2, views[0][5].Count, "view [0][5] count");
+        Assert.AreEqual(3, views[0][6].Count, "view [0][6] count");
+        Assert.AreEqual(0, views[1][0].Count, "view [1][0] count");
+        Assert.AreEqual(0, views[1][1].Count, "view [1][1] count");
+        Assert.AreEqual(1, views[1][2].Count, "view [1][2] count");
+        Assert.AreEqual(1, views[1][3].Count, "view [1][3] count");
+        Assert.AreEqual(1, views[1][4].Count, "view [1][4] count");
+        Assert.AreEqual(2, views[1][5].Count, "view [1][5] count");
+        Assert.AreEqual(0, views[2][0].Count, "view [2][0] count");
+        Assert.AreEqual(1, views[2][1].Count, "view [2][1] count");
+        Assert.AreEqual(1, views[2][2].Count, "view [2][2] count");
+        Assert.AreEqual(1, views[2][3].Count, "view [2][3] count");
+        Assert.AreEqual(2, views[2][4].Count, "view [2][4] count");
+        Assert.AreEqual(0, views[3][0].Count, "view [3][0] count");
+        Assert.AreEqual(0, views[3][1].Count, "view [3][1] count");
+        Assert.AreEqual(0, views[3][2].Count, "view [3][2] count");
+        Assert.AreEqual(1, views[3][3].Count, "view [3][3] count");
+        Assert.AreEqual(0, views[4][0].Count, "view [4][0] count");
+        Assert.AreEqual(0, views[4][1].Count, "view [4][1] count");
+        Assert.AreEqual(1, views[4][2].Count, "view [4][2] count");
+        Assert.AreEqual(0, views[5][0].Count, "view [5][0] count");
+        Assert.AreEqual(1, views[5][1].Count, "view [5][1] count");
+        Assert.AreEqual(0, views[6][0].Count, "view [6][0] count");
+
+        Assert.IsTrue(list.Check(), "list check after RemoveAll");
+      }
+
+      [Test]
+      public void RetainAll()
+      {
+        IList<int> list2 = new HashedLinkedList<int>();
+        list2.Add(2); list2.Add(4); list2.Add(5);
+        Assert.IsTrue(list.Check(), "list check before RetainAll");
+        list.RetainAll(list2);
+        Assert.AreEqual(0, views[0][0].Offset, "view [0][0] offset");
+        Assert.AreEqual(0, views[0][1].Offset, "view [0][1] offset");
+        Assert.AreEqual(0, views[0][2].Offset, "view [0][2] offset");
+        Assert.AreEqual(0, views[0][3].Offset, "view [0][3] offset");
+        Assert.AreEqual(0, views[0][4].Offset, "view [0][4] offset");
+        Assert.AreEqual(0, views[0][5].Offset, "view [0][5] offset");
+        Assert.AreEqual(0, views[0][6].Offset, "view [0][6] offset");
+        Assert.AreEqual(0, views[1][0].Offset, "view [1][0] offset");
+        Assert.AreEqual(0, views[1][1].Offset, "view [1][1] offset");
+        Assert.AreEqual(0, views[1][2].Offset, "view [1][2] offset");
+        Assert.AreEqual(0, views[1][3].Offset, "view [1][3] offset");
+        Assert.AreEqual(0, views[1][4].Offset, "view [1][4] offset");
+        Assert.AreEqual(0, views[1][5].Offset, "view [1][5] offset");
+        Assert.AreEqual(0, views[2][0].Offset, "view [2][0] offset");
+        Assert.AreEqual(0, views[2][1].Offset, "view [2][1] offset");
+        Assert.AreEqual(0, views[2][2].Offset, "view [2][2] offset");
+        Assert.AreEqual(0, views[2][3].Offset, "view [2][3] offset");
+        Assert.AreEqual(0, views[2][4].Offset, "view [2][4] offset");
+        Assert.AreEqual(1, views[3][0].Offset, "view [3][0] offset");
+        Assert.AreEqual(1, views[3][1].Offset, "view [3][1] offset");
+        Assert.AreEqual(1, views[3][2].Offset, "view [3][2] offset");
+        Assert.AreEqual(1, views[3][3].Offset, "view [3][3] offset");
+        Assert.AreEqual(1, views[4][0].Offset, "view [4][0] offset");
+        Assert.AreEqual(1, views[4][1].Offset, "view [4][1] offset");
+        Assert.AreEqual(1, views[4][2].Offset, "view [4][2] offset");
+        Assert.AreEqual(2, views[5][0].Offset, "view [5][0] offset");
+        Assert.AreEqual(2, views[5][1].Offset, "view [5][1] offset");
+        Assert.AreEqual(3, views[6][0].Offset, "view [6][0] offset");
+
+        Assert.AreEqual(0, views[0][0].Count, "view [0][0] count");
+        Assert.AreEqual(0, views[0][1].Count, "view [0][1] count");
+        Assert.AreEqual(0, views[0][2].Count, "view [0][2] count");
+        Assert.AreEqual(1, views[0][3].Count, "view [0][3] count");
+        Assert.AreEqual(1, views[0][4].Count, "view [0][4] count");
+        Assert.AreEqual(2, views[0][5].Count, "view [0][5] count");
+        Assert.AreEqual(3, views[0][6].Count, "view [0][6] count");
+        Assert.AreEqual(0, views[1][0].Count, "view [1][0] count");
+        Assert.AreEqual(0, views[1][1].Count, "view [1][1] count");
+        Assert.AreEqual(1, views[1][2].Count, "view [1][2] count");
+        Assert.AreEqual(1, views[1][3].Count, "view [1][3] count");
+        Assert.AreEqual(2, views[1][4].Count, "view [1][4] count");
+        Assert.AreEqual(3, views[1][5].Count, "view [1][5] count");
+        Assert.AreEqual(0, views[2][0].Count, "view [2][0] count");
+        Assert.AreEqual(1, views[2][1].Count, "view [2][1] count");
+        Assert.AreEqual(1, views[2][2].Count, "view [2][2] count");
+        Assert.AreEqual(2, views[2][3].Count, "view [2][3] count");
+        Assert.AreEqual(3, views[2][4].Count, "view [2][4] count");
+        Assert.AreEqual(0, views[3][0].Count, "view [3][0] count");
+        Assert.AreEqual(0, views[3][1].Count, "view [3][1] count");
+        Assert.AreEqual(1, views[3][2].Count, "view [3][2] count");
+        Assert.AreEqual(2, views[3][3].Count, "view [3][3] count");
+        Assert.AreEqual(0, views[4][0].Count, "view [4][0] count");
+        Assert.AreEqual(1, views[4][1].Count, "view [4][1] count");
+        Assert.AreEqual(2, views[4][2].Count, "view [4][2] count");
+        Assert.AreEqual(0, views[5][0].Count, "view [5][0] count");
+        Assert.AreEqual(1, views[5][1].Count, "view [5][1] count");
+        Assert.AreEqual(0, views[6][0].Count, "view [6][0] count");
+
+
+        Assert.IsTrue(list.Check(), "list check after RetainAll");
+      }
+
+      [Test]
+      public void RemoveAllCopies()
+      {
+        IList<int> list2 = new HashedLinkedList<int>();
+        list2.Add(0); list2.Add(2); list2.Add(82); list2.Add(92); list2.Add(5); list2.Add(2); list2.Add(1);
+        for (int i = 0; i < 7; i++)
+        {
+          for (int j = 0; j < 7 - i; j++)
+          {
+            list = new HashedLinkedList<int>();
+            list.AddAll(list2);
+            HashedLinkedList<int> v = (HashedLinkedList<int>)list.View(i, j);
+            list.RemoveAllCopies(2);
+            Assert.IsTrue(list.Check(), "list check after RemoveAllCopies, i=" + i + ", j=" + j);
+          }
+        }
+      }
+
+      private void checkDisposed(bool reverse, int start, int count)
+      {
+        int k = 0;
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            if (i + j <= start || i >= start + count || (i <= start && i + j >= start + count) || (reverse && start <= i && start + count >= i + j))
+            {
+              try
+              {
+                k = views[i][j].Count;
+              }
+              catch (ViewDisposedException)
+              {
+                Assert.Fail("view[" + i + "][" + j + "] threw");
+              }
+              Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] size");
+              if (reverse && ((j > 0 && start <= i && start + count >= i + j) || (j == 0 && start < i && start + count > i)))
+                Assert.AreEqual(start + (start + count - i - j), views[i][j].Offset, "view[" + i + "][" + j + "] offset (mirrored)");
+              else
+                Assert.AreEqual(i, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            }
+            else
+            {
+              try
+              {
+                k = views[i][j].Count;
+                Assert.Fail("view[" + i + "][" + j + "] no throw");
+              }
+              catch (ViewDisposedException) { }
+            }
+          }
+      }
+
+      [Test]
+      public void Reverse()
+      {
+        int start = 2, count = 3;
+        IList<int> list2 = list.View(start, count);
+        Assert.IsTrue(list.Check(), "list check before Reverse");
+        list2.Reverse();
+        Assert.IsTrue(list.Check(), "list check after Reverse");
+        checkDisposed(true, start, count);
+      }
+
+      [Test]
+      public void Sort()
+      {
+        int start = 2, count = 3;
+        IList<int> list2 = list.View(start, count);
+        Assert.IsTrue(list.Check(), "list check before Sort");
+        list2.Sort();
+        Assert.IsTrue(list.Check(), "list check after Sort");
+        checkDisposed(false, start, count);
+      }
+      [Test]
+      public void Shuffle()
+      {
+        int start = 2, count = 3;
+        IList<int> list2 = list.View(start, count);
+        Assert.IsTrue(list.Check(), "list check before Shuffle");
+        list2.Shuffle();
+        Assert.IsTrue(list.Check(), "list check after Shuffle");
+        checkDisposed(false, start, count);
+      }
+
+
+    }
+
+  }
+
+  namespace HashingAndEquals
+  {
+    [TestFixture]
+    public class ISequenced
+    {
+      private ISequenced<int> dit, dat, dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashedLinkedList<int>();
+        dat = new HashedLinkedList<int>();
+        dut = new HashedLinkedList<int>();
+      }
+
+
+      [Test]
+      public void EmptyEmpty()
+      {
+        Assert.IsTrue(dit.SequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void EmptyNonEmpty()
+      {
+        dit.Add(3);
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsFalse(dat.SequencedEquals(dit));
+      }
+
+      [Test]
+      public void HashVal()
+      {
+        Assert.AreEqual(CHC.sequencedhashcode(), dit.GetSequencedHashCode());
+        dit.Add(3);
+        Assert.AreEqual(CHC.sequencedhashcode(3), dit.GetSequencedHashCode());
+        dit.Add(7);
+        Assert.AreEqual(CHC.sequencedhashcode(3, 7), dit.GetSequencedHashCode());
+        Assert.AreEqual(CHC.sequencedhashcode(), dut.GetSequencedHashCode());
+        dut.Add(7);
+        Assert.AreEqual(CHC.sequencedhashcode(7), dut.GetSequencedHashCode());
+        dut.Add(3);
+        Assert.AreEqual(CHC.sequencedhashcode(7, 3), dut.GetSequencedHashCode());
+      }
+
+
+      [Test]
+      public void EqualHashButDifferent()
+      {
+        dit.Add(0); dit.Add(31);
+        dat.Add(1); dat.Add(0);
+        Assert.AreEqual(dit.GetSequencedHashCode(), dat.GetSequencedHashCode());
+        Assert.IsFalse(dit.SequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void Normal()
+      {
+        dit.Add(3);
+        dit.Add(7);
+        dat.Add(3);
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsFalse(dat.SequencedEquals(dit));
+        dat.Add(7);
+        Assert.IsTrue(dit.SequencedEquals(dat));
+        Assert.IsTrue(dat.SequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void WrongOrder()
+      {
+        dit.Add(3);
+        dut.Add(3);
+        Assert.IsTrue(dit.SequencedEquals(dut));
+        Assert.IsTrue(dut.SequencedEquals(dit));
+        dit.Add(7);
+        ((HashedLinkedList<int>)dut).InsertFirst(7);
+        Assert.IsFalse(dit.SequencedEquals(dut));
+        Assert.IsFalse(dut.SequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void Reflexive()
+      {
+        Assert.IsTrue(dit.SequencedEquals(dit));
+        dit.Add(3);
+        Assert.IsTrue(dit.SequencedEquals(dit));
+        dit.Add(7);
+        Assert.IsTrue(dit.SequencedEquals(dit));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+        dat = null;
+        dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class IEditableCollection
+    {
+      private ICollection<int> dit, dat, dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashedLinkedList<int>();
+        dat = new HashedLinkedList<int>();
+        dut = new HashedLinkedList<int>();
+      }
+
+
+      [Test]
+      public void EmptyEmpty()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void EmptyNonEmpty()
+      {
+        dit.Add(3);
+        Assert.IsFalse(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dat.UnsequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void HashVal()
+      {
+        Assert.AreEqual(CHC.unsequencedhashcode(), dit.GetUnsequencedHashCode());
+        dit.Add(3);
+        Assert.AreEqual(CHC.unsequencedhashcode(3), dit.GetUnsequencedHashCode());
+        dit.Add(7);
+        Assert.AreEqual(CHC.unsequencedhashcode(3, 7), dit.GetUnsequencedHashCode());
+        Assert.AreEqual(CHC.unsequencedhashcode(), dut.GetUnsequencedHashCode());
+        dut.Add(3);
+        Assert.AreEqual(CHC.unsequencedhashcode(3), dut.GetUnsequencedHashCode());
+        dut.Add(7);
+        Assert.AreEqual(CHC.unsequencedhashcode(7, 3), dut.GetUnsequencedHashCode());
+      }
+
+
+      [Test]
+      public void EqualHashButDifferent()
+      {
+        dit.Add(-1657792980); dit.Add(-1570288808);
+        dat.Add(1862883298); dat.Add(-272461342);
+        Assert.AreEqual(dit.GetUnsequencedHashCode(), dat.GetUnsequencedHashCode());
+        Assert.IsFalse(dit.UnsequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void Normal()
+      {
+        dit.Add(3);
+        dit.Add(7);
+        dat.Add(3);
+        Assert.IsFalse(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dat.UnsequencedEquals(dit));
+        dat.Add(7);
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsTrue(dat.UnsequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void WrongOrder()
+      {
+        dit.Add(3);
+        dut.Add(3);
+        Assert.IsTrue(dit.UnsequencedEquals(dut));
+        Assert.IsTrue(dut.UnsequencedEquals(dit));
+        dit.Add(7);
+        dut.Add(7);
+        Assert.IsTrue(dit.UnsequencedEquals(dut));
+        Assert.IsTrue(dut.UnsequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void Reflexive()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dit));
+        dit.Add(3);
+        Assert.IsTrue(dit.UnsequencedEquals(dit));
+        dit.Add(7);
+        Assert.IsTrue(dit.UnsequencedEquals(dit));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+        dat = null;
+        dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelUnorderedOfUnOrdered
+    {
+      private ICollection<int> dit, dat, dut;
+
+      private ICollection<ICollection<int>> Dit, Dat, Dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashedLinkedList<int>();
+        dat = new HashedLinkedList<int>();
+        dut = new HashedLinkedList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        Dit = new HashedLinkedList<ICollection<int>>();
+        Dat = new HashedLinkedList<ICollection<int>>();
+        Dut = new HashedLinkedList<ICollection<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dit.UnsequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Assert.IsTrue(Dit.UnsequencedEquals(Dat));
+        Assert.IsFalse(Dit.UnsequencedEquals(Dut));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = null;
+        Dit = Dat = Dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelOrderedOfUnOrdered
+    {
+      private ICollection<int> dit, dat, dut;
+
+      private ISequenced<ICollection<int>> Dit, Dat, Dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashedLinkedList<int>();
+        dat = new HashedLinkedList<int>();
+        dut = new HashedLinkedList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        Dit = new HashedLinkedList<ICollection<int>>();
+        Dat = new HashedLinkedList<ICollection<int>>();
+        Dut = new HashedLinkedList<ICollection<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dit.UnsequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Dut.Add(dit); Dut.Add(dut); Dut.Add(dat);
+        Assert.IsFalse(Dit.SequencedEquals(Dat));
+        Assert.IsTrue(Dit.SequencedEquals(Dut));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = null;
+        Dit = Dat = Dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelUnOrderedOfOrdered
+    {
+      private ISequenced<int> dit, dat, dut, dot;
+
+      private ICollection<ISequenced<int>> Dit, Dat, Dut, Dot;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashedLinkedList<int>();
+        dat = new HashedLinkedList<int>();
+        dut = new HashedLinkedList<int>();
+        dot = new HashedLinkedList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        dot.Add(2); dot.Add(1);
+        Dit = new HashedLinkedList<ISequenced<int>>();
+        Dat = new HashedLinkedList<ISequenced<int>>();
+        Dut = new HashedLinkedList<ISequenced<int>>();
+        Dot = new HashedLinkedList<ISequenced<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsTrue(dit.SequencedEquals(dot));
+        Assert.IsFalse(dit.SequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Dut.Add(dot); Dut.Add(dut); Dut.Add(dit);
+        Dot.Add(dit); Dot.Add(dit); Dot.Add(dut);
+        Assert.IsTrue(Dit.UnsequencedEquals(Dut));
+        Assert.IsFalse(Dit.UnsequencedEquals(Dat));
+        Assert.IsTrue(Dit.UnsequencedEquals(Dot));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = dot = null;
+        Dit = Dat = Dut = Dot = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelOrderedOfOrdered
+    {
+      private ISequenced<int> dit, dat, dut, dot;
+
+      private ISequenced<ISequenced<int>> Dit, Dat, Dut, Dot;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new HashedLinkedList<int>();
+        dat = new HashedLinkedList<int>();
+        dut = new HashedLinkedList<int>();
+        dot = new HashedLinkedList<int>();
+        dit.Add(2); dit.Add(1); //{2,1}
+        dat.Add(1); dat.Add(2); //{1,2}
+        dut.Add(3);            //{3}
+        dot.Add(2); dot.Add(1); //{2,1}
+        Dit = new HashedLinkedList<ISequenced<int>>();
+        Dat = new HashedLinkedList<ISequenced<int>>();
+        Dut = new HashedLinkedList<ISequenced<int>>();
+        Dot = new HashedLinkedList<ISequenced<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsTrue(dit.SequencedEquals(dot));
+        Assert.IsFalse(dit.SequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit); // {{2,1},{3}}
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat); // {{3},{2,1},{1,2}}
+        Dut.Add(dot); Dut.Add(dut); Dut.Add(dit); // {{2,1},{3}}
+        Dot.Add(dit); Dot.Add(dit); Dot.Add(dut); // {{2,1},{3}}
+        Assert.IsTrue(Dit.SequencedEquals(Dut));
+        Assert.IsFalse(Dit.SequencedEquals(Dat));
+        Assert.IsTrue(Dit.SequencedEquals(Dot));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = dot = null;
+        Dit = Dat = Dut = Dot = null;
+      }
+    }
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/linkedlists/LinkedListTest.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/linkedlists/LinkedListTest.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/linkedlists/LinkedListTest.cs	(revision 3)
@@ -0,0 +1,3431 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+
+namespace C5UnitTests.linkedlists.plain
+{
+  using CollectionOfInt = LinkedList<int>;
+
+  [TestFixture]
+  public class GenericTesters
+  {
+
+    [Test]
+    public void TestEvents()
+    {
+      Fun<CollectionOfInt> factory = delegate() { return new CollectionOfInt(TenEqualityComparer.Default); };
+      new C5UnitTests.Templates.Events.ListTester<CollectionOfInt>().Test(factory);
+      new C5UnitTests.Templates.Events.QueueTester<CollectionOfInt>().Test(factory);
+      new C5UnitTests.Templates.Events.StackTester<CollectionOfInt>().Test(factory);
+    }
+
+    [Test]
+    public void Extensible()
+    {
+      C5UnitTests.Templates.Extensible.Clone.Tester<CollectionOfInt>();
+      C5UnitTests.Templates.Extensible.Clone.ViewTester<CollectionOfInt>();
+      C5UnitTests.Templates.Extensible.Serialization.Tester<CollectionOfInt>();
+      C5UnitTests.Templates.Extensible.Serialization.ViewTester<CollectionOfInt>();
+    }
+
+    [Test]
+    public void List()
+    {
+      C5UnitTests.Templates.List.Dispose.Tester<CollectionOfInt>();
+      C5UnitTests.Templates.List.SCG_IList.Tester<CollectionOfInt>();
+    }
+  }
+
+  static class Factory
+  {
+    public static ICollection<T> New<T>() { return new LinkedList<T>(); }
+  }
+
+  namespace Enumerable
+  {
+    [TestFixture]
+    public class Multiops
+    {
+      private LinkedList<int> list;
+
+      private Fun<int, bool> always, never, even;
+
+
+      [SetUp]
+      public void Init()
+      {
+        list = new LinkedList<int>();
+        always = delegate { return true; };
+        never = delegate { return false; };
+        even = delegate(int i) { return i % 2 == 0; };
+      }
+
+
+      [Test]
+      public void All()
+      {
+        Assert.IsTrue(list.All(always));
+        Assert.IsTrue(list.All(never));
+        Assert.IsTrue(list.All(even));
+        list.Add(8);
+        Assert.IsTrue(list.All(always));
+        Assert.IsFalse(list.All(never));
+        Assert.IsTrue(list.All(even));
+        list.Add(5);
+        Assert.IsTrue(list.All(always));
+        Assert.IsFalse(list.All(never));
+        Assert.IsFalse(list.All(even));
+      }
+
+
+      [Test]
+      public void Exists()
+      {
+        Assert.IsFalse(list.Exists(always));
+        Assert.IsFalse(list.Exists(never));
+        Assert.IsFalse(list.Exists(even));
+        list.Add(5);
+        Assert.IsTrue(list.Exists(always));
+        Assert.IsFalse(list.Exists(never));
+        Assert.IsFalse(list.Exists(even));
+        list.Add(8);
+        Assert.IsTrue(list.Exists(always));
+        Assert.IsFalse(list.Exists(never));
+        Assert.IsTrue(list.Exists(even));
+      }
+
+
+      [Test]
+      public void Apply()
+      {
+        int sum = 0;
+        Act<int> a = delegate(int i) { sum = i + 10 * sum; };
+
+        list.Apply(a);
+        Assert.AreEqual(0, sum);
+        sum = 0;
+        list.Add(5); list.Add(8); list.Add(7); list.Add(5);
+        list.Apply(a);
+        Assert.AreEqual(5875, sum);
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+
+
+
+    [TestFixture]
+    public class GetEnumerator
+    {
+      private LinkedList<int> list;
+
+
+      [SetUp]
+      public void Init() { list = new LinkedList<int>(); }
+
+
+      [Test]
+      public void Empty()
+      {
+        SCG.IEnumerator<int> e = list.GetEnumerator();
+
+        Assert.IsFalse(e.MoveNext());
+      }
+
+
+      [Test]
+      public void Normal()
+      {
+        list.Add(5);
+        list.Add(8);
+        list.Add(5);
+        list.Add(5);
+        list.Add(10);
+        list.Add(1);
+
+        SCG.IEnumerator<int> e = list.GetEnumerator();
+
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(5, e.Current);
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(8, e.Current);
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(5, e.Current);
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(5, e.Current);
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(10, e.Current);
+        Assert.IsTrue(e.MoveNext());
+        Assert.AreEqual(1, e.Current);
+        Assert.IsFalse(e.MoveNext());
+      }
+
+
+      [Test]
+      public void DoDispose()
+      {
+        list.Add(5);
+        list.Add(8);
+        list.Add(5);
+
+        SCG.IEnumerator<int> e = list.GetEnumerator();
+
+        e.MoveNext();
+        e.MoveNext();
+        e.Dispose();
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterUpdate()
+      {
+        list.Add(5);
+        list.Add(8);
+        list.Add(5);
+
+        SCG.IEnumerator<int> e = list.GetEnumerator();
+
+        e.MoveNext();
+        list.Add(99);
+        e.MoveNext();
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+  }
+
+  namespace CollectionOrExtensible
+  {
+    [TestFixture]
+    public class Formatting
+    {
+      ICollection<int> coll;
+      IFormatProvider rad16;
+      [SetUp]
+      public void Init() { coll = Factory.New<int>(); rad16 = new RadixFormatProvider(16); }
+      [TearDown]
+      public void Dispose() { coll = null; rad16 = null; }
+      [Test]
+      public void Format()
+      {
+        Assert.AreEqual("[  ]", coll.ToString());
+        coll.AddAll<int>(new int[] { -4, 28, 129, 65530 });
+        Assert.AreEqual("[ -4, 28, 129, 65530 ]", coll.ToString());
+        Assert.AreEqual("[ -4, 1C, 81, FFFA ]", coll.ToString(null, rad16));
+        Assert.AreEqual("[ -4, 28, 129... ]", coll.ToString("L14", null));
+        Assert.AreEqual("[ -4, 1C, 81... ]", coll.ToString("L14", rad16));
+      }
+    }
+
+    [TestFixture]
+    public class CollectionOrSink
+    {
+      private LinkedList<int> list;
+
+
+      [SetUp]
+      public void Init() { list = new LinkedList<int>(); }
+
+      [Test]
+      [ExpectedException(typeof(NullReferenceException))]
+      public void NullEqualityComparerinConstructor1()
+      {
+        new LinkedList<int>(null);
+      }
+
+      [Test]
+      public void Choose()
+      {
+        list.Add(7);
+        Assert.AreEqual(7, list.Choose());
+      }
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void BadChoose()
+      {
+        list.Choose();
+      }
+
+
+      [Test]
+      public void CountEtAl()
+      {
+        Assert.AreEqual(0, list.Count);
+        Assert.IsTrue(list.IsEmpty);
+        Assert.IsTrue(list.AllowsDuplicates);
+        list.Add(5);
+        Assert.AreEqual(1, list.Count);
+        Assert.IsFalse(list.IsEmpty);
+        list.Add(5);
+        Assert.AreEqual(2, list.Count);
+        Assert.IsFalse(list.IsEmpty);
+        list.Add(8);
+        Assert.AreEqual(3, list.Count);
+      }
+
+
+      [Test]
+      public void AddAll()
+      {
+        list.Add(3); list.Add(4); list.Add(5);
+
+        LinkedList<int> list2 = new LinkedList<int>();
+
+        list2.AddAll(list);
+        Assert.IsTrue(IC.eq(list2, 3, 4, 5));
+        list.AddAll(list2);
+        Assert.IsTrue(IC.eq(list2, 3, 4, 5));
+        Assert.IsTrue(IC.eq(list, 3, 4, 5, 3, 4, 5));
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+
+    [TestFixture]
+    public class FindPredicate
+    {
+      private LinkedList<int> list;
+      Fun<int, bool> pred;
+
+      [SetUp]
+      public void Init()
+      {
+        list = new LinkedList<int>(TenEqualityComparer.Default);
+        pred = delegate(int i) { return i % 5 == 0; };
+      }
+
+      [TearDown]
+      public void Dispose() { list = null; }
+
+      [Test]
+      public void Find()
+      {
+        int i;
+        Assert.IsFalse(list.Find(pred, out i));
+        list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+        Assert.IsFalse(list.Find(pred, out i));
+        list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+        Assert.IsTrue(list.Find(pred, out i));
+        Assert.AreEqual(45, i);
+      }
+
+      [Test]
+      public void FindLast()
+      {
+        int i;
+        Assert.IsFalse(list.FindLast(pred, out i));
+        list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+        Assert.IsFalse(list.FindLast(pred, out i));
+        list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+        Assert.IsTrue(list.FindLast(pred, out i));
+        Assert.AreEqual(675, i);
+      }
+
+      [Test]
+      public void FindIndex()
+      {
+        Assert.IsFalse(0 <= list.FindIndex(pred));
+        list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+        Assert.IsFalse(0 <= list.FindIndex(pred));
+        list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+        Assert.AreEqual(4, list.FindIndex(pred));
+      }
+
+      [Test]
+      public void FindLastIndex()
+      {
+        Assert.IsFalse(0 <= list.FindLastIndex(pred));
+        list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+        Assert.IsFalse(0 <= list.FindLastIndex(pred));
+        list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+        Assert.AreEqual(6, list.FindLastIndex(pred));
+      }
+    }
+
+    [TestFixture]
+    public class UniqueItems
+    {
+      private LinkedList<int> list;
+
+      [SetUp]
+      public void Init() { list = new LinkedList<int>(); }
+
+      [TearDown]
+      public void Dispose() { list = null; }
+
+      [Test]
+      public void Test()
+      {
+        Assert.IsTrue(IC.seteq(list.UniqueItems()));
+        Assert.IsTrue(IC.seteq(list.ItemMultiplicities()));
+        list.AddAll<int>(new int[] { 7, 9, 7 });
+        Assert.IsTrue(IC.seteq(list.UniqueItems(), 7, 9));
+        Assert.IsTrue(IC.seteq(list.ItemMultiplicities(), 7, 2, 9, 1));
+      }
+    }
+
+    [TestFixture]
+    public class ArrayTest
+    {
+      private LinkedList<int> list;
+
+      int[] a;
+
+
+      [SetUp]
+      public void Init()
+      {
+        list = new LinkedList<int>();
+        a = new int[10];
+        for (int i = 0; i < 10; i++)
+          a[i] = 1000 + i;
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+
+
+      private string aeq(int[] a, params int[] b)
+      {
+        if (a.Length != b.Length)
+          return "Lengths differ: " + a.Length + " != " + b.Length;
+
+        for (int i = 0; i < a.Length; i++)
+          if (a[i] != b[i])
+            return String.Format("{0}'th elements differ: {1} != {2}", i, a[i], b[i]);
+
+        return "Alles klar";
+      }
+
+
+      [Test]
+      public void ToArray()
+      {
+        Assert.AreEqual("Alles klar", aeq(list.ToArray()));
+        list.Add(7);
+        list.Add(7);
+        Assert.AreEqual("Alles klar", aeq(list.ToArray(), 7, 7));
+      }
+
+
+      [Test]
+      public void CopyTo()
+      {
+        list.CopyTo(a, 1);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+        list.Add(6);
+        list.CopyTo(a, 2);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+        list.Add(4);
+        list.Add(4);
+        list.Add(9);
+        list.CopyTo(a, 4);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 4, 4, 9, 1008, 1009));
+        list.Clear();
+        list.Add(7);
+        list.CopyTo(a, 9);
+        Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 6, 4, 4, 9, 1008, 7));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void CopyToBad()
+      {
+        list.CopyTo(a, 11);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void CopyToBad2()
+      {
+        list.CopyTo(a, -1);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void CopyToTooFar()
+      {
+        list.Add(3);
+        list.Add(3);
+        list.CopyTo(a, 9);
+      }
+    }
+
+
+
+    [TestFixture]
+    public class Sync
+    {
+      private LinkedList<int> list;
+
+
+      [SetUp]
+      public void Init()
+      {
+        list = new LinkedList<int>();
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+
+
+      [Test]
+      public void Get()
+      {
+        Assert.IsNotNull(((System.Collections.IList)list).SyncRoot);
+      }
+    }
+  }
+
+
+
+
+  namespace EditableCollection
+  {
+    [TestFixture]
+    public class Searching
+    {
+      private LinkedList<int> list;
+
+
+      [SetUp]
+      public void Init() { list = new LinkedList<int>(); }
+
+
+      [Test]
+      public void Contains()
+      {
+        Assert.IsFalse(list.Contains(5));
+        list.Add(5);
+        Assert.IsTrue(list.Contains(5));
+        Assert.IsFalse(list.Contains(7));
+        list.Add(8);
+        list.Add(10);
+        Assert.IsTrue(list.Contains(5));
+        Assert.IsFalse(list.Contains(7));
+        Assert.IsTrue(list.Contains(8));
+        Assert.IsTrue(list.Contains(10));
+        list.Remove(8);
+        Assert.IsTrue(list.Contains(5));
+        Assert.IsFalse(list.Contains(7));
+        Assert.IsFalse(list.Contains(8));
+        Assert.IsTrue(list.Contains(10));
+      }
+
+
+      [Test]
+      public void ContainsCount()
+      {
+        Assert.AreEqual(0, list.ContainsCount(5));
+        list.Add(5);
+        Assert.AreEqual(1, list.ContainsCount(5));
+        Assert.AreEqual(0, list.ContainsCount(7));
+        list.Add(8);
+        Assert.AreEqual(1, list.ContainsCount(5));
+        Assert.AreEqual(0, list.ContainsCount(7));
+        Assert.AreEqual(1, list.ContainsCount(8));
+        list.Add(5);
+        Assert.AreEqual(2, list.ContainsCount(5));
+        Assert.AreEqual(0, list.ContainsCount(7));
+        Assert.AreEqual(1, list.ContainsCount(8));
+      }
+
+
+      [Test]
+      public void RemoveAllCopies()
+      {
+        list.Add(5); list.Add(7); list.Add(5);
+        Assert.AreEqual(2, list.ContainsCount(5));
+        Assert.AreEqual(1, list.ContainsCount(7));
+        list.RemoveAllCopies(5);
+        Assert.AreEqual(0, list.ContainsCount(5));
+        Assert.AreEqual(1, list.ContainsCount(7));
+        list.Add(5); list.Add(8); list.Add(5);
+        list.RemoveAllCopies(8);
+        Assert.IsTrue(IC.eq(list, 7, 5, 5));
+      }
+
+
+      [Test]
+      public void FindAll()
+      {
+        Fun<int, bool> f = delegate(int i) { return i % 2 == 0; };
+
+        Assert.IsTrue(list.FindAll(f).IsEmpty);
+        list.Add(5); list.Add(8); list.Add(5); list.Add(10); list.Add(8);
+        Assert.IsTrue(((LinkedList<int>)list.FindAll(f)).Check());
+        Assert.IsTrue(IC.eq(list.FindAll(f), 8, 10, 8));
+      }
+
+
+      [Test]
+      public void ContainsAll()
+      {
+        LinkedList<int> list2 = new LinkedList<int>();
+
+        Assert.IsTrue(list.ContainsAll(list2));
+        list2.Add(4);
+        Assert.IsFalse(list.ContainsAll(list2));
+        list.Add(4);
+        Assert.IsTrue(list.ContainsAll(list2));
+        list.Add(5);
+        Assert.IsTrue(list.ContainsAll(list2));
+        list2.Add(4);
+        Assert.IsFalse(list.ContainsAll(list2));
+        list.Add(4);
+        Assert.IsTrue(list.ContainsAll(list2));
+      }
+
+
+      [Test]
+      public void RetainAll()
+      {
+        LinkedList<int> list2 = new LinkedList<int>();
+
+        list.Add(4); list.Add(4); list.Add(5); list.Add(4); list.Add(6);
+        list2.Add(5); list2.Add(4); list2.Add(7); list2.Add(7); list2.Add(4);
+        list.RetainAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 4, 5));
+        list.Add(5); list.Add(4); list.Add(6);
+        list2.Clear();
+        list2.Add(5); list2.Add(5); list2.Add(6);
+        list.RetainAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 5, 5, 6));
+        list2.Clear();
+        list2.Add(7); list2.Add(8); list2.Add(9);
+        list.RetainAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list));
+      }
+
+
+      [Test]
+      public void RemoveAll()
+      {
+        LinkedList<int> list2 = new LinkedList<int>();
+
+        list.Add(4); list.Add(4); list.Add(5); list.Add(4); list.Add(6);
+        list2.Add(5); list2.Add(4); list2.Add(7); list2.Add(7); list2.Add(4);
+        list.RemoveAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 6));
+        list.Add(5); list.Add(4); list.Add(6);
+        list2.Clear();
+        list2.Add(6); list2.Add(5); list2.Add(5); list2.Add(6);
+        list.RemoveAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 4));
+        list2.Clear();
+        list2.Add(7); list2.Add(8); list2.Add(9);
+        list.RemoveAll(list2);
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 4));
+      }
+
+
+      [Test]
+      public void Remove()
+      {
+
+        Assert.IsTrue(list.FIFO);
+        list.Add(4); list.Add(4); list.Add(5); list.Add(4); list.Add(6);
+        Assert.IsFalse(list.Remove(2));
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(list.Remove(4));
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 5, 4, 6));
+        Assert.AreEqual(6, list.RemoveLast());
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 5, 4));
+        list.Add(7);
+        Assert.AreEqual(4, list.RemoveFirst());
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 5, 4, 7));
+
+        list.FIFO = false;
+        list.Clear();
+        list.Add(4); list.Add(4); list.Add(5); list.Add(4); list.Add(6);
+        Assert.IsFalse(list.Remove(2));
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(list.Remove(4));
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 4, 5, 6));
+        Assert.AreEqual(6, list.RemoveLast());
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 4, 5));
+        list.Add(7);
+        Assert.AreEqual(4, list.RemoveFirst());
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 4, 5, 7));
+      }
+
+
+      [Test]
+      public void Clear()
+      {
+        list.Add(7); list.Add(7);
+        list.Clear();
+        Assert.IsTrue(list.IsEmpty);
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+  }
+
+
+
+
+  namespace IIndexed
+  {
+    [TestFixture]
+    public class Searching
+    {
+      private IIndexed<int> dit;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new LinkedList<int>();
+      }
+
+
+      [Test]
+      public void IndexOf()
+      {
+        Assert.AreEqual(~0, dit.IndexOf(6));
+        dit.Add(7);
+        Assert.AreEqual(~1, dit.IndexOf(6));
+        Assert.AreEqual(~1, dit.LastIndexOf(6));
+        Assert.AreEqual(0, dit.IndexOf(7));
+        dit.Add(5); dit.Add(7); dit.Add(8); dit.Add(7);
+        Assert.AreEqual(~5, dit.IndexOf(6));
+        Assert.AreEqual(0, dit.IndexOf(7));
+        Assert.AreEqual(4, dit.LastIndexOf(7));
+        Assert.AreEqual(3, dit.IndexOf(8));
+        Assert.AreEqual(1, dit.LastIndexOf(5));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class Removing
+    {
+      private IIndexed<int> dit;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new LinkedList<int>();
+      }
+
+
+      [Test]
+      public void RemoveAt()
+      {
+        dit.Add(5); dit.Add(7); dit.Add(9); dit.Add(1); dit.Add(2);
+        Assert.AreEqual(7, dit.RemoveAt(1));
+        Assert.IsTrue(((LinkedList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 5, 9, 1, 2));
+        Assert.AreEqual(5, dit.RemoveAt(0));
+        Assert.IsTrue(((LinkedList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 9, 1, 2));
+        Assert.AreEqual(2, dit.RemoveAt(2));
+        Assert.IsTrue(((LinkedList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 9, 1));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void RemoveAtBad0()
+      {
+        dit.RemoveAt(0);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void RemoveAtBadM1()
+      {
+        dit.RemoveAt(-1);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void RemoveAtBad1()
+      {
+        dit.Add(8);
+        dit.RemoveAt(1);
+      }
+
+
+      [Test]
+      public void RemoveInterval()
+      {
+        dit.RemoveInterval(0, 0);
+        dit.Add(10); dit.Add(20); dit.Add(30); dit.Add(40); dit.Add(50); dit.Add(60);
+        dit.RemoveInterval(3, 0);
+        Assert.IsTrue(((LinkedList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 10, 20, 30, 40, 50, 60));
+        dit.RemoveInterval(3, 1);
+        Assert.IsTrue(((LinkedList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 10, 20, 30, 50, 60));
+        dit.RemoveInterval(1, 3);
+        Assert.IsTrue(((LinkedList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 10, 60));
+        dit.RemoveInterval(0, 2);
+        Assert.IsTrue(((LinkedList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit));
+        dit.Add(10); dit.Add(20); dit.Add(30); dit.Add(40); dit.Add(50); dit.Add(60);
+        dit.RemoveInterval(0, 2);
+        Assert.IsTrue(((LinkedList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 30, 40, 50, 60));
+        dit.RemoveInterval(2, 2);
+        Assert.IsTrue(((LinkedList<int>)dit).Check());
+        Assert.IsTrue(IC.eq(dit, 30, 40));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+      }
+    }
+  }
+
+
+
+
+  namespace IList_
+  {
+    [TestFixture]
+    public class Searching
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new LinkedList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void FirstBad()
+      {
+        int f = lst.First;
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void LastBad()
+      {
+        int f = lst.Last;
+      }
+
+
+      [Test]
+      public void FirstLast()
+      {
+        lst.Add(19);
+        Assert.AreEqual(19, lst.First);
+        Assert.AreEqual(19, lst.Last);
+        lst.Add(34); lst.InsertFirst(12);
+        Assert.AreEqual(12, lst.First);
+        Assert.AreEqual(34, lst.Last);
+      }
+
+
+      [Test]
+      public void This()
+      {
+        lst.Add(34);
+        Assert.AreEqual(34, lst[0]);
+        lst[0] = 56;
+        Assert.AreEqual(56, lst.First);
+        lst.Add(7); lst.Add(7); lst.Add(7); lst.Add(7);
+        lst[0] = 45; lst[2] = 78; lst[4] = 101;
+        Assert.IsTrue(IC.eq(lst, 45, 7, 78, 7, 101));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadEmptyGet()
+      {
+        int f = lst[0];
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadLowGet()
+      {
+        lst.Add(7);
+
+        int f = lst[-1];
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadHiGet()
+      {
+        lst.Add(6);
+
+        int f = lst[1];
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadEmptySet()
+      {
+        lst[0] = 4;
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadLowSet()
+      {
+        lst.Add(7);
+        lst[-1] = 9;
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void ThisBadHiSet()
+      {
+        lst.Add(6);
+        lst[1] = 11;
+      }
+    }
+
+
+    [TestFixture]
+    public class Combined
+    {
+      private IList<KeyValuePair<int, int>> lst;
+
+
+      [SetUp]
+      public void Init()
+      {
+        lst = new LinkedList<KeyValuePair<int, int>>(new KeyValuePairEqualityComparer<int, int>());
+        for (int i = 0; i < 10; i++)
+          lst.Add(new KeyValuePair<int, int>(i, i + 30));
+      }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void Find()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.Find(ref p));
+        Assert.AreEqual(3, p.Key);
+        Assert.AreEqual(33, p.Value);
+        p = new KeyValuePair<int, int>(13, 78);
+        Assert.IsFalse(lst.Find(ref p));
+      }
+
+
+      [Test]
+      public void FindOrAdd()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.FindOrAdd(ref p));
+        Assert.AreEqual(3, p.Key);
+        Assert.AreEqual(33, p.Value);
+        p = new KeyValuePair<int, int>(13, 79);
+        Assert.IsFalse(lst.FindOrAdd(ref p));
+        Assert.AreEqual(13, lst[10].Key);
+        Assert.AreEqual(79, lst[10].Value);
+      }
+
+
+      [Test]
+      public void Update()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.Update(p));
+        Assert.AreEqual(3, lst[3].Key);
+        Assert.AreEqual(78, lst[3].Value);
+        p = new KeyValuePair<int, int>(13, 78);
+        Assert.IsFalse(lst.Update(p));
+      }
+
+
+      [Test]
+      public void UpdateOrAdd1()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.UpdateOrAdd(p));
+        Assert.AreEqual(3, lst[3].Key);
+        Assert.AreEqual(78, lst[3].Value);
+        p = new KeyValuePair<int, int>(13, 79);
+        Assert.IsFalse(lst.UpdateOrAdd(p));
+        Assert.AreEqual(13, lst[10].Key);
+        Assert.AreEqual(79, lst[10].Value);
+      }
+
+      [Test]
+      public void UpdateOrAdd2()
+      {
+          ICollection<String> coll = new LinkedList<String>();
+          // s1 and s2 are distinct objects but contain the same text:
+          String old, s1 = "abc", s2 = ("def" + s1).Substring(3);
+          Assert.IsFalse(coll.UpdateOrAdd(s1, out old));
+          Assert.AreEqual(null, old);
+          Assert.IsTrue(coll.UpdateOrAdd(s2, out old));
+          Assert.IsTrue(Object.ReferenceEquals(s1, old));
+          Assert.IsFalse(Object.ReferenceEquals(s2, old));
+      }
+
+
+      [Test]
+      public void RemoveWithReturn()
+      {
+        KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+        Assert.IsTrue(lst.Remove(p, out p));
+        Assert.AreEqual(3, p.Key);
+        Assert.AreEqual(33, p.Value);
+        Assert.AreEqual(4, lst[3].Key);
+        Assert.AreEqual(34, lst[3].Value);
+        p = new KeyValuePair<int, int>(13, 78);
+        Assert.IsFalse(lst.Remove(p, out p));
+      }
+    }
+
+
+    [TestFixture]
+    public class Inserting
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new LinkedList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void Insert()
+      {
+        lst.Insert(0, 5);
+        Assert.IsTrue(IC.eq(lst, 5));
+        lst.Insert(0, 7);
+        Assert.IsTrue(IC.eq(lst, 7, 5));
+        lst.Insert(1, 4);
+        Assert.IsTrue(IC.eq(lst, 7, 4, 5));
+        lst.Insert(3, 2);
+        Assert.IsTrue(IC.eq(lst, 7, 4, 5, 2));
+      }
+
+      [Test]
+      public void InsertDuplicate()
+      {
+        lst.Insert(0, 5);
+        Assert.IsTrue(IC.eq(lst, 5));
+        lst.Insert(0, 7);
+        Assert.IsTrue(IC.eq(lst, 7, 5));
+        lst.Insert(1, 5);
+        Assert.IsTrue(IC.eq(lst, 7, 5, 5));
+      }
+
+      [Test]
+      public void InsertAllDuplicate1()
+      {
+        lst.Insert(0, 3);
+        Assert.IsTrue(IC.eq(lst, 3));
+        lst.Insert(0, 7);
+        Assert.IsTrue(IC.eq(lst, 7, 3));
+        lst.InsertAll<int>(1, new int[] { 1, 2, 3, 4 });
+        Assert.IsTrue(IC.eq(lst, 7, 1, 2, 3, 4, 3));
+        Assert.IsTrue(lst.Check());
+      }
+      [Test]
+      public void InsertAllDuplicate2()
+      {
+        lst.Insert(0, 3);
+        Assert.IsTrue(IC.eq(lst, 3));
+        lst.Insert(0, 7);
+        Assert.IsTrue(IC.eq(lst, 7, 3));
+        lst.InsertAll<int>(1, new int[] { 5, 6, 5, 8 });
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 5, 6, 5, 8, 3));
+      }
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void BadInsertLow()
+      {
+        lst.Add(7);
+        lst.Insert(-1, 9);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void BadInsertHi()
+      {
+        lst.Add(6);
+        lst.Insert(2, 11);
+      }
+
+
+      [Test]
+      public void FIFO()
+      {
+        for (int i = 0; i < 7; i++)
+          lst.Add(2 * i);
+
+        Assert.IsTrue(lst.FIFO);
+        Assert.AreEqual(0, lst.Remove());
+        Assert.AreEqual(2, lst.Remove());
+        lst.FIFO = false;
+        Assert.AreEqual(12, lst.Remove());
+        Assert.AreEqual(10, lst.Remove());
+        lst.FIFO = true;
+        Assert.AreEqual(4, lst.Remove());
+        Assert.AreEqual(6, lst.Remove());
+      }
+
+
+      [Test]
+      public void InsertFirstLast()
+      {
+        lst.InsertFirst(4);
+        lst.InsertLast(5);
+        lst.InsertFirst(14);
+        lst.InsertLast(15);
+        lst.InsertFirst(24);
+        lst.InsertLast(25);
+        lst.InsertFirst(34);
+        lst.InsertLast(55);
+        Assert.IsTrue(IC.eq(lst, 34, 24, 14, 4, 5, 15, 25, 55));
+      }
+
+
+      [Test]
+      public void InsertFirst()
+      {
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(2);
+        lst.Add(5);
+        lst.ViewOf(2).InsertFirst(7);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 2, 3, 2, 5));
+        lst.ViewOf(3).InsertFirst(8);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 2, 8, 3, 2, 5));
+        lst.ViewOf(5).InsertFirst(9);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 2, 8, 3, 2, 9, 5));
+      }
+
+
+      [Test]
+      public void BadInsertFirst()
+      {
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(2);
+        lst.Add(5);
+        Assert.IsNull(lst.ViewOf(4));
+      }
+
+
+      [Test]
+      public void InsertAfter()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(2);
+        lst.Add(5);
+        lst.LastViewOf(2).InsertLast(7);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 1, 2, 3, 2, 7, 5));
+        lst.LastViewOf(1).InsertLast(8);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 1, 8, 2, 3, 2, 7, 5));
+        lst.LastViewOf(5).InsertLast(9);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 1, 8, 2, 3, 2, 7, 5, 9));
+      }
+
+
+      [Test]
+      public void BadInsertAfter()
+      {
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(2);
+        lst.Add(5);
+        Assert.IsNull(lst.ViewOf(4));
+      }
+
+
+      [Test]
+      public void InsertAll()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(4);
+
+        IList<int> lst2 = new LinkedList<int>();
+
+        lst2.Add(7); lst2.Add(8); lst2.Add(9);
+        lst.InsertAll(0, lst2);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 1, 2, 3, 4));
+        lst.InsertAll(7, lst2);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 1, 2, 3, 4, 7, 8, 9));
+        lst.InsertAll(5, lst2);
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 1, 2, 7, 8, 9, 3, 4, 7, 8, 9));
+      }
+
+
+      [Test]
+      public void Map()
+      {
+        Fun<int, string> m = delegate(int i) { return "<<" + i + ">>"; };
+        IList<string> r = lst.Map(m);
+
+        Assert.IsTrue(r.Check());
+        Assert.IsTrue(r.IsEmpty);
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(4);
+        r = lst.Map(m);
+        Assert.IsTrue(r.Check());
+        Assert.AreEqual(4, r.Count);
+        for (int i = 0; i < 4; i++)
+          Assert.AreEqual("<<" + (i + 1) + ">>", r[i]);
+      }
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void BadMapper()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        Fun<int, bool> m = delegate(int i) { if (i == 2) lst.Add(7); return true; };
+        lst.Map(m);
+      }
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void ModifyingFindAll()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        Fun<int, bool> m = delegate(int i) { if (i == 2) lst.Add(7); return true; };
+        lst.FindAll(m);
+      }
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void BadMapperView()
+      {
+        lst = lst.View(0, 0);
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        Fun<int, bool> m = delegate(int i) { if (i == 2) lst.Add(7); return true; };
+        lst.Map(m);
+      }
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void ModifyingFindAllView()
+      {
+        lst = lst.View(0, 0);
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        Fun<int, bool> m = delegate(int i) { if (i == 2) lst.Add(7); return true; };
+        lst.FindAll(m);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void BadRemove() { lst.Remove(); }
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void BadRemoveFirst() { lst.RemoveFirst(); }
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void BadRemoveLast() { lst.RemoveLast(); }
+
+
+      [Test]
+      public void RemoveFirstLast()
+      {
+        lst.Add(1);
+        lst.Add(2);
+        lst.Add(3);
+        lst.Add(4);
+        Assert.AreEqual(1, lst.RemoveFirst());
+        Assert.AreEqual(4, lst.RemoveLast());
+        Assert.AreEqual(2, lst.RemoveFirst());
+        Assert.AreEqual(3, lst.RemoveLast());
+        Assert.IsTrue(lst.IsEmpty);
+      }
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void RemoveFirstEmpty()
+      {
+        lst.RemoveFirst();
+      }
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void RemoveLastEmpty()
+      {
+        lst.RemoveLast();
+      }
+
+      [Test]
+      public void Reverse()
+      {
+        for (int i = 0; i < 10; i++)
+          lst.Add(i);
+
+        lst.Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0));
+        lst.View(0, 3).Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0));
+        lst.View(7, 0).Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 6, 5, 4, 3, 2, 1, 0));
+        lst.View(7, 3).Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2));
+        lst.View(5, 1).Reverse();
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(IC.eq(lst, 7, 8, 9, 6, 5, 4, 3, 0, 1, 2));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void BadReverse()
+      {
+        for (int i = 0; i < 10; i++)
+          lst.Add(i);
+
+        lst.View(8, 3).Reverse();
+      }
+    }
+
+
+
+    [TestFixture]
+    public class SortingTests
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new LinkedList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void Sort()
+      {
+        lst.Add(5); lst.Add(6); lst.Add(5); lst.Add(7); lst.Add(3);
+        Assert.IsFalse(lst.IsSorted(new IC()));
+        lst.Sort(new IC());
+        Assert.IsTrue(lst.Check());
+        Assert.IsTrue(lst.IsSorted());
+        Assert.IsTrue(lst.IsSorted(new IC()));
+        Assert.IsTrue(IC.eq(lst, 3, 5, 5, 6, 7));
+      }
+
+
+      [Test]
+      public void Stability()
+      {
+        IList<KeyValuePair<int, string>> lst2 = new LinkedList<KeyValuePair<int, string>>();
+        SCG.IComparer<KeyValuePair<int, string>> c = new KeyValuePairComparer<int, string>(new IC());
+
+        lst2.Add(new KeyValuePair<int, string>(5, "a"));
+        lst2.Add(new KeyValuePair<int, string>(5, "b"));
+        lst2.Add(new KeyValuePair<int, string>(6, "c"));
+        lst2.Add(new KeyValuePair<int, string>(4, "d"));
+        lst2.Add(new KeyValuePair<int, string>(3, "e"));
+        lst2.Add(new KeyValuePair<int, string>(4, "f"));
+        lst2.Add(new KeyValuePair<int, string>(5, "handle"));
+        Assert.IsFalse(lst2.IsSorted(c));
+        lst2.Sort(c);
+        Assert.IsTrue(lst2.IsSorted(c));
+
+        KeyValuePair<int, string> p = lst2.RemoveFirst();
+
+        Assert.AreEqual(3, p.Key);
+        Assert.AreEqual("e", p.Value);
+        p = lst2.RemoveFirst();
+        Assert.AreEqual(4, p.Key);
+        Assert.AreEqual("d", p.Value);
+        p = lst2.RemoveFirst();
+        Assert.AreEqual(4, p.Key);
+        Assert.AreEqual("f", p.Value);
+        p = lst2.RemoveFirst();
+        Assert.AreEqual(5, p.Key);
+        Assert.AreEqual("a", p.Value);
+        p = lst2.RemoveFirst();
+        Assert.AreEqual(5, p.Key);
+        Assert.AreEqual("b", p.Value);
+        p = lst2.RemoveFirst();
+        Assert.AreEqual(5, p.Key);
+        Assert.AreEqual("handle", p.Value);
+        p = lst2.RemoveFirst();
+        Assert.AreEqual(6, p.Key);
+        Assert.AreEqual("c", p.Value);
+        Assert.IsTrue(lst2.IsEmpty);
+      }
+    }
+    [TestFixture]
+    public class ShuffleTests
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new LinkedList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void Shuffle()
+      {
+        lst.Add(5); lst.Add(6); lst.Add(5); lst.Add(7); lst.Add(3);
+        for (int i = 0; i < 100; i++)
+        {
+          lst.Shuffle(new C5Random(i + 1));
+          Assert.IsTrue(lst.Check(), "Check " + i);
+          int[] lst2 = lst.ToArray();
+          Sorting.IntroSort<int>(lst2);
+          Assert.IsTrue(IC.eq(lst2, 3, 5, 5, 6, 7), "Contents " + i);
+        }
+      }
+    }
+  }
+
+
+  namespace IStackQueue
+  {
+    [TestFixture]
+    public class Stack
+    {
+      private IStack<int> list;
+
+
+      [SetUp]
+      public void Init() { list = new LinkedList<int>(); }
+
+
+      [Test]
+      public void Normal()
+      {
+        list.Push(7);
+        list.Push(5);
+        list.Push(7);
+        list.Push(8);
+        list.Push(9);
+        Assert.AreEqual(9, list.Pop());
+        Assert.AreEqual(8, list.Pop());
+        Assert.AreEqual(7, list.Pop());
+        Assert.AreEqual(5, list.Pop());
+        Assert.AreEqual(7, list.Pop());
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void PopEmpty()
+      {
+        list.Push(5);
+        Assert.AreEqual(5, list.Pop());
+        list.Pop();
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+    [TestFixture]
+    public class Queue
+    {
+      private IQueue<int> list;
+
+
+      [SetUp]
+      public void Init() { list = new LinkedList<int>(); }
+
+
+      [Test]
+      public void Normal()
+      {
+        list.Enqueue(7);
+        list.Enqueue(5);
+        list.Enqueue(7);
+        list.Enqueue(8);
+        list.Enqueue(9);
+        Assert.AreEqual(7, list.Dequeue());
+        Assert.AreEqual(5, list.Dequeue());
+        Assert.AreEqual(7, list.Dequeue());
+        Assert.AreEqual(8, list.Dequeue());
+        Assert.AreEqual(9, list.Dequeue());
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(NoSuchItemException))]
+      public void DeQueueEmpty()
+      {
+        list.Enqueue(5);
+        Assert.AreEqual(5, list.Dequeue());
+        list.Dequeue();
+      }
+
+
+      [TearDown]
+      public void Dispose() { list = null; }
+    }
+  }
+
+
+  namespace Range
+  {
+    [TestFixture]
+    public class Range
+    {
+      private IList<int> lst;
+
+
+      [SetUp]
+      public void Init() { lst = new LinkedList<int>(); }
+
+
+      [TearDown]
+      public void Dispose() { lst = null; }
+
+
+      [Test]
+      public void GetRange()
+      {
+        //Assert.IsTrue(IC.eq(lst[0, 0)));
+        for (int i = 0; i < 10; i++) lst.Add(i);
+
+        Assert.IsTrue(IC.eq(lst[0, 3], 0, 1, 2));
+        Assert.IsTrue(IC.eq(lst[3, 4], 3, 4, 5, 6));
+        Assert.IsTrue(IC.eq(lst[6, 4], 6, 7, 8, 9));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void BadGetRange()
+      {
+        object foo = lst[0, 11];
+      }
+
+
+      [Test]
+      public void Backwards()
+      {
+        for (int i = 0; i < 10; i++) lst.Add(i);
+
+        Assert.IsTrue(IC.eq(lst.Backwards(), 9, 8, 7, 6, 5, 4, 3, 2, 1, 0));
+        Assert.IsTrue(IC.eq(lst[0, 4].Backwards(), 3, 2, 1, 0));
+        Assert.IsTrue(IC.eq(lst[3, 4].Backwards(), 6, 5, 4, 3));
+        Assert.IsTrue(IC.eq(lst[6, 4].Backwards(), 9, 8, 7, 6));
+      }
+
+
+      [Test]
+      public void DirectionAndCount()
+      {
+        for (int i = 0; i < 10; i++) lst.Add(i);
+
+        Assert.AreEqual(EnumerationDirection.Forwards, lst.Direction);
+        Assert.AreEqual(EnumerationDirection.Forwards, lst[3, 7].Direction);
+        Assert.AreEqual(EnumerationDirection.Backwards, lst[3, 7].Backwards().Direction);
+        Assert.AreEqual(EnumerationDirection.Backwards, lst.Backwards().Direction);
+        Assert.AreEqual(4, lst[3, 4].Count);
+        Assert.AreEqual(4, lst[3, 4].Backwards().Count);
+        Assert.AreEqual(10, lst.Backwards().Count);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterUpdate()
+      {
+        for (int i = 0; i < 10; i++) lst.Add(i);
+
+        foreach (int i in lst)
+        {
+          lst.Add(45 + i);
+        }
+      }
+    }
+  }
+
+
+
+
+  namespace View
+  {
+    [TestFixture]
+    public class Simple
+    {
+      LinkedList<int> list, view;
+
+
+      [SetUp]
+      public void Init()
+      {
+        list = new LinkedList<int>();
+        list.Add(0); list.Add(1); list.Add(2); list.Add(3);
+        view = (LinkedList<int>)list.View(1, 2);
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        list = view = null;
+      }
+
+
+      void check()
+      {
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(view.Check());
+      }
+
+
+      [Test]
+      public void InsertPointer()
+      {
+        IList<int> view2 = list.View(2, 0);
+        list.Insert(view2, 7);
+        check();
+        list.Insert(list, 8);
+        check();
+        view.Insert(view2, 9);
+        check();
+        view.Insert(list.View(3, 2), 10);
+        check();
+        view.Insert(list.ViewOf(0), 11);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 11, 1, 9, 7, 2, 10, 3, 8));
+        Assert.IsTrue(IC.eq(view, 11, 1, 9, 7, 2, 10));
+      }
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void InsertPointerBad1()
+      {
+        view.Insert(list.View(0, 0), 7);
+      }
+
+      [Test]
+      [ExpectedException(typeof(IndexOutOfRangeException))]
+      public void InsertPointerBad2()
+      {
+        view.Insert(list, 7);
+      }
+
+      [Test]
+      [ExpectedException(typeof(IncompatibleViewException))]
+      public void InsertPointerBad3()
+      {
+        list.Insert(new ArrayList<int>(), 7);
+      }
+
+      [Test]
+      [ExpectedException(typeof(IncompatibleViewException))]
+      public void InsertPointerBad4()
+      {
+        list.Insert(new ArrayList<int>().View(0, 0), 7);
+      }
+
+      [Test]
+      public void Span()
+      {
+        IList<int> span = list.View(1, 0).Span(list.View(2, 0));
+        Assert.IsTrue(span.Check());
+        Assert.AreEqual(1, span.Offset);
+        Assert.AreEqual(1, span.Count);
+        span = list.View(0, 2).Span(list.View(2, 2));
+        Assert.IsTrue(span.Check());
+        Assert.AreEqual(0, span.Offset);
+        Assert.AreEqual(4, span.Count);
+        span = list.View(3, 1).Span(list.View(1, 1));
+        Assert.IsNull(span);
+      }
+
+      [Test]
+      public void ViewOf()
+      {
+        for (int i = 0; i < 4; i++)
+          list.Add(i);
+        IList<int> v = view.ViewOf(2);
+        Assert.IsTrue(v.Check());
+        Assert.IsTrue(IC.eq(v, 2));
+        Assert.AreEqual(2, v.Offset);
+        v = list.ViewOf(2);
+        Assert.IsTrue(v.Check());
+        Assert.IsTrue(IC.eq(v, 2));
+        Assert.AreEqual(2, v.Offset);
+        v = list.LastViewOf(2);
+        Assert.IsTrue(v.Check());
+        Assert.IsTrue(IC.eq(v, 2));
+        Assert.AreEqual(6, v.Offset);
+      }
+
+      [Test]
+      public void BadViewOf()
+      {
+        Assert.IsNull(view.ViewOf(5));
+        Assert.IsNull(view.LastViewOf(5));
+        Assert.IsNull(view.ViewOf(3));
+        Assert.IsNull(view.LastViewOf(3));
+        Assert.IsNull(view.ViewOf(0));
+        Assert.IsNull(view.LastViewOf(0));
+      }
+
+      [Test]
+      public void ArrayStuff()
+      {
+        Assert.IsTrue(IC.eq(view.ToArray(), 1, 2));
+        int[] extarray = new int[5];
+        view.CopyTo(extarray, 2);
+        Assert.IsTrue(IC.eq(extarray, 0, 0, 1, 2, 0));
+      }
+
+
+      [Test]
+      public void Add()
+      {
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 1, 2, 3));
+        Assert.IsTrue(IC.eq(view, 1, 2));
+        view.InsertFirst(10);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 10, 1, 2, 3));
+        Assert.IsTrue(IC.eq(view, 10, 1, 2));
+        view.Clear();
+        Assert.IsFalse(view.IsReadOnly);
+        Assert.IsTrue(view.AllowsDuplicates);
+        Assert.IsTrue(view.IsEmpty);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 3));
+        Assert.IsTrue(IC.eq(view));
+        view.Add(8);
+        Assert.IsFalse(view.IsEmpty);
+        Assert.IsTrue(view.AllowsDuplicates);
+        Assert.IsFalse(view.IsReadOnly);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 3));
+        Assert.IsTrue(IC.eq(view, 8));
+        view.Add(12);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 12, 3));
+        Assert.IsTrue(IC.eq(view, 8, 12));
+        view./*ViewOf(12).*/InsertLast(15);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 12, 15, 3));
+        Assert.IsTrue(IC.eq(view, 8, 12, 15));
+        view.ViewOf(12).InsertFirst(18);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 18, 12, 15, 3));
+        Assert.IsTrue(IC.eq(view, 8, 18, 12, 15));
+
+        LinkedList<int> lst2 = new LinkedList<int>();
+
+        lst2.Add(90); lst2.Add(92);
+        view.AddAll(lst2);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 18, 12, 15, 90, 92, 3));
+        Assert.IsTrue(IC.eq(view, 8, 18, 12, 15, 90, 92));
+        view.InsertLast(66);
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 8, 18, 12, 15, 90, 92, 66, 3));
+        Assert.IsTrue(IC.eq(view, 8, 18, 12, 15, 90, 92, 66));
+      }
+
+
+      [Test]
+      public void Bxxx()
+      {
+        Assert.IsTrue(IC.eq(view.Backwards(), 2, 1));
+        Assert.AreSame(list, view.Underlying);
+        Assert.IsNull(list.Underlying);
+        Assert.AreEqual(EnumerationDirection.Forwards, view.Direction);
+        Assert.AreEqual(EnumerationDirection.Backwards, view.Backwards().Direction);
+        Assert.AreEqual(0, list.Offset);
+        Assert.AreEqual(1, view.Offset);
+      }
+
+
+      [Test]
+      public void Contains()
+      {
+        Assert.IsTrue(view.Contains(1));
+        Assert.IsFalse(view.Contains(0));
+
+        LinkedList<int> lst2 = new LinkedList<int>();
+
+        lst2.Add(2);
+        Assert.IsTrue(view.ContainsAll(lst2));
+        lst2.Add(3);
+        Assert.IsFalse(view.ContainsAll(lst2));
+        Assert.AreEqual(Speed.Linear, view.ContainsSpeed);
+        Assert.AreEqual(2, view.Count);
+        view.Add(1);
+        Assert.AreEqual(1, view.ContainsCount(2));
+        Assert.AreEqual(2, view.ContainsCount(1));
+        Assert.AreEqual(3, view.Count);
+      }
+
+
+      [Test]
+      public void CreateView()
+      {
+        LinkedList<int> view2 = (LinkedList<int>)view.View(1, 0);
+
+        Assert.AreSame(list, view2.Underlying);
+      }
+
+
+      [Test]
+      public void FIFO()
+      {
+        Assert.IsTrue(view.FIFO);
+        view.Add(23); view.Add(24); view.Add(25);
+        check();
+        Assert.IsTrue(IC.eq(view, 1, 2, 23, 24, 25));
+        Assert.AreEqual(1, view.Remove());
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 23, 24, 25));
+        view.FIFO = false;
+        Assert.IsFalse(view.FIFO);
+        Assert.AreEqual(25, view.Remove());
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 23, 24));
+      }
+
+
+      [Test]
+      public void MapEtc()
+      {
+        LinkedList<double> dbl = (LinkedList<double>)view.Map(new Fun<int, double>(delegate(int i) { return i / 10.0; }));
+
+        Assert.IsTrue(dbl.Check());
+        Assert.AreEqual(0.1, dbl[0]);
+        Assert.AreEqual(0.2, dbl[1]);
+        for (int i = 0; i < 10; i++) view.Add(i);
+
+        list = (LinkedList<int>)view.FindAll(new Fun<int, bool>(delegate(int i) { return i % 4 == 1; }));
+        Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 1, 1, 5, 9));
+      }
+
+
+      [Test]
+      public void FL()
+      {
+        Assert.AreEqual(1, view.First);
+        Assert.AreEqual(2, view.Last);
+      }
+
+
+      [Test]
+      public void Indexing()
+      {
+        list.Clear();
+        for (int i = 0; i < 20; i++) list.Add(i);
+
+        view = (LinkedList<int>)list.View(5, 7);
+        for (int i = 0; i < 7; i++) Assert.AreEqual(i + 5, view[i]);
+
+        for (int i = 0; i < 7; i++) Assert.AreEqual(i, view.IndexOf(i + 5));
+
+        for (int i = 0; i < 7; i++) Assert.AreEqual(i, view.LastIndexOf(i + 5));
+      }
+
+
+      [Test]
+      public void INsert()
+      {
+        view.Insert(0, 34);
+        view.Insert(1, 35);
+        view.Insert(4, 36);
+        Assert.IsTrue(view.Check());
+        Assert.IsTrue(IC.eq(view, 34, 35, 1, 2, 36));
+
+        IList<int> list2 = new LinkedList<int>();
+
+        list2.AddAll(view);
+        view.InsertAll(3, list2);
+        Assert.IsTrue(view.Check());
+        Assert.IsTrue(IC.eq(view, 34, 35, 1, 34, 35, 1, 2, 36, 2, 36));
+      }
+
+
+      [Test]
+      public void Sort()
+      {
+        view.Add(45); view.Add(47); view.Add(46); view.Add(48);
+        Assert.IsFalse(view.IsSorted(new IC()));
+        view.Sort(new IC());
+        check();
+        Assert.IsTrue(IC.eq(list, 0, 1, 2, 45, 46, 47, 48, 3));
+        Assert.IsTrue(IC.eq(view, 1, 2, 45, 46, 47, 48));
+      }
+
+
+      [Test]
+      public void Remove()
+      {
+        view.FIFO = false;
+        view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0);
+        Assert.IsTrue(IC.eq(view, 1, 2, 1, 5, 3, 1, 3, 0));
+        Assert.IsTrue(view.Remove(1));
+        check();
+        Assert.IsTrue(IC.eq(view, 1, 2, 1, 5, 3, 3, 0));
+        Assert.IsTrue(view.Remove(1));
+        check();
+        Assert.IsTrue(IC.eq(view, 1, 2, 5, 3, 3, 0));
+        Assert.IsTrue(view.Remove(0));
+        check();
+        Assert.IsTrue(IC.eq(view, 1, 2, 5, 3, 3));
+        view.RemoveAllCopies(3);
+        check();
+        Assert.IsTrue(IC.eq(view, 1, 2, 5));
+        Assert.IsTrue(IC.eq(list, 0, 1, 2, 5, 3));
+        view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0);
+        Assert.IsTrue(IC.eq(view, 1, 2, 5, 1, 5, 3, 1, 3, 0));
+
+        view.FIFO = true;
+        view.Clear(); view.Add(1); view.Add(2);
+
+        view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0);
+        Assert.IsTrue(IC.eq(view, 1, 2, 1, 5, 3, 1, 3, 0));
+        Assert.IsTrue(view.Remove(1));
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 1, 5, 3, 1, 3, 0));
+        Assert.IsTrue(view.Remove(1));
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 5, 3, 1, 3, 0));
+        Assert.IsTrue(view.Remove(0));
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 5, 3, 1, 3));
+        view.RemoveAllCopies(3);
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 5, 1));
+        Assert.IsTrue(IC.eq(list, 0, 2, 5, 1, 3));
+        view.Add(1); view.Add(5); view.Add(3); view.Add(1); view.Add(3); view.Add(0);
+        Assert.IsTrue(IC.eq(view, 2, 5, 1, 1, 5, 3, 1, 3, 0));
+
+        LinkedList<int> l2 = new LinkedList<int>();
+
+        l2.Add(1); l2.Add(2); l2.Add(2); l2.Add(3); l2.Add(1);
+        view.RemoveAll(l2);
+        check();
+        Assert.IsTrue(IC.eq(view, 5, 5, 1, 3, 0));
+        view.RetainAll(l2);
+        check();
+        Assert.IsTrue(IC.eq(view, 1, 3));
+        view.Add(2); view.Add(4); view.Add(5);
+        Assert.AreEqual(1, view.RemoveAt(0));
+        Assert.AreEqual(5, view.RemoveAt(3));
+        Assert.AreEqual(2, view.RemoveAt(1));
+        check();
+        Assert.IsTrue(IC.eq(view, 3, 4));
+        view.Add(8);
+        Assert.AreEqual(3, view.RemoveFirst());
+        Assert.AreEqual(8, view.RemoveLast());
+        view.Add(2); view.Add(5); view.Add(3); view.Add(1);
+        view.RemoveInterval(1, 2);
+        check();
+        Assert.IsTrue(IC.eq(view, 4, 3, 1));
+      }
+
+
+      [Test]
+      public void Reverse()
+      {
+        view.Clear();
+        for (int i = 0; i < 10; i++) view.Add(10 + i);
+
+        view.View(3, 4).Reverse();
+        check();
+        Assert.IsTrue(IC.eq(view, 10, 11, 12, 16, 15, 14, 13, 17, 18, 19));
+        view.Reverse();
+        Assert.IsTrue(IC.eq(view, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10));
+        Assert.IsTrue(IC.eq(list, 0, 19, 18, 17, 13, 14, 15, 16, 12, 11, 10, 3));
+      }
+
+
+      [Test]
+      public void Slide()
+      {
+        view.Slide(1);
+        check();
+        Assert.IsTrue(IC.eq(view, 2, 3));
+        view.Slide(-2);
+        check();
+        Assert.IsTrue(IC.eq(view, 0, 1));
+        view.Slide(0, 3);
+        check();
+        Assert.IsTrue(IC.eq(view, 0, 1, 2));
+        view.Slide(2, 1);
+        check();
+        Assert.IsTrue(IC.eq(view, 2));
+        Assert.AreEqual(view, view.Slide(-1, 0));
+        check();
+        Assert.IsTrue(IC.eq(view));
+        view.Add(28);
+        Assert.IsTrue(IC.eq(list, 0, 28, 1, 2, 3));
+      }
+      [Test]
+      public void Iterate()
+      {
+        list.Clear();
+        view = null;
+        foreach (int i in new int[] { 2, 4, 8, 13, 6, 1, 2, 7 }) list.Add(i);
+
+        view = (LinkedList<int>)list.View(list.Count - 2, 2);
+        while (true)
+        {
+          //Console.WriteLine("View: {0}:  {1} --> {2}", view.Count, view.First, view.Last);
+          if ((view.Last - view.First) % 2 == 1)
+            view.Insert(1, 666);
+          check();
+          if (view.Offset == 0)
+            break;
+          else
+            view.Slide(-1, 2);
+        }
+        //foreach (int cell in list) Console.Write(" " + cell);
+        //Assert.IsTrue(list.Check());
+        Assert.IsTrue(IC.eq(list, 2, 4, 8, 666, 13, 6, 1, 666, 2, 666, 7));
+      }
+
+
+      [Test]
+      public void SyncRoot()
+      {
+        Assert.AreSame(((System.Collections.IList)view).SyncRoot, ((System.Collections.IList)list).SyncRoot);
+      }
+    }
+
+    [TestFixture]
+    public class MulipleViews
+    {
+      IList<int> list;
+      IList<int>[][] views;
+      [SetUp]
+      public void Init()
+      {
+        list = new LinkedList<int>();
+        for (int i = 0; i < 6; i++)
+          list.Add(i);
+        views = new IList<int>[7][];
+        for (int i = 0; i < 7; i++)
+        {
+          views[i] = new IList<int>[7 - i];
+          for (int j = 0; j < 7 - i; j++)
+            views[i][j] = list.View(i, j);
+        }
+      }
+      [TearDown]
+      public void Dispose()
+      {
+        list = null;
+        views = null;
+      }
+      [Test]
+      public void Insert()
+      {
+        Assert.IsTrue(list.Check(), "list check before insert");
+        list.Insert(3, 777);
+        Assert.IsTrue(list.Check(), "list check after insert");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i < 3 && i + j > 3 ? j + 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void RemoveAt()
+      {
+        Assert.IsTrue(list.Check(), "list check before remove");
+        list.RemoveAt(3);
+        Assert.IsTrue(list.Check(), "list check after remove");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i <= 3 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i <= 3 && i + j > 3 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+      [Test]
+      public void RemoveInterval()
+      {
+        Assert.IsTrue(list.Check(), "list check before remove");
+        list.RemoveInterval(3, 2);
+        Assert.IsTrue(list.Check(), "list check after remove");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i <= 3 ? i : i <= 5 ? 3 : i - 2, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(j == 0 ? 0 : i <= 3 && i + j > 4 ? j - 2 : i > 4 || i + j <= 3 ? j : j - 1, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+
+      [Test]
+      public void InsertAtEnd()
+      {
+        Assert.IsTrue(list.Check(), "list check before insert");
+        list.InsertLast(777);
+        Assert.IsTrue(list.Check(), "list check after insert");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void RemoveAtEnd()
+      {
+        Assert.IsTrue(list.Check(), "list check before remove");
+        list.RemoveAt(5);
+        Assert.IsTrue(list.Check(), "list check after remove");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i <= 5 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i <= 5 && i + j > 5 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void InsertAtStart()
+      {
+        Assert.IsTrue(list.Check(), "list check before insert");
+        list.Insert(0, 777);
+        Assert.IsTrue(list.Check(), "list check after insert");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i == 0 && j == 0 ? 0 : i + 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void RemoveAtStart()
+      {
+        Assert.IsTrue(list.Check(), "list check before remove");
+        list.RemoveAt(0);
+        Assert.IsTrue(list.Check(), "list check after remove");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i == 0 ? i : i - 1, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i == 0 && j > 0 ? j - 1 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+      [Test]
+      public void Clear()
+      {
+        Assert.IsTrue(list.Check(), "list check before clear");
+        views[2][3].Clear();
+        Assert.IsTrue(list.Check(), "list check after clear");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i < 2 ? i : i < 6 ? 2 : i - 3, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(s(i, j), views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+      private int s(int i, int j)
+      {
+        if (j == 0) return 0;
+        int k = i + j - 1; //end
+        if (i > 4 || k <= 1) return j;
+        if (i >= 2) return k > 4 ? k - 4 : 0;
+        if (i <= 2) return k >= 4 ? j - 3 : 2 - i;
+        return -1;
+      }
+      [Test]
+      public void InsertAll()
+      {
+        LinkedList<int> list2 = new LinkedList<int>();
+        for (int i = 0; i < 5; i++) { list2.Add(100 + i); }
+        Assert.IsTrue(list.Check(), "list check before insertAll");
+        list.InsertAll(3, list2);
+        Assert.IsTrue(list.Check(), "list check after insertAll");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 5, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i < 3 && i + j > 3 ? j + 5 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+      [Test]
+      public void AddAll()
+      {
+        LinkedList<int> list2 = new LinkedList<int>();
+        for (int i = 0; i < 5; i++) { list2.Add(100 + i); }
+        Assert.IsTrue(list.Check(), "list check before AddAll");
+        list.View(1, 2).AddAll(list2);
+        Assert.IsTrue(list.Check(), "list check after AddAll");
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            Assert.AreEqual(i < 3 || (i == 3 && j == 0) ? i : i + 5, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            Assert.AreEqual(i < 3 && i + j > 3 ? j + 5 : j, views[i][j].Count, "view[" + i + "][" + j + "] count");
+          }
+      }
+
+      [Test]
+      public void RemoveAll1()
+      {
+        LinkedList<int> list2 = new LinkedList<int>();
+        list2.Add(1); list2.Add(3); list2.Add(4);
+
+        for (int i = 0; i < 7; i++)
+        {
+          for (int j = 0; j < 7 - i; j++)
+          {
+            list = new LinkedList<int>();
+            for (int k = 0; k < 6; k++) list.Add(k);
+            LinkedList<int> v = (LinkedList<int>)list.View(i, j);
+            list.RemoveAll(list2);
+            Assert.IsTrue(list.Check(), "list check after RemoveAll, i=" + i + ", j=" + j);
+          }
+        }
+      }
+      [Test]
+      public void RemoveAll2()
+      {
+        LinkedList<int> list2 = new LinkedList<int>();
+        list2.Add(1); list2.Add(3); list2.Add(4);
+        Assert.IsTrue(list.Check(), "list check before RemoveAll");
+        list.RemoveAll(list2);
+
+        Assert.AreEqual(0, views[0][0].Offset, "view [0][0] offset");
+        Assert.AreEqual(0, views[0][1].Offset, "view [0][1] offset");
+        Assert.AreEqual(0, views[0][2].Offset, "view [0][2] offset");
+        Assert.AreEqual(0, views[0][3].Offset, "view [0][3] offset");
+        Assert.AreEqual(0, views[0][4].Offset, "view [0][4] offset");
+        Assert.AreEqual(0, views[0][5].Offset, "view [0][5] offset");
+        Assert.AreEqual(0, views[0][6].Offset, "view [0][6] offset");
+        Assert.AreEqual(1, views[1][0].Offset, "view [1][0] offset");
+        Assert.AreEqual(1, views[1][1].Offset, "view [1][1] offset");
+        Assert.AreEqual(1, views[1][2].Offset, "view [1][2] offset");
+        Assert.AreEqual(1, views[1][3].Offset, "view [1][3] offset");
+        Assert.AreEqual(1, views[1][4].Offset, "view [1][4] offset");
+        Assert.AreEqual(1, views[1][5].Offset, "view [1][5] offset");
+        Assert.AreEqual(1, views[2][0].Offset, "view [2][0] offset");
+        Assert.AreEqual(1, views[2][1].Offset, "view [2][1] offset");
+        Assert.AreEqual(1, views[2][2].Offset, "view [2][2] offset");
+        Assert.AreEqual(1, views[2][3].Offset, "view [2][3] offset");
+        Assert.AreEqual(1, views[2][4].Offset, "view [2][4] offset");
+        Assert.AreEqual(2, views[3][0].Offset, "view [3][0] offset");
+        Assert.AreEqual(2, views[3][1].Offset, "view [3][1] offset");
+        Assert.AreEqual(2, views[3][2].Offset, "view [3][2] offset");
+        Assert.AreEqual(2, views[3][3].Offset, "view [3][3] offset");
+        Assert.AreEqual(2, views[4][0].Offset, "view [4][0] offset");
+        Assert.AreEqual(2, views[4][1].Offset, "view [4][1] offset");
+        Assert.AreEqual(2, views[4][2].Offset, "view [4][2] offset");
+        Assert.AreEqual(2, views[5][0].Offset, "view [5][0] offset");
+        Assert.AreEqual(2, views[5][1].Offset, "view [5][1] offset");
+        Assert.AreEqual(3, views[6][0].Offset, "view [6][0] offset");
+
+        Assert.AreEqual(0, views[0][0].Count, "view [0][0] count");
+        Assert.AreEqual(1, views[0][1].Count, "view [0][1] count");
+        Assert.AreEqual(1, views[0][2].Count, "view [0][2] count");
+        Assert.AreEqual(2, views[0][3].Count, "view [0][3] count");
+        Assert.AreEqual(2, views[0][4].Count, "view [0][4] count");
+        Assert.AreEqual(2, views[0][5].Count, "view [0][5] count");
+        Assert.AreEqual(3, views[0][6].Count, "view [0][6] count");
+        Assert.AreEqual(0, views[1][0].Count, "view [1][0] count");
+        Assert.AreEqual(0, views[1][1].Count, "view [1][1] count");
+        Assert.AreEqual(1, views[1][2].Count, "view [1][2] count");
+        Assert.AreEqual(1, views[1][3].Count, "view [1][3] count");
+        Assert.AreEqual(1, views[1][4].Count, "view [1][4] count");
+        Assert.AreEqual(2, views[1][5].Count, "view [1][5] count");
+        Assert.AreEqual(0, views[2][0].Count, "view [2][0] count");
+        Assert.AreEqual(1, views[2][1].Count, "view [2][1] count");
+        Assert.AreEqual(1, views[2][2].Count, "view [2][2] count");
+        Assert.AreEqual(1, views[2][3].Count, "view [2][3] count");
+        Assert.AreEqual(2, views[2][4].Count, "view [2][4] count");
+        Assert.AreEqual(0, views[3][0].Count, "view [3][0] count");
+        Assert.AreEqual(0, views[3][1].Count, "view [3][1] count");
+        Assert.AreEqual(0, views[3][2].Count, "view [3][2] count");
+        Assert.AreEqual(1, views[3][3].Count, "view [3][3] count");
+        Assert.AreEqual(0, views[4][0].Count, "view [4][0] count");
+        Assert.AreEqual(0, views[4][1].Count, "view [4][1] count");
+        Assert.AreEqual(1, views[4][2].Count, "view [4][2] count");
+        Assert.AreEqual(0, views[5][0].Count, "view [5][0] count");
+        Assert.AreEqual(1, views[5][1].Count, "view [5][1] count");
+        Assert.AreEqual(0, views[6][0].Count, "view [6][0] count");
+
+        Assert.IsTrue(list.Check(), "list check after RemoveAll");
+      }
+
+      [Test]
+      public void RetainAll()
+      {
+        LinkedList<int> list2 = new LinkedList<int>();
+        list2.Add(2); list2.Add(4); list2.Add(5);
+        Assert.IsTrue(list.Check(), "list check before RetainAll");
+        list.RetainAll(list2);
+        Assert.AreEqual(0, views[0][0].Offset, "view [0][0] offset");
+        Assert.AreEqual(0, views[0][1].Offset, "view [0][1] offset");
+        Assert.AreEqual(0, views[0][2].Offset, "view [0][2] offset");
+        Assert.AreEqual(0, views[0][3].Offset, "view [0][3] offset");
+        Assert.AreEqual(0, views[0][4].Offset, "view [0][4] offset");
+        Assert.AreEqual(0, views[0][5].Offset, "view [0][5] offset");
+        Assert.AreEqual(0, views[0][6].Offset, "view [0][6] offset");
+        Assert.AreEqual(0, views[1][0].Offset, "view [1][0] offset");
+        Assert.AreEqual(0, views[1][1].Offset, "view [1][1] offset");
+        Assert.AreEqual(0, views[1][2].Offset, "view [1][2] offset");
+        Assert.AreEqual(0, views[1][3].Offset, "view [1][3] offset");
+        Assert.AreEqual(0, views[1][4].Offset, "view [1][4] offset");
+        Assert.AreEqual(0, views[1][5].Offset, "view [1][5] offset");
+        Assert.AreEqual(0, views[2][0].Offset, "view [2][0] offset");
+        Assert.AreEqual(0, views[2][1].Offset, "view [2][1] offset");
+        Assert.AreEqual(0, views[2][2].Offset, "view [2][2] offset");
+        Assert.AreEqual(0, views[2][3].Offset, "view [2][3] offset");
+        Assert.AreEqual(0, views[2][4].Offset, "view [2][4] offset");
+        Assert.AreEqual(1, views[3][0].Offset, "view [3][0] offset");
+        Assert.AreEqual(1, views[3][1].Offset, "view [3][1] offset");
+        Assert.AreEqual(1, views[3][2].Offset, "view [3][2] offset");
+        Assert.AreEqual(1, views[3][3].Offset, "view [3][3] offset");
+        Assert.AreEqual(1, views[4][0].Offset, "view [4][0] offset");
+        Assert.AreEqual(1, views[4][1].Offset, "view [4][1] offset");
+        Assert.AreEqual(1, views[4][2].Offset, "view [4][2] offset");
+        Assert.AreEqual(2, views[5][0].Offset, "view [5][0] offset");
+        Assert.AreEqual(2, views[5][1].Offset, "view [5][1] offset");
+        Assert.AreEqual(3, views[6][0].Offset, "view [6][0] offset");
+
+        Assert.AreEqual(0, views[0][0].Count, "view [0][0] count");
+        Assert.AreEqual(0, views[0][1].Count, "view [0][1] count");
+        Assert.AreEqual(0, views[0][2].Count, "view [0][2] count");
+        Assert.AreEqual(1, views[0][3].Count, "view [0][3] count");
+        Assert.AreEqual(1, views[0][4].Count, "view [0][4] count");
+        Assert.AreEqual(2, views[0][5].Count, "view [0][5] count");
+        Assert.AreEqual(3, views[0][6].Count, "view [0][6] count");
+        Assert.AreEqual(0, views[1][0].Count, "view [1][0] count");
+        Assert.AreEqual(0, views[1][1].Count, "view [1][1] count");
+        Assert.AreEqual(1, views[1][2].Count, "view [1][2] count");
+        Assert.AreEqual(1, views[1][3].Count, "view [1][3] count");
+        Assert.AreEqual(2, views[1][4].Count, "view [1][4] count");
+        Assert.AreEqual(3, views[1][5].Count, "view [1][5] count");
+        Assert.AreEqual(0, views[2][0].Count, "view [2][0] count");
+        Assert.AreEqual(1, views[2][1].Count, "view [2][1] count");
+        Assert.AreEqual(1, views[2][2].Count, "view [2][2] count");
+        Assert.AreEqual(2, views[2][3].Count, "view [2][3] count");
+        Assert.AreEqual(3, views[2][4].Count, "view [2][4] count");
+        Assert.AreEqual(0, views[3][0].Count, "view [3][0] count");
+        Assert.AreEqual(0, views[3][1].Count, "view [3][1] count");
+        Assert.AreEqual(1, views[3][2].Count, "view [3][2] count");
+        Assert.AreEqual(2, views[3][3].Count, "view [3][3] count");
+        Assert.AreEqual(0, views[4][0].Count, "view [4][0] count");
+        Assert.AreEqual(1, views[4][1].Count, "view [4][1] count");
+        Assert.AreEqual(2, views[4][2].Count, "view [4][2] count");
+        Assert.AreEqual(0, views[5][0].Count, "view [5][0] count");
+        Assert.AreEqual(1, views[5][1].Count, "view [5][1] count");
+        Assert.AreEqual(0, views[6][0].Count, "view [6][0] count");
+
+
+        Assert.IsTrue(list.Check(), "list check after RetainAll");
+      }
+
+      [Test]
+      public void RemoveAllCopies()
+      {
+        LinkedList<int> list2 = new LinkedList<int>();
+        list2.Add(0); list2.Add(2); list2.Add(2); list2.Add(2); list2.Add(5); list2.Add(2); list2.Add(1);
+        for (int i = 0; i < 7; i++)
+        {
+          for (int j = 0; j < 7 - i; j++)
+          {
+            list = new LinkedList<int>();
+            list.AddAll(list2);
+            LinkedList<int> v = (LinkedList<int>)list.View(i, j);
+            list.RemoveAllCopies(2);
+            Assert.AreEqual(i == 0 ? 0 : i <= 4 ? 1 : i <= 6 ? 2 : 3, v.Offset, "v.Offset, i=" + i + ", j=" + j);
+            Assert.AreEqual((i == 0 && j > 0 ? 1 : 0) + (i <= 4 && i + j > 4 ? 1 : 0) + (i <= 6 && i + j > 6 ? 1 : 0), v.Count, "v.Count, i=" + i + ", j=" + j);
+            Assert.IsTrue(list.Check(), "list check after RemoveAllCopies, i=" + i + ", j=" + j);
+          }
+        }
+      }
+
+      private void checkDisposed(bool reverse, int start, int count)
+      {
+        int k = 0;
+        for (int i = 0; i < 7; i++)
+          for (int j = 0; j < 7 - i; j++)
+          {
+            if (i + j <= start || i >= start + count || (i <= start && i + j >= start + count) || (reverse && start <= i && start + count >= i + j))
+            {
+              try
+              {
+                k = views[i][j].Count;
+              }
+              catch (ViewDisposedException)
+              {
+                Assert.Fail("view[" + i + "][" + j + "] threw");
+              }
+              Assert.AreEqual(j, views[i][j].Count, "view[" + i + "][" + j + "] size");
+              if (reverse && ((j > 0 && start <= i && start + count >= i + j) || (j == 0 && start < i && start + count > i)))
+                Assert.AreEqual(start + (start + count - i - j), views[i][j].Offset, "view[" + i + "][" + j + "] offset (mirrored)");
+              else
+                Assert.AreEqual(i, views[i][j].Offset, "view[" + i + "][" + j + "] offset");
+            }
+            else
+            {
+              try
+              {
+                k = views[i][j].Count;
+                Assert.Fail("view[" + i + "][" + j + "] no throw");
+              }
+              catch (ViewDisposedException) { }
+            }
+          }
+      }
+
+      [Test]
+      public void Reverse()
+      {
+        int start = 2, count = 3;
+        IList<int> list2 = list.View(start, count);
+        Assert.IsTrue(list.Check(), "list check before Reverse");
+        list2.Reverse();
+        Assert.IsTrue(list.Check(), "list check after Reverse");
+        checkDisposed(true, start, count);
+      }
+      [Test]
+      public void Sort()
+      {
+        int start = 2, count = 3;
+        IList<int> list2 = list.View(start, count);
+        Assert.IsTrue(list.Check(), "list check before Sort");
+        list2.Sort();
+        Assert.IsTrue(list.Check(), "list check after Sort");
+        checkDisposed(false, start, count);
+      }
+      [Test]
+      public void Shuffle()
+      {
+        int start = 2, count = 3;
+        IList<int> list2 = list.View(start, count);
+        Assert.IsTrue(list.Check(), "list check before Shuffle");
+        list2.Shuffle();
+        Assert.IsTrue(list.Check(), "list check after Shuffle");
+        checkDisposed(false, start, count);
+      }
+
+
+    }
+
+
+    [TestFixture]
+    public class Validity
+    {
+      IList<int> list;
+      IList<int> view;
+      [SetUp]
+      public void Init()
+      {
+        list = new LinkedList<int>();
+        for (int i = 0; i < 6; i++)
+          list.Add(i);
+        view = list.View(2, 3);
+        view.Dispose();
+      }
+      [TearDown]
+      public void Dispose()
+      {
+        list = null;
+        view = null;
+      }
+
+      //Properties
+
+      //
+      /*ActiveEvents,
+AllowsDuplicates,
+ContainsSpeed,
+Count,
+CountSpeed,
+Direction,
+DuplicatesByCounting,
+FIFO,
+First,
+EqualityComparer,
+IsEmpty,
+IsReadOnly,
+this[int index],
+this[int start, int count],
+Last,
+Offset,
+SyncRoot,
+Underlying
+*/
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void Add()
+      {
+        view.Add(5);
+      }
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void AddAll_int_()
+      {
+        view.AddAll<int>(new int[] { });
+      }
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void AddAll()
+      {
+        view.AddAll<int>(new int[] { });
+      }
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void All()
+      {
+        view.All(delegate(int i) { return false; });
+      }
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void Apply()
+      {
+        view.Apply(delegate(int i) { });
+      }
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void Backwards()
+      {
+        view.Backwards();
+      }
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void Choose()
+      {
+        view.Choose();
+      }
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void Contains()
+      {
+        view.Contains(0);
+      }
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void Clear()
+      {
+        view.Clear();
+      }
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void ContainsAll()
+      {
+        view.ContainsAll<int>(new int[] { });
+      }
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void ContainsCount()
+      {
+        view.ContainsCount(0);
+      }
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void CopyTo()
+      {
+        view.CopyTo(new int[1], 0);
+      }
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void Dequeue()
+      {
+        ((LinkedList<int>)view).Dequeue();
+      }
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void Enqueue()
+      {
+        ((LinkedList<int>)view).Enqueue(0);
+      }
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void Exists()
+      {
+        view.Exists(delegate(int i) { return false; });
+      }
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void Filter()
+      {
+        view.Filter(delegate(int i) { return true; });
+      }
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void Find()
+      {
+        int i = 0;
+        view.Find(ref i);
+      }
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void FindAll()
+      {
+        view.FindAll(delegate(int i) { return false; });
+      }
+      [Test]
+      [ExpectedException(typeof(ViewDisposedException))]
+      public void FindOrAdd()
+      {
+        int i = 0;
+        view.FindOrAdd(ref i);
+      }
+
+      //TODO: wonder if it is allright to wait with the exception till the enumerator is actually used?
+      /*    [Test]
+      [ExpectedException(typeof(ListDisposedException))]
+      public void GetEnumerator()
+      {
+        view.GetEnumerator();
+      }
+    */
+      /*Method overview
+      Check(),
+      checkRange(int start, int count),
+      Dispose(),
+      Equals(object obj),
+      Finalize(),
+      fireBagItemsAdded(T item, int count),
+      fireBagItemsRemoved(T item, int count),
+      fireCollectionChanged(),
+      fireCollectionCleared(int start, int count),
+      fireItemAdded(T item),
+      fireItemInserted(T item, int index),
+      fireItemRemoved(T item),
+      fireItemRemovedAt(T item, int index),
+      GetEnumerator(),
+      GetHashCode(),
+      GetSequencedHashCode(),
+      GetType(),
+      GetUnsequencedHashCode(),
+      IndexOf(T item),
+      Insert(int i, T item),
+      ViewOf().InsertLast(T item, T target),
+      InsertAll(int i, IEnumerable<T> items),
+      ViewOf().InsertFirst(T item, T target),
+      InsertFirst(T item),
+      InsertLast(T item),
+      IsSorted(SCG.IComparer<T> c),
+      LastIndexOf(T item),
+      LastViewOf(T item),
+      Map<V>(Fun<T,V> mapper),
+      Map<V>(Fun<T,V> mapper, SCG.IEqualityComparer<V> equalityComparer),
+      MemberwiseClone(),
+      modifycheck(int stamp),
+      Pop(),
+      Push(T item),
+      Remove(),
+      Remove(T item),
+      Remove(T item, out T removeditem),
+      RemoveAll(IEnumerable<T> items),
+      RemoveAllCopies(T item),
+      RemoveAt(int i),
+      RemoveFirst(),
+      RemoveInterval(int start, int count),
+      RemoveLast(),
+      RetainAll(IEnumerable<T> items),
+      Reverse(),
+      Reverse(int start, int count),
+      SequencedEquals(ISequenced<T> that),
+      Shuffle(),
+      Shuffle(System.Random rnd),
+      Slide(int offset),
+      Slide(int offset, int size),
+      Sort(),
+      Sort(SCG.IComparer<T> c),
+      ToArray(),
+      ToString(),
+      UnsequencedEquals(ICollection<T> that),
+      Update(T item),
+      Update(T item, out T olditem),
+      updatecheck(),
+      UpdateOrAdd(T item),
+      UpdateOrAdd(T item, out T olditem),
+      View(int start, int count),
+      ViewOf(T item)
+            */
+    }
+  }
+
+
+
+
+  namespace LinkedListOfTreesORLists
+  {
+    [TestFixture]
+    public class MultiLevelUnorderedOfUnOrdered
+    {
+      private ICollection<int> dit, dat, dut;
+
+      private ICollection<ICollection<int>> Dit, Dat, Dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new LinkedList<int>();
+        dat = new TreeSet<int>(Comparer<int>.Default, EqualityComparer<int>.Default);
+        dut = new LinkedList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        Dit = new LinkedList<ICollection<int>>();
+        Dat = new LinkedList<ICollection<int>>();
+        Dut = new LinkedList<ICollection<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dit.UnsequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Assert.IsTrue(Dit.UnsequencedEquals(Dat));
+        Assert.IsFalse(Dit.UnsequencedEquals(Dut));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = null;
+        Dit = Dat = Dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelOrderedOfUnOrdered
+    {
+      private ICollection<int> dit, dat, dut;
+
+      private ISequenced<ICollection<int>> Dit, Dat, Dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new LinkedList<int>();
+        dat = new TreeSet<int>(Comparer<int>.Default, EqualityComparer<int>.Default);
+        dut = new LinkedList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        Dit = new LinkedList<ICollection<int>>();
+        Dat = new LinkedList<ICollection<int>>();
+        Dut = new LinkedList<ICollection<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dit.UnsequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Dut.Add(dit); Dut.Add(dut); Dut.Add(dat);
+        Assert.IsFalse(Dit.SequencedEquals(Dat));
+        Assert.IsTrue(Dit.SequencedEquals(Dut));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = null;
+        Dit = Dat = Dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelUnOrderedOfOrdered
+    {
+      private ISequenced<int> dit, dat, dut, dot;
+
+      private ICollection<ISequenced<int>> Dit, Dat, Dut, Dot;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new TreeSet<int>(Comparer<int>.Default, EqualityComparer<int>.Default);
+        dat = new LinkedList<int>();
+        dut = new LinkedList<int>();
+        dot = new LinkedList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(2); dat.Add(1);
+        dut.Add(3);
+        dot.Add(1); dot.Add(2);
+        Dit = new LinkedList<ISequenced<int>>();
+        Dat = new LinkedList<ISequenced<int>>();
+        Dut = new LinkedList<ISequenced<int>>();
+        Dot = new LinkedList<ISequenced<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsTrue(dit.SequencedEquals(dot));
+        Assert.IsFalse(dit.SequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Dut.Add(dot); Dut.Add(dut); Dut.Add(dit);
+        Dot.Add(dit); Dot.Add(dit); Dot.Add(dut);
+        Assert.IsTrue(Dit.UnsequencedEquals(Dut));
+        Assert.IsFalse(Dit.UnsequencedEquals(Dat));
+        Assert.IsTrue(Dit.UnsequencedEquals(Dot));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = dot = null;
+        Dit = Dat = Dut = Dot = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelOrderedOfOrdered
+    {
+      private ISequenced<int> dit, dat, dut, dot;
+
+      private ISequenced<ISequenced<int>> Dit, Dat, Dut, Dot;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new TreeSet<int>(Comparer<int>.Default, EqualityComparer<int>.Default);
+        dat = new LinkedList<int>();
+        dut = new LinkedList<int>();
+        dot = new LinkedList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(2); dat.Add(1);
+        dut.Add(3);
+        dot.Add(1); dot.Add(2);
+        Dit = new LinkedList<ISequenced<int>>();
+        Dat = new LinkedList<ISequenced<int>>();
+        Dut = new LinkedList<ISequenced<int>>();
+        Dot = new LinkedList<ISequenced<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsTrue(dit.SequencedEquals(dot));
+        Assert.IsFalse(dit.SequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Dut.Add(dot); Dut.Add(dut); Dut.Add(dit);
+        Dot.Add(dit); Dot.Add(dit); Dot.Add(dut);
+        Assert.IsTrue(Dit.SequencedEquals(Dut));
+        Assert.IsFalse(Dit.SequencedEquals(Dat));
+        Assert.IsFalse(Dit.SequencedEquals(Dot));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = dot = null;
+        Dit = Dat = Dut = Dot = null;
+      }
+    }
+  }
+
+
+
+
+  namespace HashingAndEquals
+  {
+    [TestFixture]
+    public class ISequenced
+    {
+      private ISequenced<int> dit, dat, dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new LinkedList<int>();
+        dat = new LinkedList<int>();
+        dut = new LinkedList<int>();
+      }
+
+
+      [Test]
+      public void EmptyEmpty()
+      {
+        Assert.IsTrue(dit.SequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void EmptyNonEmpty()
+      {
+        dit.Add(3);
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsFalse(dat.SequencedEquals(dit));
+      }
+
+      [Test]
+      public void HashVal()
+      {
+        Assert.AreEqual(CHC.sequencedhashcode(), dit.GetSequencedHashCode());
+        dit.Add(3);
+        Assert.AreEqual(CHC.sequencedhashcode(3), dit.GetSequencedHashCode());
+        dit.Add(7);
+        Assert.AreEqual(CHC.sequencedhashcode(3, 7), dit.GetSequencedHashCode());
+        Assert.AreEqual(CHC.sequencedhashcode(), dut.GetSequencedHashCode());
+        dut.Add(7);
+        Assert.AreEqual(CHC.sequencedhashcode(7), dut.GetSequencedHashCode());
+        dut.Add(3);
+        Assert.AreEqual(CHC.sequencedhashcode(7, 3), dut.GetSequencedHashCode());
+      }
+
+
+      [Test]
+      public void EqualHashButDifferent()
+      {
+        dit.Add(0); dit.Add(31);
+        dat.Add(1); dat.Add(0);
+        Assert.AreEqual(dit.GetSequencedHashCode(), dat.GetSequencedHashCode());
+        Assert.IsFalse(dit.SequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void Normal()
+      {
+        dit.Add(3);
+        dit.Add(7);
+        dat.Add(3);
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsFalse(dat.SequencedEquals(dit));
+        dat.Add(7);
+        Assert.IsTrue(dit.SequencedEquals(dat));
+        Assert.IsTrue(dat.SequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void WrongOrder()
+      {
+        dit.Add(3);
+        dut.Add(3);
+        Assert.IsTrue(dit.SequencedEquals(dut));
+        Assert.IsTrue(dut.SequencedEquals(dit));
+        dit.Add(7);
+        ((LinkedList<int>)dut).InsertFirst(7);
+        Assert.IsFalse(dit.SequencedEquals(dut));
+        Assert.IsFalse(dut.SequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void Reflexive()
+      {
+        Assert.IsTrue(dit.SequencedEquals(dit));
+        dit.Add(3);
+        Assert.IsTrue(dit.SequencedEquals(dit));
+        dit.Add(7);
+        Assert.IsTrue(dit.SequencedEquals(dit));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+        dat = null;
+        dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class IEditableCollection
+    {
+      private ICollection<int> dit, dat, dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new LinkedList<int>();
+        dat = new LinkedList<int>();
+        dut = new LinkedList<int>();
+      }
+
+
+      [Test]
+      public void EmptyEmpty()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void EmptyNonEmpty()
+      {
+        dit.Add(3);
+        Assert.IsFalse(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dat.UnsequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void HashVal()
+      {
+        Assert.AreEqual(CHC.unsequencedhashcode(), dit.GetUnsequencedHashCode());
+        dit.Add(3);
+        Assert.AreEqual(CHC.unsequencedhashcode(3), dit.GetUnsequencedHashCode());
+        dit.Add(7);
+        Assert.AreEqual(CHC.unsequencedhashcode(3, 7), dit.GetUnsequencedHashCode());
+        Assert.AreEqual(CHC.unsequencedhashcode(), dut.GetUnsequencedHashCode());
+        dut.Add(3);
+        Assert.AreEqual(CHC.unsequencedhashcode(3), dut.GetUnsequencedHashCode());
+        dut.Add(7);
+        Assert.AreEqual(CHC.unsequencedhashcode(7, 3), dut.GetUnsequencedHashCode());
+      }
+
+
+      [Test]
+      public void EqualHashButDifferent()
+      {
+        dit.Add(-1657792980); dit.Add(-1570288808);
+        dat.Add(1862883298); dat.Add(-272461342);
+        Assert.AreEqual(dit.GetUnsequencedHashCode(), dat.GetUnsequencedHashCode());
+        Assert.IsFalse(dit.UnsequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void Normal()
+      {
+        dit.Add(3);
+        dit.Add(7);
+        dat.Add(3);
+        Assert.IsFalse(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dat.UnsequencedEquals(dit));
+        dat.Add(7);
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsTrue(dat.UnsequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void WrongOrder()
+      {
+        dit.Add(3);
+        dut.Add(3);
+        Assert.IsTrue(dit.UnsequencedEquals(dut));
+        Assert.IsTrue(dut.UnsequencedEquals(dit));
+        dit.Add(7);
+        dut.Add(7);
+        Assert.IsTrue(dit.UnsequencedEquals(dut));
+        Assert.IsTrue(dut.UnsequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void Reflexive()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dit));
+        dit.Add(3);
+        Assert.IsTrue(dit.UnsequencedEquals(dit));
+        dit.Add(7);
+        Assert.IsTrue(dit.UnsequencedEquals(dit));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+        dat = null;
+        dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelUnorderedOfUnOrdered
+    {
+      private ICollection<int> dit, dat, dut;
+
+      private ICollection<ICollection<int>> Dit, Dat, Dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new LinkedList<int>();
+        dat = new LinkedList<int>();
+        dut = new LinkedList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        Dit = new LinkedList<ICollection<int>>();
+        Dat = new LinkedList<ICollection<int>>();
+        Dut = new LinkedList<ICollection<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dit.UnsequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Assert.IsTrue(Dit.UnsequencedEquals(Dat));
+        Assert.IsFalse(Dit.UnsequencedEquals(Dut));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = null;
+        Dit = Dat = Dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelOrderedOfUnOrdered
+    {
+      private ICollection<int> dit, dat, dut;
+
+      private ISequenced<ICollection<int>> Dit, Dat, Dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new LinkedList<int>();
+        dat = new LinkedList<int>();
+        dut = new LinkedList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        Dit = new LinkedList<ICollection<int>>();
+        Dat = new LinkedList<ICollection<int>>();
+        Dut = new LinkedList<ICollection<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dit.UnsequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Dut.Add(dit); Dut.Add(dut); Dut.Add(dat);
+        Assert.IsFalse(Dit.SequencedEquals(Dat));
+        Assert.IsTrue(Dit.SequencedEquals(Dut));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = null;
+        Dit = Dat = Dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelUnOrderedOfOrdered
+    {
+      private ISequenced<int> dit, dat, dut, dot;
+
+      private ICollection<ISequenced<int>> Dit, Dat, Dut, Dot;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new LinkedList<int>();
+        dat = new LinkedList<int>();
+        dut = new LinkedList<int>();
+        dot = new LinkedList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        dot.Add(2); dot.Add(1);
+        Dit = new LinkedList<ISequenced<int>>();
+        Dat = new LinkedList<ISequenced<int>>();
+        Dut = new LinkedList<ISequenced<int>>();
+        Dot = new LinkedList<ISequenced<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsTrue(dit.SequencedEquals(dot));
+        Assert.IsFalse(dit.SequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Dut.Add(dot); Dut.Add(dut); Dut.Add(dit);
+        Dot.Add(dit); Dot.Add(dit); Dot.Add(dut);
+        Assert.IsTrue(Dit.UnsequencedEquals(Dut));
+        Assert.IsFalse(Dit.UnsequencedEquals(Dat));
+        Assert.IsTrue(Dit.UnsequencedEquals(Dot));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = dot = null;
+        Dit = Dat = Dut = Dot = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class MultiLevelOrderedOfOrdered
+    {
+      private ISequenced<int> dit, dat, dut, dot;
+
+      private ISequenced<ISequenced<int>> Dit, Dat, Dut, Dot;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new LinkedList<int>();
+        dat = new LinkedList<int>();
+        dut = new LinkedList<int>();
+        dot = new LinkedList<int>();
+        dit.Add(2); dit.Add(1);
+        dat.Add(1); dat.Add(2);
+        dut.Add(3);
+        dot.Add(2); dot.Add(1);
+        Dit = new LinkedList<ISequenced<int>>();
+        Dat = new LinkedList<ISequenced<int>>();
+        Dut = new LinkedList<ISequenced<int>>();
+        Dot = new LinkedList<ISequenced<int>>();
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsTrue(dit.SequencedEquals(dot));
+        Assert.IsFalse(dit.SequencedEquals(dut));
+      }
+
+
+      [Test]
+      public void Multi()
+      {
+        Dit.Add(dit); Dit.Add(dut); Dit.Add(dit);
+        Dat.Add(dut); Dat.Add(dit); Dat.Add(dat);
+        Dut.Add(dot); Dut.Add(dut); Dut.Add(dit);
+        Dot.Add(dit); Dot.Add(dit); Dot.Add(dut);
+        Assert.IsTrue(Dit.SequencedEquals(Dut));
+        Assert.IsFalse(Dit.SequencedEquals(Dat));
+        Assert.IsFalse(Dit.SequencedEquals(Dot));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = dat = dut = dot = null;
+        Dit = Dat = Dut = Dot = null;
+      }
+    }
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/templates/Clone.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/templates/Clone.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/templates/Clone.cs	(revision 3)
@@ -0,0 +1,159 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+namespace C5UnitTests.Templates.Extensible
+{
+  class Clone
+  {
+    public static void Tester<U>() where U : class, IExtensible<int>, new()
+    {
+      U extensible = new U();
+      RealTester<U>(extensible);
+      extensible.Add(12);
+      extensible.Add(23);
+      extensible.Add(56);
+      RealTester<U>(extensible);
+    }
+
+    public static void ViewTester<U>() where U : class, IList<int>, new()
+    {
+      U baselist = new U();
+      baselist.Add(12);
+      baselist.Add(23);
+      baselist.Add(56);
+      baselist.Add(112);
+      baselist.Add(123);
+      baselist.Add(156);
+      U view = (U)baselist.View(2, 2);
+      RealTester<U>(view);
+    }
+
+    public static void RealTester<U>(U extensible) where U : class, IExtensible<int>, new()
+    {
+      object clone = extensible.Clone();
+      Assert.IsNotNull(clone);
+      Assert.AreEqual(typeof(U), clone.GetType(),
+        String.Format("Wrong type '{0}' of clone of '{1}'", clone.GetType(), typeof(U)));
+      U theClone = clone as U;
+      Assert.IsTrue(theClone.Check(), "Clone does not pass Check()");
+      if (typeof(ICollection<int>).IsAssignableFrom(typeof(U)))
+        Assert.IsTrue(EqualityComparer<U>.Default.Equals(extensible, theClone), "Clone has wrong contents");
+      else //merely extensible
+        Assert.IsTrue(IC.eq(theClone, extensible.ToArray()), "Clone has wrong contents");
+    }
+  }
+
+  class Serialization
+  {
+    public static void Tester<U>() where U : class, IExtensible<int>, new()
+    {
+      U extensible = new U();
+      realtester<U>(extensible);
+      extensible.Add(12);
+      extensible.Add(23);
+      extensible.Add(56);
+      realtester<U>(extensible);
+    }
+
+    public static void ViewTester<U>() where U : class, IList<int>, new()
+    {
+      U baselist = new U();
+      baselist.Add(12);
+      baselist.Add(23);
+      baselist.Add(56);
+      baselist.Add(112);
+      baselist.Add(123);
+      baselist.Add(156);
+      U view = (U)baselist.View(2, 2);
+      realtester<U>(view);
+    }
+
+    private static void realtester<U>(U extensible) where U : class, IExtensible<int>, new()
+    {
+      object clone = serializeAndDeserialize(extensible);
+
+      Assert.IsNotNull(clone);
+      Assert.AreEqual(typeof(U), clone.GetType(),
+        String.Format("Wrong type '{0}' of clone of '{1}'", clone.GetType(), typeof(U)));
+      U theClone = clone as U;
+      if (typeof(IExtensible<int>).IsAssignableFrom(typeof(U)))
+        Assert.IsTrue(((IExtensible<int>)theClone).Check(), "Clone does not pass Check()");
+      if (typeof(ICollection<int>).IsAssignableFrom(typeof(U)))
+        Assert.IsTrue(EqualityComparer<U>.Default.Equals(extensible, theClone), "Clone has wrong contents");
+      else //merely extensible
+        Assert.IsTrue(IC.eq(theClone, extensible.ToArray()), "Clone has wrong contents");
+    }
+
+    private static object serializeAndDeserialize(object extensible) 
+    {
+      System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter =
+        new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
+      System.IO.Stream stream = new System.IO.MemoryStream();
+      formatter.Serialize(stream, extensible);
+      stream.Flush();
+      stream.Seek(0L, System.IO.SeekOrigin.Begin);
+      object clone = formatter.Deserialize(stream);
+      return clone;
+    }
+
+    public static void DTester<U>() where U : class, IDictionary<int, int>, new()
+    {
+      U dict = new U();
+      realDtester<U>(dict);
+      dict.Add(12, 4);
+      dict.Add(23, 6);
+      dict.Add(56, 1);
+      realDtester<U>(dict);
+      Assert.IsTrue(IC.eq((ICollectionValue<int>)serializeAndDeserialize(dict.Keys), dict.Keys.ToArray()), "Keys clone has wrong contents");
+      Assert.IsTrue(IC.eq((ICollectionValue<int>)serializeAndDeserialize(dict.Values), dict.Values.ToArray()), "Values Clone has wrong contents");
+    }
+
+    private static void realDtester<U>(U dict) where U : class, IDictionary<int, int>, new()
+    {
+      System.Runtime.Serialization.Formatters.Binary.BinaryFormatter formatter =
+        new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
+      System.IO.Stream stream = new System.IO.MemoryStream();
+      formatter.Serialize(stream, dict);
+      stream.Flush();
+      stream.Seek(0L, System.IO.SeekOrigin.Begin);
+      object clone = formatter.Deserialize(stream);
+
+      Assert.IsNotNull(clone);
+      Assert.AreEqual(typeof(U), clone.GetType(),
+        String.Format("Wrong type '{0}' of clone of '{1}'", clone.GetType(), typeof(U)));
+      U theClone = clone as U;
+      Assert.IsTrue(theClone.Check(), "Clone does not pass Check()");
+
+      Assert.AreEqual(dict.Count, theClone.Count, "wrong size");
+      foreach (int i in dict.Keys)
+      {
+        Assert.AreEqual(dict[i], theClone[i], "Wrong value");
+      }
+    }
+  }
+
+}
+
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/templates/Events.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/templates/Events.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/templates/Events.cs	(revision 3)
@@ -0,0 +1,928 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+using System.Reflection;
+
+namespace C5UnitTests.Templates.Events
+{
+  public abstract class CollectionValueTester<TCollection, TItem> : GenericCollectionTester<TCollection, EventTypeEnum>
+    where TCollection : ICollectionValue<TItem>
+  {
+    protected TCollection collection;
+    protected CollectionEventList<TItem> seen;
+    protected EventTypeEnum listenTo;
+    protected void listen() { seen.Listen(collection, listenTo); }
+
+    public override void SetUp(TCollection list, EventTypeEnum testSpec)
+    {
+      this.collection = list;
+      listenTo = testSpec;
+      seen = new CollectionEventList<TItem>(EqualityComparer<TItem>.Default);
+    }
+
+    public SCG.IEnumerable<EventTypeEnum> SpecsBasic
+    {
+      get
+      {
+        CircularQueue<EventTypeEnum> specs = new CircularQueue<EventTypeEnum>();
+        //foreach (EventTypeEnum listenTo in Enum.GetValues(typeof(EventTypeEnum)))
+        //  if ((listenTo & ~EventTypeEnum.Basic) == 0)
+        //    specs.Enqueue(listenTo);
+        //specs.Enqueue(EventTypeEnum.Added | EventTypeEnum.Removed);
+        for (int spec = 0; spec <= (int)EventTypeEnum.Basic; spec++)
+          specs.Enqueue((EventTypeEnum)spec);
+        return specs;
+      }
+    }
+    public SCG.IEnumerable<EventTypeEnum> SpecsAll
+    {
+      get
+      {
+        CircularQueue<EventTypeEnum> specs = new CircularQueue<EventTypeEnum>();
+        //foreach (EventTypeEnum listenTo in Enum.GetValues(typeof(EventTypeEnum)))
+        //  specs.Enqueue(listenTo);
+        //specs.Enqueue(EventTypeEnum.Added | EventTypeEnum.Removed);
+
+        for (int spec = 0; spec <= (int)EventTypeEnum.All; spec++)
+          specs.Enqueue((EventTypeEnum)spec);
+        return specs;
+      }
+    }
+  }
+  public abstract class CollectionValueTester<U> : CollectionValueTester<U, int> where U : ICollectionValue<int>
+  {
+  }
+
+  public class ExtensibleTester<U> : CollectionValueTester<U> where U : IExtensible<int>
+  {
+    public override SCG.IEnumerable<EventTypeEnum> GetSpecs()
+    {
+      return SpecsBasic;
+    }
+    [Test]
+    public virtual void Listenable()
+    {
+      Assert.AreEqual(EventTypeEnum.Basic, collection.ListenableEvents);
+      Assert.AreEqual(EventTypeEnum.None, collection.ActiveEvents);
+      listen();
+      Assert.AreEqual(listenTo, collection.ActiveEvents);
+    }
+
+    [Test]
+    public void Add()
+    {
+      listen();
+      seen.Check(new CollectionEvent<int>[0]);
+      collection.Add(23);
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(23, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+    }
+
+    [Test]
+    public void AddAll()
+    {
+      for (int i = 0; i < 10; i++)
+      {
+        collection.Add(10 * i + 5);
+      }
+      listen();
+      collection.AddAll<int>(new int[] { 45, 200, 56, 67 });
+      seen.Check(collection.AllowsDuplicates ?
+        collection.DuplicatesByCounting ?
+          new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(200, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(55, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(65, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)}
+        :
+          new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(200, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(56, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)}
+          :
+          new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(200, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+      collection.AddAll<int>(new int[] { });
+      seen.Check(new CollectionEvent<int>[] { });
+    }
+
+  }
+
+  public class CollectionTester<U> : ExtensibleTester<U> where U : ICollection<int>
+  {
+    [Test]
+    public void Update()
+    {
+      collection.Add(4); collection.Add(54); collection.Add(56); collection.Add(8);
+      listen();
+      collection.Update(53);
+      seen.Check(
+        collection.AllowsDuplicates ?
+        collection.DuplicatesByCounting ?
+        new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(54, 2), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(53, 2), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+          }
+        : new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(54, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(53, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+          }
+        : new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(54, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(53, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+          });
+      collection.Update(67);
+      seen.Check(new CollectionEvent<int>[] { });
+    }
+
+    [Test]
+    public void FindOrAdd()
+    {
+      collection.Add(4); collection.Add(56); collection.Add(8);
+      listen();
+      int val = 53;
+      collection.FindOrAdd(ref val);
+      seen.Check(new CollectionEvent<int>[] { });
+      val = 67;
+      collection.FindOrAdd(ref val);
+      seen.Check(new CollectionEvent<int>[] { 
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+    }
+
+    [Test]
+    public void UpdateOrAdd()
+    {
+      collection.Add(4); collection.Add(56); collection.Add(8);
+      listen();
+      int val = 53;
+      collection.UpdateOrAdd(val);
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(53, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+      val = 67;
+      collection.UpdateOrAdd(val);
+      seen.Check(new CollectionEvent<int>[] { 
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+      collection.UpdateOrAdd(51, out val);
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(53, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(51, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+      val = 67;
+      collection.UpdateOrAdd(81, out val);
+      seen.Check(new CollectionEvent<int>[] { 
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(81, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+    }
+
+    [Test]
+    public void RemoveItem()
+    {
+      collection.Add(4); collection.Add(56); collection.Add(18);
+      listen();
+      collection.Remove(53);
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+      collection.Remove(11);
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(18, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+    }
+
+    [Test]
+    public void RemoveAll()
+    {
+      for (int i = 0; i < 10; i++)
+      {
+        collection.Add(10 * i + 5);
+      }
+      listen();
+      collection.RemoveAll<int>(new int[] { 32, 187, 45 });
+      //TODO: the order depends on internals of the HashSet
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(35, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(45, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+      collection.RemoveAll<int>(new int[] { 200, 300 });
+      seen.Check(new CollectionEvent<int>[] { });
+    }
+
+    [Test]
+    public void RetainAll()
+    {
+      for (int i = 0; i < 10; i++)
+      {
+        collection.Add(10 * i + 5);
+      }
+      listen();
+      collection.RetainAll<int>(new int[] { 32, 187, 45, 62, 75, 82, 95, 2 });
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(15, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(25, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(55, 1), collection),
+          //new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(75, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+      collection.RetainAll<int>(new int[] { 32, 187, 45, 62, 75, 82, 95, 2 });
+      seen.Check(new CollectionEvent<int>[] { });
+    }
+
+    [Test]
+    public void RemoveAllCopies()
+    {
+      for (int i = 0; i < 10; i++)
+      {
+        collection.Add(3 * i + 5);
+      }
+      listen();
+      collection.RemoveAllCopies(14);
+      seen.Check(
+        collection.AllowsDuplicates ?
+          collection.DuplicatesByCounting ?
+            new CollectionEvent<int>[] {
+              new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(11, 3), collection),
+              new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)}
+          :
+          new CollectionEvent<int>[] {
+            new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(11, 1), collection),
+            new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(14, 1), collection),
+            new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(17, 1), collection),
+            new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)}
+        :
+        new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(11, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+      collection.RemoveAllCopies(14);
+      seen.Check(new CollectionEvent<int>[] { });
+    }
+
+    [Test]
+    public virtual void Clear()
+    {
+      collection.Add(4); collection.Add(56); collection.Add(8);
+      listen();
+      collection.Clear();
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedEventArgs(true, collection.AllowsDuplicates ? 3 : 2), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+      collection.Clear();
+      seen.Check(new CollectionEvent<int>[] { });
+    }
+
+  }
+
+  public class IndexedTester<U> : CollectionTester<U> where U : IIndexed<int>
+  {
+    [Test]
+    public void RemoveAt()
+    {
+      collection.Add(4); collection.Add(16); collection.Add(28);
+      listen();
+      collection.RemoveAt(1);
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(16,1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(16, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+    }
+
+    [Test]
+    public void RemoveInterval()
+    {
+      collection.Add(4); collection.Add(56); collection.Add(18);
+      listen();
+      collection.RemoveInterval(1, 2);
+      seen.Check(new CollectionEvent<int>[] {
+        collection is IList<int> ?
+           new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(false,2,1), collection):
+           new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedEventArgs(false,2), collection),
+         new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+      collection.RemoveInterval(1, 0);
+      seen.Check(new CollectionEvent<int>[] { });
+    }
+  }
+
+  public class SortedIndexedTester<U> : IndexedTester<U> where U : IIndexedSorted<int>
+  {
+    [Test]
+    public void DeleteMinMax()
+    {
+      collection.Add(34);
+      collection.Add(56);
+      collection.Add(34);
+      collection.Add(12);
+      listen();
+      collection.DeleteMax();
+      seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection), 
+      });
+      collection.DeleteMin();
+      seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(12, 1), collection), 
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection), 
+      });
+    }
+
+    [Test]
+    public void AddSorted()
+    {
+      listen();
+      collection.AddSorted(collection.AllowsDuplicates ? new int[] { 31, 62, 63, 93 } : new int[] { 31, 62, 93 });
+      seen.Check(collection.AllowsDuplicates ?
+        collection.DuplicatesByCounting ?
+          new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(31, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(62, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(62, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(93, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)}
+        :
+          new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(31, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(62, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(63, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(93, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)}
+          :
+          new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(31, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(62, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(93, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+      collection.AddSorted(new int[] { });
+      seen.Check(new CollectionEvent<int>[] { });
+    }
+
+    [Test]
+    public void RemoveRange()
+    {
+      for (int i = 0; i < 20; i++)
+        collection.Add(i * 10 + 5);
+      listen();
+      collection.RemoveRangeFrom(173);
+      //TODO: fix order to remove in:
+      seen.Check(
+          new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(195, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(185, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(175, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+      collection.RemoveRangeFromTo(83, 113);
+      seen.Check(
+          new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(105, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(95, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(85, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+      collection.RemoveRangeTo(33);
+      seen.Check(
+          new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(5, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(15, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(25, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+      collection.RemoveRangeFrom(173);
+      seen.Check(new CollectionEvent<int>[] { });
+      collection.RemoveRangeFromTo(83, 113);
+      seen.Check(new CollectionEvent<int>[] { });
+      collection.RemoveRangeTo(33);
+      seen.Check(new CollectionEvent<int>[] { });
+    }
+  }
+
+  public class ListTester<U> : IndexedTester<U> where U : IList<int>
+  {
+    public override SCG.IEnumerable<EventTypeEnum> GetSpecs()
+    {
+      return SpecsAll;
+    }
+
+    [Test]
+    public override void Listenable()
+    {
+      Assert.AreEqual(EventTypeEnum.All, collection.ListenableEvents);
+      Assert.AreEqual(EventTypeEnum.None, collection.ActiveEvents);
+      listen();
+      Assert.AreEqual(listenTo, collection.ActiveEvents);
+    }
+    [Test]
+    public void SetThis()
+    {
+      collection.Add(4); collection.Add(56); collection.Add(8);
+      listen();
+      collection[1] = 45;
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(56,1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(45,1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+          });
+    }
+
+    [Test]
+    public void Insert()
+    {
+      collection.Add(4); collection.Add(56); collection.Add(8);
+      listen();
+      collection.Insert(1, 45);
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(45,1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+          });
+    }
+
+    [Test]
+    public void InsertAll()
+    {
+      collection.Add(4); collection.Add(56); collection.Add(8);
+      listen();
+      collection.InsertAll<int>(1, new int[] { 666, 777, 888 });
+      //seen.Print(Console.Error);
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(666,1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(666, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(777,2), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(777, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(888,3), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(888, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+          });
+      collection.InsertAll<int>(1, new int[] { });
+      seen.Check(new CollectionEvent<int>[] { });
+    }
+
+    [Test]
+    public void InsertFirstLast()
+    {
+      collection.Add(4); collection.Add(56); collection.Add(18);
+      listen();
+      collection.InsertFirst(45);
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(45,0), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+          });
+      collection.InsertLast(88);
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(88,4), collection),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(88, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+          });
+    }
+
+    [Test]
+    public void Remove()
+    {
+      collection.FIFO = false;
+      collection.Add(4); collection.Add(56); collection.Add(18);
+      listen();
+      collection.Remove();
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(18, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+      collection.FIFO = true;
+      collection.Remove();
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(4, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+    }
+
+    [Test]
+    public void RemoveFirst()
+    {
+      collection.Add(4); collection.Add(56); collection.Add(18);
+      listen();
+      collection.RemoveFirst();
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(4,0), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(4, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+    }
+
+    [Test]
+    public void RemoveLast()
+    {
+      collection.Add(4); collection.Add(56); collection.Add(18);
+      listen();
+      collection.RemoveLast();
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(18,2), collection),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(18, 1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+    }
+
+    [Test]
+    public void Reverse()
+    {
+      collection.Add(4); collection.Add(56); collection.Add(8);
+      listen();
+      collection.Reverse();
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+      collection.View(1, 0).Reverse();
+      seen.Check(new CollectionEvent<int>[] { });
+    }
+
+
+    [Test]
+    public void Sort()
+    {
+      collection.Add(4); collection.Add(56); collection.Add(8);
+      listen();
+      collection.Sort();
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+      collection.View(1, 0).Sort();
+      seen.Check(new CollectionEvent<int>[] { });
+    }
+
+    [Test]
+    public void Shuffle()
+    {
+      collection.Add(4); collection.Add(56); collection.Add(8);
+      listen();
+      collection.Shuffle();
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+      collection.View(1, 0).Shuffle();
+      seen.Check(new CollectionEvent<int>[] { });
+    }
+
+    [Test]
+    public override void Clear()
+    {
+      collection.Add(4); collection.Add(56); collection.Add(18);
+      listen();
+      collection.View(1, 1).Clear();
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(false,1,1), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+      collection.Clear();
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(true,2,0), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+      collection.Clear();
+      seen.Check(new CollectionEvent<int>[] { });
+    }
+
+    [Test]
+    public void ListDispose()
+    {
+      collection.Add(4); collection.Add(56); collection.Add(18);
+      listen();
+      collection.View(1, 1).Dispose();
+      seen.Check(new CollectionEvent<int>[] { });
+      collection.Dispose();
+      seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(true,3,0), collection),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+        });
+      collection.Dispose();
+      seen.Check(new CollectionEvent<int>[] { });
+    }
+
+    /* 
+ 
+     * /
+        //[TearDown]
+        //public void Dispose() { list = null; seen = null; }
+        /*
+        [Test]
+        [ExpectedException(typeof(UnlistenableEventException))]
+        public void ViewChanged()
+        {
+          IList<int> w = collection.View(0, 0);
+          w.CollectionChanged += new CollectionChangedHandler<int>(w_CollectionChanged);
+        }
+
+        [Test]
+        [ExpectedException(typeof(UnlistenableEventException))]
+        public void ViewCleared()
+        {
+          IList<int> w = collection.View(0, 0);
+          w.CollectionCleared += new CollectionClearedHandler<int>(w_CollectionCleared);
+        }
+
+        [Test]
+        [ExpectedException(typeof(UnlistenableEventException))]
+        public void ViewAdded()
+        {
+          IList<int> w = collection.View(0, 0);
+          w.ItemsAdded += new ItemsAddedHandler<int>(w_ItemAdded);
+        }
+
+        [Test]
+        [ExpectedException(typeof(UnlistenableEventException))]
+        public void ViewInserted()
+        {
+          IList<int> w = collection.View(0, 0);
+          w.ItemInserted += new ItemInsertedHandler<int>(w_ItemInserted);
+        }
+
+        [Test]
+        [ExpectedException(typeof(UnlistenableEventException))]
+        public void ViewRemoved()
+        {
+          IList<int> w = collection.View(0, 0);
+          w.ItemsRemoved += new ItemsRemovedHandler<int>(w_ItemRemoved);
+        }
+
+        [Test]
+        [ExpectedException(typeof(UnlistenableEventException))]
+        public void ViewRemovedAt()
+        {
+          IList<int> w = collection.View(0, 0);
+          w.ItemRemovedAt += new ItemRemovedAtHandler<int>(w_ItemRemovedAt);
+        }
+
+        void w_CollectionChanged(object sender)
+        {
+          throw new NotImplementedException();
+        }
+
+        void w_CollectionCleared(object sender, ClearedEventArgs eventArgs)
+        {
+          throw new NotImplementedException();
+        }
+
+        void w_ItemAdded(object sender, ItemCountEventArgs<int> eventArgs)
+        {
+          throw new NotImplementedException();
+        }
+
+        void w_ItemInserted(object sender, ItemAtEventArgs<int> eventArgs)
+        {
+          throw new NotImplementedException();
+        }
+
+        void w_ItemRemoved(object sender, ItemCountEventArgs<int> eventArgs)
+        {
+          throw new NotImplementedException();
+        }
+
+        void w_ItemRemovedAt(object sender, ItemAtEventArgs<int> eventArgs)
+        {
+          throw new NotImplementedException();
+        }*/
+  }
+
+  public class StackTester<U> : CollectionValueTester<U> where U : IStack<int>
+  {
+    public override SCG.IEnumerable<EventTypeEnum> GetSpecs()
+    {
+      return SpecsBasic;
+    }
+
+    [Test]
+    public void PushPop()
+    {
+      listen();
+      seen.Check(new CollectionEvent<int>[0]);
+      collection.Push(23);
+      seen.Check(new CollectionEvent<int>[] {
+              new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(23,0), collection),
+              new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(23, 1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+      collection.Push(-12);
+      seen.Check(new CollectionEvent<int>[] {
+              new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(-12,1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(-12, 1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+      collection.Pop();
+      seen.Check(new CollectionEvent<int>[] {
+              new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(-12,1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(-12, 1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+      collection.Pop();
+      seen.Check(new CollectionEvent<int>[] {
+              new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(23,0), collection),
+              new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(23, 1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+    }
+  }
+
+  public class QueueTester<U> : CollectionValueTester<U> where U : IQueue<int>
+  {
+    public override SCG.IEnumerable<EventTypeEnum> GetSpecs()
+    {
+      return SpecsBasic;
+    }
+
+    [Test]
+    public void EnqueueDequeue()
+    {
+      listen();
+      collection.Enqueue(67);
+      seen.Check(new CollectionEvent<int>[] {
+              new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(67,0), collection),
+              new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+      collection.Enqueue(2);
+      seen.Check(new CollectionEvent<int>[] {
+              new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(2,1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(2, 1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+      collection.Dequeue();
+      seen.Check(new CollectionEvent<int>[] {
+              new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(67,0), collection),
+              new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(67, 1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+      collection.Dequeue();
+      seen.Check(new CollectionEvent<int>[] {
+              new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(2,0), collection),
+              new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(2, 1), collection),
+              new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)});
+    }
+
+  }
+
+  public class PriorityQueueTester<U> : ExtensibleTester<U> where U : IPriorityQueue<int>
+  {
+    public override System.Collections.Generic.IEnumerable<EventTypeEnum> GetSpecs()
+    {
+      return SpecsBasic;
+    }
+
+    [Test]
+    public void Direct()
+    {
+      listen();
+      collection.Add(34);
+      seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(34, 1), collection), 
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection), 
+      });
+      collection.Add(56);
+      seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(56, 1), collection), 
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection), 
+      });
+      collection.AddAll<int>(new int[] { });
+      seen.Check(new CollectionEvent<int>[] {
+      });
+      collection.Add(34);
+      seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(34, 1), collection), 
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection), 
+      });
+      collection.Add(12);
+      seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(12, 1), collection), 
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection), 
+      });
+      collection.DeleteMax();
+      seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection), 
+      });
+      collection.DeleteMin();
+      seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(12, 1), collection), 
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection), 
+      });
+      collection.AddAll<int>(new int[] { 4, 5, 6, 2 });
+      seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(4, 1), collection), 
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(5, 1), collection), 
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(6, 1), collection), 
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(2, 1), collection), 
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection)
+      });
+    }
+
+    [Test]
+    public void WithHandles()
+    {
+      listen();
+      IPriorityQueueHandle<int> handle = null, handle2;
+      collection.Add(34);
+      seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(34, 1), collection), 
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection), 
+      });
+      collection.Add(56);
+      seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(56, 1), collection), 
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection), 
+      });
+      collection.Add(ref handle, 34);
+      seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(34, 1), collection), 
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection), 
+      });
+      collection.Add(12);
+      seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(12, 1), collection), 
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection), 
+      });
+      collection.DeleteMax(out handle2);
+      seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), collection),
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection), 
+      });
+      collection.DeleteMin(out handle2);
+      seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(12, 1), collection), 
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection), 
+      });
+
+      collection.Replace(handle, 117);
+      seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(34, 1), collection), 
+        new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(117, 1), collection), 
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection), 
+      });
+
+      collection.Delete(handle);
+      seen.Check(new CollectionEvent<int>[] {
+        new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(117, 1), collection), 
+        new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), collection), 
+      });
+    }
+  }
+
+  public class DictionaryTester<U> : CollectionValueTester<U, KeyValuePair<int, int>> where U : IDictionary<int, int>
+  {
+    public override SCG.IEnumerable<EventTypeEnum> GetSpecs()
+    {
+      return SpecsBasic;
+    }
+
+    [Test]
+    public virtual void Listenable()
+    {
+      Assert.AreEqual(EventTypeEnum.Basic, collection.ListenableEvents);
+      Assert.AreEqual(EventTypeEnum.None, collection.ActiveEvents);
+      listen();
+      Assert.AreEqual(listenTo, collection.ActiveEvents);
+    }
+
+    [Test]
+    public void AddAndREmove()
+    {
+      listen();
+      seen.Check(new CollectionEvent<KeyValuePair<int, int>>[0]);
+      collection.Add(23, 45);
+      seen.Check(new CollectionEvent<KeyValuePair<int,int>>[] {
+          new CollectionEvent<KeyValuePair<int,int>>(EventTypeEnum.Added, new ItemCountEventArgs<KeyValuePair<int,int>>(new KeyValuePair<int,int>(23,45), 1), collection),
+          new CollectionEvent<KeyValuePair<int,int>>(EventTypeEnum.Changed, new EventArgs(), collection)});
+      collection.Remove(25);
+      seen.Check(new CollectionEvent<KeyValuePair<int, int>>[] {
+          new CollectionEvent<KeyValuePair<int,int>>(EventTypeEnum.Removed, new ItemCountEventArgs<KeyValuePair<int,int>>(new KeyValuePair<int,int>(23,45), 1), collection),
+          new CollectionEvent<KeyValuePair<int,int>>(EventTypeEnum.Changed, new EventArgs(), collection)});
+    }
+
+
+
+  }
+
+}
+
+
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/templates/GenericCollectionTester.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/templates/GenericCollectionTester.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/templates/GenericCollectionTester.cs	(revision 3)
@@ -0,0 +1,87 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+using System.Reflection;
+
+namespace C5UnitTests.Templates
+{
+  public abstract class GenericCollectionTester<U, W>
+  {
+    protected CircularQueue<MethodInfo> testMethods;
+    public GenericCollectionTester()
+    {
+      testMethods = new CircularQueue<MethodInfo>();
+      foreach (MethodInfo minfo in this.GetType().GetMethods())
+      {
+        if (minfo.GetParameters().Length == 0 &&
+             minfo.GetCustomAttributes(typeof(TestAttribute), false).Length > 0)
+          testMethods.Enqueue(minfo);
+      }
+    }
+
+    public virtual void Test(Fun<U> factory)
+    {
+      foreach (MethodInfo minfo in testMethods)
+      {
+        foreach (W testSpec in GetSpecs())
+        {
+          SetUp(factory(), testSpec);
+          //Console.WriteLine("Testing {0}, with method {1} and testSpec {{{2}}}", typeof(U), minfo.Name, testSpec);
+          try
+          {
+            minfo.Invoke(this, null);
+          }
+          catch (TargetInvocationException)
+          {
+            //if (e.InnerException is ExpectedExceptionAttribute)
+            //{
+            //}
+            //else
+            throw;
+          }
+          //tearDown
+        }
+      }
+    }
+
+    public abstract void SetUp(U collection, W testSpec);
+    public abstract SCG.IEnumerable<W> GetSpecs();
+  }
+
+  public abstract class GenericCollectionTester<U> : GenericCollectionTester<U, int>
+  {
+    public override System.Collections.Generic.IEnumerable<int> GetSpecs()
+    {
+      return new int[] { 0 };
+    }
+
+    public override void SetUp(U collection, int testSpec)
+    {
+      SetUp(collection);
+    }
+
+    public abstract void SetUp(object collection);
+  }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/templates/List.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/templates/List.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/templates/List.cs	(revision 3)
@@ -0,0 +1,53 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+namespace C5UnitTests.Templates.List
+{
+  class Dispose
+  {
+    public static void Tester<U>() where U : class, IList<int>, new()
+    {
+      U extensible = new U();
+      extensible.Dispose();
+    }
+  }
+
+  class SCG_IList
+  {
+    public static void Tester<U>() where U : class, IList<int>, SCG.IList<int>, new()
+    {
+      SCG.IList<int> slist = new U();
+      slist.Add(4);
+      slist.Add(5);
+      slist.Add(6);
+      slist.RemoveAt(1);
+      Assert.AreEqual(2, slist.Count);
+      Assert.AreEqual(4, slist[0]);
+      Assert.AreEqual(6, slist[1]);
+    }
+  }
+}
+
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/trees/Bag.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/trees/Bag.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/trees/Bag.cs	(revision 3)
@@ -0,0 +1,2943 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+
+namespace C5UnitTests.trees.TreeBag
+{
+  using CollectionOfInt = TreeBag<int>;
+
+  [TestFixture]
+  public class GenericTesters
+  {
+    [Test]
+    public void TestEvents()
+    {
+      Fun<CollectionOfInt> factory = delegate() { return new CollectionOfInt(TenEqualityComparer.Default); };
+      new C5UnitTests.Templates.Events.SortedIndexedTester<CollectionOfInt>().Test(factory);
+    }
+
+    [Test]
+    public void Extensible()
+    {
+      C5UnitTests.Templates.Extensible.Clone.Tester<CollectionOfInt>();
+      C5UnitTests.Templates.Extensible.Serialization.Tester<CollectionOfInt>();
+    }
+  }
+
+  static class Factory
+  {
+    public static ICollection<T> New<T>() { return new TreeBag<T>(); }
+  }
+
+
+  [TestFixture]
+  public class Formatting
+  {
+    ICollection<int> coll;
+    IFormatProvider rad16;
+    [SetUp]
+    public void Init() { coll = Factory.New<int>(); rad16 = new RadixFormatProvider(16); }
+    [TearDown]
+    public void Dispose() { coll = null; rad16 = null; }
+    [Test]
+    public void Format()
+    {
+      Assert.AreEqual("{{  }}", coll.ToString());
+      coll.AddAll<int>(new int[] { -4, 28, 129, 65530, -4, 28 });
+      Assert.AreEqual("{{ -4(*2), 28(*2), 129(*1), 65530(*1) }}", coll.ToString());
+      Assert.AreEqual("{{ -4(*2), 1C(*2), 81(*1), FFFA(*1) }}", coll.ToString(null, rad16));
+      Assert.AreEqual("{{ -4(*2), 28(*2)... }}", coll.ToString("L18", null));
+      Assert.AreEqual("{{ -4(*2), 1C(*2)... }}", coll.ToString("L18", rad16));
+    }
+  }
+
+  [TestFixture]
+  public class Combined
+  {
+    private IIndexedSorted<KeyValuePair<int, int>> lst;
+
+
+    [SetUp]
+    public void Init()
+    {
+      lst = new TreeBag<KeyValuePair<int, int>>(new KeyValuePairComparer<int, int>(new IC()));
+      for (int i = 0; i < 10; i++)
+        lst.Add(new KeyValuePair<int, int>(i, i + 30));
+    }
+
+
+    [TearDown]
+    public void Dispose() { lst = null; }
+
+
+    [Test]
+    public void Find()
+    {
+      KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+      Assert.IsTrue(lst.Find(ref p));
+      Assert.AreEqual(3, p.Key);
+      Assert.AreEqual(33, p.Value);
+      p = new KeyValuePair<int, int>(13, 78);
+      Assert.IsFalse(lst.Find(ref p));
+    }
+
+
+    [Test]
+    public void FindOrAdd()
+    {
+      KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+      Assert.IsTrue(lst.FindOrAdd(ref p));
+      Assert.AreEqual(3, p.Key);
+      Assert.AreEqual(33, p.Value);
+      p = new KeyValuePair<int, int>(13, 79);
+      Assert.IsFalse(lst.FindOrAdd(ref p));
+      Assert.AreEqual(13, lst[11].Key);
+      Assert.AreEqual(79, lst[11].Value);
+    }
+
+
+    [Test]
+    public void Update()
+    {
+      KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+      Assert.IsTrue(lst.Update(p));
+      Assert.AreEqual(3, lst[3].Key);
+      Assert.AreEqual(78, lst[3].Value);
+      p = new KeyValuePair<int, int>(13, 78);
+      Assert.IsFalse(lst.Update(p));
+    }
+
+
+    [Test]
+    public void UpdateOrAdd1()
+    {
+      KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+      Assert.IsTrue(lst.UpdateOrAdd(p));
+      Assert.AreEqual(3, lst[3].Key);
+      Assert.AreEqual(78, lst[3].Value);
+      p = new KeyValuePair<int, int>(13, 79);
+      Assert.IsFalse(lst.UpdateOrAdd(p));
+      Assert.AreEqual(13, lst[10].Key);
+      Assert.AreEqual(79, lst[10].Value);
+    }
+
+    [Test]
+    public void UpdateOrAdd2()
+    {
+        ICollection<String> coll = new TreeBag<String>();
+        // s1 and s2 are distinct objects but contain the same text:
+        String old, s1 = "abc", s2 = ("def" + s1).Substring(3);
+        Assert.IsFalse(coll.UpdateOrAdd(s1, out old));
+        Assert.AreEqual(null, old);
+        Assert.IsTrue(coll.UpdateOrAdd(s2, out old));
+        Assert.IsTrue(Object.ReferenceEquals(s1, old));
+        Assert.IsFalse(Object.ReferenceEquals(s2, old));
+    }
+
+    [Test]
+    public void RemoveWithReturn()
+    {
+      KeyValuePair<int, int> p = new KeyValuePair<int, int>(3, 78);
+
+      Assert.IsTrue(lst.Remove(p, out p));
+      Assert.AreEqual(3, p.Key);
+      Assert.AreEqual(33, p.Value);
+      Assert.AreEqual(4, lst[3].Key);
+      Assert.AreEqual(34, lst[3].Value);
+      p = new KeyValuePair<int, int>(13, 78);
+      Assert.IsFalse(lst.Remove(p, out p));
+    }
+  }
+
+
+  [TestFixture]
+  public class Simple
+  {
+    private TreeBag<string> bag;
+
+
+    [SetUp]
+    public void Init()
+    {
+      bag = new TreeBag<string>(new SC());
+    }
+
+
+    [TearDown]
+    public void Dispose()
+    {
+      bag = null;
+    }
+
+    [Test]
+    public void Initial()
+    {
+      bool res;
+
+      Assert.IsFalse(bag.IsReadOnly);
+      Assert.AreEqual(0, bag.Count, "new bag should be empty");
+      Assert.AreEqual(0, bag.ContainsCount("A"));
+      Assert.AreEqual(0, bag.ContainsCount("B"));
+      Assert.AreEqual(0, bag.ContainsCount("C"));
+      Assert.IsFalse(bag.Contains("A"));
+      Assert.IsFalse(bag.Contains("B"));
+      Assert.IsFalse(bag.Contains("C"));
+      bag.Add("A");
+      Assert.AreEqual(1, bag.Count);
+      Assert.AreEqual(1, bag.ContainsCount("A"));
+      Assert.AreEqual(0, bag.ContainsCount("B"));
+      Assert.AreEqual(0, bag.ContainsCount("C"));
+      Assert.IsTrue(bag.Contains("A"));
+      Assert.IsFalse(bag.Contains("B"));
+      Assert.IsFalse(bag.Contains("C"));
+      bag.Add("C");
+      Assert.AreEqual(2, bag.Count);
+      Assert.AreEqual(1, bag.ContainsCount("A"));
+      Assert.AreEqual(0, bag.ContainsCount("B"));
+      Assert.AreEqual(1, bag.ContainsCount("C"));
+      Assert.IsTrue(bag.Contains("A"));
+      Assert.IsFalse(bag.Contains("B"));
+      Assert.IsTrue(bag.Contains("C"));
+      bag.Add("C");
+      Assert.AreEqual(3, bag.Count);
+      Assert.AreEqual(1, bag.ContainsCount("A"));
+      Assert.AreEqual(0, bag.ContainsCount("B"));
+      Assert.AreEqual(2, bag.ContainsCount("C"));
+      Assert.IsTrue(bag.Contains("A"));
+      Assert.IsFalse(bag.Contains("B"));
+      Assert.IsTrue(bag.Contains("C"));
+      bag.Add("B");
+      bag.Add("C");
+      Assert.AreEqual(5, bag.Count);
+      Assert.AreEqual(1, bag.ContainsCount("A"));
+      Assert.AreEqual(1, bag.ContainsCount("B"));
+      Assert.AreEqual(3, bag.ContainsCount("C"));
+      Assert.IsTrue(bag.Contains("A"));
+      Assert.IsTrue(bag.Contains("B"));
+      Assert.IsTrue(bag.Contains("C"));
+      res = bag.Remove("C");
+      Assert.AreEqual(4, bag.Count);
+      Assert.AreEqual(1, bag.ContainsCount("A"));
+      Assert.AreEqual(1, bag.ContainsCount("B"));
+      Assert.AreEqual(2, bag.ContainsCount("C"));
+      Assert.IsTrue(bag.Contains("A"));
+      Assert.IsTrue(bag.Contains("B"));
+      Assert.IsTrue(bag.Contains("C"));
+      res = bag.Remove("A");
+      Assert.AreEqual(3, bag.Count);
+      Assert.AreEqual(0, bag.ContainsCount("A"));
+      Assert.AreEqual(1, bag.ContainsCount("B"));
+      Assert.AreEqual(2, bag.ContainsCount("C"));
+      Assert.IsFalse(bag.Contains("A"));
+      Assert.IsTrue(bag.Contains("B"));
+      Assert.IsTrue(bag.Contains("C"));
+      bag.RemoveAllCopies("C");
+      Assert.AreEqual(1, bag.Count);
+      Assert.AreEqual(0, bag.ContainsCount("A"));
+      Assert.AreEqual(1, bag.ContainsCount("B"));
+      Assert.AreEqual(0, bag.ContainsCount("C"));
+      Assert.IsFalse(bag.Contains("A"));
+      Assert.IsTrue(bag.Contains("B"));
+      Assert.IsFalse(bag.Contains("C"));
+      Assert.IsFalse(bag.Contains("Z"));
+      Assert.IsFalse(bag.Remove("Z"));
+      bag.RemoveAllCopies("Z");
+      Assert.AreEqual(1, bag.Count);
+      Assert.AreEqual(0, bag.ContainsCount("A"));
+      Assert.AreEqual(1, bag.ContainsCount("B"));
+      Assert.AreEqual(0, bag.ContainsCount("C"));
+      Assert.IsFalse(bag.Contains("A"));
+      Assert.IsTrue(bag.Contains("B"));
+      Assert.IsFalse(bag.Contains("C"));
+      Assert.IsFalse(bag.Contains("Z"));
+    }
+  }
+
+  [TestFixture]
+  public class FindOrAdd
+  {
+    private TreeBag<KeyValuePair<int, string>> bag;
+
+
+    [SetUp]
+    public void Init()
+    {
+      bag = new TreeBag<KeyValuePair<int, string>>(new KeyValuePairComparer<int, string>(new IC()));
+    }
+
+
+    [TearDown]
+    public void Dispose()
+    {
+      bag = null;
+    }
+
+
+    [Test]
+    public void Test()
+    {
+      KeyValuePair<int, string> p = new KeyValuePair<int, string>(3, "tre");
+      Assert.IsFalse(bag.FindOrAdd(ref p));
+      p.Value = "drei";
+      Assert.IsTrue(bag.FindOrAdd(ref p));
+      Assert.AreEqual("tre", p.Value);
+      p.Value = "three";
+      Assert.AreEqual(2, bag.ContainsCount(p));
+      Assert.AreEqual("tre", bag[0].Value);
+    }
+  }
+
+
+  [TestFixture]
+  public class Enumerators
+  {
+    private TreeBag<string> bag;
+
+    private SCG.IEnumerator<string> bagenum;
+
+
+    [SetUp]
+    public void Init()
+    {
+      bag = new TreeBag<string>(new SC());
+      foreach (string s in new string[] { "A", "B", "A", "A", "B", "C", "D", "B" })
+        bag.Add(s);
+
+      bagenum = bag.GetEnumerator();
+    }
+
+
+    [TearDown]
+    public void Dispose()
+    {
+      bagenum = null;
+      bag = null;
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(CollectionModifiedException))]
+    public void MoveNextOnModified()
+    {
+      //TODO: also problem before first MoveNext!!!!!!!!!!
+      bagenum.MoveNext();
+      bag.Add("T");
+      bagenum.MoveNext();
+    }
+
+
+    [Test]
+    public void NormalUse()
+    {
+      Assert.IsTrue(bagenum.MoveNext());
+      Assert.AreEqual(bagenum.Current, "A");
+      Assert.IsTrue(bagenum.MoveNext());
+      Assert.AreEqual(bagenum.Current, "A");
+      Assert.IsTrue(bagenum.MoveNext());
+      Assert.AreEqual(bagenum.Current, "A");
+      Assert.IsTrue(bagenum.MoveNext());
+      Assert.AreEqual(bagenum.Current, "B");
+      Assert.IsTrue(bagenum.MoveNext());
+      Assert.AreEqual(bagenum.Current, "B");
+      Assert.IsTrue(bagenum.MoveNext());
+      Assert.AreEqual(bagenum.Current, "B");
+      Assert.IsTrue(bagenum.MoveNext());
+      Assert.AreEqual(bagenum.Current, "C");
+      Assert.IsTrue(bagenum.MoveNext());
+      Assert.AreEqual(bagenum.Current, "D");
+      Assert.IsFalse(bagenum.MoveNext());
+    }
+  }
+
+  [TestFixture]
+  public class Ranges
+  {
+    private TreeBag<int> tree;
+
+    private SCG.IComparer<int> c;
+
+
+    [SetUp]
+    public void Init()
+    {
+      c = new IC();
+      tree = new TreeBag<int>(c);
+      for (int i = 1; i <= 10; i++)
+      {
+        tree.Add(i * 2); tree.Add(i);
+      }
+    }
+
+
+    [Test]
+    public void Enumerator()
+    {
+      SCG.IEnumerator<int> e = tree.RangeFromTo(5, 17).GetEnumerator();
+      int i = 0;
+      int[] all = new int[] { 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16 };
+      while (e.MoveNext())
+      {
+        Assert.AreEqual(all[i++], e.Current);
+      }
+
+      Assert.AreEqual(12, i);
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(InvalidOperationException))]
+    public void Enumerator2()
+    {
+      SCG.IEnumerator<int> e = tree.RangeFromTo(5, 17).GetEnumerator();
+      int i = e.Current;
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(InvalidOperationException))]
+    public void Enumerator3()
+    {
+      SCG.IEnumerator<int> e = tree.RangeFromTo(5, 17).GetEnumerator();
+
+      while (e.MoveNext()) ;
+
+      int i = e.Current;
+    }
+
+
+    [Test]
+    public void Remove()
+    {
+      int[] all = new int[] { 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16, 18, 20 };
+
+      tree.RemoveRangeFrom(18);
+      Assert.IsTrue(IC.eq(tree, new int[] { 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16 }));
+      tree.RemoveRangeFrom(28);
+      Assert.IsTrue(IC.eq(tree, new int[] { 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16 }));
+      tree.RemoveRangeFrom(1);
+      Assert.IsTrue(IC.eq(tree));
+      foreach (int i in all) tree.Add(i);
+
+      tree.RemoveRangeTo(10);
+      Assert.IsTrue(IC.eq(tree, new int[] { 10, 10, 12, 14, 16, 18, 20 }));
+      tree.RemoveRangeTo(2);
+      Assert.IsTrue(IC.eq(tree, new int[] { 10, 10, 12, 14, 16, 18, 20 }));
+      tree.RemoveRangeTo(21);
+      Assert.IsTrue(IC.eq(tree));
+      foreach (int i in all) tree.Add(i);
+
+      tree.RemoveRangeFromTo(4, 8);
+      Assert.IsTrue(IC.eq(tree, 1, 2, 2, 3, 8, 8, 9, 10, 10, 12, 14, 16, 18, 20));
+      tree.RemoveRangeFromTo(14, 28);
+      Assert.IsTrue(IC.eq(tree, 1, 2, 2, 3, 8, 8, 9, 10, 10, 12));
+      tree.RemoveRangeFromTo(0, 9);
+      Assert.IsTrue(IC.eq(tree, 9, 10, 10, 12));
+      tree.RemoveRangeFromTo(0, 81);
+      Assert.IsTrue(IC.eq(tree));
+    }
+
+
+    [Test]
+    public void Normal()
+    {
+      int[] all = new int[] { 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16, 18, 20 };
+
+      Assert.IsTrue(IC.eq(tree, all));
+      Assert.IsTrue(IC.eq(tree.RangeAll(), all));
+      Assert.AreEqual(20, tree.RangeAll().Count);
+      Assert.IsTrue(IC.eq(tree.RangeFrom(11), new int[] { 12, 14, 16, 18, 20 }));
+      Assert.AreEqual(5, tree.RangeFrom(11).Count);
+      Assert.IsTrue(IC.eq(tree.RangeFrom(12), new int[] { 12, 14, 16, 18, 20 }));
+      Assert.IsTrue(IC.eq(tree.RangeFrom(1), all));
+      Assert.IsTrue(IC.eq(tree.RangeFrom(0), all));
+      Assert.IsTrue(IC.eq(tree.RangeFrom(21), new int[] { }));
+      Assert.IsTrue(IC.eq(tree.RangeFrom(20), new int[] { 20 }));
+      Assert.IsTrue(IC.eq(tree.RangeTo(8), new int[] { 1, 2, 2, 3, 4, 4, 5, 6, 6, 7 }));
+      Assert.IsTrue(IC.eq(tree.RangeTo(7), new int[] { 1, 2, 2, 3, 4, 4, 5, 6, 6 }));
+      Assert.AreEqual(9, tree.RangeTo(7).Count);
+      Assert.IsTrue(IC.eq(tree.RangeTo(1), new int[] { }));
+      Assert.IsTrue(IC.eq(tree.RangeTo(0), new int[] { }));
+      Assert.IsTrue(IC.eq(tree.RangeTo(3), new int[] { 1, 2, 2 }));
+      Assert.IsTrue(IC.eq(tree.RangeTo(20), new int[] { 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16, 18 }));
+      Assert.IsTrue(IC.eq(tree.RangeTo(21), all));
+      Assert.IsTrue(IC.eq(tree.RangeFromTo(7, 12), new int[] { 7, 8, 8, 9, 10, 10 }));
+      Assert.IsTrue(IC.eq(tree.RangeFromTo(6, 11), new int[] { 6, 6, 7, 8, 8, 9, 10, 10 }));
+      Assert.IsTrue(IC.eq(tree.RangeFromTo(1, 12), new int[] { 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10 }));
+      Assert.AreEqual(15, tree.RangeFromTo(1, 12).Count);
+      Assert.IsTrue(IC.eq(tree.RangeFromTo(2, 12), new int[] { 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10 }));
+      Assert.IsTrue(IC.eq(tree.RangeFromTo(6, 21), new int[] { 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16, 18, 20 }));
+      Assert.IsTrue(IC.eq(tree.RangeFromTo(6, 20), new int[] { 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16, 18 }));
+    }
+
+
+    [Test]
+    public void Backwards()
+    {
+      int[] all = new int[] { 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 8, 8, 9, 10, 10, 12, 14, 16, 18, 20 };
+      int[] lla = new int[] { 20, 18, 16, 14, 12, 10, 10, 9, 8, 8, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1 };
+
+      Assert.IsTrue(IC.eq(tree, all));
+      Assert.IsTrue(IC.eq(tree.RangeAll().Backwards(), lla));
+      Assert.IsTrue(IC.eq(tree.RangeFrom(11).Backwards(), new int[] { 20, 18, 16, 14, 12 }));
+      Assert.IsTrue(IC.eq(tree.RangeFrom(12).Backwards(), new int[] { 20, 18, 16, 14, 12 }));
+      Assert.IsTrue(IC.eq(tree.RangeFrom(1).Backwards(), lla));
+      Assert.IsTrue(IC.eq(tree.RangeFrom(0).Backwards(), lla));
+      Assert.IsTrue(IC.eq(tree.RangeFrom(21).Backwards(), new int[] { }));
+      Assert.IsTrue(IC.eq(tree.RangeFrom(20).Backwards(), new int[] { 20 }));
+      Assert.IsTrue(IC.eq(tree.RangeTo(8).Backwards(), new int[] { 7, 6, 6, 5, 4, 4, 3, 2, 2, 1 }));
+      Assert.IsTrue(IC.eq(tree.RangeTo(7).Backwards(), new int[] { 6, 6, 5, 4, 4, 3, 2, 2, 1 }));
+      Assert.IsTrue(IC.eq(tree.RangeTo(1).Backwards(), new int[] { }));
+      Assert.IsTrue(IC.eq(tree.RangeTo(0).Backwards(), new int[] { }));
+      Assert.IsTrue(IC.eq(tree.RangeTo(3).Backwards(), new int[] { 2, 2, 1 }));
+      Assert.IsTrue(IC.eq(tree.RangeTo(20).Backwards(), new int[] { 18, 16, 14, 12, 10, 10, 9, 8, 8, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1 }));
+      Assert.IsTrue(IC.eq(tree.RangeTo(21).Backwards(), lla));
+      Assert.IsTrue(IC.eq(tree.RangeFromTo(7, 12).Backwards(), new int[] { 10, 10, 9, 8, 8, 7 }));
+      Assert.IsTrue(IC.eq(tree.RangeFromTo(6, 11).Backwards(), new int[] { 10, 10, 9, 8, 8, 7, 6, 6 }));
+      Assert.IsTrue(IC.eq(tree.RangeFromTo(0, 12).Backwards(), new int[] { 10, 10, 9, 8, 8, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1 }));
+      Assert.IsTrue(IC.eq(tree.RangeFromTo(1, 12).Backwards(), new int[] { 10, 10, 9, 8, 8, 7, 6, 6, 5, 4, 4, 3, 2, 2, 1 }));
+      Assert.IsTrue(IC.eq(tree.RangeFromTo(6, 21).Backwards(), new int[] { 20, 18, 16, 14, 12, 10, 10, 9, 8, 8, 7, 6, 6 }));
+      Assert.IsTrue(IC.eq(tree.RangeFromTo(6, 20).Backwards(), new int[] { 18, 16, 14, 12, 10, 10, 9, 8, 8, 7, 6, 6 }));
+    }
+
+
+    [Test]
+    public void Direction()
+    {
+      Assert.AreEqual(EnumerationDirection.Forwards, tree.Direction);
+      Assert.AreEqual(EnumerationDirection.Forwards, tree.RangeFrom(20).Direction);
+      Assert.AreEqual(EnumerationDirection.Forwards, tree.RangeTo(7).Direction);
+      Assert.AreEqual(EnumerationDirection.Forwards, tree.RangeFromTo(1, 12).Direction);
+      Assert.AreEqual(EnumerationDirection.Forwards, tree.RangeAll().Direction);
+      Assert.AreEqual(EnumerationDirection.Backwards, tree.Backwards().Direction);
+      Assert.AreEqual(EnumerationDirection.Backwards, tree.RangeFrom(20).Backwards().Direction);
+      Assert.AreEqual(EnumerationDirection.Backwards, tree.RangeTo(7).Backwards().Direction);
+      Assert.AreEqual(EnumerationDirection.Backwards, tree.RangeFromTo(1, 12).Backwards().Direction);
+      Assert.AreEqual(EnumerationDirection.Backwards, tree.RangeAll().Backwards().Direction);
+    }
+
+
+    [TearDown]
+    public void Dispose()
+    {
+      tree = null;
+      c = null;
+    }
+  }
+
+
+
+  [TestFixture]
+  public class BagItf
+  {
+    private TreeBag<int> tree;
+
+
+    [SetUp]
+    public void Init()
+    {
+      tree = new TreeBag<int>(new IC());
+      for (int i = 10; i < 20; i++)
+      {
+        tree.Add(i);
+        tree.Add(i + 5);
+      }
+    }
+
+
+    [Test]
+    public void Both()
+    {
+      Assert.AreEqual(0, tree.ContainsCount(7));
+      Assert.AreEqual(1, tree.ContainsCount(10));
+      Assert.AreEqual(2, tree.ContainsCount(17));
+      tree.RemoveAllCopies(17);
+      Assert.AreEqual(0, tree.ContainsCount(17));
+      tree.RemoveAllCopies(7);
+    }
+
+
+    [TearDown]
+    public void Dispose()
+    {
+      tree = null;
+    }
+  }
+
+
+
+  [TestFixture]
+  public class Div
+  {
+    private TreeBag<int> tree;
+
+
+    [SetUp]
+    public void Init()
+    {
+      tree = new TreeBag<int>(new IC());
+    }
+
+
+    private void loadup()
+    {
+      for (int i = 10; i < 20; i++)
+      {
+        tree.Add(i);
+        tree.Add(i + 5);
+      }
+    }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor1()
+    {
+      new TreeBag<int>(null);
+    }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor3()
+    {
+      new TreeBag<int>(null, EqualityComparer<int>.Default);
+    }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor4()
+    {
+      new TreeBag<int>(Comparer<int>.Default, null);
+    }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor5()
+    {
+      new TreeBag<int>(null, null);
+    }
+
+    [Test]
+    public void Choose()
+    {
+      tree.Add(7);
+      Assert.AreEqual(7, tree.Choose());
+    }
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void BadChoose()
+    {
+      tree.Choose();
+    }
+
+
+    [Test]
+    public void NoDuplicates()
+    {
+      Assert.IsTrue(tree.AllowsDuplicates);
+      loadup();
+      Assert.IsTrue(tree.AllowsDuplicates);
+    }
+
+
+    [Test]
+    public void Add()
+    {
+      Assert.IsTrue(tree.Add(17));
+      Assert.IsTrue(tree.Add(17));
+      Assert.IsTrue(tree.Add(18));
+      Assert.IsTrue(tree.Add(18));
+      Assert.AreEqual(4, tree.Count);
+      Assert.IsTrue(IC.eq(tree, 17, 17, 18, 18));
+    }
+
+
+    [TearDown]
+    public void Dispose()
+    {
+      tree = null;
+    }
+  }
+
+  [TestFixture]
+  public class FindPredicate
+  {
+    private TreeBag<int> list;
+    Fun<int, bool> pred;
+
+    [SetUp]
+    public void Init()
+    {
+      list = new TreeBag<int>(TenEqualityComparer.Default);
+      pred = delegate(int i) { return i % 5 == 0; };
+    }
+
+    [TearDown]
+    public void Dispose() { list = null; }
+
+    [Test]
+    public void Find()
+    {
+      int i;
+      Assert.IsFalse(list.Find(pred, out i));
+      list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+      Assert.IsFalse(list.Find(pred, out i));
+      list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+      Assert.IsTrue(list.Find(pred, out i));
+      Assert.AreEqual(45, i);
+    }
+
+    [Test]
+    public void FindLast()
+    {
+      int i;
+      Assert.IsFalse(list.FindLast(pred, out i));
+      list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+      Assert.IsFalse(list.FindLast(pred, out i));
+      list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+      Assert.IsTrue(list.FindLast(pred, out i));
+      Assert.AreEqual(675, i);
+    }
+
+    [Test]
+    public void FindIndex()
+    {
+      Assert.IsFalse(0 <= list.FindIndex(pred));
+      list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+      Assert.IsFalse(0 <= list.FindIndex(pred));
+      list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+      Assert.AreEqual(3, list.FindIndex(pred));
+    }
+
+    [Test]
+    public void FindLastIndex()
+    {
+      Assert.IsFalse(0 <= list.FindLastIndex(pred));
+      list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+      Assert.IsFalse(0 <= list.FindLastIndex(pred));
+      list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+      Assert.AreEqual(7, list.FindLastIndex(pred));
+    }
+  }
+
+  [TestFixture]
+  public class UniqueItems
+  {
+    private TreeBag<int> list;
+
+    [SetUp]
+    public void Init() { list = new TreeBag<int>(); }
+
+    [TearDown]
+    public void Dispose() { list = null; }
+
+    [Test]
+    public void Test()
+    {
+      Assert.IsTrue(IC.seteq(list.UniqueItems()));
+      Assert.IsTrue(IC.seteq(list.ItemMultiplicities()));
+      list.AddAll<int>(new int[] { 7, 9, 7 });
+      Assert.IsTrue(IC.seteq(list.UniqueItems(), 7, 9));
+      Assert.IsTrue(IC.seteq(list.ItemMultiplicities(), 7, 2, 9, 1));
+    }
+  }
+
+  [TestFixture]
+  public class ArrayTest
+  {
+    private TreeBag<int> tree;
+
+    int[] a;
+
+
+    [SetUp]
+    public void Init()
+    {
+      tree = new TreeBag<int>(new IC());
+      a = new int[10];
+      for (int i = 0; i < 10; i++)
+        a[i] = 1000 + i;
+    }
+
+
+    [TearDown]
+    public void Dispose() { tree = null; }
+
+
+    private string aeq(int[] a, params int[] b)
+    {
+      if (a.Length != b.Length)
+        return "Lengths differ: " + a.Length + " != " + b.Length;
+
+      for (int i = 0; i < a.Length; i++)
+        if (a[i] != b[i])
+          return String.Format("{0}'th elements differ: {1} != {2}", i, a[i], b[i]);
+
+      return "Alles klar";
+    }
+
+
+    [Test]
+    public void ToArray()
+    {
+      Assert.AreEqual("Alles klar", aeq(tree.ToArray()));
+      tree.Add(4);
+      tree.Add(7);
+      tree.Add(4);
+      Assert.AreEqual("Alles klar", aeq(tree.ToArray(), 4, 4, 7));
+    }
+
+
+    [Test]
+    public void CopyTo()
+    {
+      tree.CopyTo(a, 1);
+      Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+      tree.Add(6);
+      tree.Add(6);
+      tree.CopyTo(a, 2);
+      Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 6, 1004, 1005, 1006, 1007, 1008, 1009));
+      tree.Add(4);
+      tree.Add(9);
+      tree.CopyTo(a, 4);
+      Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 6, 4, 6, 6, 9, 1008, 1009));
+      tree.Clear();
+      tree.Add(7);
+      tree.CopyTo(a, 9);
+      Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 6, 4, 6, 6, 9, 1008, 7));
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(ArgumentOutOfRangeException))]
+    public void CopyToBad()
+    {
+      tree.CopyTo(a, 11);
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(ArgumentOutOfRangeException))]
+    public void CopyToBad2()
+    {
+      tree.CopyTo(a, -1);
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(ArgumentOutOfRangeException))]
+    public void CopyToTooFar()
+    {
+      tree.Add(3);
+      tree.Add(4);
+      tree.CopyTo(a, 9);
+    }
+  }
+
+
+
+  [TestFixture]
+  public class Remove
+  {
+    private TreeBag<int> tree;
+
+
+    [SetUp]
+    public void Init()
+    {
+      tree = new TreeBag<int>(new IC());
+      for (int i = 10; i < 20; i++)
+      {
+        tree.Add(i);
+        tree.Add(i + 5);
+      }
+      //10,11,12,13,14,15,15,16,16,17,17,18,18,19,19,20,21,22,23,24
+    }
+
+
+    [Test]
+    public void SmallTrees()
+    {
+      tree.Clear();
+      tree.Add(9);
+      tree.Add(7);
+      tree.Add(9);
+      Assert.IsTrue(tree.Remove(7));
+      Assert.IsTrue(tree.Check(""));
+    }
+
+
+    [Test]
+    public void ByIndex()
+    {
+      //Remove root!
+      int n = tree.Count;
+      int i = tree[10];
+
+      Assert.AreEqual(17, tree.RemoveAt(10));
+      Assert.IsTrue(tree.Check(""));
+      Assert.IsTrue(tree.Contains(i));
+      Assert.AreEqual(n - 1, tree.Count);
+      Assert.AreEqual(17, tree.RemoveAt(9));
+      Assert.IsTrue(tree.Check(""));
+      Assert.IsFalse(tree.Contains(i));
+      Assert.AreEqual(n - 2, tree.Count);
+
+      //Low end
+      i = tree.FindMin();
+      tree.RemoveAt(0);
+      Assert.IsTrue(tree.Check(""));
+      Assert.IsFalse(tree.Contains(i));
+      Assert.AreEqual(n - 3, tree.Count);
+
+      //high end
+      i = tree.FindMax();
+      tree.RemoveAt(tree.Count - 1);
+      Assert.IsTrue(tree.Check(""));
+      Assert.IsFalse(tree.Contains(i));
+      Assert.AreEqual(n - 4, tree.Count);
+
+      //Some leaf
+      //tree.dump();
+      i = 18;
+      Assert.AreEqual(i, tree.RemoveAt(9));
+      Assert.IsTrue(tree.Check(""));
+      Assert.AreEqual(i, tree.RemoveAt(8));
+      Assert.IsTrue(tree.Check(""));
+      Assert.IsFalse(tree.Contains(i));
+      Assert.AreEqual(n - 6, tree.Count);
+    }
+
+
+    [Test]
+    public void AlmostEmpty()
+    {
+      //Almost empty
+      tree.Clear();
+      tree.Add(3);
+      tree.RemoveAt(0);
+      Assert.IsTrue(tree.Check(""));
+      Assert.IsFalse(tree.Contains(3));
+      Assert.AreEqual(0, tree.Count);
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(IndexOutOfRangeException), "Index out of range for sequenced collectionvalue")]
+    public void Empty()
+    {
+      tree.Clear();
+      tree.RemoveAt(0);
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(IndexOutOfRangeException), "Index out of range for sequenced collectionvalue")]
+    public void HighIndex()
+    {
+      tree.RemoveAt(tree.Count);
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(IndexOutOfRangeException), "Index out of range for sequenced collectionvalue")]
+    public void LowIndex()
+    {
+      tree.RemoveAt(-1);
+    }
+
+
+    [Test]
+    public void Normal()
+    {
+      //Note: ids does not match for bag
+      Assert.IsFalse(tree.Remove(-20));
+
+      //1b
+      Assert.IsTrue(tree.Remove(20));
+      Assert.IsTrue(tree.Check("T1"));
+      Assert.IsFalse(tree.Remove(20));
+
+      //1b
+      Assert.IsTrue(tree.Remove(10));
+      Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+
+      //case 1c
+      Assert.IsTrue(tree.Remove(24));
+      Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+
+      //1a (terminating)
+      Assert.IsTrue(tree.Remove(16));
+      Assert.IsTrue(tree.Remove(16));
+      Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+
+      //2
+      Assert.IsTrue(tree.Remove(18));
+      Assert.IsTrue(tree.Remove(17));
+      Assert.IsTrue(tree.Remove(18));
+      Assert.IsTrue(tree.Remove(17));
+      Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+
+      //2+1b
+      Assert.IsTrue(tree.Remove(15));
+      Assert.IsTrue(tree.Remove(15));
+      for (int i = 0; i < 5; i++) tree.Add(17 + i);
+      Assert.IsTrue(tree.Remove(23));
+      Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+
+      //1a+1b
+      Assert.IsTrue(tree.Remove(11));
+      Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+
+      //2+1c
+      for (int i = 0; i < 10; i++)
+        tree.Add(50 - 2 * i);
+
+      Assert.IsTrue(tree.Remove(42));
+      Assert.IsTrue(tree.Remove(38));
+      Assert.IsTrue(tree.Remove(22));
+      Assert.IsTrue(tree.Remove(40));
+
+      //
+      for (int i = 0; i < 48; i++)
+        tree.Remove(i);
+
+      //Almost empty tree:*
+      Assert.IsFalse(tree.Remove(26));
+      Assert.IsTrue(tree.Remove(48));
+      Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+
+      //Empty tree:*
+      Assert.IsFalse(tree.Remove(26));
+      Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+    }
+
+
+    [TearDown]
+    public void Dispose()
+    {
+      tree = null;
+    }
+  }
+
+
+
+  [TestFixture]
+  public class PredecessorStructure
+  {
+    private TreeBag<int> tree;
+
+
+    [SetUp]
+    public void Init()
+    {
+      tree = new TreeBag<int>(new IC());
+    }
+
+
+    private void loadup()
+    {
+      for (int i = 0; i < 20; i++)
+        tree.Add(2 * i);
+      for (int i = 0; i < 10; i++)
+        tree.Add(4 * i);
+    }
+
+
+    [Test]
+    public void Predecessor()
+    {
+      loadup();
+      Assert.AreEqual(6, tree.Predecessor(7));
+      Assert.AreEqual(6, tree.Predecessor(8));
+
+      //The bottom
+      Assert.AreEqual(0, tree.Predecessor(1));
+
+      //The top
+      Assert.AreEqual(38, tree.Predecessor(39));
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void PredecessorTooLow1()
+    {
+      tree.Predecessor(-2);
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void PredecessorTooLow2()
+    {
+      tree.Predecessor(0);
+    }
+
+
+    [Test]
+    public void WeakPredecessor()
+    {
+      loadup();
+      Assert.AreEqual(6, tree.WeakPredecessor(7));
+      Assert.AreEqual(8, tree.WeakPredecessor(8));
+
+      //The bottom
+      Assert.AreEqual(0, tree.WeakPredecessor(1));
+      Assert.AreEqual(0, tree.WeakPredecessor(0));
+
+      //The top
+      Assert.AreEqual(38, tree.WeakPredecessor(39));
+      Assert.AreEqual(38, tree.WeakPredecessor(38));
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void WeakPredecessorTooLow1()
+    {
+      tree.WeakPredecessor(-2);
+    }
+
+
+    [Test]
+    public void Successor()
+    {
+      loadup();
+      Assert.AreEqual(8, tree.Successor(7));
+      Assert.AreEqual(10, tree.Successor(8));
+
+      //The bottom
+      Assert.AreEqual(2, tree.Successor(0));
+      Assert.AreEqual(0, tree.Successor(-1));
+
+      //The top
+      Assert.AreEqual(38, tree.Successor(37));
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void SuccessorTooHigh1()
+    {
+      tree.Successor(38);
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void SuccessorTooHigh2()
+    {
+      tree.Successor(39);
+    }
+
+
+    [Test]
+    public void WeakSuccessor()
+    {
+      loadup();
+      Assert.AreEqual(6, tree.WeakSuccessor(6));
+      Assert.AreEqual(8, tree.WeakSuccessor(7));
+
+      //The bottom
+      Assert.AreEqual(0, tree.WeakSuccessor(-1));
+      Assert.AreEqual(0, tree.WeakSuccessor(0));
+
+      //The top
+      Assert.AreEqual(38, tree.WeakSuccessor(37));
+      Assert.AreEqual(38, tree.WeakSuccessor(38));
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void WeakSuccessorTooHigh1()
+    {
+      tree.WeakSuccessor(39);
+    }
+
+
+    [TearDown]
+    public void Dispose()
+    {
+      tree = null;
+    }
+  }
+
+
+
+  [TestFixture]
+  public class PriorityQueue
+  {
+    private TreeBag<int> tree;
+
+
+    [SetUp]
+    public void Init()
+    {
+      tree = new TreeBag<int>(new IC());
+    }
+
+
+    private void loadup()
+    {
+      foreach (int i in new int[] { 1, 2, 3, 4 })
+        tree.Add(i);
+      tree.Add(1);
+      tree.Add(3);
+    }
+
+
+    [Test]
+    public void Normal()
+    {
+      loadup();
+      Assert.AreEqual(1, tree.FindMin());
+      Assert.AreEqual(4, tree.FindMax());
+      Assert.AreEqual(1, tree.DeleteMin());
+      Assert.AreEqual(4, tree.DeleteMax());
+      Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+      Assert.AreEqual(1, tree.FindMin());
+      Assert.AreEqual(3, tree.FindMax());
+      Assert.AreEqual(1, tree.DeleteMin());
+      Assert.AreEqual(3, tree.DeleteMax());
+      Assert.IsTrue(tree.Check("Normal test 2"), "Bad tree");
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void Empty1()
+    {
+      tree.FindMin();
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void Empty2()
+    {
+      tree.FindMax();
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void Empty3()
+    {
+      tree.DeleteMin();
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void Empty4()
+    {
+      tree.DeleteMax();
+    }
+
+
+    [TearDown]
+    public void Dispose()
+    {
+      tree = null;
+    }
+  }
+
+
+
+  [TestFixture]
+  public class IndexingAndCounting
+  {
+    private TreeBag<int> tree;
+
+
+    [SetUp]
+    public void Init()
+    {
+      tree = new TreeBag<int>(new IC());
+    }
+
+
+    private void populate()
+    {
+      tree.Add(30);
+      tree.Add(30);
+      tree.Add(50);
+      tree.Add(10);
+      tree.Add(70);
+      tree.Add(70);
+    }
+
+
+    [Test]
+    public void ToArray()
+    {
+      populate();
+
+      int[] a = tree.ToArray();
+
+      Assert.AreEqual(6, a.Length);
+      Assert.AreEqual(10, a[0]);
+      Assert.AreEqual(30, a[1]);
+      Assert.AreEqual(30, a[2]);
+      Assert.AreEqual(50, a[3]);
+      Assert.AreEqual(70, a[4]);
+      Assert.AreEqual(70, a[5]);
+    }
+
+
+    [Test]
+    public void GoodIndex()
+    {
+      Assert.AreEqual(-1, tree.IndexOf(20));
+      Assert.AreEqual(-1, tree.LastIndexOf(20));
+      populate();
+      Assert.AreEqual(10, tree[0]);
+      Assert.AreEqual(30, tree[1]);
+      Assert.AreEqual(30, tree[2]);
+      Assert.AreEqual(50, tree[3]);
+      Assert.AreEqual(70, tree[4]);
+      Assert.AreEqual(70, tree[5]);
+      Assert.AreEqual(0, tree.IndexOf(10));
+      Assert.AreEqual(1, tree.IndexOf(30));
+      Assert.AreEqual(3, tree.IndexOf(50));
+      Assert.AreEqual(4, tree.IndexOf(70));
+      Assert.AreEqual(~1, tree.IndexOf(20));
+      Assert.AreEqual(~0, tree.IndexOf(0));
+      Assert.AreEqual(~6, tree.IndexOf(90));
+      Assert.AreEqual(0, tree.LastIndexOf(10));
+      Assert.AreEqual(2, tree.LastIndexOf(30));
+      Assert.AreEqual(3, tree.LastIndexOf(50));
+      Assert.AreEqual(5, tree.LastIndexOf(70));
+      Assert.AreEqual(~1, tree.LastIndexOf(20));
+      Assert.AreEqual(~0, tree.LastIndexOf(0));
+      Assert.AreEqual(~6, tree.LastIndexOf(90));
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(IndexOutOfRangeException))]
+    public void IndexTooLarge()
+    {
+      populate();
+      Console.WriteLine(tree[6]);
+    }
+
+
+    [Test]
+    [ExpectedException(typeof(IndexOutOfRangeException))]
+    public void IndexTooSmall()
+    {
+      populate();
+      Console.WriteLine(tree[-1]);
+    }
+
+
+    [Test]
+    public void FilledTreeOutsideInput()
+    {
+      populate();
+      Assert.AreEqual(0, tree.CountFrom(90));
+      Assert.AreEqual(0, tree.CountFromTo(-20, 0));
+      Assert.AreEqual(0, tree.CountFromTo(80, 100));
+      Assert.AreEqual(0, tree.CountTo(0));
+      Assert.AreEqual(6, tree.CountTo(90));
+      Assert.AreEqual(6, tree.CountFromTo(-20, 90));
+      Assert.AreEqual(6, tree.CountFrom(0));
+    }
+
+
+    [Test]
+    public void FilledTreeIntermediateInput()
+    {
+      populate();
+      Assert.AreEqual(5, tree.CountFrom(20));
+      Assert.AreEqual(2, tree.CountFromTo(20, 40));
+      Assert.AreEqual(3, tree.CountTo(40));
+    }
+
+
+    [Test]
+    public void FilledTreeMatchingInput()
+    {
+      populate();
+      Assert.AreEqual(5, tree.CountFrom(30));
+      Assert.AreEqual(3, tree.CountFromTo(30, 70));
+      Assert.AreEqual(0, tree.CountFromTo(50, 30));
+      Assert.AreEqual(0, tree.CountFromTo(50, 50));
+      Assert.AreEqual(0, tree.CountTo(10));
+      Assert.AreEqual(3, tree.CountTo(50));
+    }
+
+
+    [Test]
+    public void CountEmptyTree()
+    {
+      Assert.AreEqual(0, tree.CountFrom(20));
+      Assert.AreEqual(0, tree.CountFromTo(20, 40));
+      Assert.AreEqual(0, tree.CountTo(40));
+    }
+
+
+    [TearDown]
+    public void Dispose()
+    {
+      tree = null;
+    }
+  }
+
+
+
+
+  namespace ModificationCheck
+  {
+    [TestFixture]
+    public class Enumerator
+    {
+      private TreeBag<int> tree;
+
+      private SCG.IEnumerator<int> e;
+
+
+      [SetUp]
+      public void Init()
+      {
+        tree = new TreeBag<int>(new IC());
+        for (int i = 0; i < 10; i++)
+          tree.Add(i);
+        tree.Add(3);
+        tree.Add(7);
+        e = tree.GetEnumerator();
+      }
+
+
+      [Test]
+      public void CurrentAfterModification()
+      {
+        e.MoveNext();
+        tree.Add(34);
+        Assert.AreEqual(0, e.Current);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterAdd()
+      {
+        tree.Add(34);
+        e.MoveNext();
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterRemove()
+      {
+        tree.Remove(34);
+        e.MoveNext();
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterClear()
+      {
+        tree.Clear();
+        e.MoveNext();
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        tree = null;
+        e = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class RangeEnumerator
+    {
+      private TreeBag<int> tree;
+
+      private SCG.IEnumerator<int> e;
+
+
+      [SetUp]
+      public void Init()
+      {
+        tree = new TreeBag<int>(new IC());
+        for (int i = 0; i < 10; i++)
+          tree.Add(i);
+
+        e = tree.RangeFromTo(3, 7).GetEnumerator();
+      }
+
+
+      [Test]
+      public void CurrentAfterModification()
+      {
+        e.MoveNext();
+        tree.Add(34);
+        Assert.AreEqual(3, e.Current);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterAdd()
+      {
+        tree.Add(34);
+        e.MoveNext();
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterRemove()
+      {
+        tree.Remove(34);
+        e.MoveNext();
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterClear()
+      {
+        tree.Clear();
+        e.MoveNext();
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        tree = null;
+        e = null;
+      }
+    }
+  }
+
+
+
+
+  namespace PathcopyPersistence
+  {
+    [TestFixture]
+    public class Navigation
+    {
+      private TreeBag<int> tree, snap;
+
+      private SCG.IComparer<int> ic;
+
+
+      [SetUp]
+      public void Init()
+      {
+        ic = new IC();
+        tree = new TreeBag<int>(ic);
+        for (int i = 0; i <= 20; i++)
+          tree.Add(2 * i + 1);
+        tree.Add(13);
+        snap = (TreeBag<int>)tree.Snapshot();
+        for (int i = 0; i <= 10; i++)
+          tree.Remove(4 * i + 1);
+      }
+
+
+      private bool twomodeleven(int i)
+      {
+        return i % 11 == 2;
+      }
+
+
+      [Test]
+      public void InternalEnum()
+      {
+        Assert.IsTrue(IC.eq(snap.FindAll(new Fun<int, bool>(twomodeleven)), 13, 13, 35));
+      }
+
+
+      public void MoreCut()
+      {
+        //TODO: Assert.Fail("more tests of Cut needed");
+      }
+
+
+      [Test]
+      public void Cut()
+      {
+        int lo, hi;
+        bool lv, hv;
+
+        Assert.IsFalse(snap.Cut(new HigherOrder.CubeRoot(64), out lo, out lv, out hi, out hv));
+        Assert.IsTrue(lv && hv);
+        Assert.AreEqual(5, hi);
+        Assert.AreEqual(3, lo);
+        Assert.IsTrue(snap.Cut(new HigherOrder.CubeRoot(125), out lo, out lv, out hi, out hv));
+        Assert.IsTrue(lv && hv);
+        Assert.AreEqual(7, hi);
+        Assert.AreEqual(3, lo);
+        Assert.IsFalse(snap.Cut(new HigherOrder.CubeRoot(125000), out lo, out lv, out hi, out hv));
+        Assert.IsTrue(lv && !hv);
+        Assert.AreEqual(41, lo);
+        Assert.IsFalse(snap.Cut(new HigherOrder.CubeRoot(-27), out lo, out lv, out hi, out hv));
+        Assert.IsTrue(!lv && hv);
+        Assert.AreEqual(1, hi);
+      }
+
+
+      [Test]
+      public void Range()
+      {
+        Assert.IsTrue(IC.eq(snap.RangeFromTo(5, 16), 5, 7, 9, 11, 13, 13, 15));
+        Assert.IsTrue(IC.eq(snap.RangeFromTo(5, 17), 5, 7, 9, 11, 13, 13, 15));
+        Assert.IsTrue(IC.eq(snap.RangeFromTo(6, 16), 7, 9, 11, 13, 13, 15));
+      }
+
+
+      [Test]
+      public void Contains()
+      {
+        Assert.IsTrue(snap.Contains(5));
+        Assert.IsTrue(snap.Contains(13));
+        Assert.AreEqual(1, snap.ContainsCount(5));
+        Assert.AreEqual(2, snap.ContainsCount(13));
+      }
+
+
+      [Test]
+      public void FindMin()
+      {
+        Assert.AreEqual(1, snap.FindMin());
+      }
+
+
+      [Test]
+      public void FindMax()
+      {
+        Assert.AreEqual(41, snap.FindMax());
+      }
+
+
+      [Test]
+      public void Predecessor()
+      {
+        Assert.AreEqual(13, snap.Predecessor(15));
+        Assert.AreEqual(15, snap.Predecessor(16));
+        Assert.AreEqual(15, snap.Predecessor(17));
+        Assert.AreEqual(17, snap.Predecessor(18));
+      }
+
+
+      [Test]
+      public void Successor()
+      {
+        Assert.AreEqual(17, snap.Successor(15));
+        Assert.AreEqual(17, snap.Successor(16));
+        Assert.AreEqual(19, snap.Successor(17));
+        Assert.AreEqual(19, snap.Successor(18));
+      }
+
+
+      [Test]
+      public void WeakPredecessor()
+      {
+        Assert.AreEqual(15, snap.WeakPredecessor(15));
+        Assert.AreEqual(15, snap.WeakPredecessor(16));
+        Assert.AreEqual(17, snap.WeakPredecessor(17));
+        Assert.AreEqual(17, snap.WeakPredecessor(18));
+      }
+
+
+      [Test]
+      public void WeakSuccessor()
+      {
+        Assert.AreEqual(15, snap.WeakSuccessor(15));
+        Assert.AreEqual(17, snap.WeakSuccessor(16));
+        Assert.AreEqual(17, snap.WeakSuccessor(17));
+        Assert.AreEqual(19, snap.WeakSuccessor(18));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(NotSupportedException), "Indexing not supported for snapshots")]
+      public void CountTo()
+      {
+        int j = snap.CountTo(15);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(NotSupportedException), "Indexing not supported for snapshots")]
+      public void Indexing()
+      {
+        int j = snap[4];
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(NotSupportedException), "Indexing not supported for snapshots")]
+      public void Indexing2()
+      {
+        int j = snap.IndexOf(5);
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        tree = null;
+        ic = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class Single
+    {
+      private TreeBag<int> tree;
+
+      private SCG.IComparer<int> ic;
+
+
+      [SetUp]
+      public void Init()
+      {
+        ic = new IC();
+        tree = new TreeBag<int>(ic);
+        for (int i = 0; i < 10; i++)
+          tree.Add(2 * i + 1);
+      }
+
+
+      [Test]
+      public void EnumerationWithAdd()
+      {
+        int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };
+        int i = 0;
+        TreeBag<int> snap = (TreeBag<int>)tree.Snapshot();
+
+        foreach (int j in snap)
+        {
+          Assert.AreEqual(1 + 2 * i++, j);
+          tree.Add(21 - j);
+          Assert.IsTrue(snap.Check("M"), "Bad snap!");
+          Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+          Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+        }
+      }
+
+
+      [Test]
+      public void Remove()
+      {
+        int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };
+        TreeBag<int> snap = (TreeBag<int>)tree.Snapshot();
+
+        Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+        tree.Remove(19);
+        Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+        Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+      }
+
+
+      [Test]
+      public void RemoveNormal()
+      {
+        tree.Clear();
+        for (int i = 10; i < 20; i++)
+        {
+          tree.Add(i);
+          tree.Add(i + 10);
+        }
+        tree.Add(15);
+
+        int[] orig = new int[] { 10, 11, 12, 13, 14, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 };
+        TreeBag<int> snap = (TreeBag<int>)tree.Snapshot();
+
+        Assert.IsFalse(tree.Remove(-20));
+        Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+
+        //decrease items case
+        Assert.IsTrue(tree.Remove(15));
+        Assert.IsTrue(tree.Check("T1"));
+        Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+        //snap.dump();
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+        //No demote case, with move_item
+        Assert.IsTrue(tree.Remove(20));
+        Assert.IsTrue(tree.Check("T1"));
+        Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+        Assert.IsFalse(tree.Remove(20));
+
+        //plain case 2
+        tree.Snapshot();
+        Assert.IsTrue(tree.Remove(14));
+        Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+        Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+        //case 1b
+        Assert.IsTrue(tree.Remove(25));
+        Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+        Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+        //case 1c
+        Assert.IsTrue(tree.Remove(29));
+        Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+        Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+        //1a (terminating)
+        Assert.IsTrue(tree.Remove(10));
+        Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+        Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+        //2+1b
+        Assert.IsTrue(tree.Remove(12));
+        tree.Snapshot();
+        Assert.IsTrue(tree.Remove(11));
+        Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+        Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+        //1a+1b
+        Assert.IsTrue(tree.Remove(18));
+        Assert.IsTrue(tree.Remove(13));
+        Assert.IsTrue(tree.Remove(15));
+        Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+        Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+        //2+1c
+        for (int i = 0; i < 10; i++)
+          tree.Add(50 - 2 * i);
+
+        Assert.IsTrue(tree.Remove(42));
+        Assert.IsTrue(tree.Remove(38));
+        Assert.IsTrue(tree.Remove(28));
+        Assert.IsTrue(tree.Remove(40));
+        Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+        Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+        //
+        Assert.IsTrue(tree.Remove(16));
+        Assert.IsTrue(tree.Remove(23));
+        Assert.IsTrue(tree.Remove(17));
+        Assert.IsTrue(tree.Remove(19));
+        Assert.IsTrue(tree.Remove(50));
+        Assert.IsTrue(tree.Remove(26));
+        Assert.IsTrue(tree.Remove(21));
+        Assert.IsTrue(tree.Remove(22));
+        Assert.IsTrue(tree.Remove(24));
+        for (int i = 0; i < 48; i++)
+          tree.Remove(i);
+
+        //Almost empty tree:
+        Assert.IsFalse(tree.Remove(26));
+        Assert.IsTrue(tree.Remove(48));
+        Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+        Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+        //Empty tree:
+        Assert.IsFalse(tree.Remove(26));
+        Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+        Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+      }
+
+
+      [Test]
+      public void Add()
+      {
+        int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };
+        TreeBag<int> snap = (TreeBag<int>)tree.Snapshot();
+
+        Assert.IsTrue(snap.Check("M"), "Bad snap!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+        Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+        tree.Add(10);
+        Assert.IsTrue(snap.Check("M"), "Bad snap!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+        Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+        tree.Add(16);
+        Assert.IsTrue(snap.Check("M"), "Bad snap!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+        Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+
+        tree.Add(9);
+        Assert.IsTrue(snap.Check("M"), "Bad snap!");
+        Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+        //Promote+zigzig
+        tree.Add(40);
+        Assert.IsTrue(snap.Check("M"), "Bad snap!");
+        Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+        for (int i = 1; i < 4; i++)
+          tree.Add(40 - 2 * i);
+
+        Assert.IsTrue(snap.Check("M"), "Bad snap!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+        Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+
+        //Zigzag:
+        tree.Add(32);
+        Assert.IsTrue(snap.Check("M"), "Bad snap!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+        Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+      }
+
+
+      [Test]
+      public void Clear()
+      {
+        int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };
+        TreeBag<int> snap = (TreeBag<int>)tree.Snapshot();
+
+        tree.Clear();
+        Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+        Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+        Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+        Assert.AreEqual(0, tree.Count);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(InvalidOperationException), "Cannot snapshot a snapshot")]
+      public void SnapSnap()
+      {
+        TreeBag<int> snap = (TreeBag<int>)tree.Snapshot();
+
+        snap.Snapshot();
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        tree = null;
+        ic = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class Multiple
+    {
+      private TreeBag<int> tree;
+
+      private SCG.IComparer<int> ic;
+
+
+      private bool eq(SCG.IEnumerable<int> me, int[] that)
+      {
+        int i = 0, maxind = that.Length - 1;
+
+        foreach (int item in me)
+          if (i > maxind || ic.Compare(item, that[i++]) != 0)
+            return false;
+
+        return true;
+      }
+
+
+      [SetUp]
+      public void Init()
+      {
+        ic = new IC();
+        tree = new TreeBag<int>(ic);
+        for (int i = 0; i < 10; i++)
+          tree.Add(2 * i + 1);
+      }
+
+
+      [Test]
+      public void First()
+      {
+        TreeBag<int>[] snaps = new TreeBag<int>[10];
+
+        for (int i = 0; i < 10; i++)
+        {
+          snaps[i] = (TreeBag<int>)(tree.Snapshot());
+          tree.Add(2 * i);
+        }
+
+        for (int i = 0; i < 10; i++)
+        {
+          Assert.AreEqual(i + 10, snaps[i].Count);
+        }
+
+        snaps[5] = null;
+        snaps[9] = null;
+        GC.Collect();
+        snaps[8].Dispose();
+        tree.Remove(14);
+
+        int[] res = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19 };
+        int[] snap7 = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19 };
+        int[] snap3 = new int[] { 0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 15, 17, 19 };
+
+        Assert.IsTrue(IC.eq(snaps[3], snap3), "Snap 3 was changed!");
+        Assert.IsTrue(IC.eq(snaps[7], snap7), "Snap 7 was changed!");
+        Assert.IsTrue(IC.eq(tree, res));
+        Assert.IsTrue(tree.Check("B"));
+        Assert.IsTrue(snaps[3].Check("B"));
+        Assert.IsTrue(snaps[7].Check("B"));
+      }
+
+
+      [Test]
+      public void CollectingTheMaster()
+      {
+        TreeBag<int>[] snaps = new TreeBag<int>[10];
+
+        for (int i = 0; i < 10; i++)
+        {
+          snaps[i] = (TreeBag<int>)(tree.Snapshot());
+          tree.Add(2 * i);
+        }
+
+        tree = null;
+        GC.Collect();
+        for (int i = 0; i < 10; i++)
+        {
+          Assert.AreEqual(i + 10, snaps[i].Count);
+        }
+
+        snaps[5] = null;
+        snaps[9] = null;
+        GC.Collect();
+        snaps[8].Dispose();
+
+        int[] snap7 = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19 };
+        int[] snap3 = new int[] { 0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 15, 17, 19 };
+
+        Assert.IsTrue(IC.eq(snaps[3], snap3), "Snap 3 was changed!");
+        Assert.IsTrue(IC.eq(snaps[7], snap7), "Snap 7 was changed!");
+        Assert.IsTrue(snaps[3].Check("B"));
+        Assert.IsTrue(snaps[7].Check("B"));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        tree = null;
+        ic = null;
+      }
+    }
+  }
+
+
+
+
+  namespace HigherOrder
+  {
+    internal class CubeRoot : IComparable<int>
+    {
+      private int c;
+
+
+      internal CubeRoot(int c) { this.c = c; }
+
+
+      public int CompareTo(int that) { return c - that * that * that; }
+      public bool Equals(int that) { return c == that * that * that; }
+    }
+
+
+
+    class Interval : IComparable<int>
+    {
+      private int b, t;
+
+
+      internal Interval(int b, int t) { this.b = b; this.t = t; }
+
+
+      public int CompareTo(int that) { return that < b ? 1 : that > t ? -1 : 0; }
+      public bool Equals(int that) { return that >= b && that <= t; }
+    }
+
+
+
+    [TestFixture]
+    public class Simple
+    {
+      private TreeBag<int> tree;
+
+      private SCG.IComparer<int> ic;
+
+
+      [SetUp]
+      public void Init()
+      {
+        ic = new IC();
+        tree = new TreeBag<int>(ic);
+      }
+
+
+      private bool never(int i) { return false; }
+
+
+      private bool always(int i) { return true; }
+
+
+      private bool even(int i) { return i % 2 == 0; }
+
+
+      private string themap(int i) { return String.Format("AA {0,4} BB", i); }
+
+
+      private string badmap(int i) { return String.Format("AA {0} BB", i); }
+
+
+      private int appfield1;
+
+      private int appfield2;
+
+
+      private void apply(int i) { appfield1++; appfield2 += i * i; }
+
+
+      [Test]
+      public void Apply()
+      {
+        Simple simple1 = new Simple();
+
+        tree.Apply(new Act<int>(simple1.apply));
+        Assert.AreEqual(0, simple1.appfield1);
+        Assert.AreEqual(0, simple1.appfield2);
+
+        Simple simple2 = new Simple();
+
+        for (int i = 0; i < 10; i++) tree.Add(i);
+        tree.Add(2);
+
+        tree.Apply(new Act<int>(simple2.apply));
+        Assert.AreEqual(11, simple2.appfield1);
+        Assert.AreEqual(289, simple2.appfield2);
+      }
+
+
+      [Test]
+      public void All()
+      {
+        Assert.IsTrue(tree.All(new Fun<int, bool>(never)));
+        Assert.IsTrue(tree.All(new Fun<int, bool>(even)));
+        Assert.IsTrue(tree.All(new Fun<int, bool>(always)));
+        for (int i = 0; i < 10; i++) tree.Add(i);
+
+        Assert.IsFalse(tree.All(new Fun<int, bool>(never)));
+        Assert.IsFalse(tree.All(new Fun<int, bool>(even)));
+        Assert.IsTrue(tree.All(new Fun<int, bool>(always)));
+        tree.Clear();
+        for (int i = 0; i < 10; i++) tree.Add(i * 2);
+
+        Assert.IsFalse(tree.All(new Fun<int, bool>(never)));
+        Assert.IsTrue(tree.All(new Fun<int, bool>(even)));
+        Assert.IsTrue(tree.All(new Fun<int, bool>(always)));
+        tree.Clear();
+        for (int i = 0; i < 10; i++) tree.Add(i * 2 + 1);
+
+        Assert.IsFalse(tree.All(new Fun<int, bool>(never)));
+        Assert.IsFalse(tree.All(new Fun<int, bool>(even)));
+        Assert.IsTrue(tree.All(new Fun<int, bool>(always)));
+      }
+
+
+      [Test]
+      public void Exists()
+      {
+        Assert.IsFalse(tree.Exists(new Fun<int, bool>(never)));
+        Assert.IsFalse(tree.Exists(new Fun<int, bool>(even)));
+        Assert.IsFalse(tree.Exists(new Fun<int, bool>(always)));
+        for (int i = 0; i < 10; i++) tree.Add(i);
+
+        Assert.IsFalse(tree.Exists(new Fun<int, bool>(never)));
+        Assert.IsTrue(tree.Exists(new Fun<int, bool>(even)));
+        Assert.IsTrue(tree.Exists(new Fun<int, bool>(always)));
+        tree.Clear();
+        for (int i = 0; i < 10; i++) tree.Add(i * 2);
+
+        Assert.IsFalse(tree.Exists(new Fun<int, bool>(never)));
+        Assert.IsTrue(tree.Exists(new Fun<int, bool>(even)));
+        Assert.IsTrue(tree.Exists(new Fun<int, bool>(always)));
+        tree.Clear();
+        for (int i = 0; i < 10; i++) tree.Add(i * 2 + 1);
+
+        Assert.IsFalse(tree.Exists(new Fun<int, bool>(never)));
+        Assert.IsFalse(tree.Exists(new Fun<int, bool>(even)));
+        Assert.IsTrue(tree.Exists(new Fun<int, bool>(always)));
+      }
+
+
+      [Test]
+      public void FindAll()
+      {
+        Assert.AreEqual(0, tree.FindAll(new Fun<int, bool>(never)).Count);
+        for (int i = 0; i < 10; i++)
+          tree.Add(i);
+        tree.Add(2);
+
+        Assert.AreEqual(0, tree.FindAll(new Fun<int, bool>(never)).Count);
+        Assert.AreEqual(11, tree.FindAll(new Fun<int, bool>(always)).Count);
+        Assert.AreEqual(6, tree.FindAll(new Fun<int, bool>(even)).Count);
+        Assert.IsTrue(((TreeBag<int>)tree.FindAll(new Fun<int, bool>(even))).Check("R"));
+      }
+
+
+      [Test]
+      public void Map()
+      {
+        Assert.AreEqual(0, tree.Map(new Fun<int, string>(themap), new SC()).Count);
+        for (int i = 0; i < 14; i++)
+          tree.Add(i * i * i);
+        tree.Add(1);
+
+        IIndexedSorted<string> res = tree.Map(new Fun<int, string>(themap), new SC());
+
+        Assert.IsTrue(((TreeBag<string>)res).Check("R"));
+        Assert.AreEqual(15, res.Count);
+        Assert.AreEqual("AA    0 BB", res[0]);
+        Assert.AreEqual("AA    1 BB", res[1]);
+        Assert.AreEqual("AA    1 BB", res[2]);
+        Assert.AreEqual("AA    8 BB", res[3]);
+        Assert.AreEqual("AA   27 BB", res[4]);
+        Assert.AreEqual("AA  125 BB", res[6]);
+        Assert.AreEqual("AA 1000 BB", res[11]);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentException), "mapper not monotonic")]
+      public void BadMap()
+      {
+        for (int i = 0; i < 11; i++)
+          tree.Add(i * i * i);
+
+        ISorted<string> res = tree.Map(new Fun<int, string>(badmap), new SC());
+      }
+
+
+      [Test]
+      public void Cut()
+      {
+        for (int i = 0; i < 10; i++)
+          tree.Add(i);
+        tree.Add(3);
+
+        int low, high;
+        bool lval, hval;
+
+        Assert.IsTrue(tree.Cut(new CubeRoot(27), out low, out lval, out high, out hval));
+        Assert.IsTrue(lval && hval);
+        Assert.AreEqual(4, high);
+        Assert.AreEqual(2, low);
+        Assert.IsFalse(tree.Cut(new CubeRoot(30), out low, out lval, out high, out hval));
+        Assert.IsTrue(lval && hval);
+        Assert.AreEqual(4, high);
+        Assert.AreEqual(3, low);
+      }
+
+
+      [Test]
+      public void CutInt()
+      {
+        for (int i = 0; i < 10; i++)
+          tree.Add(2 * i);
+
+        int low, high;
+        bool lval, hval;
+
+        Assert.IsFalse(tree.Cut(new IC(3), out low, out lval, out high, out hval));
+        Assert.IsTrue(lval && hval);
+        Assert.AreEqual(4, high);
+        Assert.AreEqual(2, low);
+        Assert.IsTrue(tree.Cut(new IC(6), out low, out lval, out high, out hval));
+        Assert.IsTrue(lval && hval);
+        Assert.AreEqual(8, high);
+        Assert.AreEqual(4, low);
+      }
+
+
+      [Test]
+      public void CutInterval()
+      {
+        for (int i = 0; i < 10; i++)
+          tree.Add(2 * i);
+
+        int lo, hi;
+        bool lv, hv;
+
+        Assert.IsTrue(tree.Cut(new Interval(5, 9), out lo, out lv, out hi, out hv));
+        Assert.IsTrue(lv && hv);
+        Assert.AreEqual(10, hi);
+        Assert.AreEqual(4, lo);
+        Assert.IsTrue(tree.Cut(new Interval(6, 10), out lo, out lv, out hi, out hv));
+        Assert.IsTrue(lv && hv);
+        Assert.AreEqual(12, hi);
+        Assert.AreEqual(4, lo);
+        for (int i = 0; i < 100; i++)
+          tree.Add(2 * i);
+
+        tree.Cut(new Interval(77, 105), out lo, out lv, out hi, out hv);
+        Assert.IsTrue(lv && hv);
+        Assert.AreEqual(106, hi);
+        Assert.AreEqual(76, lo);
+        tree.Cut(new Interval(5, 7), out lo, out lv, out hi, out hv);
+        Assert.IsTrue(lv && hv);
+        Assert.AreEqual(8, hi);
+        Assert.AreEqual(4, lo);
+        tree.Cut(new Interval(80, 110), out lo, out lv, out hi, out hv);
+        Assert.IsTrue(lv && hv);
+        Assert.AreEqual(112, hi);
+        Assert.AreEqual(78, lo);
+      }
+
+
+      [Test]
+      public void UpperCut()
+      {
+        for (int i = 0; i < 10; i++)
+          tree.Add(i);
+
+        int l, h;
+        bool lv, hv;
+
+        Assert.IsFalse(tree.Cut(new CubeRoot(1000), out l, out lv, out h, out hv));
+        Assert.IsTrue(lv && !hv);
+        Assert.AreEqual(9, l);
+        Assert.IsFalse(tree.Cut(new CubeRoot(-50), out l, out lv, out h, out hv));
+        Assert.IsTrue(!lv && hv);
+        Assert.AreEqual(0, h);
+      }
+
+
+      [TearDown]
+      public void Dispose() { ic = null; tree = null; }
+    }
+  }
+
+
+
+
+  namespace MultiOps
+  {
+    [TestFixture]
+    public class AddAll
+    {
+      private int sqr(int i) { return i * i; }
+
+
+      TreeBag<int> tree;
+
+
+      [SetUp]
+      public void Init() { tree = new TreeBag<int>(new IC()); }
+
+
+      [Test]
+      public void EmptyEmpty()
+      {
+        tree.AddAll(new FunEnumerable(0, new Fun<int, int>(sqr)));
+        Assert.AreEqual(0, tree.Count);
+        Assert.IsTrue(tree.Check());
+      }
+
+
+      [Test]
+      public void SomeEmpty()
+      {
+        for (int i = 4; i < 9; i++) tree.Add(i);
+
+        tree.AddAll(new FunEnumerable(0, new Fun<int, int>(sqr)));
+        Assert.AreEqual(5, tree.Count);
+        Assert.IsTrue(tree.Check());
+      }
+
+
+      [Test]
+      public void EmptySome()
+      {
+        tree.AddAll(new FunEnumerable(4, new Fun<int, int>(sqr)));
+        Assert.AreEqual(4, tree.Count);
+        Assert.IsTrue(tree.Check());
+        Assert.AreEqual(0, tree[0]);
+        Assert.AreEqual(1, tree[1]);
+        Assert.AreEqual(4, tree[2]);
+        Assert.AreEqual(9, tree[3]);
+      }
+
+
+      [Test]
+      public void SomeSome()
+      {
+        for (int i = 5; i < 9; i++) tree.Add(i);
+        tree.Add(1);
+
+        tree.AddAll(new FunEnumerable(4, new Fun<int, int>(sqr)));
+        Assert.AreEqual(9, tree.Count);
+        Assert.IsTrue(tree.Check());
+        Assert.IsTrue(IC.eq(tree, 0, 1, 1, 4, 5, 6, 7, 8, 9));
+      }
+
+
+      [TearDown]
+      public void Dispose() { tree = null; }
+    }
+
+
+
+    [TestFixture]
+    public class AddSorted
+    {
+      private int sqr(int i) { return i * i; }
+
+      private int step(int i) { return i / 3; }
+
+
+      private int bad(int i) { return i * (5 - i); }
+
+
+      TreeBag<int> tree;
+
+
+      [SetUp]
+      public void Init() { tree = new TreeBag<int>(new IC()); }
+
+
+      [Test]
+      public void EmptyEmpty()
+      {
+        tree.AddSorted(new FunEnumerable(0, new Fun<int, int>(sqr)));
+        Assert.AreEqual(0, tree.Count);
+        Assert.IsTrue(tree.Check());
+      }
+
+
+      [Test]
+      public void SomeEmpty()
+      {
+        for (int i = 4; i < 9; i++) tree.Add(i);
+
+        tree.AddSorted(new FunEnumerable(0, new Fun<int, int>(sqr)));
+        Assert.AreEqual(5, tree.Count);
+        Assert.IsTrue(tree.Check());
+      }
+
+
+      [Test]
+      public void EmptySome()
+      {
+        tree.AddSorted(new FunEnumerable(4, new Fun<int, int>(sqr)));
+        Assert.AreEqual(4, tree.Count);
+        Assert.IsTrue(tree.Check());
+        Assert.AreEqual(0, tree[0]);
+        Assert.AreEqual(1, tree[1]);
+        Assert.AreEqual(4, tree[2]);
+        Assert.AreEqual(9, tree[3]);
+      }
+
+      [Test]
+      public void EmptySome2()
+      {
+        tree.AddSorted(new FunEnumerable(4, new Fun<int, int>(step)));
+        //tree.dump();
+        Assert.AreEqual(4, tree.Count);
+        Assert.IsTrue(tree.Check());
+        Assert.AreEqual(0, tree[0]);
+        Assert.AreEqual(0, tree[1]);
+        Assert.AreEqual(0, tree[2]);
+        Assert.AreEqual(1, tree[3]);
+      }
+
+
+      [Test]
+      public void SomeSome()
+      {
+        for (int i = 5; i < 9; i++) tree.Add(i);
+        tree.Add(1);
+
+        tree.AddSorted(new FunEnumerable(4, new Fun<int, int>(sqr)));
+        Assert.AreEqual(9, tree.Count);
+        Assert.IsTrue(tree.Check());
+        Assert.IsTrue(IC.eq(tree, 0, 1, 1, 4, 5, 6, 7, 8, 9));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentException), "Argument not sorted")]
+      public void EmptyBad()
+      {
+        tree.AddSorted(new FunEnumerable(9, new Fun<int, int>(bad)));
+      }
+
+
+      [TearDown]
+      public void Dispose() { tree = null; }
+    }
+
+
+
+    [TestFixture]
+    public class Rest
+    {
+      TreeBag<int> tree, tree2;
+
+
+      [SetUp]
+      public void Init()
+      {
+        tree = new TreeBag<int>(new IC());
+        tree2 = new TreeBag<int>(new IC());
+        for (int i = 0; i < 10; i++)
+          tree.Add(i);
+        tree.Add(4);
+
+        for (int i = 0; i < 10; i++)
+          tree2.Add(2 * i);
+      }
+
+
+      [Test]
+      public void RemoveAll()
+      {
+        tree.RemoveAll(tree2.RangeFromTo(3, 7));
+        Assert.AreEqual(9, tree.Count);
+        Assert.IsTrue(tree.Check());
+        Assert.IsTrue(IC.eq(tree, 0, 1, 2, 3, 4, 5, 7, 8, 9));
+        tree.RemoveAll(tree2.RangeFromTo(3, 7));
+        Assert.AreEqual(8, tree.Count);
+        Assert.IsTrue(tree.Check());
+        Assert.IsTrue(IC.eq(tree, 0, 1, 2, 3, 5, 7, 8, 9));
+        tree.RemoveAll(tree2.RangeFromTo(13, 17));
+        Assert.AreEqual(8, tree.Count);
+        Assert.IsTrue(tree.Check());
+        Assert.IsTrue(IC.eq(tree, 0, 1, 2, 3, 5, 7, 8, 9));
+        tree.RemoveAll(tree2.RangeFromTo(3, 17));
+        Assert.AreEqual(7, tree.Count);
+        Assert.IsTrue(tree.Check());
+        Assert.IsTrue(IC.eq(tree, 0, 1, 2, 3, 5, 7, 9));
+        for (int i = 0; i < 10; i++) tree2.Add(i);
+
+        tree.RemoveAll(tree2.RangeFromTo(-1, 10));
+        Assert.AreEqual(0, tree.Count);
+        Assert.IsTrue(tree.Check());
+        Assert.IsTrue(IC.eq(tree));
+      }
+
+      private void pint<T>(SCG.IEnumerable<T> e)
+      {
+        foreach (T i in e)
+          Console.Write("{0} ", i);
+
+        Console.WriteLine();
+      }
+
+      [Test]
+      public void RetainAll()
+      {
+        tree.Add(8); tree2.Add(6);
+        //pint<int>(tree);
+        //pint<int>(tree2);
+        tree.RetainAll(tree2.RangeFromTo(3, 17));
+        Assert.AreEqual(3, tree.Count);
+        Assert.IsTrue(tree.Check());
+        Assert.IsTrue(IC.eq(tree, 4, 6, 8));
+        tree.RetainAll(tree2.RangeFromTo(1, 17));
+        Assert.AreEqual(3, tree.Count);
+        Assert.IsTrue(tree.Check());
+        Assert.IsTrue(IC.eq(tree, 4, 6, 8));
+        tree.RetainAll(tree2.RangeFromTo(3, 5));
+        Assert.AreEqual(1, tree.Count);
+        Assert.IsTrue(tree.Check());
+        Assert.IsTrue(IC.eq(tree, 4));
+        tree.RetainAll(tree2.RangeFromTo(7, 17));
+        Assert.AreEqual(0, tree.Count);
+        Assert.IsTrue(tree.Check());
+        Assert.IsTrue(IC.eq(tree));
+        for (int i = 0; i < 10; i++) tree.Add(i);
+
+        tree.RetainAll(tree2.RangeFromTo(5, 5));
+        Assert.AreEqual(0, tree.Count);
+        Assert.IsTrue(tree.Check());
+        Assert.IsTrue(IC.eq(tree));
+        for (int i = 0; i < 10; i++) tree.Add(i);
+
+        tree.RetainAll(tree2.RangeFromTo(15, 25));
+        Assert.AreEqual(0, tree.Count);
+        Assert.IsTrue(tree.Check());
+        Assert.IsTrue(IC.eq(tree));
+      }
+
+
+      [Test]
+      public void ContainsAll()
+      {
+        Assert.IsFalse(tree.ContainsAll(tree2));
+        Assert.IsTrue(tree.ContainsAll(tree));
+        tree2.Clear();
+        Assert.IsTrue(tree.ContainsAll(tree2));
+        tree.Clear();
+        Assert.IsTrue(tree.ContainsAll(tree2));
+        tree2.Add(8);
+        Assert.IsFalse(tree.ContainsAll(tree2));
+      }
+
+
+      [Test]
+      public void RemoveInterval()
+      {
+        tree.RemoveInterval(3, 4);
+        Assert.IsTrue(tree.Check());
+        Assert.AreEqual(7, tree.Count);
+        Assert.IsTrue(IC.eq(tree, 0, 1, 2, 6, 7, 8, 9));
+        tree.RemoveInterval(2, 3);
+        Assert.IsTrue(tree.Check());
+        Assert.AreEqual(4, tree.Count);
+        Assert.IsTrue(IC.eq(tree, 0, 1, 8, 9));
+        tree.RemoveInterval(0, 4);
+        Assert.IsTrue(tree.Check());
+        Assert.AreEqual(0, tree.Count);
+        Assert.IsTrue(IC.eq(tree));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void RemoveRangeBad1()
+      {
+        tree.RemoveInterval(-3, 8);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void RemoveRangeBad2()
+      {
+        tree.RemoveInterval(3, -8);
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void RemoveRangeBad3()
+      {
+        tree.RemoveInterval(3, 9);
+      }
+
+
+      [Test]
+      public void GetRange()
+      {
+        Assert.IsTrue(IC.eq(tree[3, 3]));
+        Assert.IsTrue(IC.eq(tree[3, 4], 3));
+        Assert.IsTrue(IC.eq(tree[3, 5], 3, 4));
+        Assert.IsTrue(IC.eq(tree[3, 6], 3, 4, 4));
+        Assert.IsTrue(IC.eq(tree[3, 7], 3, 4, 4, 5));
+        Assert.IsTrue(IC.eq(tree[4, 4]));
+        Assert.IsTrue(IC.eq(tree[4, 5], 4));
+        Assert.IsTrue(IC.eq(tree[4, 6], 4, 4));
+        Assert.IsTrue(IC.eq(tree[4, 7], 4, 4, 5));
+        Assert.IsTrue(IC.eq(tree[4, 8], 4, 4, 5, 6));
+        Assert.IsTrue(IC.eq(tree[5, 5]));
+        Assert.IsTrue(IC.eq(tree[5, 6], 4));
+        Assert.IsTrue(IC.eq(tree[5, 7], 4, 5));
+        Assert.IsTrue(IC.eq(tree[5, 8], 4, 5, 6));
+        Assert.IsTrue(IC.eq(tree[5, 9], 4, 5, 6, 7));
+        Assert.IsTrue(IC.eq(tree[5, 11], 4, 5, 6, 7, 8, 9));
+      }
+
+
+      [Test]
+      public void GetRangeBackwards()
+      {
+        Assert.IsTrue(IC.eq(tree[3, 3].Backwards()));
+        Assert.IsTrue(IC.eq(tree[3, 4].Backwards(), 3));
+        Assert.IsTrue(IC.eq(tree[3, 5].Backwards(), 4, 3));
+        Assert.IsTrue(IC.eq(tree[3, 6].Backwards(), 4, 4, 3));
+        Assert.IsTrue(IC.eq(tree[3, 7].Backwards(), 5, 4, 4, 3));
+        Assert.IsTrue(IC.eq(tree[4, 4].Backwards()));
+        Assert.IsTrue(IC.eq(tree[4, 5].Backwards(), 4));
+        Assert.IsTrue(IC.eq(tree[4, 6].Backwards(), 4, 4));
+        Assert.IsTrue(IC.eq(tree[4, 7].Backwards(), 5, 4, 4));
+        Assert.IsTrue(IC.eq(tree[4, 8].Backwards(), 6, 5, 4, 4));
+        Assert.IsTrue(IC.eq(tree[5, 5].Backwards()));
+        Assert.IsTrue(IC.eq(tree[5, 6].Backwards(), 4));
+        Assert.IsTrue(IC.eq(tree[5, 7].Backwards(), 5, 4));
+        Assert.IsTrue(IC.eq(tree[5, 8].Backwards(), 6, 5, 4));
+        Assert.IsTrue(IC.eq(tree[5, 9].Backwards(), 7, 6, 5, 4));
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void GetRangeBad1()
+      {
+        object foo = tree[-3, 0];
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void GetRangeBad2()
+      {
+        object foo = tree[3, 2];
+      }
+
+
+      [Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void GetRangeBad3()
+      {
+        object foo = tree[3, 12];
+      }
+
+
+      [TearDown]
+      public void Dispose() { tree = null; tree2 = null; }
+    }
+  }
+
+
+  namespace Hashing
+  {
+    [TestFixture]
+    public class ISequenced
+    {
+      private ISequenced<int> dit, dat, dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new TreeBag<int>(Comparer<int>.Default, EqualityComparer<int>.Default);
+        dat = new TreeBag<int>(Comparer<int>.Default, EqualityComparer<int>.Default);
+        dut = new TreeBag<int>(new RevIC(), EqualityComparer<int>.Default);
+      }
+
+
+      [Test]
+      public void EmptyEmpty()
+      {
+        Assert.IsTrue(dit.SequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void EmptyNonEmpty()
+      {
+        dit.Add(3);
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsFalse(dat.SequencedEquals(dit));
+      }
+
+      [Test]
+      public void HashVal()
+      {
+        Assert.AreEqual(CHC.sequencedhashcode(), dit.GetSequencedHashCode());
+        dit.Add(3);
+        Assert.AreEqual(CHC.sequencedhashcode(3), dit.GetSequencedHashCode());
+        dit.Add(7);
+        Assert.AreEqual(CHC.sequencedhashcode(3, 7), dit.GetSequencedHashCode());
+        Assert.AreEqual(CHC.sequencedhashcode(), dut.GetSequencedHashCode());
+        dut.Add(3);
+        Assert.AreEqual(CHC.sequencedhashcode(3), dut.GetSequencedHashCode());
+        dut.Add(7);
+        Assert.AreEqual(CHC.sequencedhashcode(7, 3), dut.GetSequencedHashCode());
+      }
+
+
+      [Test]
+      public void Normal()
+      {
+        dit.Add(3);
+        dit.Add(7);
+        dat.Add(3);
+        Assert.IsFalse(dit.SequencedEquals(dat));
+        Assert.IsFalse(dat.SequencedEquals(dit));
+        dat.Add(7);
+        Assert.IsTrue(dit.SequencedEquals(dat));
+        Assert.IsTrue(dat.SequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void WrongOrder()
+      {
+        dit.Add(3);
+        dut.Add(3);
+        Assert.IsTrue(dit.SequencedEquals(dut));
+        Assert.IsTrue(dut.SequencedEquals(dit));
+        dit.Add(7);
+        dut.Add(7);
+        Assert.IsFalse(dit.SequencedEquals(dut));
+        Assert.IsFalse(dut.SequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void Reflexive()
+      {
+        Assert.IsTrue(dit.SequencedEquals(dit));
+        dit.Add(3);
+        Assert.IsTrue(dit.SequencedEquals(dit));
+        dit.Add(7);
+        Assert.IsTrue(dit.SequencedEquals(dit));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+        dat = null;
+        dut = null;
+      }
+    }
+
+
+
+    [TestFixture]
+    public class IEditableCollection
+    {
+      private ICollection<int> dit, dat, dut;
+
+
+      [SetUp]
+      public void Init()
+      {
+        dit = new TreeBag<int>(Comparer<int>.Default, EqualityComparer<int>.Default);
+        dat = new TreeBag<int>(Comparer<int>.Default, EqualityComparer<int>.Default);
+        dut = new TreeBag<int>(new RevIC(), EqualityComparer<int>.Default);
+      }
+
+
+      [Test]
+      public void EmptyEmpty()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+      }
+
+
+      [Test]
+      public void EmptyNonEmpty()
+      {
+        dit.Add(3);
+        Assert.IsFalse(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dat.UnsequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void HashVal()
+      {
+        Assert.AreEqual(CHC.unsequencedhashcode(), dit.GetUnsequencedHashCode());
+        dit.Add(3);
+        Assert.AreEqual(CHC.unsequencedhashcode(3), dit.GetUnsequencedHashCode());
+        dit.Add(7);
+        Assert.AreEqual(CHC.unsequencedhashcode(3, 7), dit.GetUnsequencedHashCode());
+        Assert.AreEqual(CHC.unsequencedhashcode(), dut.GetUnsequencedHashCode());
+        dut.Add(3);
+        Assert.AreEqual(CHC.unsequencedhashcode(3), dut.GetUnsequencedHashCode());
+        dut.Add(7);
+        Assert.AreEqual(CHC.unsequencedhashcode(7, 3), dut.GetUnsequencedHashCode());
+      }
+
+
+      [Test]
+      public void Normal()
+      {
+        dit.Add(3);
+        dit.Add(7);
+        dat.Add(3);
+        Assert.IsFalse(dit.UnsequencedEquals(dat));
+        Assert.IsFalse(dat.UnsequencedEquals(dit));
+        dat.Add(7);
+        Assert.IsTrue(dit.UnsequencedEquals(dat));
+        Assert.IsTrue(dat.UnsequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void WrongOrder()
+      {
+        dit.Add(3);
+        dut.Add(3);
+        Assert.IsTrue(dit.UnsequencedEquals(dut));
+        Assert.IsTrue(dut.UnsequencedEquals(dit));
+        dit.Add(7);
+        dut.Add(7);
+        Assert.IsTrue(dit.UnsequencedEquals(dut));
+        Assert.IsTrue(dut.UnsequencedEquals(dit));
+      }
+
+
+      [Test]
+      public void Reflexive()
+      {
+        Assert.IsTrue(dit.UnsequencedEquals(dit));
+        dit.Add(3);
+        Assert.IsTrue(dit.UnsequencedEquals(dit));
+        dit.Add(7);
+        Assert.IsTrue(dit.UnsequencedEquals(dit));
+      }
+
+
+      [TearDown]
+      public void Dispose()
+      {
+        dit = null;
+        dat = null;
+        dut = null;
+      }
+    }
+  }
+
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/trees/Dictionary.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/trees/Dictionary.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/trees/Dictionary.cs	(revision 3)
@@ -0,0 +1,527 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG=System.Collections.Generic;
+
+
+namespace C5UnitTests.trees.RBDictionary
+{
+  using DictionaryIntToInt = TreeDictionary<int, int>;
+
+  static class Factory
+  {
+    public static IDictionary<K,V> New<K,V>() { return new TreeDictionary<K,V>(); }
+  }
+
+  [TestFixture]
+  public class GenericTesters
+  {
+    [Test]
+    public void TestSerialize()
+    {
+      C5UnitTests.Templates.Extensible.Serialization.DTester<DictionaryIntToInt>();
+    }
+  }
+
+
+  [TestFixture]
+  public class Formatting
+  {
+    IDictionary<int,int> coll;
+    IFormatProvider rad16;
+    [SetUp]
+    public void Init() { coll = Factory.New<int,int>(); rad16 = new RadixFormatProvider(16); }
+    [TearDown]
+    public void Dispose() { coll = null; rad16 = null; }
+    [Test]
+    public void Format()
+    {
+      Assert.AreEqual("[  ]", coll.ToString());
+      coll.Add(23, 67); coll.Add(45, 89);
+      Assert.AreEqual("[ 23 => 67, 45 => 89 ]", coll.ToString());
+      Assert.AreEqual("[ 17 => 43, 2D => 59 ]", coll.ToString(null, rad16));
+      Assert.AreEqual("[ 23 => 67, ... ]", coll.ToString("L14", null));
+      Assert.AreEqual("[ 17 => 43, ... ]", coll.ToString("L14", rad16));
+    }
+  }
+
+  [TestFixture]
+  public class RBDict
+	{
+		private TreeDictionary<string,string> dict;
+
+
+		[SetUp]
+		public void Init() { dict = new TreeDictionary<string,string>(new SC()); }
+
+
+		[TearDown]
+		public void Dispose() { dict = null; }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor1()
+    {
+      new TreeDictionary<int,int>(null);
+    }
+
+    [Test]
+    public void Choose()
+    {
+      dict.Add("YES","NO");
+      Assert.AreEqual(new KeyValuePair<string,string>("YES","NO"), dict.Choose());
+    }
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void BadChoose()
+    {
+      dict.Choose();
+    }
+
+		[Test]
+		public void Pred1()
+		{
+			dict.Add("A", "1");
+			dict.Add("C", "2");
+			dict.Add("E", "3");
+			Assert.AreEqual("1", dict.Predecessor("B").Value);
+			Assert.AreEqual("1", dict.Predecessor("C").Value);
+			Assert.AreEqual("1", dict.WeakPredecessor("B").Value);
+			Assert.AreEqual("2", dict.WeakPredecessor("C").Value);
+			Assert.AreEqual("2", dict.Successor("B").Value);
+			Assert.AreEqual("3", dict.Successor("C").Value);
+			Assert.AreEqual("2", dict.WeakSuccessor("B").Value);
+			Assert.AreEqual("2", dict.WeakSuccessor("C").Value);
+    }
+
+    [Test]
+    public void Pred2()
+    {
+      dict.Add("A", "1");
+      dict.Add("C", "2");
+      dict.Add("E", "3");
+      KeyValuePair<String, String> res;
+      Assert.IsTrue(dict.TryPredecessor("B", out res));
+      Assert.AreEqual("1", res.Value);
+      Assert.IsTrue(dict.TryPredecessor("C", out res));
+      Assert.AreEqual("1", res.Value);
+      Assert.IsTrue(dict.TryWeakPredecessor("B", out res));
+      Assert.AreEqual("1", res.Value);
+      Assert.IsTrue(dict.TryWeakPredecessor("C", out res));
+      Assert.AreEqual("2", res.Value);
+      Assert.IsTrue(dict.TrySuccessor("B", out res));
+      Assert.AreEqual("2", res.Value);
+      Assert.IsTrue(dict.TrySuccessor("C", out res));
+      Assert.AreEqual("3", res.Value);
+      Assert.IsTrue(dict.TryWeakSuccessor("B", out res));
+      Assert.AreEqual("2", res.Value);
+      Assert.IsTrue(dict.TryWeakSuccessor("C", out res));
+      Assert.AreEqual("2", res.Value);
+
+      Assert.IsFalse(dict.TryPredecessor("A", out res));
+      Assert.AreEqual(null, res.Key);
+      Assert.AreEqual(null, res.Value);
+
+      Assert.IsFalse(dict.TryWeakPredecessor("@", out res));
+      Assert.AreEqual(null, res.Key);
+      Assert.AreEqual(null, res.Value);
+
+      Assert.IsFalse(dict.TrySuccessor("E", out res));
+      Assert.AreEqual(null, res.Key);
+      Assert.AreEqual(null, res.Value);
+
+      Assert.IsFalse(dict.TryWeakSuccessor("F", out res));
+      Assert.AreEqual(null, res.Key);
+      Assert.AreEqual(null, res.Value);
+    }   
+
+		[Test]
+		public void Initial()
+		{
+			bool res;
+			Assert.IsFalse(dict.IsReadOnly);
+
+			Assert.AreEqual(dict.Count, 0, "new dict should be empty");
+			dict.Add("A", "B");
+			Assert.AreEqual(dict.Count, 1, "bad count");
+			Assert.AreEqual(dict["A"], "B", "Wrong value for dict[A]");
+			dict.Add("C", "D");
+			Assert.AreEqual(dict.Count, 2, "bad count");
+			Assert.AreEqual(dict["A"], "B", "Wrong value");
+			Assert.AreEqual(dict["C"], "D", "Wrong value");
+			res = dict.Remove("A");
+			Assert.IsTrue(res, "bad return value from Remove(A)");
+			Assert.IsTrue(dict.Check());
+			Assert.AreEqual(dict.Count, 1, "bad count");
+			Assert.AreEqual(dict["C"], "D", "Wrong value of dict[C]");
+			res = dict.Remove("Z");
+			Assert.IsFalse(res, "bad return value from Remove(Z)");
+			Assert.AreEqual(dict.Count, 1, "bad count");
+			Assert.AreEqual(dict["C"], "D", "Wrong value of dict[C] (2)");
+			dict.Clear();
+			Assert.AreEqual(dict.Count, 0, "dict should be empty");
+		}
+		[Test]
+		public void Contains()
+		{
+			dict.Add("C", "D");
+			Assert.IsTrue(dict.Contains("C"));
+			Assert.IsFalse(dict.Contains("D"));
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(DuplicateNotAllowedException), "Key being added: 'A'")]
+		public void IllegalAdd()
+		{
+			dict.Add("A", "B");
+			dict.Add("A", "B");
+		}
+
+
+		[Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void GettingNonExisting()
+		{
+			Console.WriteLine(dict["R"]);
+		}
+
+
+		[Test]
+		public void Setter()
+		{
+			dict["R"] = "UYGUY";
+			Assert.AreEqual(dict["R"], "UYGUY");
+			dict["R"] = "UIII";
+			Assert.AreEqual(dict["R"], "UIII");
+			dict["S"] = "VVV";
+			Assert.AreEqual(dict["R"], "UIII");
+			Assert.AreEqual(dict["S"], "VVV");
+			//dict.dump();
+		}
+	}
+
+  [TestFixture]
+  public class GuardedSortedDictionaryTest
+  {
+    private GuardedSortedDictionary<string, string> dict;
+
+    [SetUp]
+    public void Init() { 
+      ISortedDictionary<string,string> dict = new TreeDictionary<string, string>(new SC());
+      dict.Add("A", "1");
+      dict.Add("C", "2");
+      dict.Add("E", "3");
+      this.dict = new GuardedSortedDictionary<string, string>(dict);
+    }
+
+    [TearDown]
+    public void Dispose() { dict = null; }
+
+    [Test]
+    public void Pred1()
+    {
+      Assert.AreEqual("1", dict.Predecessor("B").Value);
+      Assert.AreEqual("1", dict.Predecessor("C").Value);
+      Assert.AreEqual("1", dict.WeakPredecessor("B").Value);
+      Assert.AreEqual("2", dict.WeakPredecessor("C").Value);
+      Assert.AreEqual("2", dict.Successor("B").Value);
+      Assert.AreEqual("3", dict.Successor("C").Value);
+      Assert.AreEqual("2", dict.WeakSuccessor("B").Value);
+      Assert.AreEqual("2", dict.WeakSuccessor("C").Value);
+    }
+
+    [Test]
+    public void Pred2()
+    {
+      KeyValuePair<String, String> res;
+      Assert.IsTrue(dict.TryPredecessor("B", out res));
+      Assert.AreEqual("1", res.Value);
+      Assert.IsTrue(dict.TryPredecessor("C", out res));
+      Assert.AreEqual("1", res.Value);
+      Assert.IsTrue(dict.TryWeakPredecessor("B", out res));
+      Assert.AreEqual("1", res.Value);
+      Assert.IsTrue(dict.TryWeakPredecessor("C", out res));
+      Assert.AreEqual("2", res.Value);
+      Assert.IsTrue(dict.TrySuccessor("B", out res));
+      Assert.AreEqual("2", res.Value);
+      Assert.IsTrue(dict.TrySuccessor("C", out res));
+      Assert.AreEqual("3", res.Value);
+      Assert.IsTrue(dict.TryWeakSuccessor("B", out res));
+      Assert.AreEqual("2", res.Value);
+      Assert.IsTrue(dict.TryWeakSuccessor("C", out res));
+      Assert.AreEqual("2", res.Value);
+
+      Assert.IsFalse(dict.TryPredecessor("A", out res));
+      Assert.AreEqual(null, res.Key);
+      Assert.AreEqual(null, res.Value);
+
+      Assert.IsFalse(dict.TryWeakPredecessor("@", out res));
+      Assert.AreEqual(null, res.Key);
+      Assert.AreEqual(null, res.Value);
+
+      Assert.IsFalse(dict.TrySuccessor("E", out res));
+      Assert.AreEqual(null, res.Key);
+      Assert.AreEqual(null, res.Value);
+
+      Assert.IsFalse(dict.TryWeakSuccessor("F", out res));
+      Assert.AreEqual(null, res.Key);
+      Assert.AreEqual(null, res.Value);
+    }
+
+    [Test]
+    public void Initial()
+    {
+      Assert.IsTrue(dict.IsReadOnly);
+
+      Assert.AreEqual(3, dict.Count);
+      Assert.AreEqual("1", dict["A"]);
+    }
+
+    [Test]
+    public void Contains()
+    {
+      Assert.IsTrue(dict.Contains("A"));
+      Assert.IsFalse(dict.Contains("1"));
+    }
+
+    [Test]
+    [ExpectedException(typeof(ReadOnlyCollectionException))]
+    public void IllegalAdd()
+    {
+      dict.Add("Q", "7");
+    }
+
+    [Test]
+    [ExpectedException(typeof(ReadOnlyCollectionException))]
+    public void IllegalClear()
+    {
+      dict.Clear();
+    }
+    [Test]
+
+    [ExpectedException(typeof(ReadOnlyCollectionException))]
+    public void IllegalSet()
+    {
+      dict["A"] = "8";
+    }
+
+    [ExpectedException(typeof(ReadOnlyCollectionException))]
+    public void IllegalRemove()
+    {
+      dict.Remove("A");
+    }
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void GettingNonExisting()
+    {
+      Console.WriteLine(dict["R"]);
+    }
+  }
+
+	[TestFixture]
+	public class Enumerators
+	{
+		private TreeDictionary<string,string> dict;
+
+		private SCG.IEnumerator<KeyValuePair<string,string>> dictenum;
+
+
+		[SetUp]
+		public void Init()
+		{
+			dict = new TreeDictionary<string,string>(new SC());
+			dict["S"] = "A";
+			dict["T"] = "B";
+			dict["R"] = "C";
+			dictenum = dict.GetEnumerator();
+		}
+
+
+		[TearDown]
+		public void Dispose()
+		{
+			dictenum = null;
+			dict = null;
+		}
+
+		[Test]
+		public void KeysEnumerator()
+		{
+			SCG.IEnumerator<string> keys = dict.Keys.GetEnumerator();
+			Assert.AreEqual(3, dict.Keys.Count);
+			Assert.IsTrue(keys.MoveNext());
+			Assert.AreEqual("R",keys.Current);
+			Assert.IsTrue(keys.MoveNext());
+			Assert.AreEqual("S",keys.Current);
+			Assert.IsTrue(keys.MoveNext());
+			Assert.AreEqual("T",keys.Current);
+			Assert.IsFalse(keys.MoveNext());
+		}
+
+    [Test]
+    public void KeysISorted()
+    {
+      ISorted<string> keys = dict.Keys;
+      Assert.IsTrue(keys.IsReadOnly);
+      Assert.AreEqual("R", keys.FindMin());
+      Assert.AreEqual("T", keys.FindMax());
+      Assert.IsTrue(keys.Contains("S"));
+      Assert.AreEqual(3, keys.Count);
+      // This doesn't hold, maybe because the dict uses a special key comparer?
+      // Assert.IsTrue(keys.SequencedEquals(new WrappedArray<string>(new string[] { "R", "S", "T" })));
+      Assert.IsTrue(keys.UniqueItems().All(delegate(String s) { return s == "R" || s == "S" || s == "T"; }));
+      Assert.IsTrue(keys.All(delegate(String s) { return s == "R" || s == "S" || s == "T"; }));
+      Assert.IsFalse(keys.Exists(delegate(String s) { return s != "R" && s != "S" && s != "T"; }));
+      String res;
+      Assert.IsTrue(keys.Find(delegate(String s) { return s == "R"; }, out res));
+      Assert.AreEqual("R", res);
+      Assert.IsFalse(keys.Find(delegate(String s) { return s == "Q"; }, out res));
+      Assert.AreEqual(null, res);
+    }
+
+    [Test]
+    public void KeysISortedPred()
+    {
+      ISorted<string> keys = dict.Keys;
+      String res;
+      Assert.IsTrue(keys.TryPredecessor("S", out res));
+      Assert.AreEqual("R", res);
+      Assert.IsTrue(keys.TryWeakPredecessor("R", out res));
+      Assert.AreEqual("R", res);
+      Assert.IsTrue(keys.TrySuccessor("S", out res));
+      Assert.AreEqual("T", res);
+      Assert.IsTrue(keys.TryWeakSuccessor("T", out res));
+      Assert.AreEqual("T", res);
+      Assert.IsFalse(keys.TryPredecessor("R", out res));
+      Assert.AreEqual(null, res);
+      Assert.IsFalse(keys.TryWeakPredecessor("P", out res));
+      Assert.AreEqual(null, res);
+      Assert.IsFalse(keys.TrySuccessor("T", out res));
+      Assert.AreEqual(null, res);
+      Assert.IsFalse(keys.TryWeakSuccessor("U", out res));
+      Assert.AreEqual(null, res);
+
+      Assert.AreEqual("R", keys.Predecessor("S"));
+      Assert.AreEqual("R", keys.WeakPredecessor("R"));
+      Assert.AreEqual("T", keys.Successor("S"));
+      Assert.AreEqual("T", keys.WeakSuccessor("T"));
+    }
+ 
+		[Test]
+		public void ValuesEnumerator()
+		{
+			SCG.IEnumerator<string> values = dict.Values.GetEnumerator();
+			Assert.AreEqual(3, dict.Values.Count);
+			Assert.IsTrue(values.MoveNext());
+			Assert.AreEqual("C",values.Current);
+			Assert.IsTrue(values.MoveNext());
+			Assert.AreEqual("A",values.Current);
+			Assert.IsTrue(values.MoveNext());
+			Assert.AreEqual("B",values.Current);
+			Assert.IsFalse(values.MoveNext());
+		}
+
+    [Test]
+    public void Fun()
+    {
+      Assert.AreEqual("B", dict.Fun("T"));
+    }
+
+
+		[Test]
+		public void NormalUse()
+		{
+			Assert.IsTrue(dictenum.MoveNext());
+			Assert.AreEqual(dictenum.Current, new KeyValuePair<string,string>("R", "C"));
+			Assert.IsTrue(dictenum.MoveNext());
+			Assert.AreEqual(dictenum.Current, new KeyValuePair<string,string>("S", "A"));
+			Assert.IsTrue(dictenum.MoveNext());
+			Assert.AreEqual(dictenum.Current, new KeyValuePair<string,string>("T", "B"));
+			Assert.IsFalse(dictenum.MoveNext());
+		}
+	}
+
+
+	namespace PathCopyPersistence
+	{
+		[TestFixture]
+		public class Simple
+		{
+			private TreeDictionary<string,string> dict;
+
+			private TreeDictionary<string,string> snap;
+
+
+			[SetUp]
+			public void Init()
+			{
+				dict = new TreeDictionary<string,string>(new SC());
+				dict["S"] = "A";
+				dict["T"] = "B";
+				dict["R"] = "C";
+				dict["V"] = "G";
+				snap = (TreeDictionary<string,string>)dict.Snapshot();
+			}
+
+
+			[Test]
+			public void Test()
+			{
+				dict["SS"] = "D";
+				Assert.AreEqual(5, dict.Count);
+				Assert.AreEqual(4, snap.Count);
+				dict["T"] = "bb";
+				Assert.AreEqual(5, dict.Count);
+				Assert.AreEqual(4, snap.Count);
+				Assert.AreEqual("B", snap["T"]);
+				Assert.AreEqual("bb", dict["T"]);
+				Assert.IsFalse(dict.IsReadOnly);
+				Assert.IsTrue(snap.IsReadOnly);
+				//Finally, update of root node:
+				TreeDictionary<string,string> snap2 = (TreeDictionary<string,string>)dict.Snapshot();
+				dict["S"] = "abe";
+				Assert.AreEqual("abe", dict["S"]);
+			}
+
+
+			[Test]
+			[ExpectedException(typeof(ReadOnlyCollectionException))]
+			public void UpdateSnap()
+			{
+				snap["Y"] = "J";
+			}
+
+
+			[TearDown]
+			public void Dispose()
+			{
+				dict = null;
+				snap = null;
+			}
+		}
+	}
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/trees/RedBlackTreeSetTests.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/trees/RedBlackTreeSetTests.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/trees/RedBlackTreeSetTests.cs	(revision 3)
@@ -0,0 +1,3031 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+namespace C5UnitTests.trees.TreeSet
+{
+  using CollectionOfInt = TreeSet<int>;
+
+  [TestFixture]
+  public class GenericTesters
+  {
+    [Test]
+    public void TestEvents()
+    {
+      Fun<CollectionOfInt> factory = delegate() { return new CollectionOfInt(TenEqualityComparer.Default); };
+      new C5UnitTests.Templates.Events.SortedIndexedTester<CollectionOfInt>().Test(factory);
+    }
+
+    [Test]
+    public void Extensible()
+    {
+      C5UnitTests.Templates.Extensible.Clone.Tester<CollectionOfInt>();
+      C5UnitTests.Templates.Extensible.Serialization.Tester<CollectionOfInt>();
+    }
+  }
+
+  static class Factory
+  {
+    public static ICollection<T> New<T>() { return new TreeSet<T>(); }
+  }
+
+
+  [TestFixture]
+  public class Formatting
+  {
+    ICollection<int> coll;
+    IFormatProvider rad16;
+    [SetUp]
+    public void Init() { coll = Factory.New<int>(); rad16 = new RadixFormatProvider(16); }
+    [TearDown]
+    public void Dispose() { coll = null; rad16 = null; }
+    [Test]
+    public void Format()
+    {
+      Assert.AreEqual("{  }", coll.ToString());
+      coll.AddAll<int>(new int[] { -4, 28, 129, 65530 });
+      Assert.AreEqual("{ -4, 28, 129, 65530 }", coll.ToString());
+      Assert.AreEqual("{ -4, 1C, 81, FFFA }", coll.ToString(null, rad16));
+      Assert.AreEqual("{ -4, 28, 129... }", coll.ToString("L14", null));
+      Assert.AreEqual("{ -4, 1C, 81... }", coll.ToString("L14", rad16));
+    }
+  }
+
+  [TestFixture]
+  public class Combined
+	{
+		private IIndexedSorted<KeyValuePair<int,int>> lst;
+
+
+		[SetUp]
+		public void Init()
+		{
+			lst = new TreeSet<KeyValuePair<int,int>>(new KeyValuePairComparer<int,int>(new IC()));
+			for (int i = 0; i < 10; i++)
+				lst.Add(new KeyValuePair<int,int>(i, i + 30));
+		}
+
+
+		[TearDown]
+		public void Dispose() { lst = null; }
+
+
+		[Test]
+		public void Find()
+		{
+			KeyValuePair<int,int> p = new KeyValuePair<int,int>(3, 78);
+
+			Assert.IsTrue(lst.Find(ref p));
+			Assert.AreEqual(3, p.Key);
+			Assert.AreEqual(33, p.Value);
+			p = new KeyValuePair<int,int>(13, 78);
+			Assert.IsFalse(lst.Find(ref p));
+		}
+
+
+		[Test]
+		public void FindOrAdd()
+		{
+			KeyValuePair<int,int> p = new KeyValuePair<int,int>(3, 78);
+
+			Assert.IsTrue(lst.FindOrAdd(ref p));
+			Assert.AreEqual(3, p.Key);
+			Assert.AreEqual(33, p.Value);
+			p = new KeyValuePair<int,int>(13, 79);
+			Assert.IsFalse(lst.FindOrAdd(ref p));
+			Assert.AreEqual(13, lst[10].Key);
+			Assert.AreEqual(79, lst[10].Value);
+		}
+
+
+		[Test]
+		public void Update()
+		{
+			KeyValuePair<int,int> p = new KeyValuePair<int,int>(3, 78);
+
+			Assert.IsTrue(lst.Update(p));
+			Assert.AreEqual(3, lst[3].Key);
+			Assert.AreEqual(78, lst[3].Value);
+			p = new KeyValuePair<int,int>(13, 78);
+			Assert.IsFalse(lst.Update(p));
+		}
+
+
+		[Test]
+		public void UpdateOrAdd1()
+		{
+			KeyValuePair<int,int> p = new KeyValuePair<int,int>(3, 78);
+
+			Assert.IsTrue(lst.UpdateOrAdd(p));
+			Assert.AreEqual(3, lst[3].Key);
+			Assert.AreEqual(78, lst[3].Value);
+			p = new KeyValuePair<int,int>(13, 79);
+			Assert.IsFalse(lst.UpdateOrAdd(p));
+			Assert.AreEqual(13, lst[10].Key);
+			Assert.AreEqual(79, lst[10].Value);
+		}
+
+        [Test]
+        public void UpdateOrAdd2()
+        {
+            ICollection<String> coll = new TreeSet<String>();
+            // s1 and s2 are distinct objects but contain the same text:
+            String old, s1 = "abc", s2 = ("def" + s1).Substring(3);
+            Assert.IsFalse(coll.UpdateOrAdd(s1, out old));
+            Assert.AreEqual(null, old);
+            Assert.IsTrue(coll.UpdateOrAdd(s2, out old));
+            Assert.IsTrue(Object.ReferenceEquals(s1, old));
+            Assert.IsFalse(Object.ReferenceEquals(s2, old));
+        }
+
+		[Test]
+		public void RemoveWithReturn()
+		{
+			KeyValuePair<int,int> p = new KeyValuePair<int,int>(3, 78);
+
+            Assert.IsTrue(lst.Remove(p, out p));
+            Assert.AreEqual(3, p.Key);
+			Assert.AreEqual(33, p.Value);
+			Assert.AreEqual(4, lst[3].Key);
+			Assert.AreEqual(34, lst[3].Value);
+			p = new KeyValuePair<int,int>(13, 78);
+            Assert.IsFalse(lst.Remove(p, out p));
+        }
+	}
+
+
+	[TestFixture]
+	public class Ranges
+	{
+		private TreeSet<int> tree;
+
+		private SCG.IComparer<int> c;
+
+
+		[SetUp]
+		public void Init()
+		{
+			c = new IC();
+			tree = new TreeSet<int>(c);
+			for (int i = 1; i <= 10; i++)
+			{
+				tree.Add(i * 2);
+			}
+		}
+
+
+		[Test]
+		public void Enumerator()
+		{
+			SCG.IEnumerator<int> e = tree.RangeFromTo(5, 17).GetEnumerator();
+			int i = 3;
+
+			while (e.MoveNext())
+			{
+				Assert.AreEqual(2 * i++, e.Current);
+			}
+
+			Assert.AreEqual(9, i);
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(InvalidOperationException))]
+		public void Enumerator2()
+		{
+			SCG.IEnumerator<int> e = tree.RangeFromTo(5, 17).GetEnumerator();
+			int i = e.Current;
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(InvalidOperationException))]
+		public void Enumerator3()
+		{
+			SCG.IEnumerator<int> e = tree.RangeFromTo(5, 17).GetEnumerator();
+
+			while (e.MoveNext());
+
+			int i = e.Current;
+		}
+
+
+		[Test]
+		public void Remove()
+		{
+			int[] all = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
+
+			tree.RemoveRangeFrom(18);
+			Assert.IsTrue(IC.eq(tree, new int[] { 2, 4, 6, 8, 10, 12, 14, 16 }));
+			tree.RemoveRangeFrom(28);
+			Assert.IsTrue(IC.eq(tree, new int[] { 2, 4, 6, 8, 10, 12, 14, 16 }));
+			tree.RemoveRangeFrom(2);
+			Assert.IsTrue(IC.eq(tree));
+			foreach (int i in all) tree.Add(i);
+
+			tree.RemoveRangeTo(10);
+			Assert.IsTrue(IC.eq(tree, new int[] { 10, 12, 14, 16, 18, 20 }));
+			tree.RemoveRangeTo(2);
+			Assert.IsTrue(IC.eq(tree, new int[] { 10, 12, 14, 16, 18, 20 }));
+			tree.RemoveRangeTo(21);
+			Assert.IsTrue(IC.eq(tree));
+			foreach (int i in all) tree.Add(i);
+
+			tree.RemoveRangeFromTo(4, 8);
+			Assert.IsTrue(IC.eq(tree, 2, 8, 10, 12, 14, 16, 18, 20));
+			tree.RemoveRangeFromTo(14, 28);
+			Assert.IsTrue(IC.eq(tree, 2, 8, 10, 12));
+			tree.RemoveRangeFromTo(0, 9);
+			Assert.IsTrue(IC.eq(tree, 10, 12));
+			tree.RemoveRangeFromTo(0, 81);
+			Assert.IsTrue(IC.eq(tree));
+		}
+
+		[Test]
+		public void Normal()
+		{
+			int[] all = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
+
+			Assert.IsTrue(IC.eq(tree, all));
+			Assert.IsTrue(IC.eq(tree.RangeAll(), all));
+			Assert.AreEqual(10, tree.RangeAll().Count);
+			Assert.IsTrue(IC.eq(tree.RangeFrom(11), new int[] { 12, 14, 16, 18, 20 }));
+			Assert.AreEqual(5, tree.RangeFrom(11).Count);
+			Assert.IsTrue(IC.eq(tree.RangeFrom(12), new int[] { 12, 14, 16, 18, 20 }));
+			Assert.IsTrue(IC.eq(tree.RangeFrom(2), all));
+			Assert.IsTrue(IC.eq(tree.RangeFrom(1), all));
+			Assert.IsTrue(IC.eq(tree.RangeFrom(21), new int[] { }));
+			Assert.IsTrue(IC.eq(tree.RangeFrom(20), new int[] { 20 }));
+			Assert.IsTrue(IC.eq(tree.RangeTo(8), new int[] { 2, 4, 6 }));
+			Assert.IsTrue(IC.eq(tree.RangeTo(7), new int[] { 2, 4, 6 }));
+			Assert.AreEqual(3, tree.RangeTo(7).Count);
+			Assert.IsTrue(IC.eq(tree.RangeTo(2), new int[] { }));
+			Assert.IsTrue(IC.eq(tree.RangeTo(1), new int[] {  }));
+			Assert.IsTrue(IC.eq(tree.RangeTo(3), new int[] { 2 }));
+			Assert.IsTrue(IC.eq(tree.RangeTo(20), new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18 }));
+			Assert.IsTrue(IC.eq(tree.RangeTo(21), all));
+			Assert.IsTrue(IC.eq(tree.RangeFromTo(7, 12), new int[] { 8, 10 }));
+			Assert.IsTrue(IC.eq(tree.RangeFromTo(6, 11), new int[] { 6, 8, 10 }));
+			Assert.IsTrue(IC.eq(tree.RangeFromTo(1, 12), new int[] { 2, 4, 6, 8, 10 }));
+			Assert.AreEqual(5, tree.RangeFromTo(1, 12).Count);
+			Assert.IsTrue(IC.eq(tree.RangeFromTo(2, 12), new int[] { 2, 4, 6, 8, 10 }));
+			Assert.IsTrue(IC.eq(tree.RangeFromTo(6, 21), new int[] { 6, 8, 10, 12, 14, 16, 18, 20 }));
+			Assert.IsTrue(IC.eq(tree.RangeFromTo(6, 20), new int[] { 6, 8, 10, 12, 14, 16, 18 }));
+		}
+
+
+		[Test]
+		public void Backwards()
+		{
+			int[] all = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
+			int[] lla = new int[] { 20, 18, 16, 14, 12, 10, 8, 6, 4, 2 };
+
+			Assert.IsTrue(IC.eq(tree, all));
+			Assert.IsTrue(IC.eq(tree.RangeAll().Backwards(), lla));
+			Assert.IsTrue(IC.eq(tree.RangeFrom(11).Backwards(), new int[] { 20, 18, 16, 14, 12 }));
+            Assert.IsTrue(IC.eq(tree.RangeFrom(12).Backwards(), new int[] { 20, 18, 16, 14, 12 }));
+			Assert.IsTrue(IC.eq(tree.RangeFrom(2).Backwards(), lla));
+			Assert.IsTrue(IC.eq(tree.RangeFrom(1).Backwards(), lla));
+			Assert.IsTrue(IC.eq(tree.RangeFrom(21).Backwards(), new int[] { }));
+			Assert.IsTrue(IC.eq(tree.RangeFrom(20).Backwards(), new int[] { 20 }));
+			Assert.IsTrue(IC.eq(tree.RangeTo(8).Backwards(), new int[] { 6, 4, 2 }));
+			Assert.IsTrue(IC.eq(tree.RangeTo(7).Backwards(), new int[] { 6, 4, 2 }));
+			Assert.IsTrue(IC.eq(tree.RangeTo(2).Backwards(), new int[] { }));
+			Assert.IsTrue(IC.eq(tree.RangeTo(1).Backwards(), new int[] {  }));
+			Assert.IsTrue(IC.eq(tree.RangeTo(3).Backwards(), new int[] { 2 }));
+			Assert.IsTrue(IC.eq(tree.RangeTo(20).Backwards(), new int[] { 18, 16, 14, 12, 10, 8, 6, 4, 2}));
+			Assert.IsTrue(IC.eq(tree.RangeTo(21).Backwards(), lla));
+			Assert.IsTrue(IC.eq(tree.RangeFromTo(7, 12).Backwards(), new int[] { 10, 8 }));
+			Assert.IsTrue(IC.eq(tree.RangeFromTo(6, 11).Backwards(), new int[] { 10, 8, 6 }));
+			Assert.IsTrue(IC.eq(tree.RangeFromTo(1, 12).Backwards(), new int[] { 10, 8, 6, 4, 2 }));
+			Assert.IsTrue(IC.eq(tree.RangeFromTo(2, 12).Backwards(), new int[] { 10, 8, 6, 4, 2 }));
+			Assert.IsTrue(IC.eq(tree.RangeFromTo(6, 21).Backwards(), new int[] { 20, 18, 16, 14, 12, 10, 8, 6 }));
+			Assert.IsTrue(IC.eq(tree.RangeFromTo(6, 20).Backwards(), new int[] { 18, 16, 14, 12, 10, 8, 6 }));
+		}
+
+		[Test]
+		public void Direction()
+		{
+			Assert.AreEqual(EnumerationDirection.Forwards, tree.Direction);
+			Assert.AreEqual(EnumerationDirection.Forwards, tree.RangeFrom(20).Direction);
+			Assert.AreEqual(EnumerationDirection.Forwards, tree.RangeTo(7).Direction);
+			Assert.AreEqual(EnumerationDirection.Forwards, tree.RangeFromTo(1, 12).Direction);
+			Assert.AreEqual(EnumerationDirection.Forwards, tree.RangeAll().Direction);
+			Assert.AreEqual(EnumerationDirection.Backwards, tree.Backwards().Direction);
+			Assert.AreEqual(EnumerationDirection.Backwards, tree.RangeFrom(20).Backwards().Direction);
+			Assert.AreEqual(EnumerationDirection.Backwards, tree.RangeTo(7).Backwards().Direction);
+			Assert.AreEqual(EnumerationDirection.Backwards, tree.RangeFromTo(1, 12).Backwards().Direction);
+			Assert.AreEqual(EnumerationDirection.Backwards, tree.RangeAll().Backwards().Direction);
+		}
+
+
+		[TearDown]
+		public void Dispose()
+		{
+			tree = null;
+			c = null;
+		}
+	}
+
+	[TestFixture]
+	public class BagItf
+	{
+		private TreeSet<int> tree;
+
+
+		[SetUp]
+		public void Init()
+		{
+			tree = new TreeSet<int>(new IC());
+			for (int i = 10; i < 20; i++)
+			{
+				tree.Add(i);
+				tree.Add(i + 10);
+			}
+		}
+
+
+		[Test]
+		public void Both()
+		{
+			Assert.AreEqual(0, tree.ContainsCount(7));
+			Assert.AreEqual(1, tree.ContainsCount(10));
+			tree.RemoveAllCopies(10);
+			Assert.AreEqual(0, tree.ContainsCount(10));
+			tree.RemoveAllCopies(7);
+		}
+
+
+		[TearDown]
+		public void Dispose()
+		{
+			tree = null;
+		}
+	}
+
+
+	[TestFixture]
+	public class Div
+	{
+		private TreeSet<int> tree;
+
+
+		[SetUp]
+		public void Init()
+		{
+			tree = new TreeSet<int>(new IC());
+		}
+
+
+		private void loadup()
+		{
+			for (int i = 10; i < 20; i++)
+			{
+				tree.Add(i);
+				tree.Add(i + 10);
+			}
+		}
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor1()
+    {
+      new TreeSet<int>(null);
+    }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor3()
+    {
+      new TreeSet<int>(null, EqualityComparer<int>.Default);
+    }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor4()
+    {
+      new TreeSet<int>(Comparer<int>.Default, null);
+    }
+
+    [Test]
+    [ExpectedException(typeof(NullReferenceException))]
+    public void NullEqualityComparerinConstructor5()
+    {
+      new TreeSet<int>(null, null);
+    }
+
+    [Test]
+    public void Choose()
+    {
+      tree.Add(7);
+      Assert.AreEqual(7, tree.Choose());
+    }
+
+    [Test]
+    [ExpectedException(typeof(NoSuchItemException))]
+    public void BadChoose()
+    {
+      tree.Choose();
+    }
+
+
+    [Test]
+		public void NoDuplicates()
+		{
+			Assert.IsFalse(tree.AllowsDuplicates);
+			loadup();
+			Assert.IsFalse(tree.AllowsDuplicates);
+		}
+
+		[Test]
+		public void Add()
+		{
+			Assert.IsTrue(tree.Add(17));
+			Assert.IsFalse(tree.Add(17));
+			Assert.IsTrue(tree.Add(18));
+			Assert.IsFalse(tree.Add(18));
+			Assert.AreEqual(2, tree.Count);
+		}
+
+
+		[TearDown]
+		public void Dispose()
+		{
+			tree = null;
+		}
+	}
+
+
+	[TestFixture]
+	public class FindOrAdd
+	{
+		private TreeSet<KeyValuePair<int,string>> bag;
+
+
+		[SetUp]
+		public void Init()
+		{
+			bag = new TreeSet<KeyValuePair<int,string>>(new KeyValuePairComparer<int,string>(new IC()));
+		}
+
+
+		[TearDown]
+		public void Dispose()
+		{
+			bag = null;
+		}
+
+
+		[Test]
+		public void Test()
+		{
+			KeyValuePair<int,string> p = new KeyValuePair<int,string>(3, "tre");
+
+			Assert.IsFalse(bag.FindOrAdd(ref p));
+			p.Value = "drei";
+			Assert.IsTrue(bag.FindOrAdd(ref p));
+			Assert.AreEqual("tre", p.Value);
+			p.Value = "three";
+			Assert.AreEqual(1, bag.ContainsCount(p));
+			Assert.AreEqual("tre", bag[0].Value);
+		}
+	}
+
+  [TestFixture]
+  public class FindPredicate
+  {
+    private TreeSet<int> list;
+    Fun<int, bool> pred;
+
+    [SetUp]
+    public void Init()
+    {
+      list = new TreeSet<int>(TenEqualityComparer.Default);
+      pred = delegate(int i) { return i % 5 == 0; };
+    }
+
+    [TearDown]
+    public void Dispose() { list = null; }
+
+    [Test]
+    public void Find()
+    {
+      int i;
+      Assert.IsFalse(list.Find(pred, out i));
+      list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+      Assert.IsFalse(list.Find(pred, out i));
+      list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+      Assert.IsTrue(list.Find(pred, out i));
+      Assert.AreEqual(45, i);
+    }
+
+    [Test]
+    public void FindLast()
+    {
+      int i;
+      Assert.IsFalse(list.FindLast(pred, out i));
+      list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+      Assert.IsFalse(list.FindLast(pred, out i));
+      list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+      Assert.IsTrue(list.FindLast(pred, out i));
+      Assert.AreEqual(675, i);
+    }
+
+    [Test]
+    public void FindIndex()
+    {
+      Assert.IsFalse(0 <= list.FindIndex(pred));
+      list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+      Assert.IsFalse(0 <= list.FindIndex(pred));
+      list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+      Assert.AreEqual(3, list.FindIndex(pred));
+    }
+
+    [Test]
+    public void FindLastIndex()
+    {
+      Assert.IsFalse(0 <= list.FindLastIndex(pred));
+      list.AddAll<int>(new int[] { 4, 22, 67, 37 });
+      Assert.IsFalse(0 <= list.FindLastIndex(pred));
+      list.AddAll<int>(new int[] { 45, 122, 675, 137 });
+      Assert.AreEqual(7, list.FindLastIndex(pred));
+    }
+  }
+
+  [TestFixture]
+  public class UniqueItems
+  {
+    private TreeSet<int> list;
+
+    [SetUp]
+    public void Init() { list = new TreeSet<int>(); }
+
+    [TearDown]
+    public void Dispose() { list = null; }
+
+    [Test]
+    public void Test()
+    {
+      Assert.IsTrue(IC.seteq(list.UniqueItems()));
+      Assert.IsTrue(IC.seteq(list.ItemMultiplicities()));
+      list.AddAll<int>(new int[] { 7, 9, 7 });
+      Assert.IsTrue(IC.seteq(list.UniqueItems(), 7, 9));
+      Assert.IsTrue(IC.seteq(list.ItemMultiplicities(), 7, 1, 9, 1));
+    }
+  }
+
+  [TestFixture]
+  public class ArrayTest
+	{
+		private TreeSet<int> tree;
+
+		int[] a;
+
+
+		[SetUp]
+		public void Init()
+		{
+			tree = new TreeSet<int>(new IC());
+			a = new int[10];
+			for (int i = 0; i < 10; i++)
+				a[i] = 1000 + i;
+		}
+
+
+		[TearDown]
+		public void Dispose() { tree = null; }
+
+
+		private string aeq(int[] a, params int[] b)
+		{
+			if (a.Length != b.Length)
+				return "Lengths differ: " + a.Length + " != " + b.Length;
+
+			for (int i = 0; i < a.Length; i++)
+				if (a[i] != b[i])
+					return String.Format("{0}'th elements differ: {1} != {2}", i, a[i], b[i]);
+
+			return "Alles klar";
+		}
+
+
+		[Test]
+		public void ToArray()
+		{
+			Assert.AreEqual("Alles klar", aeq(tree.ToArray()));
+			tree.Add(7);
+			tree.Add(4);
+			Assert.AreEqual("Alles klar", aeq(tree.ToArray(), 4, 7));
+		}
+
+
+		[Test]
+		public void CopyTo()
+		{
+			tree.CopyTo(a, 1);
+			Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+			tree.Add(6);
+			tree.CopyTo(a, 2);
+			Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 1004, 1005, 1006, 1007, 1008, 1009));
+			tree.Add(4);
+			tree.Add(9);
+			tree.CopyTo(a, 4);
+			Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 4, 6, 9, 1007, 1008, 1009));
+			tree.Clear();
+			tree.Add(7);
+			tree.CopyTo(a, 9);
+			Assert.AreEqual("Alles klar", aeq(a, 1000, 1001, 6, 1003, 4, 6, 9, 1007, 1008, 7));
+		}
+
+
+		[Test]
+    [ExpectedException(typeof(ArgumentOutOfRangeException))]
+    public void CopyToBad()
+		{
+			tree.CopyTo(a, 11);
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(ArgumentOutOfRangeException))]
+		public void CopyToBad2()
+		{
+			tree.CopyTo(a, -1);
+		}
+
+
+		[Test]
+    [ExpectedException(typeof(ArgumentOutOfRangeException))]
+    public void CopyToTooFar()
+		{
+			tree.Add(3);
+			tree.Add(4);
+			tree.CopyTo(a, 9);
+		}
+	}
+
+
+
+
+	[TestFixture]
+	public class Remove
+	{
+		private TreeSet<int> tree;
+
+
+		[SetUp]
+		public void Init()
+		{
+			tree = new TreeSet<int>(new IC());
+			for (int i = 10; i < 20; i++)
+			{
+				tree.Add(i);
+				tree.Add(i + 10);
+			}
+		}
+
+
+		[Test]
+		public void SmallTrees()
+		{
+			tree.Clear();
+			tree.Add(7);
+			tree.Add(9);
+			Assert.IsTrue(tree.Remove(7));
+			Assert.IsTrue(tree.Check(""));
+		}
+
+
+		[Test]
+		public void ByIndex()
+		{
+			//Remove root!
+			int n = tree.Count;
+			int i = tree[10];
+
+			tree.RemoveAt(10);
+			Assert.IsTrue(tree.Check(""));
+			Assert.IsFalse(tree.Contains(i));
+			Assert.AreEqual(n - 1, tree.Count);
+
+			//Low end
+			i = tree.FindMin();
+			tree.RemoveAt(0);
+			Assert.IsTrue(tree.Check(""));
+			Assert.IsFalse(tree.Contains(i));
+			Assert.AreEqual(n - 2, tree.Count);
+
+			//high end
+			i = tree.FindMax();
+			tree.RemoveAt(tree.Count - 1);
+			Assert.IsTrue(tree.Check(""));
+			Assert.IsFalse(tree.Contains(i));
+			Assert.AreEqual(n - 3, tree.Count);
+
+			//Some leaf
+			i = 18;
+			tree.RemoveAt(7);
+			Assert.IsTrue(tree.Check(""));
+			Assert.IsFalse(tree.Contains(i));
+			Assert.AreEqual(n - 4, tree.Count);
+		}
+
+
+		[Test]
+		public void AlmostEmpty()
+		{
+			//Almost empty
+			tree.Clear();
+			tree.Add(3);
+			tree.RemoveAt(0);
+			Assert.IsTrue(tree.Check(""));
+			Assert.IsFalse(tree.Contains(3));
+			Assert.AreEqual(0, tree.Count);
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(IndexOutOfRangeException), "Index out of range for sequenced collectionvalue")]
+		public void Empty()
+		{
+			tree.Clear();
+			tree.RemoveAt(0);
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(IndexOutOfRangeException), "Index out of range for sequenced collectionvalue")]
+		public void HighIndex()
+		{
+			tree.RemoveAt(tree.Count);
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(IndexOutOfRangeException), "Index out of range for sequenced collectionvalue")]
+		public void LowIndex()
+		{
+			tree.RemoveAt(-1);
+		}
+
+
+		[Test]
+		public void Normal()
+		{
+			Assert.IsFalse(tree.Remove(-20));
+
+			//No demote case, with move_item
+			Assert.IsTrue(tree.Remove(20));
+			Assert.IsTrue(tree.Check("T1"));
+			Assert.IsFalse(tree.Remove(20));
+
+			//plain case 2
+			Assert.IsTrue(tree.Remove(14));
+			Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+
+			//case 1b
+			Assert.IsTrue(tree.Remove(25));
+			Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+
+			//case 1c
+			Assert.IsTrue(tree.Remove(29));
+			Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+
+			//1a (terminating)
+			Assert.IsTrue(tree.Remove(10));
+			Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+
+			//2+1b
+			Assert.IsTrue(tree.Remove(12));
+			Assert.IsTrue(tree.Remove(11));
+
+			//1a+1b
+			Assert.IsTrue(tree.Remove(18));
+			Assert.IsTrue(tree.Remove(13));
+			Assert.IsTrue(tree.Remove(15));
+
+			//2+1c
+			for (int i = 0; i < 10; i++)
+				tree.Add(50 - 2 * i);
+
+			Assert.IsTrue(tree.Remove(42));
+			Assert.IsTrue(tree.Remove(38));
+			Assert.IsTrue(tree.Remove(28));
+			Assert.IsTrue(tree.Remove(40));
+
+			//
+			Assert.IsTrue(tree.Remove(16));
+			Assert.IsTrue(tree.Remove(23));
+			Assert.IsTrue(tree.Remove(17));
+			Assert.IsTrue(tree.Remove(19));
+			Assert.IsTrue(tree.Remove(50));
+			Assert.IsTrue(tree.Remove(26));
+			Assert.IsTrue(tree.Remove(21));
+			Assert.IsTrue(tree.Remove(22));
+			Assert.IsTrue(tree.Remove(24));
+			for (int i = 0; i < 48; i++)
+				tree.Remove(i);
+
+			//Almost empty tree:
+			Assert.IsFalse(tree.Remove(26));
+			Assert.IsTrue(tree.Remove(48));
+			Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+
+			//Empty tree:
+			Assert.IsFalse(tree.Remove(26));
+			Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+		}
+
+
+		[TearDown]
+		public void Dispose()
+		{
+			tree = null;
+		}
+	}
+
+
+
+	[TestFixture]
+	public class PredecessorStructure
+	{
+		private TreeSet<int> tree;
+
+
+		[SetUp]
+		public void Init()
+		{
+			tree = new TreeSet<int>(new IC());
+		}
+
+
+		private void loadup()
+		{
+			for (int i = 0; i < 20; i++)
+				tree.Add(2 * i);
+		}
+
+        [Test]
+        public void FindPredecessor()
+        {
+            loadup();
+            int res;
+            Assert.IsTrue(tree.TryPredecessor(7, out res) && res == 6);
+            Assert.IsTrue(tree.TryPredecessor(8, out res) && res == 6);
+
+            //The bottom
+            Assert.IsTrue(tree.TryPredecessor(1, out res) && res == 0);
+
+            //The top
+            Assert.IsTrue(tree.TryPredecessor(39, out res) && res == 38);
+        }
+
+        [Test]
+        public void FindPredecessorTooLow1()
+        {
+            int res;
+            Assert.IsFalse(tree.TryPredecessor(-2, out res));
+            Assert.AreEqual(0, res);
+            Assert.IsFalse(tree.TryPredecessor(0, out res));
+            Assert.AreEqual(0, res);
+        }
+
+        [Test]
+        public void FindWeakPredecessor()
+        {
+            loadup();
+            int res;
+            Assert.IsTrue(tree.TryWeakPredecessor(7, out res) && res == 6);
+            Assert.IsTrue(tree.TryWeakPredecessor(8, out res) && res == 8);
+
+            //The bottom
+            Assert.IsTrue(tree.TryWeakPredecessor(1, out res) && res == 0);
+            Assert.IsTrue(tree.TryWeakPredecessor(0, out res) && res == 0);
+
+            //The top
+            Assert.IsTrue(tree.TryWeakPredecessor(39, out res) && res == 38);
+            Assert.IsTrue(tree.TryWeakPredecessor(38, out res) && res == 38);
+        }
+
+        [Test]
+        public void FindWeakPredecessorTooLow1()
+        {
+            int res;
+            Assert.IsFalse(tree.TryWeakPredecessor(-1, out res));
+            Assert.AreEqual(0, res);
+        }
+
+        [Test]
+        public void FindSuccessor()
+        {
+            loadup();
+            int res;
+            Assert.IsTrue(tree.TrySuccessor(7, out res) && res == 8);
+            Assert.IsTrue(tree.TrySuccessor(8, out res) && res == 10);
+
+            //The bottom
+            Assert.IsTrue(tree.TrySuccessor(0, out res) && res == 2);
+            Assert.IsTrue(tree.TrySuccessor(-1, out res) && res == 0);
+
+            //The top
+            Assert.IsTrue(tree.TrySuccessor(37, out res) && res == 38);
+        }
+
+        [Test]
+        public void FindSuccessorTooHigh()
+        {
+            int res;
+            Assert.IsFalse(tree.TrySuccessor(38, out res));
+            Assert.AreEqual(0, res);
+            Assert.IsFalse(tree.TrySuccessor(39, out res));
+            Assert.AreEqual(0, res);
+        }
+
+        [Test]
+        public void FindWeakSuccessor()
+        {
+            loadup();
+            int res;
+            Assert.IsTrue(tree.TryWeakSuccessor(6, out res) && res == 6);
+            Assert.IsTrue(tree.TryWeakSuccessor(7, out res) && res == 8);
+
+            //The bottom
+            Assert.IsTrue(tree.TryWeakSuccessor(-1, out res) && res == 0);
+            Assert.IsTrue(tree.TryWeakSuccessor(0, out res) && res == 0);
+
+            //The top
+            Assert.IsTrue(tree.TryWeakSuccessor(37, out res) && res == 38);
+            Assert.IsTrue(tree.TryWeakSuccessor(38, out res) && res == 38);
+        }
+
+        [Test]
+        public void FindWeakSuccessorTooHigh1()
+        {
+            int res;
+            Assert.IsFalse(tree.TryWeakSuccessor(39, out res));
+            Assert.AreEqual(0, res);
+        }
+
+
+		[Test]
+		public void Predecessor()
+		{
+			loadup();
+			Assert.AreEqual(6, tree.Predecessor(7));
+			Assert.AreEqual(6, tree.Predecessor(8));
+
+			//The bottom
+			Assert.AreEqual(0, tree.Predecessor(1));
+
+			//The top
+			Assert.AreEqual(38, tree.Predecessor(39));
+		}
+
+
+		[Test]
+        [ExpectedException(typeof(NoSuchItemException))]
+        public void PredecessorTooLow1()
+		{
+			tree.Predecessor(-2);
+		}
+
+
+		[Test]
+        [ExpectedException(typeof(NoSuchItemException))]
+        public void PredecessorTooLow2()
+		{
+			tree.Predecessor(0);
+		}
+
+
+		[Test]
+		public void WeakPredecessor()
+		{
+			loadup();
+			Assert.AreEqual(6, tree.WeakPredecessor(7));
+			Assert.AreEqual(8, tree.WeakPredecessor(8));
+
+			//The bottom
+			Assert.AreEqual(0, tree.WeakPredecessor(1));
+			Assert.AreEqual(0, tree.WeakPredecessor(0));
+
+			//The top
+			Assert.AreEqual(38, tree.WeakPredecessor(39));
+			Assert.AreEqual(38, tree.WeakPredecessor(38));
+		}
+
+
+		[Test]
+        [ExpectedException(typeof(NoSuchItemException))]
+        public void WeakPredecessorTooLow1()
+		{
+			tree.WeakPredecessor(-2);
+		}
+
+
+		[Test]
+		public void Successor()
+		{
+			loadup();
+			Assert.AreEqual(8, tree.Successor(7));
+			Assert.AreEqual(10, tree.Successor(8));
+
+			//The bottom
+			Assert.AreEqual(2, tree.Successor(0));
+			Assert.AreEqual(0, tree.Successor(-1));
+
+			//The top
+			Assert.AreEqual(38, tree.Successor(37));
+		}
+
+
+		[Test]
+        [ExpectedException(typeof(NoSuchItemException))]
+        public void SuccessorTooHigh1()
+		{
+			tree.Successor(38);
+		}
+
+
+		[Test]
+        [ExpectedException(typeof(NoSuchItemException))]
+        public void SuccessorTooHigh2()
+		{
+			tree.Successor(39);
+		}
+
+
+		[Test]
+		public void WeakSuccessor()
+		{
+			loadup();
+			Assert.AreEqual(6, tree.WeakSuccessor(6));
+			Assert.AreEqual(8, tree.WeakSuccessor(7));
+
+			//The bottom
+			Assert.AreEqual(0, tree.WeakSuccessor(-1));
+			Assert.AreEqual(0, tree.WeakSuccessor(0));
+
+			//The top
+			Assert.AreEqual(38, tree.WeakSuccessor(37));
+			Assert.AreEqual(38, tree.WeakSuccessor(38));
+		}
+
+
+		[Test]
+        [ExpectedException(typeof(NoSuchItemException))]
+        public void WeakSuccessorTooHigh1()
+		{
+			tree.WeakSuccessor(39);
+		}
+
+
+		[TearDown]
+		public void Dispose()
+		{
+			tree = null;
+		}
+	}
+
+
+
+	[TestFixture]
+	public class PriorityQueue
+	{
+		private TreeSet<int> tree;
+
+
+		[SetUp]
+		public void Init()
+		{
+			tree = new TreeSet<int>(new IC());
+		}
+
+
+		private void loadup()
+		{
+			foreach (int i in new int[] { 1, 2, 3, 4 })
+				tree.Add(i);
+		}
+
+
+		[Test]
+		public void Normal()
+		{
+			loadup();
+			Assert.AreEqual(1, tree.FindMin());
+			Assert.AreEqual(4, tree.FindMax());
+			Assert.AreEqual(1, tree.DeleteMin());
+			Assert.AreEqual(4, tree.DeleteMax());
+			Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+			Assert.AreEqual(2, tree.FindMin());
+			Assert.AreEqual(3, tree.FindMax());
+			Assert.AreEqual(2, tree.DeleteMin());
+			Assert.AreEqual(3, tree.DeleteMax());
+			Assert.IsTrue(tree.Check("Normal test 2"), "Bad tree");
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(NoSuchItemException))]
+		public void Empty1()
+		{
+			tree.FindMin();
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(NoSuchItemException))]
+		public void Empty2()
+		{
+			tree.FindMax();
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(NoSuchItemException))]
+		public void Empty3()
+		{
+			tree.DeleteMin();
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(NoSuchItemException))]
+		public void Empty4()
+		{
+			tree.DeleteMax();
+		}
+
+
+		[TearDown]
+		public void Dispose()
+		{
+			tree = null;
+		}
+	}
+
+
+
+	[TestFixture]
+	public class IndexingAndCounting
+	{
+		private TreeSet<int> tree;
+
+
+		[SetUp]
+		public void Init()
+		{
+			tree = new TreeSet<int>(new IC());
+		}
+
+
+		private void populate()
+		{
+			tree.Add(30);
+			tree.Add(50);
+			tree.Add(10);
+			tree.Add(70);
+		}
+
+
+		[Test]
+		public void ToArray()
+		{
+			populate();
+
+			int[] a = tree.ToArray();
+
+			Assert.AreEqual(4, a.Length);
+			Assert.AreEqual(10, a[0]);
+			Assert.AreEqual(30, a[1]);
+			Assert.AreEqual(50, a[2]);
+			Assert.AreEqual(70, a[3]);
+		}
+
+
+		[Test]
+		public void GoodIndex()
+		{
+			Assert.AreEqual(-1, tree.IndexOf(20));
+			Assert.AreEqual(-1, tree.LastIndexOf(20));
+			populate();
+			Assert.AreEqual(10, tree[0]);
+			Assert.AreEqual(30, tree[1]);
+			Assert.AreEqual(50, tree[2]);
+			Assert.AreEqual(70, tree[3]);
+			Assert.AreEqual(0, tree.IndexOf(10));
+			Assert.AreEqual(1, tree.IndexOf(30));
+			Assert.AreEqual(2, tree.IndexOf(50));
+			Assert.AreEqual(3, tree.IndexOf(70));
+			Assert.AreEqual(~1, tree.IndexOf(20));
+			Assert.AreEqual(~0, tree.IndexOf(0));
+			Assert.AreEqual(~4, tree.IndexOf(90));
+			Assert.AreEqual(0, tree.LastIndexOf(10));
+			Assert.AreEqual(1, tree.LastIndexOf(30));
+			Assert.AreEqual(2, tree.LastIndexOf(50));
+			Assert.AreEqual(3, tree.LastIndexOf(70));
+			Assert.AreEqual(~1, tree.LastIndexOf(20));
+			Assert.AreEqual(~0, tree.LastIndexOf(0));
+			Assert.AreEqual(~4, tree.LastIndexOf(90));
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(IndexOutOfRangeException))]
+		public void IndexTooLarge()
+		{
+			populate();
+			Console.WriteLine(tree[4]);
+		}
+
+
+		[Test]
+		[ExpectedException(typeof(IndexOutOfRangeException))]
+		public void IndexTooSmall()
+		{
+			populate();
+			Console.WriteLine(tree[-1]);
+		}
+
+
+		[Test]
+		public void FilledTreeOutsideInput()
+		{
+			populate();
+			Assert.AreEqual(0, tree.CountFrom(90));
+			Assert.AreEqual(0, tree.CountFromTo(-20, 0));
+			Assert.AreEqual(0, tree.CountFromTo(80, 100));
+			Assert.AreEqual(0, tree.CountTo(0));
+			Assert.AreEqual(4, tree.CountTo(90));
+			Assert.AreEqual(4, tree.CountFromTo(-20, 90));
+			Assert.AreEqual(4, tree.CountFrom(0));
+		}
+
+
+		[Test]
+		public void FilledTreeIntermediateInput()
+		{
+			populate();
+			Assert.AreEqual(3, tree.CountFrom(20));
+			Assert.AreEqual(1, tree.CountFromTo(20, 40));
+			Assert.AreEqual(2, tree.CountTo(40));
+		}
+
+
+		[Test]
+		public void FilledTreeMatchingInput()
+		{
+			populate();
+			Assert.AreEqual(3, tree.CountFrom(30));
+			Assert.AreEqual(2, tree.CountFromTo(30, 70));
+			Assert.AreEqual(0, tree.CountFromTo(50, 30));
+			Assert.AreEqual(0, tree.CountFromTo(50, 50));
+			Assert.AreEqual(0, tree.CountTo(10));
+			Assert.AreEqual(2, tree.CountTo(50));
+		}
+
+
+		[Test]
+		public void CountEmptyTree()
+		{
+			Assert.AreEqual(0, tree.CountFrom(20));
+			Assert.AreEqual(0, tree.CountFromTo(20, 40));
+			Assert.AreEqual(0, tree.CountTo(40));
+		}
+
+
+		[TearDown]
+		public void Dispose()
+		{
+			tree = null;
+		}
+	}
+
+
+
+
+	namespace ModificationCheck
+	{
+		[TestFixture]
+		public class Enumerator
+		{
+			private TreeSet<int> tree;
+
+			private SCG.IEnumerator<int> e;
+
+
+			[SetUp]
+			public void Init()
+			{
+				tree = new TreeSet<int>(new IC());
+				for (int i = 0; i < 10; i++)
+					tree.Add(i);
+
+				e = tree.GetEnumerator();
+			}
+
+
+			[Test]
+			public void CurrentAfterModification()
+			{
+				e.MoveNext();
+				tree.Add(34);
+				Assert.AreEqual(0, e.Current);
+			}
+
+
+			[Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterAdd()
+			{
+				tree.Add(34);
+				e.MoveNext();
+			}
+
+
+
+
+			[Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterRemove()
+			{
+				tree.Remove(34);
+				e.MoveNext();
+			}
+
+
+			[Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterClear()
+			{
+				tree.Clear();
+				e.MoveNext();
+			}
+
+
+			[TearDown]
+			public void Dispose()
+			{
+				tree = null;
+				e = null;
+			}
+		}
+
+
+
+		[TestFixture]
+		public class RangeEnumerator
+		{
+			private TreeSet<int> tree;
+
+			private SCG.IEnumerator<int> e;
+
+
+			[SetUp]
+			public void Init()
+			{
+				tree = new TreeSet<int>(new IC());
+				for (int i = 0; i < 10; i++)
+					tree.Add(i);
+
+				e = tree.RangeFromTo(3, 7).GetEnumerator();
+			}
+
+
+			[Test]
+			public void CurrentAfterModification()
+			{
+				e.MoveNext();
+				tree.Add(34);
+				Assert.AreEqual(3, e.Current);
+			}
+
+
+			[Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterAdd()
+			{
+				tree.Add(34);
+				e.MoveNext();
+			}
+
+
+
+
+			[Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterRemove()
+			{
+				tree.Remove(34);
+				e.MoveNext();
+			}
+
+
+			[Test]
+      [ExpectedException(typeof(CollectionModifiedException))]
+      public void MoveNextAfterClear()
+			{
+				tree.Clear();
+				e.MoveNext();
+			}
+
+
+			[TearDown]
+			public void Dispose()
+			{
+				tree = null;
+				e = null;
+			}
+		}
+	}
+
+
+
+
+	namespace PathcopyPersistence
+	{
+		[TestFixture]
+		public class Navigation
+		{
+			private TreeSet<int> tree, snap;
+
+			private SCG.IComparer<int> ic;
+
+
+			[SetUp]
+			public void Init()
+			{
+				ic = new IC();
+				tree = new TreeSet<int>(ic);
+				for (int i = 0; i <= 20; i++)
+					tree.Add(2 * i + 1);
+
+				snap = (TreeSet<int>)tree.Snapshot();
+				for (int i = 0; i <= 10; i++)
+					tree.Remove(4 * i + 1);
+			}
+
+
+			private bool twomodeleven(int i)
+			{
+				return i % 11 == 2;
+			}
+
+
+			[Test]
+			public void InternalEnum()
+			{
+				Assert.IsTrue(IC.eq(snap.FindAll(new Fun<int, bool>(twomodeleven)), 13, 35));
+			}
+
+			
+			public void MoreCut() { }
+
+			[Test]
+			public void Cut()
+			{
+				int lo, hi;
+				bool lv, hv;
+
+				Assert.IsFalse(snap.Cut(new HigherOrder.CubeRoot(64), out lo, out lv, out hi, out hv));
+				Assert.IsTrue(lv && hv);
+				Assert.AreEqual(5, hi);
+				Assert.AreEqual(3, lo);
+				Assert.IsTrue(snap.Cut(new HigherOrder.CubeRoot(125), out lo, out lv, out hi, out hv));
+				Assert.IsTrue(lv && hv);
+				Assert.AreEqual(7, hi);
+				Assert.AreEqual(3, lo);
+				Assert.IsFalse(snap.Cut(new HigherOrder.CubeRoot(125000), out lo, out lv, out hi, out hv));
+				Assert.IsTrue(lv && !hv);
+				Assert.AreEqual(41, lo);
+				Assert.IsFalse(snap.Cut(new HigherOrder.CubeRoot(-27), out lo, out lv, out hi, out hv));
+				Assert.IsTrue(!lv && hv);
+				Assert.AreEqual(1, hi);
+			}
+
+
+			[Test]
+			public void Range()
+			{
+				Assert.IsTrue(IC.eq(snap.RangeFromTo(5, 16), 5, 7, 9, 11, 13, 15));
+				Assert.IsTrue(IC.eq(snap.RangeFromTo(5, 17), 5, 7, 9, 11, 13, 15));
+				Assert.IsTrue(IC.eq(snap.RangeFromTo(6, 16), 7, 9, 11, 13, 15));
+				//Assert.AreEqual(snap.RangeFromTo(6, 16).Count, 5);
+			}
+
+
+			[Test]
+			public void Contains()
+			{
+				Assert.IsTrue(snap.Contains(5));
+			}
+
+
+			[Test]
+			public void FindMin()
+			{
+				Assert.AreEqual(1, snap.FindMin());
+			}
+
+
+			[Test]
+			public void FindMax()
+			{
+				Assert.AreEqual(41, snap.FindMax());
+			}
+
+            [Test]
+            public void FindPredecessor()
+            {
+                int res;
+                Assert.IsTrue(snap.TryPredecessor(15, out res) && res == 13);
+                Assert.IsTrue(snap.TryPredecessor(16, out res) && res == 15);
+                Assert.IsTrue(snap.TryPredecessor(17, out res) && res == 15);
+                Assert.IsTrue(snap.TryPredecessor(18, out res) && res == 17);
+
+                Assert.IsTrue(snap.TryPredecessor(2, out res) && res == 1);
+
+                Assert.IsFalse(snap.TryPredecessor(1, out res));
+                Assert.AreEqual(0, res);
+            }
+
+
+            [Test]
+            public void FindSuccessor()
+            {
+                int res;
+                Assert.IsTrue(snap.TrySuccessor(15, out res) && res == 17);
+                Assert.IsTrue(snap.TrySuccessor(16, out res) && res == 17);
+                Assert.IsTrue(snap.TrySuccessor(17, out res) && res == 19);
+                Assert.IsTrue(snap.TrySuccessor(18, out res) && res == 19);
+
+                Assert.IsTrue(snap.TrySuccessor(40, out res) && res == 41);
+                
+                Assert.IsFalse(snap.TrySuccessor(41, out res));
+                Assert.AreEqual(0, res);
+            }
+
+
+            [Test]
+            public void FindWeakPredecessor()
+            {
+                int res;
+                Assert.IsTrue(snap.TryWeakPredecessor(15, out res) && res == 15);
+                Assert.IsTrue(snap.TryWeakPredecessor(16, out res) && res == 15);
+                Assert.IsTrue(snap.TryWeakPredecessor(17, out res) && res == 17);
+                Assert.IsTrue(snap.TryWeakPredecessor(18, out res) && res == 17);
+
+                Assert.IsTrue(snap.TryWeakPredecessor(1, out res) && res == 1);
+
+                Assert.IsFalse(snap.TryWeakPredecessor(0, out res));
+                Assert.AreEqual(0, res);
+            }
+
+
+            [Test]
+            public void FindWeakSuccessor()
+            {
+                int res;
+                Assert.IsTrue(snap.TryWeakSuccessor(15, out res) && res == 15);
+                Assert.IsTrue(snap.TryWeakSuccessor(16, out res) && res == 17);
+                Assert.IsTrue(snap.TryWeakSuccessor(17, out res) && res == 17);
+                Assert.IsTrue(snap.TryWeakSuccessor(18, out res) && res == 19);
+
+                Assert.IsTrue(snap.TryWeakSuccessor(41, out res) && res == 41);
+
+                Assert.IsFalse(snap.TryWeakSuccessor(42, out res));
+                Assert.AreEqual(0, res);
+            }
+
+
+			[Test]
+			public void Predecessor()
+			{
+				Assert.AreEqual(13, snap.Predecessor(15));
+				Assert.AreEqual(15, snap.Predecessor(16));
+				Assert.AreEqual(15, snap.Predecessor(17));
+				Assert.AreEqual(17, snap.Predecessor(18));
+			}
+
+
+			[Test]
+			public void Successor()
+			{
+				Assert.AreEqual(17, snap.Successor(15));
+				Assert.AreEqual(17, snap.Successor(16));
+				Assert.AreEqual(19, snap.Successor(17));
+				Assert.AreEqual(19, snap.Successor(18));
+			}
+
+
+			[Test]
+			public void WeakPredecessor()
+			{
+				Assert.AreEqual(15, snap.WeakPredecessor(15));
+				Assert.AreEqual(15, snap.WeakPredecessor(16));
+				Assert.AreEqual(17, snap.WeakPredecessor(17));
+				Assert.AreEqual(17, snap.WeakPredecessor(18));
+			}
+
+
+			[Test]
+			public void WeakSuccessor()
+			{
+				Assert.AreEqual(15, snap.WeakSuccessor(15));
+				Assert.AreEqual(17, snap.WeakSuccessor(16));
+				Assert.AreEqual(17, snap.WeakSuccessor(17));
+				Assert.AreEqual(19, snap.WeakSuccessor(18));
+			}
+
+
+			[Test]
+			[ExpectedException(typeof(NotSupportedException), "Indexing not supported for snapshots")]
+			public void CountTo()
+			{
+				int j = snap.CountTo(15);
+			}
+
+
+			[Test]
+			[ExpectedException(typeof(NotSupportedException), "Indexing not supported for snapshots")]
+			public void Indexing()
+			{
+				int j = snap[4];
+			}
+
+
+			[Test]
+			[ExpectedException(typeof(NotSupportedException), "Indexing not supported for snapshots")]
+			public void Indexing2()
+			{
+				int j = snap.IndexOf(5);
+			}
+
+
+			[TearDown]
+			public void Dispose()
+			{
+				tree = null;
+				ic = null;
+			}
+		}
+
+
+
+		[TestFixture]
+		public class Single
+		{
+			private TreeSet<int> tree;
+
+			private SCG.IComparer<int> ic;
+
+
+			[SetUp]
+			public void Init()
+			{
+				ic = new IC();
+				tree = new TreeSet<int>(ic);
+				for (int i = 0; i < 10; i++)
+					tree.Add(2 * i + 1);
+			}
+
+
+			[Test]
+			public void EnumerationWithAdd()
+			{
+				int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };
+				int i = 0;
+				TreeSet<int> snap = (TreeSet<int>)tree.Snapshot();
+
+				foreach (int j in snap)
+				{
+					Assert.AreEqual(1 + 2 * i++, j);
+					tree.Add(21 - j);
+					Assert.IsTrue(snap.Check("M"), "Bad snap!");
+					Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+					Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+				}
+			}
+
+
+			[Test]
+			public void Remove()
+			{
+				int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };
+				TreeSet<int> snap = (TreeSet<int>)tree.Snapshot();
+
+				Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+				tree.Remove(19);
+				Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+				Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+			}
+
+
+			[Test]
+			public void RemoveNormal()
+			{
+				tree.Clear();
+				for (int i = 10; i < 20; i++)
+				{
+					tree.Add(i);
+					tree.Add(i + 10);
+				}
+
+				int[] orig = new int[] { 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29 };
+				TreeSet<int> snap = (TreeSet<int>)tree.Snapshot();
+
+				Assert.IsFalse(tree.Remove(-20));
+				Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+				//No demote case, with move_item
+				Assert.IsTrue(tree.Remove(20));
+				Assert.IsTrue(tree.Check("T1"));
+				Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+				Assert.IsFalse(tree.Remove(20));
+
+				//plain case 2
+				tree.Snapshot();
+				Assert.IsTrue(tree.Remove(14));
+				Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+				Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+				//case 1b
+				Assert.IsTrue(tree.Remove(25));
+				Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+				Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+				//case 1c
+				Assert.IsTrue(tree.Remove(29));
+				Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+				Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+				//1a (terminating)
+				Assert.IsTrue(tree.Remove(10));
+				Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+				Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+				//2+1b
+				Assert.IsTrue(tree.Remove(12));
+				tree.Snapshot();
+				Assert.IsTrue(tree.Remove(11));
+				Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+				Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+				//1a+1b
+				Assert.IsTrue(tree.Remove(18));
+				Assert.IsTrue(tree.Remove(13));
+				Assert.IsTrue(tree.Remove(15));
+				Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+				Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+				//2+1c
+				for (int i = 0; i < 10; i++)
+					tree.Add(50 - 2 * i);
+
+				Assert.IsTrue(tree.Remove(42));
+				Assert.IsTrue(tree.Remove(38));
+				Assert.IsTrue(tree.Remove(28));
+				Assert.IsTrue(tree.Remove(40));
+				Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+				Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+				//
+				Assert.IsTrue(tree.Remove(16));
+				Assert.IsTrue(tree.Remove(23));
+				Assert.IsTrue(tree.Remove(17));
+				Assert.IsTrue(tree.Remove(19));
+				Assert.IsTrue(tree.Remove(50));
+				Assert.IsTrue(tree.Remove(26));
+				Assert.IsTrue(tree.Remove(21));
+				Assert.IsTrue(tree.Remove(22));
+				Assert.IsTrue(tree.Remove(24));
+				for (int i = 0; i < 48; i++)
+					tree.Remove(i);
+
+				//Almost empty tree:
+				Assert.IsFalse(tree.Remove(26));
+				Assert.IsTrue(tree.Remove(48));
+				Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+				Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+
+				//Empty tree:
+				Assert.IsFalse(tree.Remove(26));
+				Assert.IsTrue(tree.Check("Normal test 1"), "Bad tree");
+				Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+			}
+
+
+			[Test]
+			public void Add()
+			{
+				int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };
+				TreeSet<int> snap = (TreeSet<int>)tree.Snapshot();
+
+				Assert.IsTrue(snap.Check("M"), "Bad snap!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+				Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+				tree.Add(10);
+				Assert.IsTrue(snap.Check("M"), "Bad snap!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+				Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+				tree.Add(16);
+				Assert.IsTrue(snap.Check("M"), "Bad snap!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+				Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+
+				//Promote+zigzig
+				tree.Add(40);
+				Assert.IsTrue(snap.Check("M"), "Bad snap!");
+				Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+				for (int i = 1; i < 4; i++)
+					tree.Add(40 - 2 * i);
+
+				Assert.IsTrue(snap.Check("M"), "Bad snap!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+				Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+
+				//Zigzag:
+				tree.Add(32);
+				Assert.IsTrue(snap.Check("M"), "Bad snap!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+				Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+			}
+
+
+			[Test]
+			public void Clear()
+			{
+				int[] orig = new int[] { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };
+				TreeSet<int> snap = (TreeSet<int>)tree.Snapshot();
+
+				tree.Clear();
+				Assert.IsTrue(snap.Check("Snap"), "Bad snap!");
+				Assert.IsTrue(tree.Check("Tree"), "Bad tree!");
+				Assert.IsTrue(IC.eq(snap, orig), "Snap was changed!");
+				Assert.AreEqual(0, tree.Count);
+			}
+
+
+			[Test]
+			[ExpectedException(typeof(InvalidOperationException), "Cannot snapshot a snapshot")]
+			public void SnapSnap()
+			{
+				TreeSet<int> snap = (TreeSet<int>)tree.Snapshot();
+
+				snap.Snapshot();
+			}
+
+
+			[TearDown]
+			public void Dispose()
+			{
+				tree = null;
+				ic = null;
+			}
+		}
+
+
+
+		[TestFixture]
+		public class Multiple
+		{
+			private TreeSet<int> tree;
+
+			private SCG.IComparer<int> ic;
+
+
+			private bool eq(SCG.IEnumerable<int> me, int[] that)
+			{
+				int i = 0, maxind = that.Length - 1;
+
+				foreach (int item in me)
+					if (i > maxind || ic.Compare(item, that[i++]) != 0)
+						return false;
+
+				return true;
+			}
+
+
+			[SetUp]
+			public void Init()
+			{
+				ic = new IC();
+				tree = new TreeSet<int>(ic);
+				for (int i = 0; i < 10; i++)
+					tree.Add(2 * i + 1);
+			}
+
+
+			[Test]
+			public void First()
+			{
+				TreeSet<int>[] snaps = new TreeSet<int>[10];
+
+				for (int i = 0; i < 10; i++)
+				{
+					snaps[i] = (TreeSet<int>)(tree.Snapshot());
+					tree.Add(2 * i);
+				}
+
+				for (int i = 0; i < 10; i++)
+				{
+					Assert.AreEqual(i + 10, snaps[i].Count);
+				}
+
+				snaps[5] = null;
+				snaps[9] = null;
+				GC.Collect();
+				snaps[8].Dispose();
+				tree.Remove(14);
+
+				int[] res = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 16, 17, 18, 19 };
+				int[] snap7 = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19 };
+				int[] snap3 = new int[] { 0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 15, 17, 19 };
+
+				Assert.IsTrue(IC.eq(snaps[3], snap3), "Snap 3 was changed!");
+				Assert.IsTrue(IC.eq(snaps[7], snap7), "Snap 7 was changed!");
+				Assert.IsTrue(IC.eq(tree, res));
+				Assert.IsTrue(tree.Check("B"));
+				Assert.IsTrue(snaps[3].Check("B"));
+				Assert.IsTrue(snaps[7].Check("B"));
+			}
+
+
+			[Test]
+			public void CollectingTheMaster()
+			{
+				TreeSet<int>[] snaps = new TreeSet<int>[10];
+
+				for (int i = 0; i < 10; i++)
+				{
+					snaps[i] = (TreeSet<int>)(tree.Snapshot());
+					tree.Add(2 * i);
+				}
+
+				tree = null;
+				GC.Collect();
+				for (int i = 0; i < 10; i++)
+				{
+					Assert.AreEqual(i + 10, snaps[i].Count);
+				}
+
+				snaps[5] = null;
+				snaps[9] = null;
+				GC.Collect();
+				snaps[8].Dispose();
+
+				int[] snap7 = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 15, 17, 19 };
+				int[] snap3 = new int[] { 0, 1, 2, 3, 4, 5, 7, 9, 11, 13, 15, 17, 19 };
+
+				Assert.IsTrue(IC.eq(snaps[3], snap3), "Snap 3 was changed!");
+				Assert.IsTrue(IC.eq(snaps[7], snap7), "Snap 7 was changed!");
+				Assert.IsTrue(snaps[3].Check("B"));
+				Assert.IsTrue(snaps[7].Check("B"));
+			}
+
+
+			[TearDown]
+			public void Dispose()
+			{
+				tree = null;
+				ic = null;
+			}
+		}
+	}
+
+
+
+
+	namespace HigherOrder
+	{
+		internal class CubeRoot: IComparable<int>
+		{
+			private int c;
+
+
+			internal CubeRoot(int c) { this.c = c; }
+
+
+			public int CompareTo(int that) { return c - that * that * that; }
+            public bool Equals(int that) { return c == that * that * that; }
+        }
+
+
+
+        class Interval: IComparable<int>
+		{
+			private int b, t;
+
+
+			internal Interval(int b, int t) { this.b = b; this.t = t; }
+
+
+			public int CompareTo(int that) { return that < b ? 1 : that > t ? -1 : 0; }
+            public bool Equals(int that) { return that >= b && that <= t; }
+        }
+
+
+
+        [TestFixture]
+		public class Simple
+		{
+			private TreeSet<int> tree;
+
+			private SCG.IComparer<int> ic;
+
+
+			[SetUp]
+			public void Init()
+			{
+				ic = new IC();
+				tree = new TreeSet<int>(ic);
+			}
+
+
+			private bool never(int i) { return false; }
+
+
+			private bool always(int i) { return true; }
+
+
+			private bool even(int i) { return i % 2 == 0; }
+
+
+			private string themap(int i) { return String.Format("AA {0,4} BB", i); }
+
+
+			private string badmap(int i) { return String.Format("AA {0} BB", i); }
+
+
+			private int appfield1;
+
+			private int appfield2;
+
+
+			private void apply(int i) { appfield1++; appfield2 += i * i; }
+
+
+			[Test]
+			public void Apply()
+			{
+				Simple simple1 = new Simple();
+
+				tree.Apply(new Act<int>(simple1.apply));
+				Assert.AreEqual(0, simple1.appfield1);
+				Assert.AreEqual(0, simple1.appfield2);
+
+				Simple simple2 = new Simple();
+
+				for (int i = 0; i < 10; i++) tree.Add(i);
+
+				tree.Apply(new Act<int>(simple2.apply));
+				Assert.AreEqual(10, simple2.appfield1);
+				Assert.AreEqual(285, simple2.appfield2);
+			}
+
+
+			[Test]
+			public void All()
+			{
+				Assert.IsTrue(tree.All(new Fun<int, bool>(never)));
+				Assert.IsTrue(tree.All(new Fun<int, bool>(even)));
+				Assert.IsTrue(tree.All(new Fun<int, bool>(always)));
+				for (int i = 0; i < 10; i++)					tree.Add(i);
+
+				Assert.IsFalse(tree.All(new Fun<int, bool>(never)));
+				Assert.IsFalse(tree.All(new Fun<int, bool>(even)));
+				Assert.IsTrue(tree.All(new Fun<int, bool>(always)));
+				tree.Clear();
+				for (int i = 0; i < 10; i++)					tree.Add(i * 2);
+
+				Assert.IsFalse(tree.All(new Fun<int, bool>(never)));
+				Assert.IsTrue(tree.All(new Fun<int, bool>(even)));
+				Assert.IsTrue(tree.All(new Fun<int, bool>(always)));
+				tree.Clear();
+				for (int i = 0; i < 10; i++)					tree.Add(i * 2 + 1);
+
+				Assert.IsFalse(tree.All(new Fun<int, bool>(never)));
+				Assert.IsFalse(tree.All(new Fun<int, bool>(even)));
+				Assert.IsTrue(tree.All(new Fun<int, bool>(always)));
+			}
+
+
+			[Test]
+			public void Exists()
+			{
+				Assert.IsFalse(tree.Exists(new Fun<int, bool>(never)));
+				Assert.IsFalse(tree.Exists(new Fun<int, bool>(even)));
+				Assert.IsFalse(tree.Exists(new Fun<int, bool>(always)));
+				for (int i = 0; i < 10; i++)					tree.Add(i);
+
+				Assert.IsFalse(tree.Exists(new Fun<int, bool>(never)));
+				Assert.IsTrue(tree.Exists(new Fun<int, bool>(even)));
+				Assert.IsTrue(tree.Exists(new Fun<int, bool>(always)));
+				tree.Clear();
+				for (int i = 0; i < 10; i++)					tree.Add(i * 2);
+
+				Assert.IsFalse(tree.Exists(new Fun<int, bool>(never)));
+				Assert.IsTrue(tree.Exists(new Fun<int, bool>(even)));
+				Assert.IsTrue(tree.Exists(new Fun<int, bool>(always)));
+				tree.Clear();
+				for (int i = 0; i < 10; i++)					tree.Add(i * 2 + 1);
+
+				Assert.IsFalse(tree.Exists(new Fun<int, bool>(never)));
+				Assert.IsFalse(tree.Exists(new Fun<int, bool>(even)));
+				Assert.IsTrue(tree.Exists(new Fun<int, bool>(always)));
+			}
+
+
+			[Test]
+			public void FindAll()
+			{
+				Assert.AreEqual(0, tree.FindAll(new Fun<int, bool>(never)).Count);
+				for (int i = 0; i < 10; i++)
+					tree.Add(i);
+
+				Assert.AreEqual(0, tree.FindAll(new Fun<int, bool>(never)).Count);
+				Assert.AreEqual(10, tree.FindAll(new Fun<int, bool>(always)).Count);
+				Assert.AreEqual(5, tree.FindAll(new Fun<int, bool>(even)).Count);
+				Assert.IsTrue(((TreeSet<int>)tree.FindAll(new Fun<int, bool>(even))).Check("R"));
+			}
+
+
+			[Test]
+			public void Map()
+			{
+				Assert.AreEqual(0, tree.Map(new Fun<int,string>(themap), new SC()).Count);
+				for (int i = 0; i < 11; i++)
+					tree.Add(i * i * i);
+
+				IIndexedSorted<string> res = tree.Map(new Fun<int,string>(themap), new SC());
+
+				Assert.IsTrue(((TreeSet<string>)res).Check("R"));
+				Assert.AreEqual(11, res.Count);
+				Assert.AreEqual("AA    0 BB", res[0]);
+				Assert.AreEqual("AA   27 BB", res[3]);
+				Assert.AreEqual("AA  125 BB", res[5]);
+				Assert.AreEqual("AA 1000 BB", res[10]);
+			}
+
+
+			[Test]
+			[ExpectedException(typeof(ArgumentException), "mapper not monotonic")]
+			public void BadMap()
+			{
+				for (int i = 0; i < 11; i++)
+					tree.Add(i * i * i);
+
+				ISorted<string> res = tree.Map(new Fun<int,string>(badmap), new SC());
+			}
+
+
+			[Test]
+			public void Cut()
+			{
+				for (int i = 0; i < 10; i++)
+					tree.Add(i);
+
+				int low, high;
+				bool lval, hval;
+
+				Assert.IsTrue(tree.Cut(new CubeRoot(27), out low, out lval, out high, out hval));
+				Assert.IsTrue(lval && hval);
+				Assert.AreEqual(4, high);
+				Assert.AreEqual(2, low);
+				Assert.IsFalse(tree.Cut(new CubeRoot(30), out low, out lval, out high, out hval));
+				Assert.IsTrue(lval && hval);
+				Assert.AreEqual(4, high);
+				Assert.AreEqual(3, low);
+			}
+
+
+			[Test]
+			public void CutInt()
+			{
+				for (int i = 0; i < 10; i++)
+					tree.Add(2 * i);
+
+				int low, high;
+				bool lval, hval;
+
+				Assert.IsFalse(tree.Cut(new IC(3), out low, out lval, out high, out hval));
+				Assert.IsTrue(lval && hval);
+				Assert.AreEqual(4, high);
+				Assert.AreEqual(2, low);
+				Assert.IsTrue(tree.Cut(new IC(6), out low, out lval, out high, out hval));
+				Assert.IsTrue(lval && hval);
+				Assert.AreEqual(8, high);
+				Assert.AreEqual(4, low);
+			}
+
+
+			[Test]
+			public void CutInterval()
+			{
+				for (int i = 0; i < 10; i++)
+					tree.Add(2 * i);
+
+				int lo, hi;
+				bool lv, hv;
+
+				Assert.IsTrue(tree.Cut(new Interval(5, 9), out lo, out lv, out hi, out hv));
+				Assert.IsTrue(lv && hv);
+				Assert.AreEqual(10, hi);
+				Assert.AreEqual(4, lo);
+				Assert.IsTrue(tree.Cut(new Interval(6, 10), out lo, out lv, out hi, out hv));
+				Assert.IsTrue(lv && hv);
+				Assert.AreEqual(12, hi);
+				Assert.AreEqual(4, lo);
+				for (int i = 0; i < 100; i++)
+					tree.Add(2 * i);
+
+				tree.Cut(new Interval(77, 105), out lo, out lv, out hi, out hv);
+				Assert.IsTrue(lv && hv);
+				Assert.AreEqual(106, hi);
+				Assert.AreEqual(76, lo);
+				tree.Cut(new Interval(5, 7), out lo, out lv, out hi, out hv);
+				Assert.IsTrue(lv && hv);
+				Assert.AreEqual(8, hi);
+				Assert.AreEqual(4, lo);
+				tree.Cut(new Interval(80, 110), out lo, out lv, out hi, out hv);
+				Assert.IsTrue(lv && hv);
+				Assert.AreEqual(112, hi);
+				Assert.AreEqual(78, lo);
+			}
+
+
+			[Test]
+			public void UpperCut()
+			{
+				for (int i = 0; i < 10; i++)
+					tree.Add(i);
+
+				int l, h;
+				bool lv, hv;
+
+				Assert.IsFalse(tree.Cut(new CubeRoot(1000), out l, out lv, out h, out hv));
+				Assert.IsTrue(lv && !hv);
+				Assert.AreEqual(9, l);
+				Assert.IsFalse(tree.Cut(new CubeRoot(-50), out l, out lv, out h, out hv));
+				Assert.IsTrue(!lv && hv);
+				Assert.AreEqual(0, h);
+			}
+
+
+			[TearDown]
+			public void Dispose() { ic = null; tree = null; }
+		}
+	}
+
+
+
+
+	namespace MultiOps
+	{
+		[TestFixture]
+		public class AddAll
+		{
+			private int sqr(int i) { return i * i; }
+
+
+			TreeSet<int> tree;
+
+
+			[SetUp]
+			public void Init() { tree = new TreeSet<int>(new IC()); }
+
+
+			[Test]
+			public void EmptyEmpty()
+			{
+				tree.AddAll(new FunEnumerable(0, new Fun<int,int>(sqr)));
+				Assert.AreEqual(0, tree.Count);
+				Assert.IsTrue(tree.Check());
+			}
+
+
+			[Test]
+			public void SomeEmpty()
+			{
+				for (int i = 4; i < 9; i++) tree.Add(i);
+
+				tree.AddAll(new FunEnumerable(0, new Fun<int,int>(sqr)));
+				Assert.AreEqual(5, tree.Count);
+				Assert.IsTrue(tree.Check());
+			}
+
+
+			[Test]
+			public void EmptySome()
+			{
+				tree.AddAll(new FunEnumerable(4, new Fun<int,int>(sqr)));
+				Assert.AreEqual(4, tree.Count);
+				Assert.IsTrue(tree.Check());
+				Assert.AreEqual(0, tree[0]);
+				Assert.AreEqual(1, tree[1]);
+				Assert.AreEqual(4, tree[2]);
+				Assert.AreEqual(9, tree[3]);
+			}
+
+
+			[Test]
+			public void SomeSome()
+			{
+				for (int i = 5; i < 9; i++) tree.Add(i);
+
+				tree.AddAll(new FunEnumerable(4, new Fun<int,int>(sqr)));
+				Assert.AreEqual(8, tree.Count);
+				Assert.IsTrue(tree.Check());
+				Assert.IsTrue(IC.eq(tree, 0, 1, 4, 5, 6, 7, 8, 9));
+			}
+
+
+			[TearDown]
+			public void Dispose() { tree = null; }
+		}
+
+
+
+		[TestFixture]
+		public class AddSorted
+		{
+			private int sqr(int i) { return i * i; }
+
+
+			private int bad(int i) { return i * (5 - i); }
+
+
+			TreeSet<int> tree;
+
+
+			[SetUp]
+			public void Init() { tree = new TreeSet<int>(new IC()); }
+
+
+			[Test]
+			public void EmptyEmpty()
+			{
+				tree.AddSorted(new FunEnumerable(0, new Fun<int,int>(sqr)));
+				Assert.AreEqual(0, tree.Count);
+				Assert.IsTrue(tree.Check());
+			}
+
+
+
+			[Test]
+			public void SomeEmpty()
+			{
+				for (int i = 4; i < 9; i++) tree.Add(i);
+
+				tree.AddSorted(new FunEnumerable(0, new Fun<int,int>(sqr)));
+				Assert.AreEqual(5, tree.Count);
+				Assert.IsTrue(tree.Check());
+			}
+
+
+
+			[Test]
+			public void EmptySome()
+			{
+				tree.AddSorted(new FunEnumerable(4, new Fun<int,int>(sqr)));
+				Assert.AreEqual(4, tree.Count);
+				Assert.IsTrue(tree.Check());
+				Assert.AreEqual(0, tree[0]);
+				Assert.AreEqual(1, tree[1]);
+				Assert.AreEqual(4, tree[2]);
+				Assert.AreEqual(9, tree[3]);
+			}
+
+
+
+			[Test]
+			public void SomeSome()
+			{
+				for (int i = 5; i < 9; i++) tree.Add(i);
+
+				tree.AddSorted(new FunEnumerable(4, new Fun<int,int>(sqr)));
+				Assert.AreEqual(8, tree.Count);
+				Assert.IsTrue(tree.Check());
+				Assert.IsTrue(IC.eq(tree, 0, 1, 4, 5, 6, 7, 8, 9));
+			}
+
+			[Test]
+			[ExpectedException(typeof(ArgumentException), "Argument not sorted")]
+			public void EmptyBad()
+			{
+				tree.AddSorted(new FunEnumerable(9, new Fun<int,int>(bad)));
+			}
+
+
+			[TearDown]
+			public void Dispose() { tree = null; }
+		}
+
+		[TestFixture]
+		public class Rest
+		{
+			TreeSet<int> tree, tree2;
+
+
+			[SetUp]
+			public void Init()
+			{
+				tree = new TreeSet<int>(new IC());
+				tree2 = new TreeSet<int>(new IC());
+				for (int i = 0; i < 10; i++)
+					tree.Add(i);
+
+				for (int i = 0; i < 10; i++)
+					tree2.Add(2 * i);
+			}
+
+
+			[Test]
+			public void RemoveAll()
+			{
+				tree.RemoveAll(tree2.RangeFromTo(3, 7));
+				Assert.AreEqual(8, tree.Count);
+				Assert.IsTrue(tree.Check());
+				Assert.IsTrue(IC.eq(tree, 0, 1, 2, 3, 5, 7, 8, 9));
+				tree.RemoveAll(tree2.RangeFromTo(3, 7));
+				Assert.AreEqual(8, tree.Count);
+				Assert.IsTrue(tree.Check());
+				Assert.IsTrue(IC.eq(tree, 0, 1, 2, 3, 5, 7, 8, 9));
+				tree.RemoveAll(tree2.RangeFromTo(13, 17));
+				Assert.AreEqual(8, tree.Count);
+				Assert.IsTrue(tree.Check());
+				Assert.IsTrue(IC.eq(tree, 0, 1, 2, 3, 5, 7, 8, 9));
+				tree.RemoveAll(tree2.RangeFromTo(3, 17));
+				Assert.AreEqual(7, tree.Count);
+				Assert.IsTrue(tree.Check());
+				Assert.IsTrue(IC.eq(tree, 0, 1, 2, 3, 5, 7, 9));
+				for (int i = 0; i < 10; i++) tree2.Add(i);
+
+				tree.RemoveAll(tree2.RangeFromTo(-1, 10));
+				Assert.AreEqual(0, tree.Count);
+				Assert.IsTrue(tree.Check());
+				Assert.IsTrue(IC.eq(tree));
+			}
+
+
+			[Test]
+			public void RetainAll()
+			{
+				tree.RetainAll(tree2.RangeFromTo(3, 17));
+				Assert.AreEqual(3, tree.Count);
+				Assert.IsTrue(tree.Check());
+				Assert.IsTrue(IC.eq(tree, 4, 6, 8));
+				tree.RetainAll(tree2.RangeFromTo(1, 17));
+				Assert.AreEqual(3, tree.Count);
+				Assert.IsTrue(tree.Check());
+				Assert.IsTrue(IC.eq(tree, 4, 6, 8));
+				tree.RetainAll(tree2.RangeFromTo(3, 5));
+				Assert.AreEqual(1, tree.Count);
+				Assert.IsTrue(tree.Check());
+				Assert.IsTrue(IC.eq(tree, 4));
+				tree.RetainAll(tree2.RangeFromTo(7, 17));
+				Assert.AreEqual(0, tree.Count);
+				Assert.IsTrue(tree.Check());
+				Assert.IsTrue(IC.eq(tree));
+				for (int i = 0; i < 10; i++) tree.Add(i);
+
+				tree.RetainAll(tree2.RangeFromTo(5, 5));
+				Assert.AreEqual(0, tree.Count);
+				Assert.IsTrue(tree.Check());
+				Assert.IsTrue(IC.eq(tree));
+				for (int i = 0; i < 10; i++) tree.Add(i);
+
+				tree.RetainAll(tree2.RangeFromTo(15, 25));
+				Assert.AreEqual(0, tree.Count);
+				Assert.IsTrue(tree.Check());
+				Assert.IsTrue(IC.eq(tree));
+			}
+
+
+			[Test]
+			public void ContainsAll()
+			{
+				Assert.IsFalse(tree.ContainsAll(tree2));
+				Assert.IsTrue(tree.ContainsAll(tree));
+				tree2.Clear();
+				Assert.IsTrue(tree.ContainsAll(tree2));
+				tree.Clear();
+				Assert.IsTrue(tree.ContainsAll(tree2));
+				tree2.Add(8);
+				Assert.IsFalse(tree.ContainsAll(tree2));
+			}
+
+
+			[Test]
+			public void RemoveInterval()
+			{
+				tree.RemoveInterval(3, 4);
+				Assert.IsTrue(tree.Check());
+				Assert.AreEqual(6, tree.Count);
+				Assert.IsTrue(IC.eq(tree, 0, 1, 2, 7, 8, 9));
+				tree.RemoveInterval(2, 3);
+				Assert.IsTrue(tree.Check());
+				Assert.AreEqual(3, tree.Count);
+				Assert.IsTrue(IC.eq(tree, 0, 1, 9));
+				tree.RemoveInterval(0, 3);
+				Assert.IsTrue(tree.Check());
+				Assert.AreEqual(0, tree.Count);
+				Assert.IsTrue(IC.eq(tree));
+			}
+
+
+			[Test]
+			[ExpectedException(typeof(ArgumentOutOfRangeException))]
+			public void RemoveRangeBad1()
+			{
+				tree.RemoveInterval(-3, 8);
+			}
+
+
+			[Test]
+			[ExpectedException(typeof(ArgumentOutOfRangeException))]
+			public void RemoveRangeBad2()
+			{
+				tree.RemoveInterval(3, -8);
+			}
+
+
+			[Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void RemoveRangeBad3()
+			{
+				tree.RemoveInterval(3, 8);
+			}
+
+
+			[Test]
+			public void GetRange()
+			{
+				SCG.IEnumerable<int> e = tree[3, 6];
+
+				Assert.IsTrue(IC.eq(e, 3, 4, 5));
+				e = tree[3, 3];
+				Assert.IsTrue(IC.eq(e));
+			}
+
+
+			[Test]
+			[ExpectedException(typeof(ArgumentOutOfRangeException))]
+			public void GetRangeBad1()
+			{
+				object foo = tree[-3, 0];
+			}
+
+
+			[Test]
+			[ExpectedException(typeof(ArgumentOutOfRangeException))]
+			public void GetRangeBad2()
+			{
+				object foo = tree[3, 2];
+			}
+
+
+			[Test]
+      [ExpectedException(typeof(ArgumentOutOfRangeException))]
+      public void GetRangeBad3()
+			{
+				object foo = tree[3, 11];
+			}
+
+
+			[TearDown]
+			public void Dispose() { tree = null; tree2 = null; }
+		}
+	}
+
+
+
+
+	namespace Sync
+	{
+		[TestFixture]
+		public class SyncRoot
+		{
+			private TreeSet<int> tree;
+      private readonly Object mySyncRoot = new Object();
+			int sz = 5000;
+
+
+			[Test]
+			public void Safe()
+			{
+				System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ThreadStart(safe1));
+				System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ThreadStart(safe2));
+
+				t1.Start();
+				t2.Start();
+				t1.Join();
+				t2.Join();
+				Assert.AreEqual(2 * sz + 1, tree.Count);
+				Assert.IsTrue(tree.Check());
+			}
+
+
+			//[Test]
+			public void UnSafe()
+			{
+				bool bad = false;
+
+				for (int i = 0; i < 10; i++)
+				{
+					System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe1));
+					System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe2));
+
+					t1.Start();
+					t2.Start();
+					t1.Join();
+					t2.Join();
+					if (bad = 2 * sz + 1 != tree.Count)
+					{
+						Console.WriteLine("{0}::Unsafe(): bad at {1}", GetType(), i);
+						break;
+					}
+				}
+
+				Assert.IsTrue(bad, "No sync problems!");
+			}
+
+
+			[Test]
+			public void SafeUnSafe()
+			{
+				System.Threading.Thread t1 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe1));
+				System.Threading.Thread t2 = new System.Threading.Thread(new System.Threading.ThreadStart(unsafe2));
+
+				t1.Start();
+				t1.Join();
+				t2.Start();
+				t2.Join();
+				Assert.AreEqual(2 * sz + 1, tree.Count);
+			}
+
+
+			[SetUp]
+			public void Init() { tree = new TreeSet<int>(new IC()); }
+
+
+			private void unsafe1()
+			{
+				for (int i = 0; i < 2 * sz; i++)
+					tree.Add(i * 2);
+
+				for (int i = 1; i < sz; i++)
+					tree.Remove(i * 4);
+			}
+
+
+			private void safe1()
+			{
+				for (int i = 0; i < 2 * sz; i++)
+					lock (mySyncRoot)
+						tree.Add(i * 2);
+
+				for (int i = 1; i < sz; i++)
+					lock (mySyncRoot)
+						tree.Remove(i * 4);
+			}
+
+
+			private void unsafe2()
+			{
+				for (int i = 2 * sz; i > 0; i--)
+					tree.Add(i * 2 + 1);
+
+				for (int i = sz; i > 0; i--)
+					tree.Remove(i * 4 + 1);
+			}
+
+
+			private void safe2()
+			{
+				for (int i = 2 * sz; i > 0; i--)
+					lock (mySyncRoot)
+						tree.Add(i * 2 + 1);
+
+				for (int i = sz; i > 0; i--)
+					lock (mySyncRoot)
+						tree.Remove(i * 4 + 1);
+			}
+
+
+			[TearDown]
+			public void Dispose() { tree = null; }
+		}
+
+
+
+		//[TestFixture]
+		public class ConcurrentQueries
+		{
+			private TreeSet<int> tree;
+
+			int sz = 500000;
+
+
+			[SetUp]
+			public void Init()
+			{
+				tree = new TreeSet<int>(new IC());
+				for (int i = 0; i < sz; i++)
+				{
+					tree.Add(i);
+				}
+			}
+
+
+
+			class A
+			{
+				public int count = 0;
+
+				TreeSet<int> t;
+
+
+				public A(TreeSet<int> t) { this.t = t; }
+
+
+				public void a(int i) { count++; }
+
+
+				public void traverse() { t.Apply(new Act<int>(a)); }
+			}
+
+
+
+
+			[Test]
+			public void Safe()
+			{
+				A a = new A(tree);
+
+				a.traverse();
+				Assert.AreEqual(sz, a.count);
+			}
+
+
+			[Test]
+			public void RegrettablyUnsafe()
+			{
+				System.Threading.Thread[] t = new System.Threading.Thread[10];
+				A[] a = new A[10];
+				for (int i = 0; i < 10; i++)
+				{
+					a[i] = new A(tree);
+					t[i] = new System.Threading.Thread(new System.Threading.ThreadStart(a[i].traverse));
+				}
+
+				for (int i = 0; i < 10; i++)
+					t[i].Start();
+				for (int i = 0; i < 10; i++)
+					t[i].Join();
+				for (int i = 0; i < 10; i++)
+					Assert.AreEqual(sz,a[i].count);
+
+			}
+
+
+			[TearDown]
+			public void Dispose() { tree = null; }
+		}
+	}
+
+
+
+
+	namespace Hashing
+	{
+		[TestFixture]
+		public class ISequenced
+		{
+			private ISequenced<int> dit, dat, dut;
+
+
+			[SetUp]
+			public void Init()
+			{
+                dit = new TreeSet<int>(Comparer<int>.Default, EqualityComparer<int>.Default);
+                dat = new TreeSet<int>(Comparer<int>.Default, EqualityComparer<int>.Default);
+                dut = new TreeSet<int>(new RevIC(), EqualityComparer<int>.Default);
+			}
+
+
+			[Test]
+			public void EmptyEmpty()
+			{
+				Assert.IsTrue(dit.SequencedEquals(dat));
+			}
+
+
+			[Test]
+			public void EmptyNonEmpty()
+			{
+				dit.Add(3);
+				Assert.IsFalse(dit.SequencedEquals(dat));
+				Assert.IsFalse(dat.SequencedEquals(dit));
+			}
+
+			[Test]
+			public void HashVal()
+			{
+				Assert.AreEqual(CHC.sequencedhashcode(), dit.GetSequencedHashCode());
+				dit.Add(3);
+				Assert.AreEqual(CHC.sequencedhashcode(3), dit.GetSequencedHashCode());
+				dit.Add(7);
+				Assert.AreEqual(CHC.sequencedhashcode(3, 7), dit.GetSequencedHashCode());
+				Assert.AreEqual(CHC.sequencedhashcode(), dut.GetSequencedHashCode());
+				dut.Add(3);
+				Assert.AreEqual(CHC.sequencedhashcode(3), dut.GetSequencedHashCode());
+				dut.Add(7);
+				Assert.AreEqual(CHC.sequencedhashcode(7, 3), dut.GetSequencedHashCode());
+			}
+
+
+			[Test]
+			public void Normal()
+			{
+				dit.Add(3);
+				dit.Add(7);
+				dat.Add(3);
+				Assert.IsFalse(dit.SequencedEquals(dat));
+				Assert.IsFalse(dat.SequencedEquals(dit));
+				dat.Add(7);
+				Assert.IsTrue(dit.SequencedEquals(dat));
+				Assert.IsTrue(dat.SequencedEquals(dit));
+			}
+
+
+			[Test]
+			public void WrongOrder()
+			{
+				dit.Add(3);
+				dut.Add(3);
+				Assert.IsTrue(dit.SequencedEquals(dut));
+				Assert.IsTrue(dut.SequencedEquals(dit));
+				dit.Add(7);
+				dut.Add(7);
+				Assert.IsFalse(dit.SequencedEquals(dut));
+				Assert.IsFalse(dut.SequencedEquals(dit));
+			}
+
+
+			[Test]
+			public void Reflexive()
+			{
+				Assert.IsTrue(dit.SequencedEquals(dit));
+				dit.Add(3);
+				Assert.IsTrue(dit.SequencedEquals(dit));
+				dit.Add(7);
+				Assert.IsTrue(dit.SequencedEquals(dit));
+			}
+
+
+			[TearDown]
+			public void Dispose()
+			{
+				dit = null;
+				dat = null;
+				dut = null;
+			}
+		}
+
+
+
+		[TestFixture]
+		public class IEditableCollection
+		{
+			private ICollection<int> dit, dat, dut;
+
+
+			[SetUp]
+			public void Init()
+			{
+                dit = new TreeSet<int>(Comparer<int>.Default, EqualityComparer<int>.Default);
+                dat = new TreeSet<int>(Comparer<int>.Default, EqualityComparer<int>.Default);
+                dut = new TreeSet<int>(new RevIC(), EqualityComparer<int>.Default);
+			}
+
+
+			[Test]
+			public void EmptyEmpty()
+			{
+				Assert.IsTrue(dit.UnsequencedEquals(dat));
+			}
+
+
+			[Test]
+			public void EmptyNonEmpty()
+			{
+				dit.Add(3);
+				Assert.IsFalse(dit.UnsequencedEquals(dat));
+				Assert.IsFalse(dat.UnsequencedEquals(dit));
+			}
+
+
+			[Test]
+			public void HashVal()
+			{
+                Assert.AreEqual(CHC.unsequencedhashcode(), dit.GetUnsequencedHashCode());
+                dit.Add(3);
+                Assert.AreEqual(CHC.unsequencedhashcode(3), dit.GetUnsequencedHashCode());
+                dit.Add(7);
+                Assert.AreEqual(CHC.unsequencedhashcode(3, 7), dit.GetUnsequencedHashCode());
+                Assert.AreEqual(CHC.unsequencedhashcode(), dut.GetUnsequencedHashCode());
+                dut.Add(3);
+                Assert.AreEqual(CHC.unsequencedhashcode(3), dut.GetUnsequencedHashCode());
+                dut.Add(7);
+                Assert.AreEqual(CHC.unsequencedhashcode(7, 3), dut.GetUnsequencedHashCode());
+            }
+
+
+			[Test]
+			public void Normal()
+			{
+				dit.Add(3);
+				dit.Add(7);
+				dat.Add(3);
+				Assert.IsFalse(dit.UnsequencedEquals(dat));
+				Assert.IsFalse(dat.UnsequencedEquals(dit));
+				dat.Add(7);
+				Assert.IsTrue(dit.UnsequencedEquals(dat));
+				Assert.IsTrue(dat.UnsequencedEquals(dit));
+			}
+
+
+			[Test]
+			public void WrongOrder()
+			{
+				dit.Add(3);
+				dut.Add(3);
+				Assert.IsTrue(dit.UnsequencedEquals(dut));
+				Assert.IsTrue(dut.UnsequencedEquals(dit));
+				dit.Add(7);
+				dut.Add(7);
+				Assert.IsTrue(dit.UnsequencedEquals(dut));
+				Assert.IsTrue(dut.UnsequencedEquals(dit));
+			}
+
+
+			[Test]
+			public void Reflexive()
+			{
+				Assert.IsTrue(dit.UnsequencedEquals(dit));
+				dit.Add(3);
+				Assert.IsTrue(dit.UnsequencedEquals(dit));
+				dit.Add(7);
+				Assert.IsTrue(dit.UnsequencedEquals(dit));
+			}
+
+
+			[TearDown]
+			public void Dispose()
+			{
+				dit = null;
+				dat = null;
+				dut = null;
+			}
+		}
+
+	}
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/AssemblyInfo.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/AssemblyInfo.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/AssemblyInfo.cs	(revision 3)
@@ -0,0 +1,79 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System.Reflection;
+using System.Runtime.CompilerServices;
+
+//
+// General Information about an assembly is controlled through the following 
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+//
+[assembly: AssemblyTitle("")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("")]
+[assembly: AssemblyCopyright("")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+//
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version 
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Revision and Build Numbers 
+// by using the '*' as shown below:
+
+[assembly: AssemblyVersion("1.0.*")]
+
+//
+// In order to sign your assembly you must specify a key to use. Refer to the 
+// Microsoft .NET Framework documentation for more information on assembly signing.
+//
+// Use the attributes below to control which key is used for signing. 
+//
+// Notes: 
+//   (*) If no key is specified, the assembly is not signed.
+//   (*) KeyName refers to a key that has been installed in the Crypto Service
+//       Provider (CSP) on your machine. KeyFile refers to a file which contains
+//       a key.
+//   (*) If the KeyFile and the KeyName values are both specified, the 
+//       following processing occurs:
+//       (1) If the KeyName can be found in the CSP, that key is used.
+//       (2) If the KeyName does not exist and the KeyFile does exist, the key 
+//           in the KeyFile is installed into the CSP and used.
+//   (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
+//       When specifying the KeyFile, the location of the KeyFile should be
+//       relative to the project output directory which is
+//       %Project Directory%\obj\<configuration>. For example, if your KeyFile is
+//       located in the project directory, you would specify the AssemblyKeyFile 
+//       attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
+//   (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
+//       documentation for more information on this.
+//
+[assembly: AssemblyDelaySign(false)]
+[assembly: AssemblyKeyFile("")]
+[assembly: AssemblyKeyName("")]
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/BasesTest.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/BasesTest.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/BasesTest.cs	(revision 3)
@@ -0,0 +1,569 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+
+namespace C5UnitTests.support
+{
+  namespace bases
+  {
+    [TestFixture]
+    public class ArrayBaseTest
+    {
+      class ABT : ArrayBase<string>
+      {
+        public ABT() : base(8,NaturalEqualityComparer<string>.Default) { }
+
+        public override string Choose() { if (size > 0) return array[0]; throw new NoSuchItemException(); }
+
+        public string this[int i] { get { return array[i]; } set { array[i] = value; } }
+
+
+        public int thesize { get { return size; } set { size = value; } }
+      }
+
+
+      [Test]
+      public void Check()
+      {
+        ABT abt = new ABT();
+
+        abt.thesize = 3;
+        abt[2] = "aaa";
+        // Assert.IsFalse(abt.Check());
+        abt[0] = "##";
+        abt[1] = "##";
+        Assert.IsTrue(abt.Check());
+      }
+    }
+  }
+
+  namespace itemops
+  {
+    [TestFixture]
+    public class Comparers
+    {
+      class dbl : IComparable<dbl>
+      {
+        double d;
+
+        public dbl(double din) { d = din; }
+
+        public int CompareTo(dbl that)
+        {
+          return d < that.d ? -1 : d == that.d ? 0 : 1;
+        }
+        public bool Equals(dbl that) { return d == that.d; }
+      }
+
+      [Test]
+      [ExpectedException(typeof(NotComparableException))]
+      public void NotComparable()
+      {
+        SCG.IComparer<object> foo = Comparer<object>.Default;
+      }
+
+      [Test]
+      public void GenericC()
+      {
+        SCG.IComparer<dbl> h = new NaturalComparer<dbl>();
+        dbl s = new dbl(3.4);
+        dbl t = new dbl(3.4);
+        dbl u = new dbl(7.4);
+
+        Assert.AreEqual(0, h.Compare(s, t));
+        Assert.IsTrue(h.Compare(s, u) < 0);
+      }
+
+
+      [Test]
+      public void OrdinaryC()
+      {
+        SCG.IComparer<string> h = new NaturalComparerO<string>();
+        string s = "bamse";
+        string t = "bamse";
+        string u = "bimse";
+
+        Assert.AreEqual(0, h.Compare(s, t));
+        Assert.IsTrue(h.Compare(s, u) < 0);
+      }
+
+
+      [Test]
+      public void GenericCViaBuilder()
+      {
+        SCG.IComparer<dbl> h = Comparer<dbl>.Default;
+        dbl s = new dbl(3.4);
+        dbl t = new dbl(3.4);
+        dbl u = new dbl(7.4);
+
+        Assert.AreEqual(0, h.Compare(s, t));
+        Assert.IsTrue(h.Compare(s, u) < 0);
+        Assert.AreSame(h, Comparer<dbl>.Default);
+      }
+
+
+      [Test]
+      public void OrdinaryCViaBuilder()
+      {
+        SCG.IComparer<string> h = Comparer<string>.Default;
+        string s = "bamse";
+        string t = "bamse";
+        string u = "bimse";
+
+        Assert.AreEqual(0, h.Compare(s, t));
+        Assert.IsTrue(h.Compare(s, u) < 0);
+        Assert.AreSame(h, Comparer<string>.Default);
+
+      }
+
+      public void ComparerViaBuilderTest<T>(T item1, T item2)
+          where T : IComparable<T>
+      {
+        SCG.IComparer<T> h = Comparer<T>.Default;
+        Assert.AreSame(h, Comparer<T>.Default);
+        Assert.AreEqual(0, h.Compare(item1, item1));
+        Assert.AreEqual(0, h.Compare(item2, item2));
+        Assert.IsTrue(h.Compare(item1, item2) < 0);
+        Assert.IsTrue(h.Compare(item2, item1) > 0);
+        Assert.AreEqual(Math.Sign(item1.CompareTo(item2)), Math.Sign(h.Compare(item1, item2)));
+        Assert.AreEqual(Math.Sign(item2.CompareTo(item1)), Math.Sign(h.Compare(item2, item1)));
+      }
+
+      [Test]
+      public void PrimitiveComparersViaBuilder()
+      {
+        ComparerViaBuilderTest<char>('A', 'a');
+        ComparerViaBuilderTest<sbyte>(-122, 126);
+        ComparerViaBuilderTest<byte>(122, 126);
+        ComparerViaBuilderTest<short>(-30000, 3);
+        ComparerViaBuilderTest<ushort>(3, 50000);
+        ComparerViaBuilderTest<int>(-10000000, 10000);
+        ComparerViaBuilderTest<uint>(10000000, 3000000000);
+        ComparerViaBuilderTest<long>(-1000000000000, 10000000);
+        ComparerViaBuilderTest<ulong>(10000000000000UL, 10000000000004UL);
+        ComparerViaBuilderTest<float>(-0.001F, 0.00001F);
+        ComparerViaBuilderTest<double>(-0.001, 0.00001E-200);
+        ComparerViaBuilderTest<decimal>(-20.001M, 19.999M);
+      }
+
+      // This test is obsoleted by the one above, but we keep it for good measure
+      [Test]
+      public void IntComparerViaBuilder()
+      {
+        SCG.IComparer<int> h = Comparer<int>.Default;
+        int s = 4;
+        int t = 4;
+        int u = 5;
+
+        Assert.AreEqual(0, h.Compare(s, t));
+        Assert.IsTrue(h.Compare(s, u) < 0);
+        Assert.AreSame(h, Comparer<int>.Default);
+      }
+
+      [Test]
+      public void Nulls()
+      {
+        Assert.IsTrue(Comparer<string>.Default.Compare(null, "abe") < 0);
+        Assert.IsTrue(Comparer<string>.Default.Compare(null, null) == 0);
+        Assert.IsTrue(Comparer<string>.Default.Compare("abe", null) > 0);
+      }
+    }
+
+    [TestFixture]
+    public class EqualityComparers
+    {
+      [Test]
+      public void ReftypeequalityComparer()
+      {
+        SCG.IEqualityComparer<string> h = NaturalEqualityComparer<string>.Default;
+        string s = "bamse";
+        string t = "bamse";
+        string u = "bimse";
+
+        Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s));
+        Assert.IsTrue(h.Equals(s, t));
+        Assert.IsFalse(h.Equals(s, u));
+      }
+
+
+      [Test]
+      public void ValuetypeequalityComparer()
+      {
+        SCG.IEqualityComparer<double> h = NaturalEqualityComparer<double>.Default;
+        double s = 3.4;
+        double t = 3.4;
+        double u = 5.7;
+
+        Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s));
+        Assert.IsTrue(h.Equals(s, t));
+        Assert.IsFalse(h.Equals(s, u));
+      }
+
+      internal class REHTest { public override int GetHashCode() { return 37; } }
+
+      [Test]
+      public void ReferenceEqualityEqualityComparerTest()
+      {
+        REHTest rehtest = new REHTest();
+        SCG.IEqualityComparer<REHTest> equalityComparer = ReferenceEqualityComparer<REHTest>.Default;
+        Assert.AreEqual(37, rehtest.GetHashCode());
+        Assert.IsFalse(equalityComparer.GetHashCode(rehtest) == 37);
+      }
+
+      [Test]
+      public void ReftypeequalityComparerViaBuilder()
+      {
+        SCG.IEqualityComparer<string> h = EqualityComparer<string>.Default;
+        string s = "bamse";
+        string t = "bamse";
+        string u = "bimse";
+
+        Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s));
+        Assert.IsTrue(h.Equals(s, t));
+        Assert.IsFalse(h.Equals(s, u));
+        Assert.AreSame(h, EqualityComparer<string>.Default);
+      }
+
+
+      [Test]
+      public void ValuetypeequalityComparerViaBuilder()
+      {
+        SCG.IEqualityComparer<double> h = EqualityComparer<double>.Default;
+        double s = 3.4;
+        double t = 3.4;
+        double u = 5.7;
+
+        Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s));
+        Assert.IsTrue(h.Equals(s, t));
+        Assert.IsFalse(h.Equals(s, u));
+        Assert.AreSame(h, EqualityComparer<double>.Default);
+      }
+
+      [Test]
+      public void CharequalityComparerViaBuilder()
+      {
+        SCG.IEqualityComparer<char> h = EqualityComparer<char>.Default;
+        char s = '�';
+        char t = '�';
+        char u = 'r';
+
+        Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s));
+        Assert.IsTrue(h.Equals(s, t));
+        Assert.IsFalse(h.Equals(s, u));
+        Assert.AreSame(h, EqualityComparer<char>.Default);
+      }
+
+      [Test]
+      public void SbyteequalityComparerViaBuilder()
+      {
+        SCG.IEqualityComparer<sbyte> h = EqualityComparer<sbyte>.Default;
+        sbyte s = 3;
+        sbyte t = 3;
+        sbyte u = -5;
+
+        Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s));
+        Assert.IsTrue(h.Equals(s, t));
+        Assert.IsFalse(h.Equals(s, u));
+        Assert.AreSame(h, EqualityComparer<sbyte>.Default);
+      }
+
+      [Test]
+      public void ByteequalityComparerViaBuilder()
+      {
+        SCG.IEqualityComparer<byte> h = EqualityComparer<byte>.Default;
+        byte s = 3;
+        byte t = 3;
+        byte u = 5;
+
+        Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s));
+        Assert.IsTrue(h.Equals(s, t));
+        Assert.IsFalse(h.Equals(s, u));
+        Assert.AreSame(h, EqualityComparer<byte>.Default);
+      }
+
+      [Test]
+      public void ShortequalityComparerViaBuilder()
+      {
+        SCG.IEqualityComparer<short> h = EqualityComparer<short>.Default;
+        short s = 3;
+        short t = 3;
+        short u = -5;
+
+        Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s));
+        Assert.IsTrue(h.Equals(s, t));
+        Assert.IsFalse(h.Equals(s, u));
+        Assert.AreSame(h, EqualityComparer<short>.Default);
+      }
+
+      [Test]
+      public void UshortequalityComparerViaBuilder()
+      {
+        SCG.IEqualityComparer<ushort> h = EqualityComparer<ushort>.Default;
+        ushort s = 3;
+        ushort t = 3;
+        ushort u = 60000;
+
+        Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s));
+        Assert.IsTrue(h.Equals(s, t));
+        Assert.IsFalse(h.Equals(s, u));
+        Assert.AreSame(h, EqualityComparer<ushort>.Default);
+      }
+
+      [Test]
+      public void IntequalityComparerViaBuilder()
+      {
+        SCG.IEqualityComparer<int> h = EqualityComparer<int>.Default;
+        int s = 3;
+        int t = 3;
+        int u = -5;
+
+        Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s));
+        Assert.IsTrue(h.Equals(s, t));
+        Assert.IsFalse(h.Equals(s, u));
+        Assert.AreSame(h, EqualityComparer<int>.Default);
+      }
+
+      [Test]
+      public void UintequalityComparerViaBuilder()
+      {
+        SCG.IEqualityComparer<uint> h = EqualityComparer<uint>.Default;
+        uint s = 3;
+        uint t = 3;
+        uint u = 3000000000;
+
+        Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s));
+        Assert.IsTrue(h.Equals(s, t));
+        Assert.IsFalse(h.Equals(s, u));
+        Assert.AreSame(h, EqualityComparer<uint>.Default);
+      }
+
+      [Test]
+      public void LongequalityComparerViaBuilder()
+      {
+        SCG.IEqualityComparer<long> h = EqualityComparer<long>.Default;
+        long s = 3;
+        long t = 3;
+        long u = -500000000000000L;
+
+        Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s));
+        Assert.IsTrue(h.Equals(s, t));
+        Assert.IsFalse(h.Equals(s, u));
+        Assert.AreSame(h, EqualityComparer<long>.Default);
+      }
+
+      [Test]
+      public void UlongequalityComparerViaBuilder()
+      {
+        SCG.IEqualityComparer<ulong> h = EqualityComparer<ulong>.Default;
+        ulong s = 3;
+        ulong t = 3;
+        ulong u = 500000000000000UL;
+
+        Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s));
+        Assert.IsTrue(h.Equals(s, t));
+        Assert.IsFalse(h.Equals(s, u));
+        Assert.AreSame(h, EqualityComparer<ulong>.Default);
+      }
+
+      [Test]
+      public void FloatequalityComparerViaBuilder()
+      {
+        SCG.IEqualityComparer<float> h = EqualityComparer<float>.Default;
+        float s = 3.1F;
+        float t = 3.1F;
+        float u = -5.2F;
+
+        Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s));
+        Assert.IsTrue(h.Equals(s, t));
+        Assert.IsFalse(h.Equals(s, u));
+        Assert.AreSame(h, EqualityComparer<float>.Default);
+      }
+
+      [Test]
+      public void DoubleequalityComparerViaBuilder()
+      {
+        SCG.IEqualityComparer<double> h = EqualityComparer<double>.Default;
+        double s = 3.12345;
+        double t = 3.12345;
+        double u = -5.2;
+
+        Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s));
+        Assert.IsTrue(h.Equals(s, t));
+        Assert.IsFalse(h.Equals(s, u));
+        Assert.AreSame(h, EqualityComparer<double>.Default);
+      }
+
+      [Test]
+      public void DecimalequalityComparerViaBuilder()
+      {
+        SCG.IEqualityComparer<decimal> h = EqualityComparer<decimal>.Default;
+        decimal s = 3.0001M;
+        decimal t = 3.0001M;
+        decimal u = -500000000000000M;
+
+        Assert.AreEqual(s.GetHashCode(), h.GetHashCode(s));
+        Assert.IsTrue(h.Equals(s, t));
+        Assert.IsFalse(h.Equals(s, u));
+        Assert.AreSame(h, EqualityComparer<decimal>.Default);
+      }
+
+      [Test]
+      public void UnseqequalityComparerViaBuilder()
+      {
+        SCG.IEqualityComparer<ICollection<int>> h = EqualityComparer<ICollection<int>>.Default;
+        ICollection<int> s = new LinkedList<int>();
+        ICollection<int> t = new LinkedList<int>();
+        ICollection<int> u = new LinkedList<int>();
+        s.Add(1); s.Add(2); s.Add(3);
+        t.Add(3); t.Add(2); t.Add(1);
+        u.Add(3); u.Add(2); u.Add(4);
+        Assert.AreEqual(s.GetUnsequencedHashCode(), h.GetHashCode(s));
+        Assert.IsTrue(h.Equals(s, t));
+        Assert.IsFalse(h.Equals(s, u));
+        Assert.AreSame(h, EqualityComparer<ICollection<int>>.Default);
+      }
+
+      [Test]
+      public void SeqequalityComparerViaBuilder2()
+      {
+        SCG.IEqualityComparer<LinkedList<int>> h = EqualityComparer<LinkedList<int>>.Default;
+        LinkedList<int> s = new LinkedList<int>();
+        s.Add(1); s.Add(2); s.Add(3);
+        Assert.AreEqual(CHC.sequencedhashcode(1, 2, 3), h.GetHashCode(s));
+      }
+
+      [Test]
+      public void UnseqequalityComparerViaBuilder2()
+      {
+        SCG.IEqualityComparer<HashSet<int>> h = EqualityComparer<HashSet<int>>.Default;
+        HashSet<int> s = new HashSet<int>();
+        s.Add(1); s.Add(2); s.Add(3);
+        Assert.AreEqual(CHC.unsequencedhashcode(1, 2, 3), h.GetHashCode(s));
+      }
+
+      //generic types implementing collection interfaces
+      [Test]
+      public void SeqequalityComparerViaBuilder3()
+      {
+        SCG.IEqualityComparer<IList<int>> h = EqualityComparer<IList<int>>.Default;
+        IList<int> s = new LinkedList<int>();
+        s.Add(1); s.Add(2); s.Add(3);
+        Assert.AreEqual(CHC.sequencedhashcode(1, 2, 3), h.GetHashCode(s));
+      }
+
+      interface IFoo<T> : ICollection<T> { void Bamse();      }
+
+      class Foo<T> : HashSet<T>, IFoo<T>
+      {
+        internal Foo() : base() { }
+        public void Bamse() { }
+      }
+
+      [Test]
+      public void UnseqequalityComparerViaBuilder3()
+      {
+        SCG.IEqualityComparer<IFoo<int>> h = EqualityComparer<IFoo<int>>.Default;
+        IFoo<int> s = new Foo<int>();
+        s.Add(1); s.Add(2); s.Add(3);
+        Assert.AreEqual(CHC.unsequencedhashcode(1, 2, 3), h.GetHashCode(s));
+      }
+
+      //Nongeneric types implementing collection types:
+      interface IBaz : ISequenced<int> { void Bamse(); }
+
+      class Baz : LinkedList<int>, IBaz
+      {
+        internal Baz() : base() { }
+        public void Bamse() { }
+        //int ISequenced<int>.GetHashCode() { return sequencedhashcode(); }
+        //bool ISequenced<int>.Equals(ISequenced<int> that) { return sequencedequals(that); }
+      }
+
+      [Test]
+      public void SeqequalityComparerViaBuilder4()
+      {
+        SCG.IEqualityComparer<IBaz> h = EqualityComparer<IBaz>.Default;
+        IBaz s = new Baz();
+        s.Add(1); s.Add(2); s.Add(3);
+        Assert.AreEqual(CHC.sequencedhashcode(1, 2, 3), h.GetHashCode(s));
+      }
+
+      interface IBar : ICollection<int>
+      {
+        void Bamse();
+      }
+
+      class Bar : HashSet<int>, IBar
+      {
+        internal Bar() : base() { }
+        public void Bamse() { }
+
+        //TODO: remove all this workaround stuff:
+ 
+        bool ICollection<int>.ContainsAll<U>(System.Collections.Generic.IEnumerable<U> items) 
+        {
+          throw new NotImplementedException();
+        }
+ 
+        void ICollection<int>.RemoveAll<U>(System.Collections.Generic.IEnumerable<U> items) 
+        {
+          throw new NotImplementedException();
+        }
+
+        void ICollection<int>.RetainAll<U>(System.Collections.Generic.IEnumerable<U> items) 
+        {
+          throw new NotImplementedException();
+        }
+
+        void IExtensible<int>.AddAll<U>(System.Collections.Generic.IEnumerable<U> items) 
+        {
+          throw new NotImplementedException();
+        }
+
+      }
+
+      [Test]
+      public void UnseqequalityComparerViaBuilder4()
+      {
+        SCG.IEqualityComparer<IBar> h = EqualityComparer<IBar>.Default;
+        IBar s = new Bar();
+        s.Add(1); s.Add(2); s.Add(3);
+        Assert.AreEqual(CHC.unsequencedhashcode(1, 2, 3), h.GetHashCode(s));
+      }
+      
+      [Test]
+      public void StaticEqualityComparerWithNull()
+      {
+          ArrayList<double> arr = new ArrayList<double>();
+          SCG.IEqualityComparer<double> eqc = EqualityComparer<double>.Default;
+          Assert.IsTrue(CollectionBase<double>.StaticEquals(arr, arr, eqc));
+          Assert.IsTrue(CollectionBase<double>.StaticEquals(null, null, eqc));
+          Assert.IsFalse(CollectionBase<double>.StaticEquals(arr, null, eqc));
+          Assert.IsFalse(CollectionBase<double>.StaticEquals(null, arr, eqc));
+      }
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/InterfacesTest.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/InterfacesTest.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/InterfacesTest.cs	(revision 3)
@@ -0,0 +1,453 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+
+namespace C5UnitTests.interfaces
+{
+  [TestFixture]
+  public class ICollectionsTests
+  {
+    public void TryC5Coll(ICollection<double> coll)
+    {
+      Assert.AreEqual(0, coll.Count);
+      double[] arr = { };
+      coll.CopyTo(arr, 0);
+      Assert.IsFalse(coll.IsReadOnly);
+      coll.Add(2.3);
+      coll.Add(3.2);
+      Assert.AreEqual(2, coll.Count);
+      Assert.IsTrue(coll.Contains(2.3));
+      Assert.IsFalse(coll.Contains(3.1));
+      Assert.IsFalse(coll.Remove(3.1));
+      Assert.IsTrue(coll.Remove(3.2));
+      Assert.IsFalse(coll.Contains(3.1));
+      Assert.AreEqual(1, coll.Count);
+      coll.Clear();
+      Assert.AreEqual(0, coll.Count);
+      Assert.IsFalse(coll.Remove(3.1));
+    }
+
+    public void TrySCGColl(SCG.ICollection<double> coll)
+    {
+      // All members of SCG.ICollection<T>
+      Assert.AreEqual(0, coll.Count);
+      double[] arr = { };
+      coll.CopyTo(arr, 0);
+      Assert.IsFalse(coll.IsReadOnly);
+      coll.Add(2.3);
+      coll.Add(3.2);
+      Assert.AreEqual(2, coll.Count);
+      Assert.IsTrue(coll.Contains(2.3));
+      Assert.IsFalse(coll.Contains(3.1));
+      Assert.IsFalse(coll.Remove(3.1));
+      Assert.IsTrue(coll.Remove(3.2));
+      Assert.IsFalse(coll.Contains(3.1));
+      Assert.AreEqual(1, coll.Count);
+      coll.Clear();
+      Assert.AreEqual(0, coll.Count);
+      Assert.IsFalse(coll.Remove(3.1));
+    }
+
+    public void TryBothColl(ICollection<double> coll)
+    {
+      TryC5Coll(coll);
+      TrySCGColl(coll);
+    }
+
+
+    [Test]
+    public void Test1()
+    {
+      TryBothColl(new HashSet<double>());
+      TryBothColl(new HashBag<double>());
+      TryBothColl(new TreeSet<double>());
+      TryBothColl(new TreeBag<double>());
+      TryBothColl(new ArrayList<double>());
+      TryBothColl(new LinkedList<double>());
+      TryBothColl(new HashedArrayList<double>());
+      TryBothColl(new HashedLinkedList<double>());
+      TryBothColl(new SortedArray<double>());
+    }
+  }
+
+  [TestFixture]
+  public class SCIListTests
+  {
+    class A { }
+    class B : A { }
+    class C : B { }
+
+    public void TrySCIList(System.Collections.IList list)
+    {
+      // Should be called with a C5.IList<B> which is not a WrappedArray
+      Assert.AreEqual(0, list.Count);
+      list.CopyTo(new A[0], 0);
+      list.CopyTo(new B[0], 0);
+      list.CopyTo(new C[0], 0);
+      Assert.IsTrue(!list.IsFixedSize);
+      Assert.IsFalse(list.IsReadOnly);
+      Assert.IsFalse(list.IsSynchronized);
+      Assert.AreNotEqual(null, list.SyncRoot);
+      Object b1 = new B(), b2 = new B(), c1 = new C(), c2 = new C();
+      Assert.AreEqual(0, list.Add(b1));
+      Assert.AreEqual(1, list.Add(c1));
+      Assert.AreEqual(2, list.Count);
+      Assert.IsTrue(list.Contains(c1));
+      Assert.IsFalse(list.Contains(b2));
+      list[0] = b2;
+      Assert.AreEqual(b2, list[0]);
+      list[1] = c2;
+      Assert.AreEqual(c2, list[1]);
+      Assert.IsTrue(list.Contains(b2));
+      Assert.IsTrue(list.Contains(c2));
+      Array arrA = new A[2], arrB = new B[2];
+      list.CopyTo(arrA, 0);
+      list.CopyTo(arrB, 0);
+      Assert.AreEqual(b2, arrA.GetValue(0));
+      Assert.AreEqual(b2, arrB.GetValue(0));
+      Assert.AreEqual(c2, arrA.GetValue(1));
+      Assert.AreEqual(c2, arrB.GetValue(1));
+      Assert.AreEqual(0, list.IndexOf(b2));
+      Assert.AreEqual(-1, list.IndexOf(b1));
+      list.Remove(b1);
+      list.Remove(b2);
+      Assert.IsFalse(list.Contains(b2));
+      Assert.AreEqual(1, list.Count); // Contains c2 only
+      list.Insert(0, b2);
+      list.Insert(2, b1);
+      Assert.AreEqual(b2, list[0]);
+      Assert.AreEqual(c2, list[1]);
+      Assert.AreEqual(b1, list[2]);
+      list.Remove(c2);
+      Assert.AreEqual(b2, list[0]);
+      Assert.AreEqual(b1, list[1]);
+      list.RemoveAt(1);
+      Assert.AreEqual(b2, list[0]); 
+      list.Clear();
+      Assert.AreEqual(0, list.Count);
+      list.Remove(b1);
+    }
+
+    [Test]
+    public void Test1()
+    {
+      TrySCIList(new ArrayList<B>());
+      TrySCIList(new HashedArrayList<B>());
+      TrySCIList(new LinkedList<B>());
+      TrySCIList(new HashedLinkedList<B>());
+    }
+
+    [Test]
+    public void TryWrappedArrayAsSCIList1()
+    {
+      B[] myarray = new B[] { new B(), new B(), new C() };
+      System.Collections.IList list = new WrappedArray<B>(myarray);
+      // Should be called with a three-element WrappedArray<B>
+      Assert.AreEqual(3, list.Count);
+      Assert.IsTrue(list.IsFixedSize);
+      Assert.IsFalse(list.IsSynchronized);
+      Assert.AreNotEqual(null, list.SyncRoot);
+      Assert.AreEqual(myarray.SyncRoot, list.SyncRoot);
+      Object b1 = new B(), b2 = new B(), c1 = new C(), c2 = new C();
+      list[0] = b2;
+      Assert.AreEqual(b2, list[0]);
+      list[1] = c2;
+      Assert.AreEqual(c2, list[1]);
+      Assert.IsTrue(list.Contains(b2));
+      Assert.IsTrue(list.Contains(c2));
+      Array arrA = new A[3], arrB = new B[3];
+      list.CopyTo(arrA, 0);
+      list.CopyTo(arrB, 0);
+      Assert.AreEqual(b2, arrA.GetValue(0));
+      Assert.AreEqual(b2, arrB.GetValue(0));
+      Assert.AreEqual(c2, arrA.GetValue(1));
+      Assert.AreEqual(c2, arrB.GetValue(1));
+      Assert.AreEqual(0, list.IndexOf(b2));
+      Assert.AreEqual(-1, list.IndexOf(b1));
+      Assert.AreEqual(-1, list.IndexOf(c1));
+      Assert.IsFalse(list.Contains(b1));
+      Assert.IsFalse(list.Contains(c1));
+    }
+
+    [Test]
+    public void TryWrappedArrayAsSCIList2()
+    {
+      B[] myarray = new B[] { };
+      System.Collections.IList list = new WrappedArray<B>(myarray);
+      // Should be called with an empty WrappedArray<B>
+      Assert.AreEqual(0, list.Count);
+      list.CopyTo(new A[0], 0);
+      list.CopyTo(new B[0], 0);
+      list.CopyTo(new C[0], 0);
+      Assert.IsFalse(list.IsSynchronized);
+      Assert.AreNotEqual(null, list.SyncRoot);
+      Object b1 = new B(), b2 = new B(), c1 = new C(), c2 = new C();
+      Assert.IsFalse(list.Contains(b2));
+      Assert.IsFalse(list.Contains(c2));
+      Assert.AreEqual(-1, list.IndexOf(b1));
+      Assert.AreEqual(-1, list.IndexOf(c1));
+    }
+
+    [Test]
+    public void TryGuardedListAsSCIList1()
+    {
+      B b1_ = new B(), b2_ = new B();
+      C c1_ = new C(), c2_ = new C();
+      ArrayList<B> mylist = new ArrayList<B>();
+      mylist.AddAll(new B[] { b1_, b2_, c1_ });
+      System.Collections.IList list = new GuardedList<B>(mylist);
+      Object b1 = b1_, b2 = b2_, c1 = c1_, c2 = c2_;
+      // Should be called with a three-element GuardedList<B>
+      Assert.AreEqual(3, list.Count);
+      Assert.IsTrue(list.IsFixedSize);
+      Assert.IsTrue(list.IsReadOnly);
+      Assert.IsFalse(list.IsSynchronized);
+      Assert.AreNotEqual(null, list.SyncRoot);
+      Assert.AreEqual(list.SyncRoot, ((System.Collections.IList)mylist).SyncRoot);
+      Assert.IsTrue(list.Contains(b1)); 
+      Assert.IsTrue(list.Contains(b2));
+      Assert.IsTrue(list.Contains(c1));
+      Assert.IsFalse(list.Contains(c2));
+      Array arrA = new A[3], arrB = new B[3];
+      list.CopyTo(arrA, 0);
+      list.CopyTo(arrB, 0);
+      Assert.AreEqual(b1, arrA.GetValue(0));
+      Assert.AreEqual(b1, arrB.GetValue(0));
+      Assert.AreEqual(b2, arrA.GetValue(1));
+      Assert.AreEqual(b2, arrB.GetValue(1));
+      Assert.AreEqual(0, list.IndexOf(b1));
+      Assert.AreEqual(-1, list.IndexOf(c2));
+    }
+
+    [Test]
+    public void TryGuardedListAsSCIList2()
+    {
+      System.Collections.IList list = new GuardedList<B>(new ArrayList<B>());
+      // Should be called with an empty GuardedList<B>
+      Assert.AreEqual(0, list.Count);
+      list.CopyTo(new A[0], 0);
+      list.CopyTo(new B[0], 0);
+      list.CopyTo(new C[0], 0);
+      Assert.IsFalse(list.IsSynchronized);
+      Assert.AreNotEqual(null, list.SyncRoot);
+      Object b1 = new B(), b2 = new B(), c1 = new C(), c2 = new C();
+      Assert.IsFalse(list.Contains(b2));
+      Assert.IsFalse(list.Contains(c2));
+      Assert.AreEqual(-1, list.IndexOf(b1));
+      Assert.AreEqual(-1, list.IndexOf(c1));
+    }
+
+    [Test]
+    public void TryViewOfGuardedListAsSCIList1()
+    {
+      B b1_ = new B(), b2_ = new B();
+      C c1_ = new C(), c2_ = new C();
+      ArrayList<B> mylist = new ArrayList<B>();
+      mylist.AddAll(new B[] { new B(), b1_, b2_, c1_, new B()});
+      System.Collections.IList list = new GuardedList<B>(mylist).View(1, 3);
+      Object b1 = b1_, b2 = b2_, c1 = c1_, c2 = c2_;
+      // Should be called with a three-element view of a GuardedList<B>
+      Assert.AreEqual(3, list.Count);
+      Assert.IsTrue(list.IsFixedSize);
+      Assert.IsTrue(list.IsReadOnly);
+      Assert.IsFalse(list.IsSynchronized);
+      Assert.AreNotEqual(null, list.SyncRoot);
+      Assert.AreEqual(list.SyncRoot, ((System.Collections.IList)mylist).SyncRoot);
+      Assert.IsTrue(list.Contains(b1));
+      Assert.IsTrue(list.Contains(b2));
+      Assert.IsTrue(list.Contains(c1));
+      Assert.IsFalse(list.Contains(c2));
+      Array arrA = new A[3], arrB = new B[3];
+      list.CopyTo(arrA, 0);
+      list.CopyTo(arrB, 0);
+      Assert.AreEqual(b1, arrA.GetValue(0));
+      Assert.AreEqual(b1, arrB.GetValue(0));
+      Assert.AreEqual(b2, arrA.GetValue(1));
+      Assert.AreEqual(b2, arrB.GetValue(1));
+      Assert.AreEqual(0, list.IndexOf(b1));
+      Assert.AreEqual(-1, list.IndexOf(c2));
+    }
+
+    [Test]
+    public void TryViewOfGuardedListAsSCIList2()
+    {
+      System.Collections.IList list = new GuardedList<B>(new ArrayList<B>()).View(0, 0);
+      Assert.AreEqual(0, list.Count);
+      list.CopyTo(new A[0], 0);
+      list.CopyTo(new B[0], 0);
+      list.CopyTo(new C[0], 0);
+      Assert.IsFalse(list.IsSynchronized);
+      Assert.AreNotEqual(null, list.SyncRoot);
+      Object b1 = new B(), b2 = new B(), c1 = new C(), c2 = new C();
+      Assert.IsFalse(list.Contains(b2));
+      Assert.IsFalse(list.Contains(c2));
+      Assert.AreEqual(-1, list.IndexOf(b1));
+      Assert.AreEqual(-1, list.IndexOf(c1));
+    }
+
+    void TryListViewAsSCIList1(IList<B> mylist)
+    {
+      B b1_ = new B(), b2_ = new B();
+      C c1_ = new C(), c2_ = new C();
+      mylist.AddAll(new B[] { new B(), b1_, b2_, c1_, new B() });
+      System.Collections.IList list = mylist.View(1, 3);
+      Object b1 = b1_, b2 = b2_, c1 = c1_, c2 = c2_;
+      // Should be called with a three-element view on ArrayList<B>
+      Assert.AreEqual(3, list.Count);
+      Assert.IsFalse(list.IsSynchronized);
+      Assert.AreNotEqual(null, list.SyncRoot);
+      Assert.AreEqual(list.SyncRoot, mylist.SyncRoot);
+      Assert.IsTrue(list.Contains(b1));
+      Assert.IsTrue(list.Contains(b2));
+      Assert.IsTrue(list.Contains(c1));
+      Assert.IsFalse(list.Contains(c2));
+      Array arrA = new A[3], arrB = new B[3];
+      list.CopyTo(arrA, 0);
+      list.CopyTo(arrB, 0);
+      Assert.AreEqual(b1, arrA.GetValue(0));
+      Assert.AreEqual(b1, arrB.GetValue(0));
+      Assert.AreEqual(b2, arrA.GetValue(1));
+      Assert.AreEqual(b2, arrB.GetValue(1));
+      Assert.AreEqual(0, list.IndexOf(b1));
+      Assert.AreEqual(-1, list.IndexOf(c2));
+    }
+
+    void TryListViewAsSCIList2(IList<B> mylist)
+    {
+      System.Collections.IList list = mylist.View(0, 0);
+      Assert.AreEqual(0, list.Count);
+      list.CopyTo(new A[0], 0);
+      list.CopyTo(new B[0], 0);
+      list.CopyTo(new C[0], 0);
+      Assert.IsFalse(list.IsSynchronized);
+      Assert.AreNotEqual(null, list.SyncRoot);
+      Assert.AreEqual(list.SyncRoot, mylist.SyncRoot);
+      Object b1 = new B(), b2 = new B(), c1 = new C(), c2 = new C();
+      Assert.IsFalse(list.Contains(b2));
+      Assert.IsFalse(list.Contains(c2));
+      Assert.AreEqual(-1, list.IndexOf(b1));
+      Assert.AreEqual(-1, list.IndexOf(c1));
+    }
+
+    [Test]
+    public void TryArrayListViewAsSCIList()
+    {
+      TryListViewAsSCIList1(new ArrayList<B>());
+      TryListViewAsSCIList2(new ArrayList<B>());
+    }
+
+    [Test]
+    public void TryLinkedListViewAsSCIList()
+    {
+      TryListViewAsSCIList1(new LinkedList<B>());
+      TryListViewAsSCIList2(new LinkedList<B>());
+    }
+
+    [Test]
+    public void TryHashedArrayListViewAsSCIList()
+    {
+      TryListViewAsSCIList1(new HashedArrayList<B>());
+      TryListViewAsSCIList2(new HashedArrayList<B>());
+    }
+
+    [Test]
+    public void TryHashedLinkedListViewAsSCIList()
+    {
+      TryListViewAsSCIList1(new HashedLinkedList<B>());
+      TryListViewAsSCIList2(new HashedLinkedList<B>());
+    }
+
+    [Test]
+    public void TryGuardedViewAsSCIList()
+    {
+      ArrayList<B> mylist = new ArrayList<B>();
+      TryListViewAsSCIList2(new GuardedList<B>(mylist));
+    }
+  }
+
+  [TestFixture]
+  public class IDictionaryTests
+  {
+    public void TryDictionary(IDictionary<string,string> dict)
+    {
+      Assert.AreEqual(0, dict.Count);
+      Assert.IsTrue(dict.IsEmpty);
+      Assert.IsFalse(dict.IsReadOnly);
+      KeyValuePair<string,string>[] arr = { };
+      dict.CopyTo(arr, 0);
+      dict["R"] = "A";
+      dict["S"] = "B";
+      dict["T"] = "C";
+      String old;
+      Assert.IsTrue(dict.Update("R", "A1"));
+      Assert.AreEqual("A1", dict["R"]);
+
+      Assert.IsFalse(dict.Update("U", "D1"));
+      Assert.IsFalse(dict.Contains("U"));
+      
+      Assert.IsTrue(dict.Update("R", "A2", out old));
+      Assert.AreEqual("A2", dict["R"]);
+      Assert.AreEqual("A1", old);
+      
+      Assert.IsFalse(dict.Update("U", "D2", out old));
+      Assert.AreEqual(null, old);
+      Assert.IsFalse(dict.Contains("U"));
+
+      Assert.IsTrue(dict.UpdateOrAdd("R", "A3"));
+      Assert.AreEqual("A3", dict["R"]);
+      
+      Assert.IsFalse(dict.UpdateOrAdd("U", "D3"));
+      Assert.IsTrue(dict.Contains("U"));
+      Assert.AreEqual("D3", dict["U"]);
+
+      Assert.IsTrue(dict.UpdateOrAdd("R", "A4", out old));
+      Assert.AreEqual("A4", dict["R"]);
+      Assert.AreEqual("A3", old);
+      
+      Assert.IsTrue(dict.UpdateOrAdd("U", "D4", out old));
+      Assert.IsTrue(dict.Contains("U"));
+      Assert.AreEqual("D4", dict["U"]);
+      Assert.AreEqual("D3", old);
+
+      Assert.IsFalse(dict.UpdateOrAdd("V", "E1", out old));
+      Assert.IsTrue(dict.Contains("V"));
+      Assert.AreEqual("E1", dict["V"]);
+      Assert.AreEqual(null, old);
+    }
+
+    [Test]
+    public void TestHashDictionary()
+    {
+      TryDictionary(new HashDictionary<string,string>());
+    }
+
+    [Test]
+    public void TestTreeDictionary()
+    {
+      TryDictionary(new TreeDictionary<string, string>());
+    }
+  }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/Records.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/Records.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/Records.cs	(revision 3)
@@ -0,0 +1,119 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+namespace C5UnitTests.RecordsTests
+{
+  [TestFixture]
+  public class Basic
+  {
+    [SetUp]
+    public void Init()
+    {
+    }
+    [Test]
+    public void FourElement()
+    {
+      Rec<string, string, int, int> rec1, rec2, rec3;
+      rec1 = new Rec<string, string, int, int>("abe", null, 0, 1);
+      rec2 = new Rec<string, string, int, int>("abe", null, 0, 1);
+      rec3 = new Rec<string, string, int, int>("abe", "kat", 0, 1);
+      Assert.IsTrue(rec1 == rec2);
+      Assert.IsFalse(rec1 != rec2);
+      Assert.IsFalse(rec1 == rec3);
+      Assert.IsTrue(rec1 != rec3);
+      Assert.IsTrue(rec1.Equals(rec2));
+      Assert.IsFalse(rec1.Equals(rec3));
+      //
+      Assert.IsFalse(rec1.Equals(null));
+      Assert.IsFalse(rec1.Equals("bamse"));
+      //
+      Assert.IsTrue(rec1.GetHashCode() == rec2.GetHashCode());
+      Assert.IsFalse(rec1.GetHashCode() == rec3.GetHashCode());
+      //
+      Assert.AreEqual("abe", rec1.X1);
+      Assert.IsNull(rec1.X2);
+      Assert.AreEqual(0, rec1.X3);
+      Assert.AreEqual(1, rec1.X4);
+    }
+
+
+    [Test]
+    public void ThreeElement()
+    {
+      Rec<string, string, int> rec1, rec2, rec3;
+      rec1 = new Rec<string, string, int>("abe", null, 0);
+      rec2 = new Rec<string, string, int>("abe", null, 0);
+      rec3 = new Rec<string, string, int>("abe", "kat", 0);
+      Assert.IsTrue(rec1 == rec2);
+      Assert.IsFalse(rec1 != rec2);
+      Assert.IsFalse(rec1 == rec3);
+      Assert.IsTrue(rec1 != rec3);
+      Assert.IsTrue(rec1.Equals(rec2));
+      Assert.IsFalse(rec1.Equals(rec3));
+      //
+      Assert.IsFalse(rec1.Equals(null));
+      Assert.IsFalse(rec1.Equals("bamse"));
+      //
+      Assert.IsTrue(rec1.GetHashCode() == rec2.GetHashCode());
+      Assert.IsFalse(rec1.GetHashCode() == rec3.GetHashCode());
+      //
+      Assert.AreEqual("abe", rec1.X1);
+      Assert.IsNull(rec1.X2);
+      Assert.AreEqual(0, rec1.X3);
+
+    }
+
+    [Test]
+    public void TwoElement()
+    {
+      Rec<string, string> rec1, rec2, rec3;
+      rec1 = new Rec<string, string>("abe", null);
+      rec2 = new Rec<string, string>("abe", null);
+      rec3 = new Rec<string, string>("abe", "kat");
+      Assert.IsTrue(rec1 == rec2);
+      Assert.IsFalse(rec1 != rec2);
+      Assert.IsFalse(rec1 == rec3);
+      Assert.IsTrue(rec1 != rec3);
+      Assert.IsTrue(rec1.Equals(rec2));
+      Assert.IsFalse(rec1.Equals(rec3));
+      //
+      Assert.IsFalse(rec1.Equals(null));
+      Assert.IsFalse(rec1.Equals("bamse"));
+      //
+      Assert.IsTrue(rec1.GetHashCode() == rec2.GetHashCode());
+      Assert.IsFalse(rec1.GetHashCode() == rec3.GetHashCode());
+      //
+      Assert.AreEqual("abe", rec1.X1);
+      Assert.IsNull(rec1.X2);
+    }
+
+    [TearDown]
+    public void Dispose()
+    {
+    }
+  }
+
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/Sorting.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/Sorting.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/Sorting.cs	(revision 3)
@@ -0,0 +1,268 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+namespace C5UnitTests.SortingTests
+{
+	[TestFixture]
+	public class SortRandom
+	{
+		IC ic;
+
+		Random ran;
+
+		int[] a;
+
+		int length;
+
+
+		[SetUp]
+		public void Init()
+		{
+			ic = new IC();
+			ran = new Random(3456);
+			length = 100000;
+			a = new int[length];
+			for (int i = 0; i < length; i++)
+				a[i] = ran.Next();
+		}
+
+
+		[Test]
+		public void HeapSort()
+		{
+			Sorting.HeapSort<int>(a, 0, length, ic);
+			for (int i = 1; i < length; i++)
+				Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i);
+		}
+
+
+		[Test]
+		public void IntroSort()
+		{
+			Sorting.IntroSort<int>(a, 0, length, ic);
+			for (int i = 1; i < length; i++)
+				Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i);
+		}
+
+
+		[Test]
+		public void InsertionSort()
+		{
+			length = 1000;
+			Sorting.InsertionSort<int>(a, 0, length, ic);
+			for (int i = 1; i < length; i++)
+				Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i);
+
+			Sorting.InsertionSort<int>(a, length, 2 * length, ic);
+			for (int i = length + 1; i < 2 * length; i++)
+				Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i);
+		}
+
+
+		[TearDown]
+		public void Dispose() { ic = null; }
+	}
+
+
+
+	[TestFixture]
+	public class SortRandomDuplicates
+	{
+		IC ic;
+
+		Random ran;
+
+		int[] a;
+
+		int length;
+
+
+		[SetUp]
+		public void Init()
+		{
+			ic = new IC();
+			ran = new Random(3456);
+			length = 100000;
+			a = new int[length];
+			for (int i = 0; i < length; i++)
+				a[i] = ran.Next(3, 23);
+		}
+
+
+		[Test]
+		public void HeapSort()
+		{
+			Sorting.HeapSort<int>(a, 0, length, ic);
+			for (int i = 1; i < length; i++)
+				Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i);
+		}
+
+
+		[Test]
+		public void IntroSort()
+		{
+			Sorting.IntroSort<int>(a, 0, length, ic);
+			for (int i = 1; i < length; i++)
+				Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i);
+		}
+
+
+		[Test]
+		public void InsertionSort()
+		{
+			length = 1000;
+			Sorting.InsertionSort<int>(a, 0, length, ic);
+			for (int i = 1; i < length; i++)
+				Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i);
+
+			Sorting.InsertionSort<int>(a, length, 2 * length, ic);
+			for (int i = length + 1; i < 2 * length; i++)
+				Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i);
+		}
+
+
+		[TearDown]
+		public void Dispose() { ic = null; a = null; ran = null; }
+	}
+
+
+
+	[TestFixture]
+	public class SortIncreasing
+	{
+		IC ic;
+
+		int[] a;
+
+		int length;
+
+
+		[SetUp]
+		public void Init()
+		{
+			ic = new IC();
+			length = 100000;
+			a = new int[length];
+			for (int i = 0; i < length; i++)
+				a[i] = i;
+		}
+
+
+		[Test]
+		public void HeapSort()
+		{
+			Sorting.HeapSort<int>(a, 0, length, ic);
+			for (int i = 1; i < length; i++)
+				Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i);
+		}
+
+
+		[Test]
+		public void IntroSort()
+		{
+			Sorting.IntroSort<int>(a, 0, length, ic);
+			for (int i = 1; i < length; i++)
+				Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i);
+		}
+
+
+		[Test]
+		public void InsertionSort()
+		{
+			length = 1000;
+			Sorting.InsertionSort<int>(a, 0, length, ic);
+			for (int i = 1; i < length; i++)
+				Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i);
+
+			Sorting.InsertionSort<int>(a, length, 2 * length, ic);
+			for (int i = length + 1; i < 2 * length; i++)
+				Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i);
+		}
+
+
+		[TearDown]
+		public void Dispose() { ic = null; a = null; }
+	}
+
+
+
+	[TestFixture]
+	public class SortDecreasing
+	{
+		IC ic;
+
+		int[] a;
+
+		int length;
+
+
+		[SetUp]
+		public void Init()
+		{
+			ic = new IC();
+			length = 100000;
+			a = new int[length];
+			for (int i = 0; i < length; i++)
+				a[i] = -i;
+		}
+
+
+		[Test]
+		public void HeapSort()
+		{
+			Sorting.HeapSort<int>(a, 0, length, ic);
+			for (int i = 1; i < length; i++)
+				Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i);
+		}
+
+
+		[Test]
+		public void IntroSort()
+		{
+			Sorting.IntroSort<int>(a, 0, length, ic);
+			for (int i = 1; i < length; i++)
+				Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i);
+		}
+
+
+		[Test]
+		public void InsertionSort()
+		{
+			length = 1000;
+			Sorting.InsertionSort<int>(a, 0, length, ic);
+			for (int i = 1; i < length; i++)
+				Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i);
+
+			Sorting.InsertionSort<int>(a, length, 2 * length, ic);
+			for (int i = length + 1; i < 2 * length; i++)
+				Assert.IsTrue(a[i - 1] <= a[i], "Inversion at " + i);
+		}
+
+
+		[TearDown]
+		public void Dispose() { ic = null; a = null; }
+	}
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/SupportClasses.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/SupportClasses.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/SupportClasses.cs	(revision 3)
@@ -0,0 +1,493 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+
+namespace C5UnitTests
+{
+  class SC : SCG.IComparer<string>
+  {
+    public int Compare(string a, string b)
+    {
+      return a.CompareTo(b);
+    }
+
+
+    public void appl(String s)
+    {
+      System.Console.WriteLine("--{0}", s);
+    }
+  }
+
+  class TenEqualityComparer : SCG.IEqualityComparer<int>, SCG.IComparer<int>
+  {
+    TenEqualityComparer() { }
+    public static TenEqualityComparer Default { get { return new TenEqualityComparer(); } }
+    public int GetHashCode(int item) { return (item / 10).GetHashCode(); }
+    public bool Equals(int item1, int item2) { return item1 / 10 == item2 / 10; }
+    public int Compare(int a, int b) { return (a / 10).CompareTo(b / 10); }
+  }
+
+  class IC : SCG.IComparer<int>, IComparable<int>, SCG.IComparer<IC>, IComparable<IC>
+  {
+    public int Compare(int a, int b)
+    {
+      return a > b ? 1 : a < b ? -1 : 0;
+    }
+
+
+    public int Compare(IC a, IC b)
+    {
+      return a._i > b._i ? 1 : a._i < b._i ? -1 : 0;
+    }
+
+
+    private int _i;
+
+
+    public int i
+    {
+      get { return _i; }
+      set { _i = value; }
+    }
+
+
+    public IC() { }
+
+
+    public IC(int i) { _i = i; }
+
+
+    public int CompareTo(int that) { return _i > that ? 1 : _i < that ? -1 : 0; }
+
+    public bool Equals(int that) { return _i == that; }
+
+
+    public int CompareTo(IC that) { return _i > that._i ? 1 : _i < that._i ? -1 : 0; }
+    public bool Equals(IC that) { return _i == that._i; }
+
+
+    public static bool eq(SCG.IEnumerable<int> me, params int[] that)
+    {
+      int i = 0, maxind = that.Length - 1;
+
+      foreach (int item in me)
+        if (i > maxind || item != that[i++])
+          return false;
+
+      return i == maxind + 1;
+    }
+    public static bool seteq(ICollectionValue<int> me, params int[] that)
+    {
+      int[] me2 = me.ToArray();
+
+      Array.Sort(me2);
+
+      int i = 0, maxind = that.Length - 1;
+
+      foreach (int item in me2)
+        if (i > maxind || item != that[i++])
+          return false;
+
+      return i == maxind + 1;
+    }
+    public static bool seteq(ICollectionValue<KeyValuePair<int, int>> me, params int[] that)
+    {
+      ArrayList<KeyValuePair<int, int>> first = new ArrayList<KeyValuePair<int, int>>();
+      first.AddAll(me);
+      ArrayList<KeyValuePair<int, int>> other = new ArrayList<KeyValuePair<int, int>>();
+      for (int i = 0; i < that.Length; i += 2)
+      {
+        other.Add(new KeyValuePair<int, int>(that[i], that[i + 1]));
+      }
+      return other.UnsequencedEquals(first);
+    }
+  }
+
+  class RevIC : SCG.IComparer<int>
+  {
+    public int Compare(int a, int b)
+    {
+      return a > b ? -1 : a < b ? 1 : 0;
+    }
+  }
+
+  public class FunEnumerable : SCG.IEnumerable<int>
+  {
+    int size;
+    Fun<int, int> f;
+
+    public FunEnumerable(int size, Fun<int, int> f)
+    {
+      this.size = size; this.f = f;
+    }
+
+    public SCG.IEnumerator<int> GetEnumerator()
+    {
+      for (int i = 0; i < size; i++)
+        yield return f(i);
+    }
+
+
+    #region IEnumerable Members
+
+    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
+    {
+      throw new Exception("The method or operation is not implemented.");
+    }
+
+    #endregion
+  }
+
+  public class BadEnumerableException : Exception { }
+
+  public class BadEnumerable<T> : CollectionValueBase<T>, ICollectionValue<T>
+  {
+    T[] contents;
+    Exception exception;
+
+    public BadEnumerable(Exception exception, params T[] contents)
+    {
+      this.contents = (T[])contents.Clone();
+      this.exception = exception;
+    }
+
+    public override SCG.IEnumerator<T> GetEnumerator()
+    {
+      for (int i = 0; i < contents.Length; i++)
+        yield return contents[i];
+      throw exception;
+    }
+
+    public override bool IsEmpty { get { return false; } }
+
+    public override int Count { get { return contents.Length + 1; } }
+
+    public override Speed CountSpeed { get { return Speed.Constant; } }
+
+    public override T Choose() { throw exception; }
+  }
+
+  public class CollectionEventList<T>
+  {
+    ArrayList<CollectionEvent<T>> happened;
+    EventTypeEnum listenTo;
+    SCG.IEqualityComparer<T> itemequalityComparer;
+    public CollectionEventList(SCG.IEqualityComparer<T> itemequalityComparer)
+    {
+      happened = new ArrayList<CollectionEvent<T>>();
+      this.itemequalityComparer = itemequalityComparer;
+    }
+    public void Listen(ICollectionValue<T> list, EventTypeEnum listenTo)
+    {
+      this.listenTo = listenTo;
+      if ((listenTo & EventTypeEnum.Changed) != 0)
+        list.CollectionChanged += new CollectionChangedHandler<T>(changed);
+      if ((listenTo & EventTypeEnum.Cleared) != 0)
+        list.CollectionCleared += new CollectionClearedHandler<T>(cleared);
+      if ((listenTo & EventTypeEnum.Removed) != 0)
+        list.ItemsRemoved += new ItemsRemovedHandler<T>(removed);
+      if ((listenTo & EventTypeEnum.Added) != 0)
+        list.ItemsAdded += new ItemsAddedHandler<T>(added);
+      if ((listenTo & EventTypeEnum.Inserted) != 0)
+        list.ItemInserted += new ItemInsertedHandler<T>(inserted);
+      if ((listenTo & EventTypeEnum.RemovedAt) != 0)
+        list.ItemRemovedAt += new ItemRemovedAtHandler<T>(removedAt);
+    }
+    public void Add(CollectionEvent<T> e) { happened.Add(e); }
+    /// <summary>
+    /// Check that we have seen exactly the events in expected that match listenTo.
+    /// </summary>
+    /// <param name="expected"></param>
+    public void Check(SCG.IEnumerable<CollectionEvent<T>> expected)
+    {
+      int i = 0;
+      foreach (CollectionEvent<T> expectedEvent in expected)
+      {
+        if ((expectedEvent.Act & listenTo) == 0)
+          continue;
+        if (i >= happened.Count)
+          Assert.Fail(string.Format("Event number {0} did not happen:\n expected {1}", i, expectedEvent));
+        if (!expectedEvent.Equals(happened[i], itemequalityComparer))
+          Assert.Fail(string.Format("Event number {0}:\n expected {1}\n but saw {2}", i, expectedEvent, happened[i]));
+        i++;
+      }
+      if (i < happened.Count)
+        Assert.Fail(string.Format("Event number {0} seen but no event expected:\n {1}", i, happened[i]));
+      happened.Clear();
+    }
+    public void Clear() { happened.Clear(); }
+    public void Print(System.IO.TextWriter writer)
+    {
+      happened.Apply(delegate(CollectionEvent<T> e) { writer.WriteLine(e); });
+    }
+    void changed(object sender)
+    {
+      happened.Add(new CollectionEvent<T>(EventTypeEnum.Changed, new EventArgs(), sender));
+    }
+    void cleared(object sender, ClearedEventArgs eventArgs)
+    {
+      happened.Add(new CollectionEvent<T>(EventTypeEnum.Cleared, eventArgs, sender));
+    }
+    void added(object sender, ItemCountEventArgs<T> eventArgs)
+    {
+      happened.Add(new CollectionEvent<T>(EventTypeEnum.Added, eventArgs, sender));
+    }
+    void removed(object sender, ItemCountEventArgs<T> eventArgs)
+    {
+      happened.Add(new CollectionEvent<T>(EventTypeEnum.Removed, eventArgs, sender));
+    }
+    void inserted(object sender, ItemAtEventArgs<T> eventArgs)
+    {
+      happened.Add(new CollectionEvent<T>(EventTypeEnum.Inserted, eventArgs, sender));
+    }
+    void removedAt(object sender, ItemAtEventArgs<T> eventArgs)
+    {
+      happened.Add(new CollectionEvent<T>(EventTypeEnum.RemovedAt, eventArgs, sender));
+    }
+  }
+
+  public sealed class CollectionEvent<T>
+  {
+    public readonly EventTypeEnum Act;
+    public readonly EventArgs Args;
+    public readonly object Sender;
+
+    public CollectionEvent(EventTypeEnum act, EventArgs args, object sender)
+    {
+      this.Act = act;
+      this.Args = args;
+      this.Sender = sender;
+    }
+
+    public bool Equals(CollectionEvent<T> otherEvent, SCG.IEqualityComparer<T> itemequalityComparer)
+    {
+      if (otherEvent == null || Act != otherEvent.Act || !object.ReferenceEquals(Sender, otherEvent.Sender))
+        return false;
+      switch (Act)
+      {
+        case EventTypeEnum.None:
+          break;
+        case EventTypeEnum.Changed:
+          return true;
+        case EventTypeEnum.Cleared:
+          if (Args is ClearedRangeEventArgs)
+          {
+            ClearedRangeEventArgs a = Args as ClearedRangeEventArgs, o = otherEvent.Args as ClearedRangeEventArgs;
+            if (o == null)
+              return false;
+            return a.Full == o.Full && a.Start == o.Start && a.Count == o.Count;
+          }
+          else
+          {
+            if (otherEvent.Args is ClearedRangeEventArgs)
+              return false;
+            ClearedEventArgs a = Args as ClearedEventArgs, o = otherEvent.Args as ClearedEventArgs;
+            return a.Full == o.Full && a.Count == o.Count;
+          }
+        case EventTypeEnum.Added:
+          {
+            ItemCountEventArgs<T> a = Args as ItemCountEventArgs<T>, o = otherEvent.Args as ItemCountEventArgs<T>;
+            return itemequalityComparer.Equals(a.Item, o.Item) && a.Count == o.Count;
+          }
+        case EventTypeEnum.Removed:
+          {
+            ItemCountEventArgs<T> a = Args as ItemCountEventArgs<T>, o = otherEvent.Args as ItemCountEventArgs<T>;
+            return itemequalityComparer.Equals(a.Item, o.Item) && a.Count == o.Count;
+          }
+        case EventTypeEnum.Inserted:
+          {
+            ItemAtEventArgs<T> a = Args as ItemAtEventArgs<T>, o = otherEvent.Args as ItemAtEventArgs<T>;
+            return a.Index == o.Index && itemequalityComparer.Equals(a.Item, o.Item);
+          }
+        case EventTypeEnum.RemovedAt:
+          {
+            ItemAtEventArgs<T> a = Args as ItemAtEventArgs<T>, o = otherEvent.Args as ItemAtEventArgs<T>;
+            return a.Index == o.Index && itemequalityComparer.Equals(a.Item, o.Item);
+          }
+      }
+      throw new ApplicationException("Illegat Act: " + Act);
+    }
+
+    public override string ToString()
+    {
+      return string.Format("Act: {0}, Args : {1}, Source : {2}", Act, Args, Sender);
+    }
+
+  }
+
+  public class CHC
+  {
+    static public int unsequencedhashcode(params int[] a)
+    {
+      int h = 0;
+      foreach (int i in a)
+      {
+        h += (int)(((uint)i * 1529784657 + 1) ^ ((uint)i * 2912831877) ^ ((uint)i * 1118771817 + 2));
+      }
+      return h;
+    }
+    static public int sequencedhashcode(params int[] a)
+    {
+      int h = 0;
+      foreach (int i in a) { h = h * 31 + i; }
+      return h;
+    }
+  }
+
+  //This class is a modified sample from VS2005 beta1 documentation
+  public class RadixFormatProvider : IFormatProvider
+  {
+    RadixFormatter _radixformatter;
+    public RadixFormatProvider(int radix)
+    {
+      if (radix < 2 || radix > 36)
+        throw new ArgumentException(String.Format(
+            "The radix \"{0}\" is not in the range 2..36.",
+            radix));
+      _radixformatter = new RadixFormatter(radix);
+    }
+    public object GetFormat(Type argType)
+    {
+      if (argType == typeof(ICustomFormatter))
+        return _radixformatter;
+      else
+        return null;
+    }
+  }
+
+  //This class is a modified sample from VS2005 beta1 documentation
+  public class RadixFormatter : ICustomFormatter
+  {
+    int radix;
+    public RadixFormatter(int radix)
+    {
+      if (radix < 2 || radix > 36)
+        throw new ArgumentException(String.Format(
+            "The radix \"{0}\" is not in the range 2..36.",
+            radix));
+      this.radix = radix;
+    }
+
+    // The value to be formatted is returned as a signed string 
+    // of digits from the rDigits array. 
+    private static char[] rDigits = {
+        '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 
+        'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 
+        'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 
+        'U', 'V', 'W', 'X', 'Y', 'Z' };
+
+    public string Format(string formatString,
+        object argToBeFormatted, IFormatProvider provider)
+    {
+      /*switch (Type.GetTypeCode(argToBeFormatted.GetType()))
+      {
+        case TypeCode.Boolean:
+          break;
+        case TypeCode.Byte:
+          break;
+        case TypeCode.Char:
+          break;
+        case TypeCode.DBNull:
+          break;
+        case TypeCode.DateTime:
+          break;
+        case TypeCode.Decimal:
+          break;
+        case TypeCode.Double:
+          break;
+        case TypeCode.Empty:
+          break;
+        case TypeCode.Int16:
+          break;
+        case TypeCode.Int32:
+          break;
+        case TypeCode.Int64:
+          break;
+        case TypeCode.Object:
+          break;
+        case TypeCode.SByte:
+          break;
+        case TypeCode.Single:
+          break;
+        case TypeCode.String:
+          break;
+        case TypeCode.UInt16:
+          break;
+        case TypeCode.UInt32:
+          break;
+        case TypeCode.UInt64:
+          break;
+      }*/
+      int intToBeFormatted;
+      try
+      {
+        intToBeFormatted = (int)argToBeFormatted;
+      }
+      catch (Exception)
+      {
+        if (argToBeFormatted is IFormattable)
+          return ((IFormattable)argToBeFormatted).
+              ToString(formatString, provider);
+        else
+          return argToBeFormatted.ToString();
+      }
+      return formatInt(intToBeFormatted);
+    }
+
+    private string formatInt(int intToBeFormatted)
+    {
+      // The formatting is handled here.
+      if (intToBeFormatted == 0)
+        return "0";
+      int digitIndex = 0;
+      int intPositive;
+      char[] outDigits = new char[31];
+
+      // Verify that the argument can be converted to a int integer.
+      // Extract the magnitude for conversion.
+      intPositive = Math.Abs(intToBeFormatted);
+
+      // Convert the magnitude to a digit string.
+      for (digitIndex = 0; digitIndex <= 32; digitIndex++)
+      {
+        if (intPositive == 0) break;
+
+        outDigits[outDigits.Length - digitIndex - 1] =
+            rDigits[intPositive % radix];
+        intPositive /= radix;
+      }
+
+      // Add a minus sign if the argument is negative.
+      if (intToBeFormatted < 0)
+        outDigits[outDigits.Length - digitIndex++ - 1] =
+            '-';
+
+      return new string(outDigits,
+          outDigits.Length - digitIndex, digitIndex);
+    }
+  }
+
+}
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/WrappersTest.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/WrappersTest.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/WrappersTest.cs	(revision 3)
@@ -0,0 +1,857 @@
+/*
+ Copyright (c) 2003-2006 Niels Kokholm and Peter Sestoft
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+ 
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+ 
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE.
+*/
+
+using System;
+using C5;
+using NUnit.Framework;
+using SCG = System.Collections.Generic;
+
+
+namespace C5UnitTests.wrappers
+{
+  namespace events
+  {
+    [TestFixture]
+    public class IList_
+    {
+      private ArrayList<int> list;
+      ICollectionValue<int> guarded;
+      CollectionEventList<int> seen;
+
+      [SetUp]
+      public void Init()
+      {
+        list = new ArrayList<int>(TenEqualityComparer.Default);
+        guarded = new GuardedList<int>(list);
+        seen = new CollectionEventList<int>(IntEqualityComparer.Default);
+      }
+
+      private void listen() { seen.Listen(guarded, EventTypeEnum.All); }
+
+      [Test]
+      public void Listenable()
+      {
+        Assert.AreEqual(EventTypeEnum.All, guarded.ListenableEvents);
+        Assert.AreEqual(EventTypeEnum.None, guarded.ActiveEvents);
+        listen();
+        Assert.AreEqual(EventTypeEnum.All, guarded.ActiveEvents);
+      }
+
+      [Test]
+      public void SetThis()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list[1] = 45;
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(56,1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(45,1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)
+          });
+      }
+
+      [Test]
+      public void Insert()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.Insert(1, 45);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(45,1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)
+          });
+      }
+
+      [Test]
+      public void InsertAll()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.InsertAll<int>(1, new int[] { 666, 777, 888 });
+        //seen.Print(Console.Error);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(666,1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(666, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(777,2), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(777, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(888,3), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(888, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)
+          });
+        list.InsertAll<int>(1, new int[] {});
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void InsertFirstLast()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.InsertFirst(45);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(45,0), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)
+          });
+        list.InsertLast(88);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(88,4), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(88, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)
+          });
+      }
+
+      [Test]
+      public void Remove()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.Remove();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(8, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+      }
+
+      [Test]
+      public void RemoveFirst()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.RemoveFirst();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(4,0), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(4, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+      }
+
+      [Test]
+      public void RemoveLast()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.RemoveLast();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(8,2), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(8, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+      }
+
+      [Test]
+      public void Reverse()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.Reverse();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)
+        });
+        list.View(1, 0).Reverse();
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+
+      [Test]
+      public void Sort()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.Sort();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)
+        });
+        list.View(1, 0).Sort();
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void Shuffle()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.Shuffle();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)
+        });
+        list.View(1, 0).Shuffle();
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void RemoveAt()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.RemoveAt(1);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(56,1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+      }
+
+      [Test]
+      public void RemoveInterval()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.RemoveInterval(1, 2);
+        seen.Check(new CollectionEvent<int>[] {
+           new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(false,2,1), guarded),
+         new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)
+        });
+        list.RemoveInterval(1, 0);
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void Update()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.Update(53);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(53, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)
+          });
+        list.Update(67);
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void FindOrAdd()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        int val = 53;
+        list.FindOrAdd(ref val);
+        seen.Check(new CollectionEvent<int>[] {});
+        val = 67;
+        list.FindOrAdd(ref val);
+        seen.Check(new CollectionEvent<int>[] { 
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)
+        });
+      }
+
+      [Test]
+      public void UpdateOrAdd()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        int val = 53;
+        list.UpdateOrAdd(val);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(53, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)
+        });
+        val = 67;
+        list.UpdateOrAdd(val);
+        seen.Check(new CollectionEvent<int>[] { 
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)
+        });
+        list.UpdateOrAdd(51, out val);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(53, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(51, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)
+        });
+        val = 67;
+        list.UpdateOrAdd(81, out val);
+        seen.Check(new CollectionEvent<int>[] { 
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(81, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)
+        });
+      }
+
+      [Test]
+      public void RemoveItem()
+      {
+        list.Add(4); list.Add(56); list.Add(18);
+        listen();
+        list.Remove(53);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(56, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+        list.Remove(11);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(18, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+      }
+
+      [Test]
+      public void RemoveAll()
+      {
+        for (int i = 0; i < 10; i++)
+        {
+          list.Add(10 * i + 5);
+        }
+        listen();
+        list.RemoveAll<int>(new int[] { 32, 187, 45 });
+        //TODO: the order depends on internals of the HashSet
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(35, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(45, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+        list.RemoveAll<int>(new int[] { 200, 300 });
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void Clear()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.View(1, 1).Clear();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(false,1,1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)
+        });
+        list.Clear();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(true,2,0), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)
+        });
+        list.Clear();
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void ListDispose()
+      {
+        list.Add(4); list.Add(56); list.Add(8);
+        listen();
+        list.View(1, 1).Dispose();
+        seen.Check(new CollectionEvent<int>[] {});
+        list.Dispose();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Cleared, new ClearedRangeEventArgs(true,3,0), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)
+        });
+        list.Dispose();
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+
+      [Test]
+      public void RetainAll()
+      {
+        for (int i = 0; i < 10; i++)
+        {
+          list.Add(10 * i + 5);
+        }
+        listen();
+        list.RetainAll<int>(new int[] { 32, 187, 45, 62, 82, 95, 2 });
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(15, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(25, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(55, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(75, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+        list.RetainAll<int>(new int[] { 32, 187, 45, 62, 82, 95, 2 });
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void RemoveAllCopies()
+      {
+        for (int i = 0; i < 10; i++)
+        {
+          list.Add(3 * i + 5);
+        }
+        listen();
+        list.RemoveAllCopies(14);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(11, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(14, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(17, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+        list.RemoveAllCopies(14);
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [Test]
+      public void Add()
+      {
+        listen();
+        seen.Check(new CollectionEvent<int>[0]);
+        list.Add(23);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(23, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+      }
+
+      [Test]
+      public void AddAll()
+      {
+        for (int i = 0; i < 10; i++)
+        {
+          list.Add(10 * i + 5);
+        }
+        listen();
+        list.AddAll<int>(new int[] { 45, 56, 67 });
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(45, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(56, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+        list.AddAll<int>(new int[] { });
+        seen.Check(new CollectionEvent<int>[] {});
+      }
+
+      [TearDown]
+      public void Dispose() { list = null; seen = null; }
+
+      [Test]
+      [ExpectedException(typeof(UnlistenableEventException))]
+      public void ViewChanged()
+      {
+        IList<int> w = list.View(0, 0);
+        w.CollectionChanged += new CollectionChangedHandler<int>(w_CollectionChanged);
+      }
+
+      [Test]
+      [ExpectedException(typeof(UnlistenableEventException))]
+      public void ViewCleared()
+      {
+        IList<int> w = list.View(0, 0);
+        w.CollectionCleared += new CollectionClearedHandler<int>(w_CollectionCleared);
+      }
+
+      [Test]
+      [ExpectedException(typeof(UnlistenableEventException))]
+      public void ViewAdded()
+      {
+        IList<int> w = list.View(0, 0);
+        w.ItemsAdded += new ItemsAddedHandler<int>(w_ItemAdded);
+      }
+
+      [Test]
+      [ExpectedException(typeof(UnlistenableEventException))]
+      public void ViewInserted()
+      {
+        IList<int> w = list.View(0, 0);
+        w.ItemInserted += new ItemInsertedHandler<int>(w_ItemInserted);
+      }
+
+      [Test]
+      [ExpectedException(typeof(UnlistenableEventException))]
+      public void ViewRemoved()
+      {
+        IList<int> w = list.View(0, 0);
+        w.ItemsRemoved += new ItemsRemovedHandler<int>(w_ItemRemoved);
+      }
+
+      [Test]
+      [ExpectedException(typeof(UnlistenableEventException))]
+      public void ViewRemovedAt()
+      {
+        IList<int> w = list.View(0, 0);
+        w.ItemRemovedAt += new ItemRemovedAtHandler<int>(w_ItemRemovedAt);
+      }
+
+      void w_CollectionChanged(object sender)
+      {
+        throw new NotImplementedException();
+      }
+
+      void w_CollectionCleared(object sender, ClearedEventArgs eventArgs)
+      {
+        throw new NotImplementedException();
+      }
+
+      void w_ItemAdded(object sender, ItemCountEventArgs<int> eventArgs)
+      {
+        throw new NotImplementedException();
+      }
+
+      void w_ItemInserted(object sender, ItemAtEventArgs<int> eventArgs)
+      {
+        throw new NotImplementedException();
+      }
+
+      void w_ItemRemoved(object sender, ItemCountEventArgs<int> eventArgs)
+      {
+        throw new NotImplementedException();
+      }
+
+      void w_ItemRemovedAt(object sender, ItemAtEventArgs<int> eventArgs)
+      {
+        throw new NotImplementedException();
+      }
+    }
+
+    [TestFixture]
+    public class StackQueue
+    {
+      private ArrayList<int> list;
+      ICollectionValue<int> guarded;
+      CollectionEventList<int> seen;
+
+      [SetUp]
+      public void Init()
+      {
+        list = new ArrayList<int>(TenEqualityComparer.Default);
+        guarded = new GuardedList<int>(list);
+        seen = new CollectionEventList<int>(IntEqualityComparer.Default);
+      }
+
+      private void listen() { seen.Listen(guarded, EventTypeEnum.All); }
+
+
+      [Test]
+      public void EnqueueDequeue()
+      {
+        listen();
+        list.Enqueue(67);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(67,0), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(67, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+        list.Enqueue(2);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(2,1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(2, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+        list.Dequeue();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(67,0), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(67, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+        list.Dequeue();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(2,0), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(2, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+      }
+
+      [Test]
+      public void PushPop()
+      {
+        listen();
+        seen.Check(new CollectionEvent<int>[0]);
+        list.Push(23);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(23,0), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(23, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+        list.Push(-12);
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.Inserted, new ItemAtEventArgs<int>(-12,1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Added, new ItemCountEventArgs<int>(-12, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+        list.Pop();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(-12,1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(-12, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+        list.Pop();
+        seen.Check(new CollectionEvent<int>[] {
+          new CollectionEvent<int>(EventTypeEnum.RemovedAt, new ItemAtEventArgs<int>(23,0), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Removed, new ItemCountEventArgs<int>(23, 1), guarded),
+          new CollectionEvent<int>(EventTypeEnum.Changed, new EventArgs(), guarded)});
+      }
+
+      [TearDown]
+      public void Dispose() { list = null; seen = null; }
+    }
+
+
+  }
+
+  namespace wrappedarray
+  {
+    [TestFixture]
+    public class Basic
+    {
+
+      [SetUp]
+      public void Init()
+      {
+      }
+
+      [TearDown]
+      public void Dispose()
+      {
+      }
+
+      [Test]
+      public void NoExc()
+      {
+        WrappedArray<int> wrapped = new WrappedArray<int>(new int[] { 4, 6, 5 });
+        Assert.AreEqual(6, wrapped[1]);
+        Assert.IsTrue(IC.eq(wrapped[1, 2], 6, 5));
+        //
+        Fun<int, bool> is4 = delegate(int i) { return i == 4; };
+        Assert.AreEqual(EventTypeEnum.None, wrapped.ActiveEvents);
+        Assert.AreEqual(false, wrapped.All(is4));
+        Assert.AreEqual(true, wrapped.AllowsDuplicates);
+        wrapped.Apply(delegate(int i) { });
+        Assert.AreEqual("{ 5, 6, 4 }", wrapped.Backwards().ToString());
+        Assert.AreEqual(true, wrapped.Check());
+        wrapped.Choose();
+        Assert.AreEqual(true, wrapped.Contains(4));
+        Assert.AreEqual(true, wrapped.ContainsAll(new ArrayList<int>()));
+        Assert.AreEqual(1, wrapped.ContainsCount(4));
+        Assert.AreEqual(Speed.Linear, wrapped.ContainsSpeed);
+        int[] extarray = new int[5];
+        wrapped.CopyTo(extarray, 1);
+        Assert.IsTrue(IC.eq(extarray, 0, 4, 6, 5, 0));
+        Assert.AreEqual(3, wrapped.Count);
+        Assert.AreEqual(Speed.Constant, wrapped.CountSpeed);
+        Assert.AreEqual(EnumerationDirection.Forwards, wrapped.Direction);
+        Assert.AreEqual(false, wrapped.DuplicatesByCounting);
+        Assert.AreEqual(IntEqualityComparer.Default, wrapped.EqualityComparer);
+        Assert.AreEqual(true, wrapped.Exists(is4));
+        Assert.IsTrue(IC.eq(wrapped.Filter(is4), 4));
+        int j = 5;
+        Assert.AreEqual(true, wrapped.Find(ref j));
+        Assert.AreEqual(true, wrapped.Find(is4, out j));
+        Assert.AreEqual("[ 0:4 ]", wrapped.FindAll(is4).ToString());
+        Assert.AreEqual(0, wrapped.FindIndex(is4));
+        Assert.AreEqual(true, wrapped.FindLast(is4, out j));
+        Assert.AreEqual(0, wrapped.FindLastIndex(is4));
+        Assert.AreEqual(4, wrapped.First);
+        wrapped.GetEnumerator();
+        Assert.AreEqual(CHC.sequencedhashcode(4, 6, 5), wrapped.GetSequencedHashCode());
+        Assert.AreEqual(CHC.unsequencedhashcode(4, 6, 5), wrapped.GetUnsequencedHashCode());
+        Assert.AreEqual(Speed.Constant, wrapped.IndexingSpeed);
+        Assert.AreEqual(2, wrapped.IndexOf(5));
+        Assert.AreEqual(false, wrapped.IsEmpty);
+        Assert.AreEqual(true, wrapped.IsReadOnly);
+        Assert.AreEqual(false, wrapped.IsSorted());
+        Assert.AreEqual(true, wrapped.IsValid);
+        Assert.AreEqual(5, wrapped.Last);
+        Assert.AreEqual(2, wrapped.LastIndexOf(5));
+        Assert.AreEqual(EventTypeEnum.None, wrapped.ListenableEvents);
+        Fun<int, string> i2s = delegate(int i) { return string.Format("T{0}", i); };
+        Assert.AreEqual("[ 0:T4, 1:T6, 2:T5 ]", wrapped.Map<string>(i2s).ToString());
+        Assert.AreEqual(0, wrapped.Offset);
+        wrapped.Reverse();
+        Assert.AreEqual("[ 0:5, 1:6, 2:4 ]", wrapped.ToString());
+        IList<int> other = new ArrayList<int>(); other.AddAll<int>(new int[] { 4, 5, 6 });
+        Assert.IsFalse(wrapped.SequencedEquals(other));
+        j = 30;
+        Assert.AreEqual(true, wrapped.Show(new System.Text.StringBuilder(), ref j, null));
+        wrapped.Sort();
+        Assert.AreEqual("[ 0:4, 1:5, 2:6 ]", wrapped.ToString());
+        Assert.IsTrue(IC.eq(wrapped.ToArray(), 4, 5, 6));
+        Assert.AreEqual("[ ... ]", wrapped.ToString("L4", null));
+        Assert.AreEqual(null, wrapped.Underlying);
+        Assert.IsTrue(IC.seteq(wrapped.UniqueItems(), 4, 5, 6));
+        Assert.IsTrue(wrapped.UnsequencedEquals(other));
+        wrapped.Shuffle();
+        Assert.IsTrue(IC.seteq(wrapped.UniqueItems(), 4, 5, 6));
+      }
+
+      [Test]
+      public void WithExc()
+      {
+        WrappedArray<int> wrapped = new WrappedArray<int>(new int[] { 3, 4, 6, 5, 7 });
+        //
+        try { wrapped.Add(1); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.AddAll<int>(null); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.Clear(); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.Dispose(); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        int j = 1;
+        try { wrapped.FindOrAdd(ref j); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.Insert(1, 1); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.Insert(wrapped.View(0, 0), 1); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.InsertAll<int>(1, null); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.InsertFirst(1); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.InsertLast(1); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.Remove(); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.Remove(1); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.RemoveAll<int>(null); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.RemoveAllCopies(1); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.RemoveAt(1); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.RemoveFirst(); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.RemoveInterval(0, 0); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.RemoveLast(); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.RetainAll<int>(null); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.Update(1, out j); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.UpdateOrAdd(1); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+      }
+
+      [Test]
+      public void View()
+      {
+        int[] inner = new int[] { 3, 4, 6, 5, 7 };
+        WrappedArray<int> outerwrapped = new WrappedArray<int>(inner);
+        WrappedArray<int> wrapped = (WrappedArray<int>)outerwrapped.View(1, 3);
+        //
+        Assert.AreEqual(6, wrapped[1]);
+        Assert.IsTrue(IC.eq(wrapped[1, 2], 6, 5));
+        //
+        Fun<int, bool> is4 = delegate(int i) { return i == 4; };
+        Assert.AreEqual(EventTypeEnum.None, wrapped.ActiveEvents);
+        Assert.AreEqual(false, wrapped.All(is4));
+        Assert.AreEqual(true, wrapped.AllowsDuplicates);
+        wrapped.Apply(delegate(int i) { });
+        Assert.AreEqual("{ 5, 6, 4 }", wrapped.Backwards().ToString());
+        Assert.AreEqual(true, wrapped.Check());
+        wrapped.Choose();
+        Assert.AreEqual(true, wrapped.Contains(4));
+        Assert.AreEqual(true, wrapped.ContainsAll(new ArrayList<int>()));
+        Assert.AreEqual(1, wrapped.ContainsCount(4));
+        Assert.AreEqual(Speed.Linear, wrapped.ContainsSpeed);
+        int[] extarray = new int[5];
+        wrapped.CopyTo(extarray, 1);
+        Assert.IsTrue(IC.eq(extarray, 0, 4, 6, 5, 0));
+        Assert.AreEqual(3, wrapped.Count);
+        Assert.AreEqual(Speed.Constant, wrapped.CountSpeed);
+        Assert.AreEqual(EnumerationDirection.Forwards, wrapped.Direction);
+        Assert.AreEqual(false, wrapped.DuplicatesByCounting);
+        Assert.AreEqual(IntEqualityComparer.Default, wrapped.EqualityComparer);
+        Assert.AreEqual(true, wrapped.Exists(is4));
+        Assert.IsTrue(IC.eq(wrapped.Filter(is4), 4));
+        int j = 5;
+        Assert.AreEqual(true, wrapped.Find(ref j));
+        Assert.AreEqual(true, wrapped.Find(is4, out j));
+        Assert.AreEqual("[ 0:4 ]", wrapped.FindAll(is4).ToString());
+        Assert.AreEqual(0, wrapped.FindIndex(is4));
+        Assert.AreEqual(true, wrapped.FindLast(is4, out j));
+        Assert.AreEqual(0, wrapped.FindLastIndex(is4));
+        Assert.AreEqual(4, wrapped.First);
+        wrapped.GetEnumerator();
+        Assert.AreEqual(CHC.sequencedhashcode(4, 6, 5), wrapped.GetSequencedHashCode());
+        Assert.AreEqual(CHC.unsequencedhashcode(4, 6, 5), wrapped.GetUnsequencedHashCode());
+        Assert.AreEqual(Speed.Constant, wrapped.IndexingSpeed);
+        Assert.AreEqual(2, wrapped.IndexOf(5));
+        Assert.AreEqual(false, wrapped.IsEmpty);
+        Assert.AreEqual(true, wrapped.IsReadOnly);
+        Assert.AreEqual(false, wrapped.IsSorted());
+        Assert.AreEqual(true, wrapped.IsValid);
+        Assert.AreEqual(5, wrapped.Last);
+        Assert.AreEqual(2, wrapped.LastIndexOf(5));
+        Assert.AreEqual(EventTypeEnum.None, wrapped.ListenableEvents);
+        Fun<int, string> i2s = delegate(int i) { return string.Format("T{0}", i); };
+        Assert.AreEqual("[ 0:T4, 1:T6, 2:T5 ]", wrapped.Map<string>(i2s).ToString());
+        Assert.AreEqual(1, wrapped.Offset);
+        wrapped.Reverse();
+        Assert.AreEqual("[ 0:5, 1:6, 2:4 ]", wrapped.ToString());
+        IList<int> other = new ArrayList<int>(); other.AddAll<int>(new int[] { 4, 5, 6 });
+        Assert.IsFalse(wrapped.SequencedEquals(other));
+        j = 30;
+        Assert.AreEqual(true, wrapped.Show(new System.Text.StringBuilder(), ref j, null));
+        wrapped.Sort();
+        Assert.AreEqual("[ 0:4, 1:5, 2:6 ]", wrapped.ToString());
+        Assert.IsTrue(IC.eq(wrapped.ToArray(), 4, 5, 6));
+        Assert.AreEqual("[ ... ]", wrapped.ToString("L4", null));
+        Assert.AreEqual(outerwrapped, wrapped.Underlying);
+        Assert.IsTrue(IC.seteq(wrapped.UniqueItems(), 4, 5, 6));
+        Assert.IsTrue(wrapped.UnsequencedEquals(other));
+        //
+        Assert.IsTrue(wrapped.TrySlide(1));
+        Assert.IsTrue(IC.eq(wrapped, 5, 6, 7));
+        Assert.IsTrue(wrapped.TrySlide(-1, 2));
+        Assert.IsTrue(IC.eq(wrapped, 4, 5));
+        Assert.IsFalse(wrapped.TrySlide(-2));
+        Assert.IsTrue(IC.eq(wrapped.Span(outerwrapped.ViewOf(7)), 4, 5, 6, 7));
+        //
+        wrapped.Shuffle();
+        Assert.IsTrue(IC.seteq(wrapped.UniqueItems(), 4, 5));
+        Assert.IsTrue(wrapped.IsValid);
+        wrapped.Dispose();
+        Assert.IsFalse(wrapped.IsValid);
+      }
+
+      [Test]
+      public void ViewWithExc()
+      {
+        int[] inner = new int[] { 3, 4, 6, 5, 7 };
+        WrappedArray<int> outerwrapped = new WrappedArray<int>(inner);
+        WrappedArray<int> wrapped = (WrappedArray<int>)outerwrapped.View(1, 3);
+        //
+        try { wrapped.Add(1); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.AddAll<int>(null); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.Clear(); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        //Should not throw
+        //try { wrapped.Dispose(); Assert.Fail("No throw"); }
+        //catch (FixedSizeCollectionException) { }
+        int j = 1;
+        try { wrapped.FindOrAdd(ref j); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.Insert(1, 1); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.Insert(wrapped.View(0, 0), 1); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.InsertAll<int>(1, null); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.InsertFirst(1); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.InsertLast(1); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.Remove(); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.Remove(1); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.RemoveAll<int>(null); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.RemoveAllCopies(1); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.RemoveAt(1); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.RemoveFirst(); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.RemoveInterval(0, 0); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.RemoveLast(); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.RetainAll<int>(null); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.Update(1, out j); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+        try { wrapped.UpdateOrAdd(1); Assert.Fail("No throw"); }
+        catch (FixedSizeCollectionException) { }
+      }
+    }
+  }
+}
+
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/nunit.csproj
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/nunit.csproj	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/nunit/nunit.csproj	(revision 3)
@@ -0,0 +1,134 @@
+﻿<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}</ProjectGuid>
+    <OutputType>Library</OutputType>
+    <StartupObject>
+    </StartupObject>
+    <RootNamespace>nunit</RootNamespace>
+    <NoStandardLibraries>false</NoStandardLibraries>
+    <AssemblyName>nunit</AssemblyName>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <UpgradeBackupLocation>
+    </UpgradeBackupLocation>
+    <OldToolsVersion>2.0</OldToolsVersion>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
+    <DebugSymbols>true</DebugSymbols>
+    <Optimize>false</Optimize>
+    <OutputPath>.\bin\Debug\</OutputPath>
+    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <WarningLevel>4</WarningLevel>
+    <IncrementalBuild>false</IncrementalBuild>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
+    <DebugSymbols>false</DebugSymbols>
+    <Optimize>true</Optimize>
+    <OutputPath>.\bin\Release\</OutputPath>
+    <EnableUnmanagedDebugging>false</EnableUnmanagedDebugging>
+    <DefineConstants>TRACE</DefineConstants>
+    <WarningLevel>4</WarningLevel>
+    <IncrementalBuild>false</IncrementalBuild>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'DebugSnk' ">
+    <DebugSymbols>true</DebugSymbols>
+    <OutputPath>bin\DebugSnk\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)' == 'ReleaseSnk' ">
+    <OutputPath>bin\ReleaseSnk\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <Optimize>true</Optimize>
+    <PlatformTarget>AnyCPU</PlatformTarget>
+  </PropertyGroup>
+  <ItemGroup>
+    <ProjectReference Include="..\C5\C5.csproj">
+      <Project>{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}</Project>
+      <Package>{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</Package>
+      <Name>C5</Name>
+    </ProjectReference>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="arrays\CircularQueueTest.cs" />
+    <Compile Include="AssemblyInfo.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="BasesTest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="InterfacesTest.cs" />
+    <Compile Include="Records.cs" />
+    <Compile Include="Sorting.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="SupportClasses.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="arrays\ArrayListTest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="arrays\HashedArrayListTest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="arrays\SortedArrayTests.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="hashing\HashBagTests.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="hashing\HashDictionaryTests.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="hashing\HashTableTests.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="heaps\HeapTests.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="linkedlists\HashedLinkedListTest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="linkedlists\LinkedListTest.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="templates\Clone.cs" />
+    <Compile Include="templates\Events.cs" />
+    <Compile Include="templates\GenericCollectionTester.cs" />
+    <Compile Include="templates\List.cs" />
+    <Compile Include="trees\Bag.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="trees\Dictionary.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="trees\RedBlackTreeSetTests.cs">
+      <SubType>Code</SubType>
+    </Compile>
+    <Compile Include="WrappersTest.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <AppDesigner Include="Properties\" />
+  </ItemGroup>
+  <ItemGroup>
+    <Reference Include="nunit.framework, Version=2.2.9.0, Culture=neutral, PublicKeyToken=96d09a1eb7f44a77, processorArchitecture=MSIL" />
+  </ItemGroup>
+  <ItemGroup>
+    <Folder Include="Properties\" />
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSHARP.Targets" />
+  <PropertyGroup>
+    <PreBuildEvent>
+    </PreBuildEvent>
+    <PostBuildEvent>
+    </PostBuildEvent>
+  </PropertyGroup>
+  <ProjectExtensions>
+    <VisualStudio>
+    </VisualStudio>
+  </ProjectExtensions>
+</Project>
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/BUILD.txt
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/BUILD.txt	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/BUILD.txt	(revision 3)
@@ -0,0 +1,82 @@
+BUILDING THE C5 GENERIC COLLECTION LIBRARY FOR C#/CLI
+Updated 2008-02-10
+
+The C5 library can be built by opening the solution file C5.sln in the
+current directory with Microsoft Visual Studio 2008 or Microsoft
+Visual C# 2008 Express Edition and performing a build all.
+
+Or execute 'msbuild C5.sln' from the command line in this directory.
+
+This will build C5 in file C5/bin/Release/C5.dll 
+
+Building all in the C5.sln solution will also build these projects:
+
+  * The 'PreProcess' project generates some of the C5 sources by
+    preprocessing files.  This is necessary for the C5 build.
+
+  * The 'docNet' project generates on-line documentation; see below.
+
+  * The 'UserGuideExample' project compiles the examples from chapter
+    11 of the technical report ITU-TR-2006-76
+
+  * The 'nunit' project compiles the unit tests but does not run them;
+    see below.  An enormous number of compilation errors will result
+    unless you have NUnit 2 installed.  The project is configured for
+    NUnit version 2.2.9 and was tested with that version.
+
+The build should complete with a few dozen compilation warnings.
+
+------------------------------------------------------------
+
+Generating the online documentation
+
+ * Build C5 in Debug mode
+
+ * Run docNet/dodoc.cmd, e.g. by double-clicking in Explorer
+
+ * Press return
+
+The generation process should take less than 20 seconds.
+
+The generated documentation is in directory docNet/docbuild/ and
+subdirectories.  The start page is docNet/docbuild/frames.htm
+
+Note: The generated online documentation is currently incomplete.
+Please refer to the Technical Report (ITU-TR-2006-76) instead.
+
+------------------------------------------------------------
+
+Running the NUnit tests
+
+Prerequisites:
+
+ * You must have NUnit installed (version 2.2.x). 
+
+ * The nunit project (nunit/nunit.csproj) must include a reference to
+   to the installed nunit-framework.dll.  Add the reference by
+   right-clicking "References" under "nunit" in Visual Studio's
+   Solution Explorer.
+
+Steps to build and run unit tests:
+
+ * Build the project called "nunit".  
+
+ * Start NUnit, select File > Open > nunit/bin/Debug/nunit.dll, or
+   simply double-click nunit/bin/Debug/nunit.dll
+
+ * Press Run in the NUnit user interface
+
+There are more than 1400 NUnit test cases which should execute in less
+than 30 seconds.  All should pass when C5 is built in Debug mode.
+
+Note 1: The Release builds of C5 use randomized hashing for
+efficiency, whereas the Debug builds use deterministic hashing to
+simplify testing.  This means that approximately 13 hashtable test
+cases will fail (harmlessly) when C5 is built and tested in Release
+mode, using File > Open > nunit/bin/Release/nunit.dll
+
+Note 2: C5 version 1.1.0 includes the test case
+support.itemops.EqualityComparers.SeqequalityComparerViaBuilder4 which
+works on VS2008 C#/CLR version 3.5, but failed on VS2005 with C#/CLR
+2.0 due to a bug in that platform.  Omit this test case if you need to
+build C5 on VS2005 with C#/CLR 2.0.
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5.build
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5.build	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5.build	(revision 3)
@@ -0,0 +1,183 @@
+<?xml version="1.0"?>
+<project name="C5" default="build" basedir=".">
+	<description>C5 Generic Collection Library</description>
+
+	<!-- Build Environment Setup -->
+
+	<property name="debug" value="true" overwrite="false" />
+
+	<property name="baseDir" value="${project::get-base-directory()}" />
+	<if test="${debug == 'true'}">
+		<property name="releaseConfig" value="Debug" />
+	</if>
+	<if test="${debug == 'false'}">
+		<property name="releaseConfig" value="Release" />
+	</if>
+
+	<property name="buildDirC5" value="${baseDir}/C5/bin" />
+	<property name="buildDirDocNet" value="${baseDir}/docNet/bin" />
+	<property name="buildDirNunit" value="${baseDir}/nunit/bin" />
+	<property name="buildDirPreProcess" value="${baseDir}/PreProcess/bin" />
+
+	<property name="outputDirC5" value="${buildDirC5}/${releaseConfig}" />
+	<property name="outputDirDocNet" value="${buildDirDocNet}/${releaseConfig}" />
+	<property name="outputDirNunit" value="${buildDirNunit}/${releaseConfig}" />
+	<property name="outputDirPreProcess" value="${buildDirPreProcess}/${releaseConfig}" />
+
+	<!-- NUnit Environment Setup -->
+
+	<property name="nunitBaseDir" value="C:/Program Files/NUnit 2.2.6" />
+	<property name="nunit.framework.dll" 
+		value="${nunitBaseDir}/bin/nunit.framework.dll" />
+	<property name="nunit-console.exe" 
+		value="${nunitBaseDir}/bin/nunit-console.exe" />
+
+	<!-- Create output directories -->
+
+	<target name="makedirs">
+		<mkdir dir="${outputDirC5}/" />
+		<mkdir dir="${outputDirDocNet}/" />
+		<mkdir dir="${outputDirNunit}/" />
+		<mkdir dir="${outputDirPreProcess}/" />
+
+		<mkdir dir="${baseDir}/docNet/docbuild/types" />
+	</target>
+
+	<!-- Clean up output directories -->
+
+	<target name="clean" description="remove all generated files">
+		<delete dir="${buildDirC5}" failonerror="false" />
+		<delete dir="${buildDirDocNet}" failonerror="false" />
+		<delete dir="${buildDirNunit}" failonerror="false" />
+		<delete dir="${buildDirPreProcess}" failonerror="false" />
+
+		<delete dir="${baseDir}/docNet/docbuild/types" />
+	</target>
+
+	<!-- Run the pre-processing program to generate source code -->
+
+	<target name="preprocess" depends="makedirs">
+		<csc target="exe" output="${outputDirPreProcess}/PreProcess.exe" debug="${debug}">
+			<sources basedir="${baseDir}/PreProcess">
+				<include name="Program.cs" />
+			</sources>
+		</csc>
+		<exec program="${outputDirPreProcess}/PreProcess.exe" workingdir="${outputDirPreProcess}/" />
+	</target>
+
+	<!-- Build the C5 library -->
+
+	<target name="build" depends="preprocess">
+		<csc target="library" output="${outputDirC5}/C5.dll" debug="${debug}">
+			<sources basedir="${baseDir}/C5">
+				<include name="arrays/CircularQueue.cs" />
+				<include name="arrays/HashedArrayList.cs" />
+				<include name="AssemblyInfo.cs"/>
+				<include name="Attributes.cs" />
+				<include name="Builtin.cs" />
+				<include name="Comparer.cs"/>
+				<include name="Delegates.cs" />
+				<include name="Enums.cs" />
+				<include name="Exceptions.cs" />
+				<include name="Formatting.cs" />
+				<include name="Hashers.cs" />
+				<include name="Events.cs" />
+				<include name="Collections.cs"/>
+				<include name="Dictionaries.cs"/>
+				<include name="Interfaces.cs"/>
+				<include name="linkedlists/HashedLinkedList.cs" />
+				<include name="Random.cs" />
+				<include name="Records.cs" />
+				<include name="Sorting.cs" />
+				<include name="ViewSupport.cs" />
+				<include name="MappedEnumerators.cs" />
+				<include name="WrappedArray.cs" />
+				<include name="Wrappers.cs" />
+				<include name="arrays/ArrayList.cs" />
+				<include name="arrays/HashedArrayList.cs" />
+				<include name="arrays/SortedArray.cs" />
+				<include name="hashing/HashBag.cs" />
+				<include name="hashing/HashDictionary.cs" />
+				<include name="hashing/HashTable.cs" />
+				<include name="heaps/IntervalHeap.cs" />
+				<include name="linkedlists/HashedLinkedList.cs" />
+				<include name="linkedlists/LinkedList.cs" />
+				<include name="trees/RedBlackTreeSet.cs" />
+				<include name="trees/RedBlackTreeBag.cs" />
+				<include name="trees/RedBlackTreeDictionary.cs" />
+			</sources>
+		</csc>
+	</target>
+
+	<!-- Build documentation tool -->
+
+	<target name="docnet" depends="build">
+		<csc target="exe" output="${outputDirDocNet}/docNet.exe" debug="${debug}">
+			<sources basedir="${baseDir}/docNet">
+				<include name="AssemblyInfo.cs" />
+				<include name="docnet.cs" />
+				<include name="Test.cs" />
+				<include name="Timer.cs" />
+			</sources>
+			<references>
+				<include name="${outputDirC5}/C5.dll" />
+			</references>
+		</csc>
+
+		<copy todir="${outputDirDocNet}/">
+			<fileset basedir="${outputDirC5}/">
+				<include name="*.*" />
+			</fileset>
+		</copy>
+
+		<!-- Not running dodoc.cmd here, since it waits for user input.. -->
+
+	</target>
+
+	<!-- Build and run NUnit tests -->
+
+	<target name="test" depends="build">
+		<csc target="library" output="${outputDirNunit}/nunit.dll" debug="${debug}">
+			<sources basedir="${baseDir}/nunit">
+				<include name="PreProcess/Program.cs" />
+				<include name="arrays/CircularQueueTest.cs" />
+				<include name="AssemblyInfo.cs" />
+				<include name="BasesTest.cs" />
+				<include name="Records.cs" />
+				<include name="Sorting.cs" />
+				<include name="SupportClasses.cs" />
+				<include name="arrays/ArrayListTest.cs" />
+				<include name="arrays/HashedArrayListTest.cs" />
+				<include name="arrays/SortedArrayTests.cs" />
+				<include name="hashing/HashBagTests.cs" />
+				<include name="hashing/HashDictionaryTests.cs" />
+				<include name="hashing/HashTableTests.cs" />
+				<include name="heaps/HeapTests.cs" />
+				<include name="linkedlists/HashedLinkedListTest.cs" />
+				<include name="linkedlists/LinkedListTest.cs" />
+				<include name="templates/Clone.cs" />
+				<include name="templates/Events.cs" />
+				<include name="templates/GenericCollectionTester.cs" />
+				<include name="templates/List.cs" />
+				<include name="trees/Bag.cs" />
+				<include name="trees/Dictionary.cs" />
+				<include name="trees/RedBlackTreeSetTests.cs" />
+				<include name="WrappersTest.cs" />
+			</sources>
+			<references>
+				<include name="${outputDirC5}/C5.dll" />
+				<include name="${nunit.framework.dll}" />
+			</references>
+		</csc>
+
+		<copy todir="${outputDirNunit}/">
+			<fileset basedir="${outputDirC5}/">
+				<include name="*.*" />
+			</fileset>
+		</copy>
+
+		<exec program="${nunit-console.exe}" 
+			commandline="${outputDirNunit}/nunit.dll /nologo" />
+	</target>
+
+</project>
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5.dll
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5.dll
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5.dll	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5.dll	(revision 3)

Property changes on: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5.dll
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5.pdb
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5.pdb
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5.pdb	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5.pdb	(revision 3)

Property changes on: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5.pdb
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5.sln
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5.sln	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/C5.sln	(revision 3)
@@ -0,0 +1,150 @@
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual Studio 2008
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "C5", "C5\C5.csproj", "{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}"
+	ProjectSection(ProjectDependencies) = postProject
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F} = {6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}
+	EndProjectSection
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "nunit", "nunit\nunit.csproj", "{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "docNet", "docNet\docNet.csproj", "{42811A81-6A99-4C7A-A6DA-DF104C767B72}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UserGuideExamples", "UserGuideExamples\UserGuideExamples.csproj", "{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PreProcess", "PreProcess\PreProcess.csproj", "{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Debug|Mixed platforms = Debug|Mixed platforms
+		Debug|Win32 = Debug|Win32
+		DebugSnk|Any CPU = DebugSnk|Any CPU
+		DebugSnk|Mixed platforms = DebugSnk|Mixed platforms
+		DebugSnk|Win32 = DebugSnk|Win32
+		Release|Any CPU = Release|Any CPU
+		Release|Mixed platforms = Release|Mixed platforms
+		Release|Win32 = Release|Win32
+		ReleaseSnk|Any CPU = ReleaseSnk|Any CPU
+		ReleaseSnk|Mixed platforms = ReleaseSnk|Mixed platforms
+		ReleaseSnk|Win32 = ReleaseSnk|Win32
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.Debug|Mixed platforms.ActiveCfg = Debug|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.Debug|Mixed platforms.Build.0 = Debug|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.Debug|Win32.ActiveCfg = Debug|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.Debug|Win32.Build.0 = Debug|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.DebugSnk|Any CPU.ActiveCfg = DebugSnk|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.DebugSnk|Any CPU.Build.0 = DebugSnk|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.DebugSnk|Mixed platforms.ActiveCfg = DebugSnk|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.DebugSnk|Mixed platforms.Build.0 = DebugSnk|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.DebugSnk|Win32.ActiveCfg = DebugSnk|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.DebugSnk|Win32.Build.0 = DebugSnk|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.Release|Any CPU.Build.0 = Release|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.Release|Mixed platforms.ActiveCfg = Release|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.Release|Mixed platforms.Build.0 = Release|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.Release|Win32.ActiveCfg = Release|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.ReleaseSnk|Any CPU.ActiveCfg = ReleaseSnk|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.ReleaseSnk|Any CPU.Build.0 = ReleaseSnk|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.ReleaseSnk|Mixed platforms.ActiveCfg = ReleaseSnk|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.ReleaseSnk|Mixed platforms.Build.0 = ReleaseSnk|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.ReleaseSnk|Win32.ActiveCfg = ReleaseSnk|Any CPU
+		{D70489CD-ABDA-48FF-BD1E-BE3F7495BE71}.ReleaseSnk|Win32.Build.0 = ReleaseSnk|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.Debug|Mixed platforms.ActiveCfg = Debug|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.Debug|Mixed platforms.Build.0 = Debug|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.Debug|Win32.ActiveCfg = Debug|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.Debug|Win32.Build.0 = Debug|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.DebugSnk|Any CPU.ActiveCfg = DebugSnk|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.DebugSnk|Any CPU.Build.0 = DebugSnk|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.DebugSnk|Mixed platforms.ActiveCfg = DebugSnk|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.DebugSnk|Mixed platforms.Build.0 = DebugSnk|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.DebugSnk|Win32.ActiveCfg = DebugSnk|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.DebugSnk|Win32.Build.0 = DebugSnk|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.Release|Mixed platforms.ActiveCfg = Release|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.Release|Mixed platforms.Build.0 = Release|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.Release|Win32.ActiveCfg = Release|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.ReleaseSnk|Any CPU.ActiveCfg = ReleaseSnk|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.ReleaseSnk|Any CPU.Build.0 = ReleaseSnk|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.ReleaseSnk|Mixed platforms.ActiveCfg = ReleaseSnk|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.ReleaseSnk|Mixed platforms.Build.0 = ReleaseSnk|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.ReleaseSnk|Win32.ActiveCfg = ReleaseSnk|Any CPU
+		{08CBFDEB-A2E2-4F0E-A4E1-B996B05569DE}.ReleaseSnk|Win32.Build.0 = ReleaseSnk|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.Debug|Mixed platforms.ActiveCfg = Debug|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.Debug|Mixed platforms.Build.0 = Debug|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.Debug|Win32.ActiveCfg = Debug|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.Debug|Win32.Build.0 = Debug|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.DebugSnk|Any CPU.ActiveCfg = DebugSnk|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.DebugSnk|Any CPU.Build.0 = DebugSnk|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.DebugSnk|Mixed platforms.ActiveCfg = DebugSnk|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.DebugSnk|Mixed platforms.Build.0 = DebugSnk|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.DebugSnk|Win32.ActiveCfg = DebugSnk|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.DebugSnk|Win32.Build.0 = DebugSnk|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.Release|Any CPU.Build.0 = Release|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.Release|Mixed platforms.ActiveCfg = Release|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.Release|Mixed platforms.Build.0 = Release|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.Release|Win32.ActiveCfg = Release|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.ReleaseSnk|Any CPU.ActiveCfg = ReleaseSnk|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.ReleaseSnk|Any CPU.Build.0 = ReleaseSnk|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.ReleaseSnk|Mixed platforms.ActiveCfg = ReleaseSnk|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.ReleaseSnk|Mixed platforms.Build.0 = ReleaseSnk|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.ReleaseSnk|Win32.ActiveCfg = ReleaseSnk|Any CPU
+		{42811A81-6A99-4C7A-A6DA-DF104C767B72}.ReleaseSnk|Win32.Build.0 = ReleaseSnk|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.Debug|Mixed platforms.ActiveCfg = Debug|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.Debug|Mixed platforms.Build.0 = Debug|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.Debug|Win32.ActiveCfg = Debug|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.Debug|Win32.Build.0 = Debug|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.DebugSnk|Any CPU.ActiveCfg = DebugSnk|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.DebugSnk|Any CPU.Build.0 = DebugSnk|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.DebugSnk|Mixed platforms.ActiveCfg = DebugSnk|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.DebugSnk|Mixed platforms.Build.0 = DebugSnk|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.DebugSnk|Win32.ActiveCfg = DebugSnk|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.DebugSnk|Win32.Build.0 = DebugSnk|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.Release|Mixed platforms.ActiveCfg = Release|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.Release|Mixed platforms.Build.0 = Release|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.Release|Win32.ActiveCfg = Release|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.ReleaseSnk|Any CPU.ActiveCfg = ReleaseSnk|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.ReleaseSnk|Any CPU.Build.0 = ReleaseSnk|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.ReleaseSnk|Mixed platforms.ActiveCfg = ReleaseSnk|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.ReleaseSnk|Mixed platforms.Build.0 = ReleaseSnk|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.ReleaseSnk|Win32.ActiveCfg = ReleaseSnk|Any CPU
+		{B2A29FF2-A5C5-4F07-8CE7-FF5D744D7562}.ReleaseSnk|Win32.Build.0 = ReleaseSnk|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.Debug|Mixed platforms.ActiveCfg = Debug|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.Debug|Mixed platforms.Build.0 = Debug|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.Debug|Win32.ActiveCfg = Debug|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.Debug|Win32.Build.0 = Debug|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.DebugSnk|Any CPU.ActiveCfg = DebugSnk|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.DebugSnk|Any CPU.Build.0 = DebugSnk|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.DebugSnk|Mixed platforms.ActiveCfg = DebugSnk|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.DebugSnk|Mixed platforms.Build.0 = DebugSnk|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.DebugSnk|Win32.ActiveCfg = DebugSnk|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.DebugSnk|Win32.Build.0 = DebugSnk|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.Release|Any CPU.Build.0 = Release|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.Release|Mixed platforms.ActiveCfg = Release|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.Release|Mixed platforms.Build.0 = Release|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.Release|Win32.ActiveCfg = Release|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.ReleaseSnk|Any CPU.ActiveCfg = ReleaseSnk|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.ReleaseSnk|Any CPU.Build.0 = ReleaseSnk|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.ReleaseSnk|Mixed platforms.ActiveCfg = ReleaseSnk|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.ReleaseSnk|Mixed platforms.Build.0 = ReleaseSnk|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.ReleaseSnk|Win32.ActiveCfg = ReleaseSnk|Any CPU
+		{6222CA51-7D1A-4D42-B6A7-B5CE9608C18F}.ReleaseSnk|Win32.Build.0 = ReleaseSnk|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/LICENSE.txt
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/LICENSE.txt	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/LICENSE.txt	(revision 3)
@@ -0,0 +1,19 @@
+Copyright (c) 2003-2008 Niels Kokholm and Peter Sestoft.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
Index: branches/compiler/cSharp/ooasCompiler/src/libs/c5/RELEASE-NOTES.txt
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/c5/RELEASE-NOTES.txt	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/c5/RELEASE-NOTES.txt	(revision 3)
@@ -0,0 +1,121 @@
+RELEASE NOTES FOR C5 GENERIC COLLECTION LIBRARY FOR C#/CLI
+------------------------------
+
+Release 1.1.0 of 2008-02-10
+
+New functionality:
+
+ * Interface C5.ICollection<T> now extends generic interface
+   System.Collections.Generic.ICollection<T>.  The C5.ICollection<T>
+   interface in some cases describe different exceptions than
+   specified by SCG.ICollection<T>, but we have not attempted to fix
+   this because the .NET collection implemented in some cases throw
+   other exceptions than those specified anyway.
+
+ * Interface C5.IList<T> now extends interface non-generic interface
+   System.Collections.IList, so C5 list collections can be passed to
+   .NET GUI components and other framework methods.
+
+ * Exception-free methods 
+
+  	bool TryPredecessor(T x, out T res)
+ 	bool TrySuccessor(T x, out T res)
+ 	bool TryWeakPredecessor(T x, out T res)
+ 	bool TryWeakSuccessor(T x, out T res)
+
+   have been added to the ISorted<T> interface and the classes that
+   implement it.   
+
+ * Added methods analogous to the above to ISortedDictionary<K,V> and
+   the classes that implement it.
+
+ * Event raising on SortedDictionary<T> finally implemented, thanks to
+   Markus Griep.  Hence all unit tests should now succeed.
+
+ * The missing custom comparers and equality comparers have been added
+   for all primitive types except bool.  
+
+ * The book "The C5 Generic Collection Library" has been updated
+   to reflect these changes.
+
+Bugs fixed:
+
+ * SortedArray<T>.UpdateOrAdd and SortedArray<T>.FindOrAdd did not
+   expand the underlying array correctly
+
+ * HashDictionary.UpdateOrAdd returned the new value, not the old one.
+
+ * CollectionBase.StaticEquals threw exception when exactly one
+   argument was null.  
+
+ * HashedLinkedList<T>.Remove could fail with NullReferenceException.
+
+ * HashSet<T>.UpdateOrAdd(item, out old) did not set old=default(T)
+   when item was not already in the set.
+
+ * HashBag<T>.CopyTo could throw when copying from empty collection.
+
+------------------------------
+
+Release 1.0.2 of 2007-06-01
+
+Bugs fixed:
+
+ * SortedDictionaryBase was not marked as [Serializable]
+ 
+ * ArrayList.expand did not update the array field of (other) views
+
+ * IntervalHeap::Replace would throw an exception on one-element heap
+
+------------------------------
+
+Release 1.0.1 of 2006-06-27
+
+Bugs fixed:
+
+ * CircularQueue<T> indexer was wrong
+
+ * Some equality comparers created by C5.EqualityComparer<T>.Default
+   were not marked serializable
+
+ * HashSet<T>.RetainAll could leave internal data inconsistent
+
+ * TreeDictionary<K,V> was not marked serializable
+
+ * HashedLinkedList<T> problem related to tag group implementation
+
+ * Dispose() could fail on newly created lists
+
+New features:
+
+ * A strong name (.snk) is included 
+
+ * C5.IList<T> now derives from System.Collections.Generic.IList<T>
+
+ * Added C5.build file for NAnt, due to Johan Warlander
+
+The technical report has been updated to reflect the above changes.
+
+------------------------------
+
+Release 1.00 of 2006-01-30
+
+First complete release.  There are lots of changes since the
+PreRelease:
+
+ * Interface design has been reorganized and simplified
+
+ * New functionality added (too much to describe here)
+
+ * Updated for Microsoft C#/CLI 2.0 release version
+
+ * Comprehensive documentation in ITU Technical Report ITU-TR-2006-76
+
+------------------------------
+
+PreRelease 0.5 of 2004-08-06
+
+First public release, essentially a preview of the library, for beta 1
+of Microsoft C#/CLI 2.0.
+
+------------------------------
Index: branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Runtime.dll
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Runtime.dll
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Runtime.dll	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Runtime.dll	(revision 3)

Property changes on: branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Runtime.dll
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Runtime.dll.mdb
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Runtime.dll.mdb
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Runtime.dll.mdb	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Runtime.dll.mdb	(revision 3)

Property changes on: branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Runtime.dll.mdb
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Runtime.xml
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Runtime.xml	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Runtime.xml	(revision 3)
@@ -0,0 +1,3842 @@
+<?xml version="1.0"?>
+<doc>
+    <assembly>
+        <name>/home/verequus/Arbeit/ANTLR/code/antlr/main/runtime/CSharp/Sources/Antlr3.Runtime/bin/Debug/net-2.0/Antlr3.Runtime</name>
+    </assembly>
+    <members>
+        <member name="T:Antlr.Runtime.ANTLRFileStream">
+            <summary>
+            A character stream - an <see cref="T:Antlr.Runtime.ICharStream" /> - that loads
+            and caches the contents of it's underlying file fully during
+            object construction
+            </summary>
+            <remarks>
+            This looks very much like an ANTLReaderStream or an ANTLRInputStream
+            but, it is a special case. Since we know the exact size of the file to
+            load, we can avoid lots of data copying and buffer resizing.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRFileStream.#ctor">
+            <summary>
+            Initializes a new instance of the ANTLRFileStream class
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRFileStream.#ctor(System.String)">
+            <summary>
+            Initializes a new instance of the ANTLRFileStream class for the
+            specified file name
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRFileStream.#ctor(System.String,System.Text.Encoding)">
+            <summary>
+            Initializes a new instance of the ANTLRFileStream class for the
+            specified file name and encoding
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.ANTLRFileStream.fileName">
+            <summary>Fully qualified name of the stream's underlying file</summary>
+        </member>
+        <member name="P:Antlr.Runtime.ANTLRFileStream.SourceName">
+            <summary>
+            Gets the file name of this ANTLRFileStream underlying file
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRFileStream.Load(System.String,System.Text.Encoding)">
+            <summary>
+            Loads and buffers the specified file to be used as this
+            ANTLRFileStream's source
+            </summary>
+            <param name="fileName">File to load</param>
+            <param name="encoding">Encoding to apply to file</param>
+        </member>
+        <member name="T:Antlr.Runtime.ANTLRStringStream">
+            <summary>
+            A pretty quick <see cref="T:Antlr.Runtime.ICharStream" /> that uses a character array
+            directly as it's underlying source.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRStringStream.#ctor">
+            <summary>
+            Initializes a new instance of the ANTLRStringStream class
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRStringStream.#ctor(System.String)">
+            <summary>
+            Initializes a new instance of the ANTLRStringStream class for the
+            specified string. This copies data from the string to a local
+            character array
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRStringStream.#ctor(System.Char[],System.Int32)">
+            <summary>
+            Initializes a new instance of the ANTLRStringStream class for the
+            specified character array. This is the preferred constructor as
+            no data is copied
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.ANTLRStringStream.data">
+            <summary>The data for the stream</summary>
+        </member>
+        <member name="F:Antlr.Runtime.ANTLRStringStream.n">
+            <summary>How many characters are actually in the buffer?</summary>
+        </member>
+        <member name="F:Antlr.Runtime.ANTLRStringStream.p">
+            <summary>Index in our array for the next char (0..n-1)</summary>
+        </member>
+        <member name="F:Antlr.Runtime.ANTLRStringStream.line">
+            <summary>Current line number within the input (1..n )</summary>
+        </member>
+        <member name="F:Antlr.Runtime.ANTLRStringStream.charPositionInLine">
+            <summary>
+            The index of the character relative to the beginning of the
+            line (0..n-1)
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.ANTLRStringStream.markDepth">
+            <summary>
+            Tracks the depth of nested <see cref="M:Antlr.Runtime.IIntStream.Mark" /> calls
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.ANTLRStringStream.markers">
+            <summary>
+            A list of CharStreamState objects that tracks the stream state
+            (i.e. line, charPositionInLine, and p) that can change as you
+            move through the input stream.  Indexed from 1..markDepth.
+            A null is kept @ index 0.  Create upon first call to Mark().
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.ANTLRStringStream.lastMarker">
+            <summary>
+            Track the last Mark() call result value for use in Rewind().
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.ANTLRStringStream.name">
+            <summary>
+            What is name or source of this char stream?
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.ANTLRStringStream.Line">
+            <summary>
+            Current line position in stream.
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.ANTLRStringStream.CharPositionInLine">
+            <summary>
+            Current character position on the current line stream
+            (i.e. columnn position)
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.ANTLRStringStream.Count">
+            <summary>
+            Returns the size of the stream
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRStringStream.Reset">
+            <summary>
+            Resets the stream so that it is in the same state it was
+            when the object was created *except* the data array is not
+            touched.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRStringStream.Consume">
+            <summary>
+            Advances the read position of the stream. Updates line and column state
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRStringStream.LA(System.Int32)">
+            <summary>
+            Return lookahead characters at the specified offset from the current read position.
+            The lookahead offset can be negative.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRStringStream.Index">
+            <summary>
+            Return the current input symbol index 0..n where n indicates the
+            last symbol has been read. The index is the index of char to
+            be returned from LA(1).
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRStringStream.Size">
+            <summary>
+            Returns the size of the stream
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRStringStream.Seek(System.Int32)">
+            <summary>Seeks to the specified position.</summary>
+            <remarks>
+            Consume ahead until p==index; can't just set p=index as we must
+            update line and charPositionInLine.
+            </remarks>
+        </member>
+        <member name="T:Antlr.Runtime.BitSet">
+            <summary>
+            A stripped-down version of org.antlr.misc.BitSet that is just
+            good enough to handle runtime requirements such as FOLLOW sets
+            for automatic error recovery.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BitSet.#ctor">
+            <summary>Construct a bitset of size one word (64 bits) </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BitSet.#ctor(System.UInt64[])">
+            <summary>Construction from a static array of ulongs </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BitSet.#ctor(System.Collections.IList)">
+            <summary>Construction from a list of integers </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BitSet.#ctor(System.Int32)">
+            <summary>Construct a bitset given the size</summary>
+            <param name="nbits">The size of the bitset in bits</param>
+        </member>
+        <member name="F:Antlr.Runtime.BitSet.MOD_MASK">
+            <summary> We will often need to do a mod operator (i mod nbits).
+            Its turns out that, for powers of two, this mod operation is
+            same as <![CDATA[(i & (nbits-1))]]>.  Since mod is slow, we use a precomputed
+            mod mask to do the mod instead.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.BitSet.bits">
+            <summary>The actual data bits </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BitSet.Or(Antlr.Runtime.BitSet)">
+            <summary>return "this | a" in a new set </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BitSet.Add(System.Int32)">
+            <summary>Or this element into this set (grow as necessary to accommodate)</summary>
+        </member>
+        <member name="M:Antlr.Runtime.BitSet.GrowToInclude(System.Int32)">
+            <summary> Grows the set to a larger number of bits.</summary>
+            <param name="bit">element that must fit in set
+            </param>
+        </member>
+        <member name="M:Antlr.Runtime.BitSet.LengthInLongWords">
+            <summary>return how much space is being used by the bits array not
+            how many actually have member bits on.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BitSet.SetSize(System.Int32)">
+            <summary> Sets the size of a set.</summary>
+            <param name="nwords">how many words the new set should be
+            </param>
+        </member>
+        <member name="T:Antlr.Runtime.ICharStream">
+            <summary>A source of characters for an ANTLR lexer </summary>
+        </member>
+        <member name="P:Antlr.Runtime.ICharStream.Line">
+            <summary>
+            The current line in the character stream (ANTLR tracks the
+            line information automatically. To support rewinding character
+            streams, we are able to [re-]set the line.
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.ICharStream.CharPositionInLine">
+            <summary>
+            The index of the character relative to the beginning of the
+            line (0..n-1). To support rewinding character streams, we are
+            able to [re-]set the character position.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ICharStream.LT(System.Int32)">
+            <summary>
+            Get the ith character of lookahead.  This is usually the same as
+            LA(i).  This will be used for labels in the generated lexer code.
+            I'd prefer to return a char here type-wise, but it's probably
+            better to be 32-bit clean and be consistent with LA.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ICharStream.Substring(System.Int32,System.Int32)">
+            <summary>
+            This primarily a useful interface for action code (just make sure
+            actions don't use this on streams that don't support it).
+            For infinite streams, you don't need this.
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.CharStreamState">
+            <summary>
+            This is the complete state of a stream.
+            When walking ahead with cyclic DFA for syntactic predicates, we
+            need to record the state of the input stream (char index, line,
+            etc...) so that we can rewind the state after scanning ahead.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.CharStreamState.p">
+            <summary>Index into the char stream of next lookahead char </summary>
+        </member>
+        <member name="F:Antlr.Runtime.CharStreamState.line">
+            <summary>What line number is the scanner at before processing buffer[p]? </summary>
+        </member>
+        <member name="F:Antlr.Runtime.CharStreamState.charPositionInLine">
+            <summary>What char position 0..n-1 in line is scanner before processing buffer[p]? </summary>
+        </member>
+        <member name="T:Antlr.Runtime.ClassicToken">
+            <summary>
+            A Token object like we'd use in ANTLR 2.x; has an actual string created
+            and associated with this object.  These objects are needed for imaginary
+            tree nodes that have payload objects.  We need to create a Token object
+            that has a string; the tree node will point at this token.  CommonToken
+            has indexes into a char stream and hence cannot be used to introduce
+            new strings.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.ClassicToken.index">
+            <summary>What token number is this from 0..n-1 tokens </summary>
+        </member>
+        <member name="F:Antlr.Runtime.CommonToken.text">
+            <summary>We need to be able to change the text once in a while.  If
+            this is non-null, then getText should return this.  Note that
+            start/stop are not affected by changing this.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.CommonToken.index">
+            <summary>What token number is this from 0..n-1 tokens; &lt; 0 implies invalid index </summary>
+        </member>
+        <member name="F:Antlr.Runtime.CommonToken.start">
+            <summary>The char position into the input buffer where this token starts </summary>
+        </member>
+        <member name="F:Antlr.Runtime.CommonToken.stop">
+            <summary>The char position into the input buffer where this token stops </summary>
+        </member>
+        <member name="T:Antlr.Runtime.DFA">
+            <summary>
+            A DFA implemented as a set of transition tables.
+            </summary>
+            <remarks>
+                <para>
+            Any state that has a semantic predicate edge is special; those states are
+            generated with if-then-else structures in a SpecialStateTransition()
+            which is generated by cyclicDFA template.
+            </para>
+                <para>
+            There are at most 32767 states (16-bit signed short). Could get away with byte
+            sometimes but would have to generate different types and the simulation code too.
+            </para>
+                <para>
+            As a point of reference, the Tokens rule DFA for the lexer in the Java grammar
+            sample has approximately 326 states.
+            </para>
+            </remarks>
+        </member>
+        <member name="F:Antlr.Runtime.DFA.recognizer">
+            <summary>
+            Which recognizer encloses this DFA?  Needed to check backtracking
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.DFA.Predict(Antlr.Runtime.IIntStream)">
+            <summary>
+            From the input stream, predict what alternative will succeed using this
+            DFA (representing the covering regular approximation to the underlying CFL).
+            </summary>
+            <param name="input">Input stream</param>
+            <returns>Return an alternative number 1..n.  Throw an exception upon error.</returns>
+        </member>
+        <member name="M:Antlr.Runtime.DFA.Error(Antlr.Runtime.NoViableAltException)">
+            <summary>
+            A hook for debugging interface
+            </summary>
+            <param name="nvae">
+            </param>
+        </member>
+        <member name="T:Antlr.Runtime.EarlyExitException">
+            <summary>
+            The recognizer did not match anything for a (..)+ loop.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.EarlyExitException.#ctor">
+            <summary>Used for remote debugger deserialization </summary>
+        </member>
+        <member name="T:Antlr.Runtime.FailedPredicateException">
+            <summary>
+            A semantic predicate failed during validation.  Validation of predicates
+            occurs when normally parsing the alternative just like matching a token.
+            Disambiguating predicate evaluation occurs when we hoist a predicate into
+            a prediction decision.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.FailedPredicateException.#ctor">
+            <summary>Used for remote debugger deserialization </summary>
+        </member>
+        <member name="T:Antlr.Runtime.IIntStream">
+            <summary>
+            A simple stream of integers. This is useful when all we care about is the char
+            or token type sequence (such as for interpretation).
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.IIntStream.Count">
+            <summary>Returns the size of the entire stream.</summary>
+            <remarks>
+            Only makes sense for streams that buffer everything up probably,
+            but might be useful to display the entire stream or for testing.
+            This value includes a single EOF.
+            </remarks>
+        </member>
+        <member name="P:Antlr.Runtime.IIntStream.SourceName">
+            <summary>
+            Where are you getting symbols from?  Normally, implementations will
+            pass the buck all the way to the lexer who can ask its input stream
+            for the file name or whatever.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.IIntStream.LA(System.Int32)">
+            <summary>
+            Get int at current input pointer + i ahead (where i=1 is next int)
+            Negative indexes are allowed.  LA(-1) is previous token (token just matched).
+            LA(-i) where i is before first token should yield -1, invalid char or EOF.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.IIntStream.Mark">
+            <summary>Tell the stream to start buffering if it hasn't already.</summary>
+            <remarks>
+            Executing Rewind(Mark()) on a stream should not affect the input position.
+            The Lexer tracks line/col info as well as input index so its markers are
+            not pure input indexes.  Same for tree node streams.													*/
+            </remarks>
+            <returns>Return a marker that can be passed to
+            <see cref="M:Antlr.Runtime.IIntStream.Rewind(System.Int32)" /> to return to the current position.
+            This could be the current input position, a value return from
+            <see cref="M:Antlr.Runtime.IIntStream.Index" />, or some other marker.</returns>
+        </member>
+        <member name="M:Antlr.Runtime.IIntStream.Index">
+            <summary>
+            Return the current input symbol index 0..n where n indicates the
+            last symbol has been read. The index is the symbol about to be
+            read not the most recently read symbol.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.IIntStream.Rewind(System.Int32)">
+            <summary>
+            Resets the stream so that the next call to
+            <see cref="M:Antlr.Runtime.IIntStream.Index" /> would  return marker.
+            </summary>
+            <remarks>
+            The marker will usually be <see cref="M:Antlr.Runtime.IIntStream.Index" /> but
+            it doesn't have to be.  It's just a marker to indicate what
+            state the stream was in.  This is essentially calling
+            <see cref="M:Antlr.Runtime.IIntStream.Release(System.Int32)" /> and <see cref="M:Antlr.Runtime.IIntStream.Seek(System.Int32)" />.
+            If there are other markers created after the specified marker,
+            this routine must unroll them like a stack.  Assumes the state the
+            stream was in when this marker was created.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.IIntStream.Rewind">
+            <summary>
+            Rewind to the input position of the last marker.
+            </summary>
+            <remarks>
+            Used currently only after a cyclic DFA and just before starting
+            a sem/syn predicate to get the input position back to the start
+            of the decision. Do not "pop" the marker off the state.  Mark(i)
+            and Rewind(i) should balance still. It is like invoking
+            Rewind(last marker) but it should not "pop" the marker off.
+            It's like Seek(last marker's input position).
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.IIntStream.Release(System.Int32)">
+            <summary>
+            You may want to commit to a backtrack but don't want to force the
+            stream to keep bookkeeping objects around for a marker that is
+            no longer necessary.  This will have the same behavior as
+            <see cref="M:Antlr.Runtime.IIntStream.Rewind(System.Int32)" /> except it releases resources without
+            the backward seek.
+            </summary>
+            <remarks>
+            This must throw away resources for all markers back to the marker
+            argument. So if you're nested 5 levels of Mark(), and then Release(2)
+            you have to release resources for depths 2..5.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.IIntStream.Seek(System.Int32)">
+            <summary>
+            Set the input cursor to the position indicated by index.  This is
+            normally used to seek ahead in the input stream.
+            </summary>
+            <remarks>
+            No buffering is required to do this unless you know your stream
+            will use seek to move backwards such as when backtracking.
+            This is different from rewind in its multi-directional requirement
+            and in that its argument is strictly an input cursor (index).
+            For char streams, seeking forward must update the stream state such
+            as line number.  For seeking backwards, you will be presumably
+            backtracking using the
+            <see cref="M:Antlr.Runtime.IIntStream.Mark" />/<see cref="M:Antlr.Runtime.IIntStream.Rewind(System.Int32)" />
+            mechanism that restores state and so this method does not need to
+            update state when seeking backwards.
+            Currently, this method is only used for efficient backtracking using
+            memoization, but in the future it may be used for incremental parsing.
+            The index is 0..n-1. A seek to position i means that LA(1) will return
+            the ith symbol.  So, seeking to 0 means LA(1) will return the first
+            element in the stream.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.IIntStream.Size">
+            <summary>Returns the size of the entire stream.</summary>
+            <remarks>
+            Only makes sense for streams that buffer everything up probably,
+            but might be useful to display the entire stream or for testing.
+            This value includes a single EOF.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.MismatchedNotSetException.#ctor">
+            <summary>Used for remote debugger deserialization </summary>
+        </member>
+        <member name="M:Antlr.Runtime.MismatchedRangeException.#ctor">
+            <summary>
+            Used for remote debugger deserialization
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.MismatchedSetException.#ctor">
+            <summary>Used for remote debugger deserialization </summary>
+        </member>
+        <member name="T:Antlr.Runtime.MismatchedTokenException">
+            <summary>
+            A mismatched char or Token or tree node.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.MismatchedTokenException.#ctor">
+            <summary>
+            Used for remote debugger deserialization
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.NoViableAltException.#ctor">
+            <summary>Used for remote debugger deserialization</summary>
+        </member>
+        <member name="T:Antlr.Runtime.Parser">
+            <summary>A parser for TokenStreams.  Parser grammars result in a subclass
+            of this.
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Parser.TokenStream">
+            <summary>Set the token stream and reset the parser </summary>
+        </member>
+        <member name="T:Antlr.Runtime.ParserRuleReturnScope">
+            <summary>
+            Rules that return more than a single value must return an object
+            containing all the values.  Besides the properties defined in
+            RuleLabelScope.PredefinedRulePropertiesScope there may be user-defined
+            return values.  This class simply defines the minimum properties that
+            are always defined and methods to access the others that might be
+            available depending on output option such as template and tree.
+            Note text is not an actual property of the return value, it is computed
+            from start and stop using the input stream's ToString() method.  I
+            could add a ctor to this so that we can pass in and store the input
+            stream, but I'm not sure we want to do that.  It would seem to be undefined
+            to get the .text property anyway if the rule matches tokens from multiple
+            input streams.
+            I do not use getters for fields of objects that are used simply to
+            group values such as this aggregate.
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.ParserRuleReturnScope.Start">
+            <summary>Return the start token or tree </summary>
+        </member>
+        <member name="P:Antlr.Runtime.ParserRuleReturnScope.Stop">
+            <summary>Return the stop token or tree </summary>
+        </member>
+        <member name="T:Antlr.Runtime.RecognitionException">
+            <summary>The root of the ANTLR exception hierarchy.</summary>
+            <remarks>
+            To avoid English-only error messages and to generally make things
+            as flexible as possible, these exceptions are not created with strings,
+            but rather the information necessary to generate an error.  Then
+            the various reporting methods in Parser and Lexer can be overridden
+            to generate a localized error message.  For example, MismatchedToken
+            exceptions are built with the expected token type.
+            So, don't expect getMessage() to return anything.
+            You can access the stack trace, which means that you can compute the
+            complete trace of rules from the start symbol. This gives you considerable
+            context information with which to generate useful error messages.
+            ANTLR generates code that throws exceptions upon recognition error and
+            also generates code to catch these exceptions in each rule.  If you
+            want to quit upon first error, you can turn off the automatic error
+            handling mechanism using rulecatch action, but you still need to
+            override methods mismatch and recoverFromMismatchSet.
+            In general, the recognition exceptions can track where in a grammar a
+            problem occurred and/or what was the expected input.  While the parser
+            knows its state (such as current input symbol and line info) that
+            state can change before the exception is reported so current token index
+            is computed and stored at exception time.  From this info, you can
+            perhaps print an entire line of input not just a single token, for example.
+            Better to just say the recognizer had a problem and then let the parser
+            figure out a fancy report.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.RecognitionException.#ctor">
+            <summary>Used for remote debugger deserialization </summary>
+        </member>
+        <member name="F:Antlr.Runtime.RecognitionException.input">
+            <summary>What input stream did the error occur in? </summary>
+        </member>
+        <member name="F:Antlr.Runtime.RecognitionException.index">
+            <summary>
+            What is index of token/char were we looking at when the error occurred?
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.RecognitionException.token">
+            <summary>
+            The current Token when an error occurred.  Since not all streams
+            can retrieve the ith Token, we have to track the Token object.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.RecognitionException.node">
+            <summary>[Tree parser] Node with the problem.</summary>
+        </member>
+        <member name="F:Antlr.Runtime.RecognitionException.c">
+            <summary>The current char when an error occurred. For lexers. </summary>
+        </member>
+        <member name="F:Antlr.Runtime.RecognitionException.line">
+            <summary>Track the line at which the error occurred in case this is
+            generated from a lexer.  We need to track this since the
+            unexpected char doesn't carry the line info.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.RecognitionException.approximateLineInfo">
+            <summary>
+            If you are parsing a tree node stream, you will encounter some
+            imaginary nodes w/o line/col info.  We now search backwards looking
+            for most recent token with line/col info, but notify getErrorHeader()
+            that info is approximate.
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.RecognitionException.Input">
+            <summary>Returns the input stream in which the error occurred</summary>
+        </member>
+        <member name="P:Antlr.Runtime.RecognitionException.Index">
+            <summary>
+            Returns the token/char index in the stream when the error occurred
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.RecognitionException.Token">
+            <summary>
+            Returns the current Token when the error occurred (for parsers
+            although a tree parser might also set the token)
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.RecognitionException.Node">
+            <summary>
+            Returns the [tree parser] node where the error occured (for tree parsers).
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.RecognitionException.Char">
+            <summary>
+            Returns the current char when the error occurred (for lexers)
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.RecognitionException.CharPositionInLine">
+            <summary>
+            Returns the character position in the line when the error
+            occurred (for lexers)
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.RecognitionException.Line">
+            <summary>
+            Returns the line at which the error occurred (for lexers)
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.RecognitionException.UnexpectedType">
+            <summary>
+            Returns the token type or char of the unexpected input element
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.RuleReturnScope">
+            <summary>
+            Rules can return start/stop info as well as possible trees and templates
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.RuleReturnScope.Start">
+            <summary>Return the start token or tree </summary>
+        </member>
+        <member name="P:Antlr.Runtime.RuleReturnScope.Stop">
+            <summary>Return the stop token or tree </summary>
+        </member>
+        <member name="P:Antlr.Runtime.RuleReturnScope.Tree">
+            <summary>Has a value potentially if output=AST; </summary>
+        </member>
+        <member name="P:Antlr.Runtime.RuleReturnScope.Template">
+            <summary>
+            Has a value potentially if output=template;
+            Don't use StringTemplate type to avoid dependency on ST assembly
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Token.DOWN">
+            <summary>imaginary tree navigation type; traverse "get child" link </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Token.UP">
+            <summary>imaginary tree navigation type; finish with a child list </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Token.DEFAULT_CHANNEL">
+            <summary>
+            All tokens go to the parser (unless skip() is called in that rule)
+            on a particular "channel".  The parser tunes to a particular channel
+            so that whitespace etc... can go to the parser on a "hidden" channel.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Token.HIDDEN_CHANNEL">
+            <summary>
+            Anything on different channel than DEFAULT_CHANNEL is not parsed by parser.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Token.SKIP_TOKEN">
+            <summary>
+            In an action, a lexer rule can set token to this SKIP_TOKEN and ANTLR
+            will avoid creating a token for this symbol and try to fetch another.
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.ITokenSource">
+            <summary>
+            A source of tokens must provide a sequence of tokens via NextToken()
+            and also must reveal it's source of characters; CommonToken's text is
+            computed from a CharStream; it only store indices into the char stream.
+            Errors from the lexer are never passed to the parser.  Either you want
+            to keep going or you do not upon token recognition error.  If you do not
+            want to continue lexing then you do not want to continue parsing.  Just
+            throw an exception not under RecognitionException and Java will naturally
+            toss you all the way out of the recognizers.  If you want to continue
+            lexing then you should not throw an exception to the parser--it has already
+            requested a token.  Keep lexing until you get a valid one.  Just report
+            errors and keep going, looking for a valid token.
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.ITokenSource.SourceName">
+            <summary>
+            Where are you getting tokens from? normally the implication will simply
+            ask lexers input stream.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ITokenSource.NextToken">
+            <summary>
+            Returns a Token object from the input stream (usually a CharStream).
+            Does not fail/return upon lexing error; just keeps chewing on the
+            characters until it gets a good one; errors are not passed through
+            to the parser.
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.MissingTokenException">
+            <summary>
+            We were expecting a token but it's not found. The current token
+            is actually what we wanted next. Used for tree node errors too.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.MissingTokenException.#ctor">
+            <summary>
+            Used for remote debugger deserialization
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.CommonErrorNode">
+             A node representing erroneous token range in token stream</member>
+        <member name="T:Antlr.Runtime.UnwantedTokenException">
+            <summary>
+            An extra token while parsing a TokenStream.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.UnwantedTokenException.#ctor">
+            <summary>
+            Used for remote debugger deserialization
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Collections.CollectionUtils.ListToString(System.Collections.IList)">
+            <summary>
+            Returns a string representation of this IList.
+            </summary>
+            <remarks>
+            The string representation is a list of the collection's elements in the order
+            they are returned by its IEnumerator, enclosed in square brackets ("[]").
+            The separator is a comma followed by a space i.e. ", ".
+            </remarks>
+            <param name="coll">Collection whose string representation will be returned</param>
+            <returns>A string representation of the specified collection or "null"</returns>
+        </member>
+        <member name="M:Antlr.Runtime.Collections.CollectionUtils.DictionaryToString(System.Collections.IDictionary)">
+            <summary>
+            Returns a string representation of this IDictionary.
+            </summary>
+            <remarks>
+            The string representation is a list of the collection's elements in the order
+            they are returned by its IEnumerator, enclosed in curly brackets ("{}").
+            The separator is a comma followed by a space i.e. ", ".
+            </remarks>
+            <param name="dict">Dictionary whose string representation will be returned</param>
+            <returns>A string representation of the specified dictionary or "null"</returns>
+        </member>
+        <member name="T:Antlr.Runtime.Collections.HashList">
+            <summary>
+            An Hashtable-backed dictionary that enumerates Keys and Values in
+            insertion order.
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Collections.StackList">
+            <summary>
+            Stack abstraction that also supports the IList interface
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Collections.StackList.Push(System.Object)">
+            <summary>
+            Adds an element to the top of the stack list.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Collections.StackList.Pop">
+            <summary>
+            Removes the element at the top of the stack list and returns it.
+            </summary>
+            <returns>The element at the top of the stack.</returns>
+        </member>
+        <member name="M:Antlr.Runtime.Collections.StackList.Peek">
+            <summary>
+            Removes the element at the top of the stack list without removing it.
+            </summary>
+            <returns>The element at the top of the stack.</returns>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.BaseTree">
+            <summary>
+            A generic tree implementation with no payload.  You must subclass to
+            actually have any user data.  ANTLR v3 uses a list of children approach
+            instead of the child-sibling approach in v2.  A flat tree (a list) is
+            an empty node whose children represent the list.  An empty, but
+            non-null node is called "nil".
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTree.#ctor(Antlr.Runtime.Tree.ITree)">
+            <summary>Create a new node from an existing node does nothing for BaseTree
+            as there are no fields other than the children list, which cannot
+            be copied as the children are not considered part of this node.
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.BaseTree.Children">
+            <summary>
+            Get the children internal list of children. Manipulating the list
+            directly is not a supported operation (i.e. you do so at your own risk)
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.BaseTree.ChildIndex">
+            <summary>BaseTree doesn't track child indexes.</summary>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.BaseTree.Parent">
+            <summary>BaseTree doesn't track parent pointers.</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTree.AddChild(Antlr.Runtime.Tree.ITree)">
+            <summary>
+            Add t as child of this node.
+            </summary>
+            <remarks>
+            Warning: if t has no children, but child does and child isNil then
+            this routine moves children to t via t.children = child.children;
+            i.e., without copying the array.
+            </remarks>
+            <param name="t">
+            </param>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTree.AddChildren(System.Collections.IList)">
+            <summary>
+            Add all elements of kids list as children of this node
+            </summary>
+            <param name="kids">
+            </param>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTree.ReplaceChildren(System.Int32,System.Int32,System.Object)">
+            <summary>
+            Delete children from start to stop and replace with t even if t is
+            a list (nil-root tree).
+            </summary>
+            <remarks>
+            Number of children can increase or decrease.
+            For huge child lists, inserting children can force walking rest of
+            children to set their childindex; could be slow.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTree.CreateChildrenList">
+            <summary>Override in a subclass to change the impl of children list </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTree.FreshenParentAndChildIndexes">
+            <summary>Set the parent and child index values for all child of t</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTree.HasAncestor(System.Int32)">
+            <summary>
+            Walk upwards looking for ancestor with this token type.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTree.GetAncestor(System.Int32)">
+            <summary>
+            Walk upwards and get first ancestor with this token type.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTree.GetAncestors">
+            <summary>
+            Return a list of all ancestors of this node.  The first node of
+            list is the root and the last is the parent of this node.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTree.ToStringTree">
+            <summary>
+            Print out a whole tree not just a node
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTree.ToString">
+            <summary>
+            Force base classes override and say how a node (not a tree)
+            should look as text
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.BaseTreeAdaptor">
+            <summary>
+            A TreeAdaptor that works with any Tree implementation
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.BaseTreeAdaptor.treeToUniqueIDMap">
+            <summary>A map of tree node to unique IDs.</summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.BaseTreeAdaptor.uniqueNodeID">
+            <summary>Next available unique ID.</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTreeAdaptor.ErrorNode(Antlr.Runtime.ITokenStream,Antlr.Runtime.IToken,Antlr.Runtime.IToken,Antlr.Runtime.RecognitionException)">
+            <summary>
+            Create tree node that holds the start and stop tokens associated
+            with an error.
+            </summary>
+            <remarks>
+                <para>If you specify your own kind of tree nodes, you will likely have to
+            override this method. CommonTree returns Token.INVALID_TOKEN_TYPE
+            if no token payload but you might have to set token type for diff
+            node type.</para>
+                <para>You don't have to subclass CommonErrorNode; you will likely need to
+            subclass your own tree node class to avoid class cast exception.</para>
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTreeAdaptor.DupTree(System.Object,System.Object)">
+            <summary>
+            This is generic in the sense that it will work with any kind of
+            tree (not just the ITree interface).  It invokes the adaptor routines
+            not the tree node routines to do the construction.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTreeAdaptor.AddChild(System.Object,System.Object)">
+            <summary>
+            Add a child to the tree t.  If child is a flat tree (a list), make all
+            in list children of t.
+            </summary>
+            <remarks>
+                <para>
+            Warning: if t has no children, but child does and child isNil
+            then you can decide it is ok to move children to t via
+            t.children = child.children; i.e., without copying the array.
+            Just make sure that this is consistent with how the user will build
+            ASTs.
+            	</para>
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTreeAdaptor.BecomeRoot(System.Object,System.Object)">
+            <summary>
+            If oldRoot is a nil root, just copy or move the children to newRoot.
+            If not a nil root, make oldRoot a child of newRoot.
+            </summary>
+            <remarks>
+            old=^(nil a b c), new=r yields ^(r a b c)
+            old=^(a b c), new=r yields ^(r ^(a b c))
+            If newRoot is a nil-rooted single child tree, use the single
+            child as the new root node.
+            old=^(nil a b c), new=^(nil r) yields ^(r a b c)
+            old=^(a b c), new=^(nil r) yields ^(r ^(a b c))
+            If oldRoot was null, it's ok, just return newRoot (even if isNil).
+            old=null, new=r yields r
+            old=null, new=^(nil r) yields ^(nil r)
+            Return newRoot.  Throw an exception if newRoot is not a
+            simple node or nil root with a single child node--it must be a root
+            node.  If newRoot is ^(nil x) return x as newRoot.
+            Be advised that it's ok for newRoot to point at oldRoot's
+            children; i.e., you don't have to copy the list.  We are
+            constructing these nodes so we should have this control for
+            efficiency.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTreeAdaptor.RulePostProcessing(System.Object)">
+            <summary>Transform ^(nil x) to x and nil to null</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTreeAdaptor.GetUniqueID(System.Object)">
+            <summary>
+            For identifying trees. How to identify nodes so we can say "add node
+            to a prior node"?
+            </summary>
+            <remarks>
+                <para>
+            System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode() is
+            not available in .NET 1.0. It is "broken/buggy" in .NET 1.1
+            (for multi-appdomain scenarios).
+            </para>
+                <para>
+            We are tracking uniqueness of IDs ourselves manually since ANTLR
+            v3.1 release using hashtables. We will be tracking . Even though
+            it is expensive, we will create a hashtable with all tree nodes
+            in it as this is only for debugging.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTreeAdaptor.CreateToken(System.Int32,System.String)">
+            <summary>
+            Tell me how to create a token for use with imaginary token nodes.
+            For example, there is probably no input symbol associated with imaginary
+            token DECL, but you need to create it as a payload or whatever for
+            the DECL node as in ^(DECL type ID).
+            If you care what the token payload objects' type is, you should
+            override this method and any other createToken variant.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTreeAdaptor.CreateToken(Antlr.Runtime.IToken)">
+            <summary>
+            Tell me how to create a token for use with imaginary token nodes.
+            For example, there is probably no input symbol associated with imaginary
+            token DECL, but you need to create it as a payload or whatever for
+            the DECL node as in ^(DECL type ID).
+            This is a variant of createToken where the new token is derived from
+            an actual real input token.  Typically this is for converting '{'
+            tokens to BLOCK etc...  You'll see
+            r : lc='{' ID+ '}' -&gt; ^(BLOCK[$lc] ID+) ;
+            If you care what the token payload objects' type is, you should
+            override this method and any other createToken variant.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTreeAdaptor.GetParent(System.Object)">
+            <summary>
+            Who is the parent node of this node; if null, implies node is root.
+            </summary>
+            <remarks>
+            If your node type doesn't handle this, it's ok but the tree rewrites
+            in tree parsers need this functionality.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTreeAdaptor.GetChildIndex(System.Object)">
+            <summary>
+            What index is this node in the child list? Range: 0..n-1
+            </summary>
+            <remarks>
+            If your node type doesn't handle this, it's ok but the tree rewrites
+            in tree parsers need this functionality.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.BaseTreeAdaptor.ReplaceChildren(System.Object,System.Int32,System.Int32,System.Object)">
+            <summary>
+            Replace from start to stop child index of parent with t, which might
+            be a list.  Number of children may be different after this call.
+            </summary>
+            <remarks>
+            If parent is null, don't do anything; must be at root of overall tree.
+            Can't replace whatever points to the parent externally.  Do nothing.
+            </remarks>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.CommonTree">
+            <summary>A tree node that is wrapper for a Token object. </summary>
+            <remarks>
+            After 3.0 release while building tree rewrite stuff, it became clear
+            that computing parent and child index is very difficult and cumbersome.
+            Better to spend the space in every tree node.  If you don't want these
+            extra fields, it's easy to cut them out in your own BaseTree subclass.
+            </remarks>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.CommonTree.startIndex">
+            <summary>
+            What token indexes bracket all tokens associated with this node
+            and below?
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.CommonTree.token">
+            <summary>A single token is the payload </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.CommonTree.parent">
+            <summary>Who is the parent node of this node; if null, implies node is root</summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.CommonTree.childIndex">
+            <summary>What index is this node in the child list? Range: 0..n-1</summary>
+        </member>
+        <!--FIXME: Invalid documentation markup was found for member M:Antlr.Runtime.Tree.CommonTree.SetUnknownTokenBoundaries-->
+        <member name="T:Antlr.Runtime.Tree.CommonTreeAdaptor">
+            <summary>
+            A TreeAdaptor that works with any Tree implementation.  It provides
+            really just factory methods; all the work is done by BaseTreeAdaptor.
+            If you would like to have different tokens created than ClassicToken
+            objects, you need to override this and then set the parser tree adaptor to
+            use your subclass.
+            To get your parser to build nodes of a different type, override
+            Create(Token), ErrorNode(), and to be safe, YourTreeClass.DupNode().
+            DupNode() is called to duplicate nodes during rewrite operations.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.CommonTreeAdaptor.DupNode(System.Object)">
+            <summary>
+            Duplicate a node.  This is part of the factory;
+            override if you want another kind of node to be built.
+            I could use reflection to prevent having to override this
+            but reflection is slow.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.CommonTreeAdaptor.CreateToken(System.Int32,System.String)">
+            <summary>Create an imaginary token from a type and text </summary>
+            <remarks>
+            Tell me how to create a token for use with imaginary token nodes.
+            For example, there is probably no input symbol associated with imaginary
+            token DECL, but you need to create it as a payload or whatever for
+            the DECL node as in ^(DECL type ID).
+            If you care what the token payload objects' type is, you should
+            override this method and any other createToken variant.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.CommonTreeAdaptor.CreateToken(Antlr.Runtime.IToken)">
+            <summary>Create an imaginary token, copying the contents of a previous token </summary>
+            <remarks>
+            Tell me how to create a token for use with imaginary token nodes.
+            For example, there is probably no input symbol associated with imaginary
+            token DECL, but you need to create it as a payload or whatever for
+            the DECL node as in ^(DECL type ID).
+            This is a variant of createToken where the new token is derived from
+            an actual real input token.  Typically this is for converting '{'
+            tokens to BLOCK etc...  You'll see
+            r : lc='{' ID+ '}' -&gt; ^(BLOCK[$lc] ID+) ;
+            If you care what the token payload objects' type is, you should
+            override this method and any other createToken variant.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.CommonTreeAdaptor.SetTokenBoundaries(System.Object,Antlr.Runtime.IToken,Antlr.Runtime.IToken)">
+            <summary>track start/stop token for subtree root created for a rule </summary>
+            <remarks>
+            Track start/stop token for subtree root created for a rule.
+            Only works with Tree nodes.  For rules that match nothing,
+            seems like this will yield start=i and stop=i-1 in a nil node.
+            Might be useful info so I'll not force to be i..i.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.CommonTreeAdaptor.GetToken(System.Object)">
+            <summary>
+            What is the Token associated with this node?
+            </summary>
+            <remarks>
+            If you are not using CommonTree, then you must override this in your
+            own adaptor.
+            </remarks>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.CommonTreeNodeStream">
+            <summary>
+            A buffered stream of tree nodes.  Nodes can be from a tree of ANY kind.
+            </summary>
+            <remarks>
+            This node stream sucks all nodes out of the tree specified in the
+            constructor during construction and makes pointers into the tree
+            using an array of Object pointers. The stream necessarily includes
+            pointers to DOWN and UP and EOF nodes.
+            This stream knows how to mark/release for backtracking.
+            This stream is most suitable for tree interpreters that need to
+            jump around a lot or for tree parsers requiring speed (at cost of memory).
+            There is some duplicated functionality here with UnBufferedTreeNodeStream
+            but just in bookkeeping, not tree walking etc...
+            <see cref="T:Antlr.Runtime.Tree.UnBufferedTreeNodeStream" /></remarks>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.CommonTreeNodeStream.nodes">
+            <summary>
+            The complete mapping from stream index to tree node. This buffer
+            includes pointers to DOWN, UP, and EOF nodes.
+            It is built upon ctor invocation.  The elements are type Object
+            as we don't what the trees look like. Load upon first need of
+            the buffer so we can set token types of interest for reverseIndexing.
+            Slows us down a wee bit  to do all of the if p==-1 testing everywhere though.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.CommonTreeNodeStream.root">
+            <summary>Pull nodes from which tree? </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.CommonTreeNodeStream.tokens">
+            <summary>IF this tree (root) was created from a token stream, track it</summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.CommonTreeNodeStream.adaptor">
+            <summary>What tree adaptor was used to build these trees</summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.CommonTreeNodeStream.uniqueNavigationNodes">
+            <summary>
+            Reuse same DOWN, UP navigation nodes unless this is true
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.CommonTreeNodeStream.p">
+            <summary>
+            The index into the nodes list of the current node (next node
+            to consume).  If -1, nodes array not filled yet.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.CommonTreeNodeStream.lastMarker">
+            <summary>
+            Track the last mark() call result value for use in rewind().
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.CommonTreeNodeStream.calls">
+            <summary>
+            Stack of indexes used for push/pop calls
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.CommonTreeNodeStream.TreeSource">
+            <summary>
+            Where is this stream pulling nodes from?  This is not the name, but
+            the object that provides node objects.
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.CommonTreeNodeStream.Count">
+            <summary>
+            Expensive to compute so I won't bother doing the right thing.
+            This method only returns how much input has been seen so far.  So
+            after parsing it returns true size.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.CommonTreeNodeStream.FillBuffer">
+            <summary>
+            Walk tree with depth-first-search and fill nodes buffer.
+            Don't do DOWN, UP nodes if its a list (t is isNil).
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.CommonTreeNodeStream.GetNodeIndex(System.Object)">
+            <summary>
+            Returns the stream index for the spcified node in the range 0..n-1 or,
+            -1 if node not found.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.CommonTreeNodeStream.AddNavigationNode(System.Int32)">
+            <summary>
+            As we flatten the tree, we use UP, DOWN nodes to represent
+            the tree structure.  When debugging we need unique nodes
+            so instantiate new ones when uniqueNavigationNodes is true.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.CommonTreeNodeStream.LB(System.Int32)">
+            <summary>
+            Look backwards k nodes
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.CommonTreeNodeStream.Push(System.Int32)">
+            <summary>
+            Make stream jump to a new location, saving old location.
+            Switch back with pop().
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.CommonTreeNodeStream.Pop">
+            <summary>
+            Seek back to previous index saved during last Push() call.
+            Return top of stack (return index).
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.CommonTreeNodeStream.Mark">
+            <summary>
+            Record the current state of the tree walk which includes
+            the current node and stack state.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.CommonTreeNodeStream.Rewind(System.Int32)">
+            <summary>
+            Rewind the current state of the tree walk to the state it
+            was in when Mark() was called and it returned marker.  Also,
+            wipe out the lookahead which will force reloading a few nodes
+            but it is better than making a copy of the lookahead buffer
+            upon Mark().
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.CommonTreeNodeStream.Seek(System.Int32)">
+            <summary>
+            Consume() ahead until we hit index.  Can't just jump ahead--must
+            spit out the navigation nodes.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.CommonTreeNodeStream.Size">
+            <summary>
+            Expensive to compute so I won't bother doing the right thing.
+            This method only returns how much input has been seen so far.  So
+            after parsing it returns true size.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.CommonTreeNodeStream.ToString">
+            <summary>
+            Used for testing, just return the token type stream
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.CommonTreeNodeStream.ToTokenString(System.Int32,System.Int32)">
+             Debugging</member>
+        <member name="T:Antlr.Runtime.Tree.ITree">
+            <summary>
+            What does a tree look like?  ANTLR has a number of support classes
+            such as CommonTreeNodeStream that work on these kinds of trees.  You
+            don't have to make your trees implement this interface, but if you do,
+            you'll be able to use more support code.
+            NOTE: When constructing trees, ANTLR can build any kind of tree; it can
+            even use Token objects as trees if you add a child list to your tokens.
+            This is a tree node without any payload; just navigation and factory stuff.
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.ITree.ChildIndex">
+            <summary>This node is what child index? 0..n-1</summary>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.ITree.IsNil">
+            <summary>
+            Indicates the node is a nil node but may still have children, meaning
+            the tree is a flat list.
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.ITree.Type">
+            <summary>Return a token type; needed for tree parsing </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.ITree.Line">
+            <summary>In case we don't have a token payload, what is the line for errors? </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.ITree.TokenStartIndex">
+            <summary>
+            What is the smallest token index (indexing from 0) for this node
+            and its children?
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.ITree.TokenStopIndex">
+            <summary>
+            What is the largest token index (indexing from 0) for this node
+            and its children?
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITree.HasAncestor(System.Int32)">
+            <summary>
+            Is there is a node above with token type ttype?
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITree.GetAncestor(System.Int32)">
+            <summary>
+            Walk upwards and get first ancestor with this token type.
+            </summary>
+            <param name="ttype">
+            A <see cref="T:System.Int32" /></param>
+            <returns>
+            A <see cref="T:Antlr.Runtime.Tree.ITree" /></returns>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITree.GetAncestors">
+            <summary>
+            Return a list of all ancestors of this node.  The first node of
+            list is the root and the last is the parent of this node.
+            </summary>
+            <returns>
+            A <see cref="T:System.Collections.IList" /></returns>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITree.FreshenParentAndChildIndexes">
+            <summary>Set (or reset) the parent and child index values for all children</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITree.AddChild(Antlr.Runtime.Tree.ITree)">
+            <summary>
+            Add t as a child to this node.  If t is null, do nothing.  If t
+            is nil, add all children of t to this' children.
+            </summary>
+            <param name="t">Tree to add</param>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITree.SetChild(System.Int32,Antlr.Runtime.Tree.ITree)">
+            <summary>Set ith child (0..n-1) to t; t must be non-null and non-nil node</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITree.ReplaceChildren(System.Int32,System.Int32,System.Object)">
+            <summary>
+            Delete children from start to stop and replace with t even if t is
+            a list (nil-root tree).  num of children can increase or decrease.
+            For huge child lists, inserting children can force walking rest of
+            children to set their childindex; could be slow.
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.ITreeAdaptor">
+            <summary>
+            How to create and navigate trees.  Rather than have a separate factory
+            and adaptor, I've merged them.  Makes sense to encapsulate.
+            This takes the place of the tree construction code generated in the
+            generated code in 2.x and the ASTFactory.
+            I do not need to know the type of a tree at all so they are all
+            generic Objects.  This may increase the amount of typecasting needed. :(
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.Create(Antlr.Runtime.IToken)">
+            <summary>
+            Create a tree node from Token object; for CommonTree type trees,
+            then the token just becomes the payload.
+            </summary>
+            <remarks>
+            This is the most common create call. Override if you want another kind of node to be built.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.DupNode(System.Object)">
+            <summary>Duplicate a single tree node </summary>
+            <remarks> Override if you want another kind of node to be built.</remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.DupTree(System.Object)">
+            <summary>Duplicate tree recursively, using DupNode() for each node </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.GetNilNode">
+            <summary>
+            Return a nil node (an empty but non-null node) that can hold
+            a list of element as the children.  If you want a flat tree (a list)
+            use "t=adaptor.nil(); t.AddChild(x); t.AddChild(y);"
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.ErrorNode(Antlr.Runtime.ITokenStream,Antlr.Runtime.IToken,Antlr.Runtime.IToken,Antlr.Runtime.RecognitionException)">
+            <summary>
+            Return a tree node representing an error. This node records the
+            tokens consumed during error recovery. The start token indicates the
+            input symbol at which the error was detected. The stop token indicates
+            the last symbol consumed during recovery.
+            </summary>
+            <remarks>
+                <para>You must specify the input stream so that the erroneous text can
+            be packaged up in the error node. The exception could be useful
+            to some applications; default implementation stores ptr to it in
+            the CommonErrorNode.</para>
+                <para>This only makes sense during token parsing, not tree parsing.
+            Tree parsing should happen only when parsing and tree construction
+            succeed.</para>
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.IsNil(System.Object)">
+            <summary>
+            Is tree considered a nil node used to make lists of child nodes?
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.AddChild(System.Object,System.Object)">
+            <summary>
+            Add a child to the tree t.  If child is a flat tree (a list), make all
+            in list children of t.
+            </summary>
+            <remarks>
+                <para>
+            Warning: if t has no children, but child does and child isNil then you
+            can decide it is ok to move children to t via t.children = child.children;
+            i.e., without copying the array.  Just make sure that this is consistent
+            with have the user will build ASTs. Do nothing if t or child is null.
+            </para>
+                <para>
+            This is for construction and I'm not sure it's completely general for
+            a tree's addChild method to work this way.  Make sure you differentiate
+            between your tree's addChild and this parser tree construction addChild
+            if it's not ok to move children to t with a simple assignment.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.BecomeRoot(System.Object,System.Object)">
+            <summary>
+            If oldRoot is a nil root, just copy or move the children to newRoot.
+            If not a nil root, make oldRoot a child of newRoot.
+            </summary>
+            <remarks>
+            old=^(nil a b c), new=r yields ^(r a b c)
+            old=^(a b c), new=r yields ^(r ^(a b c))
+            If newRoot is a nil-rooted single child tree, use the single
+            child as the new root node.
+            old=^(nil a b c), new=^(nil r) yields ^(r a b c)
+            old=^(a b c), new=^(nil r) yields ^(r ^(a b c))
+            If oldRoot was null, it's ok, just return newRoot (even if isNil).
+            old=null, new=r yields r
+            old=null, new=^(nil r) yields ^(nil r)
+            Return newRoot.  Throw an exception if newRoot is not a
+            simple node or nil root with a single child node--it must be a root
+            node.  If newRoot is ^(nil x) return x as newRoot.
+            Be advised that it's ok for newRoot to point at oldRoot's
+            children; i.e., you don't have to copy the list.  We are
+            constructing these nodes so we should have this control for
+            efficiency.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.RulePostProcessing(System.Object)">
+            <summary>
+            Given the root of the subtree created for this rule, post process
+            it to do any simplifications or whatever you want.  A required
+            behavior is to convert ^(nil singleSubtree) to singleSubtree
+            as the setting of start/stop indexes relies on a single non-nil root
+            for non-flat trees.
+            Flat trees such as for lists like "idlist : ID+ ;" are left alone
+            unless there is only one ID.  For a list, the start/stop indexes
+            are set in the nil node.
+            This method is executed after all rule tree construction and right
+            before SetTokenBoundaries().
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.GetUniqueID(System.Object)">
+            <summary>
+            For identifying trees. How to identify nodes so we can say "add node
+            to a prior node"?
+            </summary>
+            <remarks>
+            Even BecomeRoot is an issue. Ok, we could:
+            <list type="number"><item>Number the nodes as they are created?</item><item>
+            			Use the original framework assigned hashcode that's unique
+            			across instances of a given type.
+            			WARNING: This is usually implemented either as IL to make a
+            			non-virt call to object.GetHashCode() or by via a call to
+            			System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode().
+            			Both have issues especially on .NET 1.x and Mono.
+            		</item></list></remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.BecomeRoot(Antlr.Runtime.IToken,System.Object)">
+            <summary>
+            Create a node for newRoot make it the root of oldRoot.
+            If oldRoot is a nil root, just copy or move the children to newRoot.
+            If not a nil root, make oldRoot a child of newRoot.
+            Return node created for newRoot.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.Create(System.Int32,Antlr.Runtime.IToken)">
+            <summary>Create a new node derived from a token, with a new token type.
+            This is invoked from an imaginary node ref on right side of a
+            rewrite rule as IMAG[$tokenLabel].
+            This should invoke createToken(Token).
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.Create(System.Int32,Antlr.Runtime.IToken,System.String)">
+            <summary>Same as Create(tokenType,fromToken) except set the text too.
+            This is invoked from an imaginary node ref on right side of a
+            rewrite rule as IMAG[$tokenLabel, "IMAG"].
+            This should invoke createToken(Token).
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.Create(System.Int32,System.String)">
+            <summary>Create a new node derived from a token, with a new token type.
+            This is invoked from an imaginary node ref on right side of a
+            rewrite rule as IMAG["IMAG"].
+            This should invoke createToken(int,String).
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.GetNodeType(System.Object)">
+            <summary>For tree parsing, I need to know the token type of a node </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.SetNodeType(System.Object,System.Int32)">
+            <summary>Node constructors can set the type of a node </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.SetNodeText(System.Object,System.String)">
+            <summary>Node constructors can set the text of a node </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.GetToken(System.Object)">
+            <summary>
+            Return the token object from which this node was created.
+            </summary>
+            <remarks>
+            Currently used only for printing an error message. The error
+            display routine in BaseRecognizer needs to display where the
+            input the error occurred. If your tree of limitation does not
+            store information that can lead you to the token, you can create
+            a token filled with the appropriate information and pass that back.
+            <see cref="M:Antlr.Runtime.BaseRecognizer.GetErrorMessage(Antlr.Runtime.RecognitionException,System.String[])" /></remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.SetTokenBoundaries(System.Object,Antlr.Runtime.IToken,Antlr.Runtime.IToken)">
+            <summary>
+            Where are the bounds in the input token stream for this node and
+            all children?
+            </summary>
+            <remarks>
+            Each rule that creates AST nodes will call this
+            method right before returning.  Flat trees (i.e., lists) will
+            still usually have a nil root node just to hold the children list.
+            That node would contain the start/stop indexes then.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.GetTokenStartIndex(System.Object)">
+            <summary>
+            Get the token start index for this subtree; return -1 if no such index
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.GetTokenStopIndex(System.Object)">
+            <summary>
+            Get the token stop index for this subtree; return -1 if no such index
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.GetChild(System.Object,System.Int32)">
+            <summary>Get a child 0..n-1 node </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.SetChild(System.Object,System.Int32,System.Object)">
+            <summary>Set ith child (0..n-1) to t; t must be non-null and non-nil node</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.DeleteChild(System.Object,System.Int32)">
+            <summary>Remove ith child and shift children down from right.</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.GetChildCount(System.Object)">
+            <summary>How many children?  If 0, then this is a leaf node </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.GetParent(System.Object)">
+            <summary>
+            Who is the parent node of this node; if null, implies node is root.
+            </summary>
+            <remarks>
+            If your node type doesn't handle this, it's ok but the tree rewrites
+            in tree parsers need this functionality.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.GetChildIndex(System.Object)">
+            <summary>
+            What index is this node in the child list? Range: 0..n-1
+            </summary>
+            <remarks>
+            If your node type doesn't handle this, it's ok but the tree rewrites
+            in tree parsers need this functionality.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeAdaptor.ReplaceChildren(System.Object,System.Int32,System.Int32,System.Object)">
+            <summary>
+            Replace from start to stop child index of parent with t, which might
+            be a list.  Number of children may be different after this call.
+            </summary>
+            <remarks>
+            If parent is null, don't do anything; must be at root of overall tree.
+            Can't replace whatever points to the parent externally.  Do nothing.
+            </remarks>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.ITreeNodeStream">
+            <summary>A stream of tree nodes, accessing nodes from a tree of some kind </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.ITreeNodeStream.TreeSource">
+            <summary>
+            Where is this stream pulling nodes from?  This is not the name, but
+            the object that provides node objects.
+            TODO: do we really need this?
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.ITreeNodeStream.TokenStream">
+            <summary>
+            Get the ITokenStream from which this stream's Tree was created
+            (may be null)
+            </summary>
+            <remarks>
+            If the tree associated with this stream was created from a
+            TokenStream, you can specify it here.  Used to do rule $text
+            attribute in tree parser.  Optional unless you use tree parser
+            rule text attribute or output=template and rewrite=true options.
+            </remarks>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.ITreeNodeStream.TreeAdaptor">
+            <summary>
+            What adaptor can tell me how to interpret/navigate nodes and trees.
+            E.g., get text of a node.
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.ITreeNodeStream.HasUniqueNavigationNodes">
+            <summary>
+            As we flatten the tree, we use UP, DOWN nodes to represent
+            the tree structure.  When debugging we need unique nodes
+            so we have to instantiate new ones.  When doing normal tree
+            parsing, it's slow and a waste of memory to create unique
+            navigation nodes.  Default should be false;
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeNodeStream.Get(System.Int32)">
+            <summary>Get a tree node at an absolute index i; 0..n-1.</summary>
+            <remarks>
+            If you don't want to buffer up nodes, then this method makes no
+            sense for you.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeNodeStream.LT(System.Int32)">
+            <summary>
+            Get tree node at current input pointer + i ahead where i=1 is next node.
+            i&lt;0 indicates nodes in the past.  So LT(-1) is previous node, but
+            implementations are not required to provide results for k &lt; -1.
+            LT(0) is undefined.  For i&gt;=n, return null.
+            Return null for LT(0) and any index that results in an absolute address
+            that is negative.
+            This is analogus to the LT() method of the TokenStream, but this
+            returns a tree node instead of a token.  Makes code gen identical
+            for both parser and tree grammars. :)
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeNodeStream.ToString(System.Object,System.Object)">
+            <summary>Return the text of all nodes from start to stop, inclusive.
+            If the stream does not buffer all the nodes then it can still
+            walk recursively from start until stop.  You can always return
+            null or "" too, but users should not access $ruleLabel.text in
+            an action of course in that case.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeNodeStream.ReplaceChildren(System.Object,System.Int32,System.Int32,System.Object)">
+            <summary>
+            Replace from start to stop child index of parent with t, which might
+            be a list.  Number of children may be different after this call.
+            </summary>
+            <remarks>
+            The stream is notified because it is walking the tree and might need
+            to know you are monkeying with the underlying tree.  Also, it might be
+            able to modify the node stream to avoid restreaming for future phases.
+            If parent is null, don't do anything; must be at root of overall tree.
+            Can't replace whatever points to the parent externally.  Do nothing.
+            </remarks>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.ParseTree">
+            <summary>
+            A record of the rules used to Match a token sequence.  The tokens
+            end up as the leaves of this tree and rule nodes are the interior nodes.
+            This really adds no functionality, it is just an alias for CommonTree
+            that is more meaningful (specific) and holds a String to display for a node.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ParseTree.ToStringWithHiddenTokens">
+             Emit a token and all hidden nodes before.  EOF node holds all
+            		 *  hidden tokens after last real token.</member>
+        <member name="M:Antlr.Runtime.Tree.ParseTree.ToInputString">
+             Print out the leaves of this tree, which means printing original
+            		 *  input back out.</member>
+        <member name="T:Antlr.Runtime.Tree.TreeParser">
+            <summary>
+            A parser for a stream of tree nodes.  "tree grammars" result in a subclass
+            of this.  All the error reporting and recovery is shared with Parser via
+            the BaseRecognizer superclass.
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.TreeParser.TreeNodeStream">
+            <summary>Set the input stream</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeParser.Reset">
+            <summary>Reset the parser </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeParser.MatchAny(Antlr.Runtime.IIntStream)">
+            <summary>
+            Match '.' in tree parser.
+            </summary>
+            <remarks>
+            Match '.' in tree parser has special meaning.  Skip node or
+            entire tree if node has children.  If children, scan until
+            corresponding UP node.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeParser.RecoverFromMismatchedToken(Antlr.Runtime.IIntStream,System.Int32,Antlr.Runtime.BitSet)">
+            <summary>We have DOWN/UP nodes in the stream that have no line info; override.
+            plus we want to alter the exception type. Don't try to recover
+            from tree parser errors inline...
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeParser.GetErrorHeader(Antlr.Runtime.RecognitionException)">
+            <summary>
+            Prefix error message with the grammar name because message is
+            always intended for the programmer because the parser built
+            the input tree not the user.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeParser.GetErrorMessage(Antlr.Runtime.RecognitionException,System.String[])">
+            <summary>
+            Tree parsers parse nodes they usually have a token object as
+            payload. Set the exception token and do the default behavior.
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.TreeRuleReturnScope">
+            <summary>
+            This is identical to the ParserRuleReturnScope except that
+            the start property is a tree node and not a Token object
+            when you are parsing trees.  To be generic the tree node types
+            have to be Object :(
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.TreeRuleReturnScope.start">
+            <summary>First node or root node of tree matched for this rule.</summary>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.TreeRuleReturnScope.Start">
+            <summary>Return the start token or tree </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Debug.DebugEventSocketProxy">
+            <summary>
+            A proxy debug event listener that forwards events over a socket to
+            debugger (or any other listener) using a simple text-based protocol;
+            one event per line.
+            </summary>
+            <remarks>
+            ANTLRWorks listens on server socket with a
+            RemoteDebugEventSocketListener instance.  These two objects must therefore
+            be kept in sync.  New events must be handled on both sides of socket.
+            </remarks>
+        </member>
+        <member name="F:Antlr.Runtime.Debug.DebugEventSocketProxy.adaptor">
+            <summary>
+            Almost certainly the recognizer will have adaptor set, but
+            we don't know how to cast it (Parser or TreeParser) to get
+            the adaptor field.  Must be set with a constructor. :(
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.DebugParser.#ctor(Antlr.Runtime.ITokenStream,Antlr.Runtime.Debug.IDebugEventListener,Antlr.Runtime.RecognizerSharedState)">
+            <summary>
+            Create a normal parser except wrap the token stream in a debug
+            proxy that fires consume events.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Debug.DebugParser.dbg">
+            <summary>Who to notify when events in the parser occur. </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Debug.DebugParser.isCyclicDecision">
+            <summary>
+            Used to differentiate between fixed lookahead and cyclic DFA decisions
+            while profiling.
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Debug.DebugParser.DebugListener">
+            <summary>
+            Provide a new debug event listener for this parser.  Notify the
+            input stream too that it should send events to this listener.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Debug.DebugTokenStream.lastMarker">
+            <summary>
+            Track the last Mark() call result value for use in Rewind().
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.DebugTokenStream.ConsumeInitialHiddenTokens">
+            <summary>consume all initial off-channel tokens</summary>
+        </member>
+        <member name="T:Antlr.Runtime.Debug.IDebugEventListener">
+            <summary>
+            All debugging events that a recognizer can trigger.
+            </summary>
+            <remarks>
+            I did not create a separate AST debugging interface as it would create
+            lots of extra classes and DebugParser has a dbg var defined, which makes
+            it hard to change to ASTDebugEventListener.  I looked hard at this issue
+            and it is easier to understand as one monolithic event interface for all
+            possible events.  Hopefully, adding ST debugging stuff won't be bad.  Leave
+            for future. 4/26/2006.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.EnterRule(System.String,System.String)">
+            <summary>
+            The parser has just entered a rule.  No decision has been made about
+            which alt is predicted.  This is fired AFTER init actions have been
+            executed.  Attributes are defined and available etc...
+            The grammarFileName allows composite grammars to jump around among
+            multiple grammar files.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.EnterAlt(System.Int32)">
+            <summary>
+            Because rules can have lots of alternatives, it is very useful to
+            know which alt you are entering.  This is 1..n for n alts.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.ExitRule(System.String,System.String)">
+            <summary>
+            This is the last thing executed before leaving a rule.  It is
+            executed even if an exception is thrown.  This is triggered after
+            error reporting and recovery have occurred (unless the exception is
+            not caught in this rule).  This implies an "exitAlt" event.
+            The grammarFileName allows composite grammars to jump around among
+            multiple grammar files.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.EnterSubRule(System.Int32)">
+            <summary>Track entry into any (...) subrule other EBNF construct </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.EnterDecision(System.Int32)">
+            <summary>
+            Every decision, fixed k or arbitrary, has an enter/exit event
+            so that a GUI can easily track what LT/Consume events are
+            associated with prediction.  You will see a single enter/exit
+            subrule but multiple enter/exit decision events, one for each
+            loop iteration.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.ConsumeToken(Antlr.Runtime.IToken)">
+            <summary>
+            An input token was consumed; matched by any kind of element.
+            Trigger after the token was matched by things like Match(), MatchAny().
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.ConsumeHiddenToken(Antlr.Runtime.IToken)">
+            <summary>
+            An off-channel input token was consumed.
+            Trigger after the token was matched by things like Match(), MatchAny().
+            (unless of course the hidden token is first stuff in the input stream).
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.LT(System.Int32,Antlr.Runtime.IToken)">
+            <summary>
+            Somebody (anybody) looked ahead.  Note that this actually gets
+            triggered by both LA and LT calls.  The debugger will want to know
+            which Token object was examined.  Like ConsumeToken, this indicates
+            what token was seen at that depth.  A remote debugger cannot look
+            ahead into a file it doesn't have so LT events must pass the token
+            even if the info is redundant.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.Mark(System.Int32)">
+            <summary>
+            The parser is going to look arbitrarily ahead; mark this location,
+            the token stream's marker is sent in case you need it.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.Rewind(System.Int32)">
+            <summary>
+            After an arbitrairly long lookahead as with a cyclic DFA (or with
+            any backtrack), this informs the debugger that stream should be
+            rewound to the position associated with marker.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.Rewind">
+            <summary>
+            Rewind to the input position of the last marker.
+            Used currently only after a cyclic DFA and just
+            before starting a sem/syn predicate to get the
+            input position back to the start of the decision.
+            Do not "pop" the marker off the state.  Mark(i)
+            and Rewind(i) should balance still.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.Location(System.Int32,System.Int32)">
+            <summary>
+            To watch a parser move through the grammar, the parser needs to
+            inform the debugger what line/charPos it is passing in the grammar.
+            For now, this does not know how to switch from one grammar to the
+            other and back for island grammars etc...
+            This should also allow breakpoints because the debugger can stop
+            the parser whenever it hits this line/pos.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.RecognitionException(Antlr.Runtime.RecognitionException)">
+            <summary>
+            A recognition exception occurred such as NoViableAltException.  I made
+            this a generic event so that I can alter the exception hierachy later
+            without having to alter all the debug objects.
+            Upon error, the stack of enter rule/subrule must be properly unwound.
+            If no viable alt occurs it is within an enter/exit decision, which
+            also must be rewound.  Even the rewind for each mark must be unwount.
+            In the C# target this is pretty easy using try/finally, if a bit
+            ugly in the generated code.  The rewind is generated in DFA.Predict()
+            actually so no code needs to be generated for that.  For languages
+            w/o this "finally" feature (C++?), the target implementor will have
+            to build an event stack or something.
+            Across a socket for remote debugging, only the RecognitionException
+            data fields are transmitted.  The token object or whatever that
+            caused the problem was the last object referenced by LT.  The
+            immediately preceding LT event should hold the unexpected Token or
+            char.
+            Here is a sample event trace for grammar:
+            b : C ({;}A|B) // {;} is there to prevent A|B becoming a set
+            | D
+            ;
+            The sequence for this rule (with no viable alt in the subrule) for
+            input 'c c' (there are 3 tokens) is:
+            Commence
+            LT(1)
+            EnterRule b
+            Location 7 1
+            enter decision 3
+            LT(1)
+            exit decision 3
+            enterAlt1
+            Location 7 5
+            LT(1)
+            ConsumeToken <![CDATA[[c/<4>,1:0]]]>
+            Location 7 7
+            EnterSubRule 2
+            enter decision 2
+            LT(1)
+            LT(1)
+            RecognitionException NoViableAltException 2 1 2
+            exit decision 2
+            ExitSubRule 2
+            BeginResync
+            LT(1)
+            ConsumeToken <![CDATA[[c/<4>,1:1]]]>
+            LT(1)
+            EndResync
+            LT(-1)
+            ExitRule b
+            Terminate
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.BeginResync">
+            <summary>
+            Indicates the recognizer is about to consume tokens to resynchronize
+            the parser.  Any Consume events from here until the recovered event
+            are not part of the parse--they are dead tokens.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.EndResync">
+            <summary>
+            Indicates that the recognizer has finished consuming tokens in order
+            to resychronize.  There may be multiple BeginResync/EndResync pairs
+            before the recognizer comes out of errorRecovery mode (in which
+            multiple errors are suppressed).  This will be useful
+            in a gui where you want to probably grey out tokens that are consumed
+            but not matched to anything in grammar.  Anything between
+            a BeginResync/EndResync pair was tossed out by the parser.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.SemanticPredicate(System.Boolean,System.String)">
+            <summary>
+            A semantic predicate was evaluate with this result and action text
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.Commence">
+            <summary>
+            Announce that parsing has begun.  Not technically useful except for
+            sending events over a socket.  A GUI for example will launch a thread
+            to connect and communicate with a remote parser.  The thread will want
+            to notify the GUI when a connection is made.  ANTLR parsers
+            trigger this upon entry to the first rule (the ruleLevel is used to
+            figure this out).
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.Terminate">
+            <summary>
+            Parsing is over; successfully or not.  Mostly useful for telling
+            remote debugging listeners that it's time to quit.  When the rule
+            invocation level goes to zero at the end of a rule, we are done
+            parsing.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.ConsumeNode(System.Object)">
+            <summary>
+            Input for a tree parser is an AST, but we know nothing for sure
+            about a node except its type and text (obtained from the adaptor).
+            This is the analog of the ConsumeToken method.  Again, the ID is
+            the hashCode usually of the node so it only works if hashCode is
+            not implemented.  If the type is UP or DOWN, then
+            the ID is not really meaningful as it's fixed--there is
+            just one UP node and one DOWN navigation node.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.LT(System.Int32,System.Object)">
+            <summary>
+            The tree parser lookedahead.  If the type is UP or DOWN,
+            then the ID is not really meaningful as it's fixed--there is
+            just one UP node and one DOWN navigation node.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.GetNilNode(System.Object)">
+            <summary>
+            Announce the creation of a nil node
+            </summary>
+            <remarks>
+            A nil was created (even nil nodes have a unique ID...
+            they are not "null" per se).  As of 4/28/2006, this
+            seems to be uniquely triggered when starting a new subtree
+            such as when entering a subrule in automatic mode and when
+            building a tree in rewrite mode.
+            If you are receiving this event over a socket via
+            RemoteDebugEventSocketListener then only t.ID is set.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.ErrorNode(System.Object)">
+            <summary>
+            Upon syntax error, recognizers bracket the error with an error node
+            if they are building ASTs.
+            </summary>
+            <param name="t">The object</param>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.CreateNode(System.Object)">
+            <summary>
+            Announce a new node built from token elements such as type etc...
+            </summary>
+            <remarks>
+            If you are receiving this event over a socket via
+            RemoteDebugEventSocketListener then only t.ID, type,
+            text are set.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.CreateNode(System.Object,Antlr.Runtime.IToken)">
+            <summary>
+            Announce a new node built from an existing token.
+            </summary>
+            <remarks>
+            If you are receiving this event over a socket via
+            RemoteDebugEventSocketListener then only node.ID
+            and token.tokenIndex are set.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.BecomeRoot(System.Object,System.Object)">
+            <summary>
+            Make a node the new root of an existing root.
+            </summary>
+            <remarks>
+            Note: the newRootID parameter is possibly different
+            than the TreeAdaptor.BecomeRoot() newRoot parameter.
+            In our case, it will always be the result of calling
+            TreeAdaptor.BecomeRoot() and not root_n or whatever.
+            The listener should assume that this event occurs
+            only when the current subrule (or rule) subtree is
+            being reset to newRootID.
+            <see cref="M:Antlr.Runtime.Tree.ITreeAdaptor.BecomeRoot(System.Object,System.Object)" />
+            If you are receiving this event over a socket via
+            RemoteDebugEventSocketListener then only IDs are set.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.AddChild(System.Object,System.Object)">
+            <summary>
+            Make childID a child of rootID.
+            </summary>
+            <remarks>
+            If you are receiving this event over a socket via
+            RemoteDebugEventSocketListener then only IDs are set.
+            </remarks>
+            <see cref="M:Antlr.Runtime.Tree.ITreeAdaptor.AddChild(System.Object,System.Object)" />
+        </member>
+        <member name="M:Antlr.Runtime.Debug.IDebugEventListener.SetTokenBoundaries(System.Object,System.Int32,System.Int32)">
+            <summary>
+            Set the token start/stop token index for a subtree root or node
+            </summary>
+            <remarks>
+            If you are receiving this event over a socket via
+            RemoteDebugEventSocketListener then only IDs are set.
+            </remarks>
+        </member>
+        <member name="T:Antlr.Runtime.Debug.DebugTreeAdaptor">
+            <summary>
+            A TreeAdaptor proxy that fires debugging events to a DebugEventListener
+            delegate and uses the TreeAdaptor delegate to do the actual work.  All
+            AST events are triggered by this adaptor; no code gen changes are needed
+            in generated rules.  Debugging events are triggered *after* invoking
+            tree adaptor routines.
+            Trees created with actions in rewrite actions like "-&gt; ^(ADD {foo} {bar})"
+            cannot be tracked as they might not use the adaptor to create foo, bar.
+            The debug listener has to deal with tree node IDs for which it did
+            not see a CreateNode event.  A single &lt;unknown&gt; node is sufficient even
+            if it represents a whole tree.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.DebugTreeAdaptor.SimulateTreeConstruction(System.Object)">
+             ^(A B C): emit create A, create B, add child, ...</member>
+        <member name="T:Antlr.Runtime.Constants">
+            <summary>
+            Global constants
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Messages">
+            <summary>
+            A strongly-typed resource class, for looking up localized strings, etc.
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Messages.ResourceManager">
+            <summary>
+            Returns the cached ResourceManager instance used by this class.
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Messages.Culture">
+            <summary>
+            Overrides the current thread's CurrentUICulture property for all
+            resource lookups using this strongly typed resource class.
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Debug.DebugTreeNodeStream">
+            <summary>
+            Debug any tree node stream.  The constructor accepts the stream
+            and a debug listener.  As node stream calls come in, debug events
+            are triggered.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Debug.DebugTreeNodeStream.lastMarker">
+            <summary>Track the last mark() call result value for use in rewind().</summary>
+        </member>
+        <member name="P:Antlr.Runtime.Debug.DebugTreeNodeStream.HasUniqueNavigationNodes">
+            <summary>
+            It is normally this object that instructs the node stream to
+            create unique nav nodes, but to satisfy interface, we have to
+            define it.  It might be better to ignore the parameter but
+            there might be a use for it later, so I'll leave.
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Debug.BlankDebugEventListener">
+            <summary>
+            A blank listener that does nothing; useful for real classes so
+            they don't have to have lots of blank methods and are less
+            sensitive to updates to debug interface.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Debug.RemoteDebugEventSocketListener.version">
+            <summary>Version of ANTLR (dictates events)</summary>
+        </member>
+        <member name="F:Antlr.Runtime.Debug.RemoteDebugEventSocketListener.previousTokenIndex">
+            <summary>
+            Track the last token index we saw during a consume.  If same, then
+            set a flag that we have a problem.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.RemoteDebugEventSocketListener.start">
+            <summary>Create a thread to listen to the remote running recognizer </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Debug.TraceDebugEventListener">
+            <summary>
+            Print out (most of) the events... Useful for debugging, testing...
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Debug.DebugEventHub">
+            <summary>
+            Broadcast debug events to multiple listeners.
+            </summary>
+            <remarks>
+            Lets you debug and still use the event mechanism to build
+            parse trees etc...
+            Not thread-safe. Don't add events in one thread while parser
+            fires events in another.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.DebugEventHub.AddListener(Antlr.Runtime.Debug.IDebugEventListener)">
+            <summary>
+            Add another listener to broadcast events too.
+            </summary>
+            <remarks>
+            Not thread-safe. Don't add events in one thread while parser
+            fires events in another.
+            </remarks>
+        </member>
+        <member name="T:Antlr.Runtime.Debug.DebugEventRepeater">
+            <summary>
+            A simple event repeater (proxy) that delegates all functionality to
+            the listener sent into the ctor.
+            </summary>
+            <remarks>
+            Useful if you want to listen in on a few debug events w/o
+            interrupting the debugger.  Just subclass the repeater and override
+            the methods you want to listen in on.  Remember to call the method
+            in this class so the event will continue on to the original recipient.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.DebugTreeParser.#ctor(Antlr.Runtime.Tree.ITreeNodeStream,Antlr.Runtime.Debug.IDebugEventListener,Antlr.Runtime.RecognizerSharedState)">
+            <summary>
+            Create a normal parser except wrap the token stream in a debug
+            proxy that fires consume events.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Debug.DebugTreeParser.dbg">
+            <summary>Who to notify when events in the parser occur.</summary>
+        </member>
+        <member name="F:Antlr.Runtime.Debug.DebugTreeParser.isCyclicDecision">
+            <summary>
+            Used to differentiate between fixed lookahead and cyclic DFA decisions
+            while profiling.
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Debug.DebugTreeParser.DebugListener">
+            <summary>
+            Provide a new debug event listener for this parser.  Notify the
+            input stream too that it should send events to this listener.
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Debug.ParseTreeBuilder">
+            <summary>
+            This parser listener tracks rule entry/exit and token matches
+            to build a simple parse tree using ParseTree nodes.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.ParseTreeBuilder.Create(System.Object)">
+            <summary>
+            What kind of node to create.  You might want to override
+            so I factored out creation here.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.ParseTreeBuilder.EnterDecision(System.Int32)">
+             Backtracking or cyclic DFA, don't want to add nodes to tree</member>
+        <member name="T:Antlr.Runtime.Debug.Profiler">
+            <summary>
+            Using the debug event interface, track what is happening in the parser
+            and record statistics about the runtime.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Debug.Profiler.Version">
+            <summary>
+            Because I may change the stats, I need to track that for later
+            computations to be consistent.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.Profiler.ExamineRuleMemoization(Antlr.Runtime.IIntStream,System.Int32,System.String)">
+            <summary>Track memoization</summary>
+            <remarks>
+            This is not part of standard debug interface but is triggered by
+            profiling.  Code gen inserts an override for this method in the
+            recognizer, which triggers this method.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.Profiler.InDecision">
+            <summary>
+            The parser is in a decision if the decision depth &gt; 0.  This works
+            for backtracking also, which can have nested decisions.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.Profiler.LT(System.Int32,Antlr.Runtime.IToken)">
+            <summary>
+            Track refs to lookahead if in a fixed/nonfixed decision.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.Profiler.BeginBacktrack(System.Int32)">
+            <summary>
+            Track backtracking decisions.  You'll see a fixed or cyclic decision
+            and then a backtrack.
+            </summary>
+            <remarks>
+            	enter rule
+            	...
+            	enter decision
+            	LA and possibly consumes (for cyclic DFAs)
+            	begin backtrack level
+            	mark m
+            	rewind m
+            	end backtrack level, success
+            	exit decision
+            	...
+            	exit rule
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.Profiler.EndBacktrack(System.Int32,System.Boolean)">
+            <summary>Successful or not, track how much lookahead synpreds use</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Debug.Profiler.GetNumberOfHiddenTokens(System.Int32,System.Int32)">
+            <summary>Get num hidden tokens between i..j inclusive</summary>
+        </member>
+        <member name="T:Antlr.Runtime.Debug.Tracer">
+            <summary>
+            The default tracer mimics the traceParser behavior of ANTLR 2.x.
+            This listens for debugging events from the parser and implies
+            that you cannot debug and trace at the same time.
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Misc.Stats">
+            <summary>Stats routines needed by profiler etc...</summary>
+            <remarks>
+            Note that these routines return 0.0 if no values exist in X[]
+            which is not "correct" but, it is useful so I don't generate NaN
+            in my output
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Misc.Stats.Stddev(System.Int32[])">
+            <summary>Compute the sample (unbiased estimator) standard deviation</summary>
+            <remarks>
+            The computation follows:
+            Computing Deviations: Standard Accuracy
+            Tony F. Chan and John Gregg Lewis
+            Stanford University
+            Communications of ACM September 1979 of Volume 22 the ACM Number 9
+            The "two-pass" method from the paper; supposed to have better
+            numerical properties than the textbook summation/sqrt.  To me
+            this looks like the textbook method, but I ain't no numerical
+            methods guy.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Misc.Stats.Avg(System.Int32[])">
+            <summary>Compute the sample mean</summary>
+        </member>
+        <member name="T:Antlr.Runtime.Misc.ErrorManager">
+            <summary>A minimal ANTLR3 error [message] manager with the ST bits</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Misc.ErrorManager.GetLastNonErrorManagerCodeLocation(System.Exception)">
+            <summary>
+            Return first non ErrorManager code location for generating messages
+            </summary>
+            <param name="e">Current exception</param>
+            <returns>
+            </returns>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.TreeWizard">
+            <summary>
+            Build and navigate trees with this object.  Must know about the names
+            of tokens so you have to pass in a map or array of token names (from which
+            this class can build the map).  I.e., Token DECL means nothing unless the
+            class can translate it to a token type.
+            </summary>
+            <remarks>
+            In order to create nodes and navigate, this class needs a TreeAdaptor.
+            This class can build a token type -&gt; node index for repeated use or for
+            iterating over the various nodes with a particular type.
+            This class works in conjunction with the TreeAdaptor rather than moving
+            all this functionality into the adaptor.  An adaptor helps build and
+            navigate trees using methods.  This class helps you do it with string
+            patterns like "(A B C)".  You can create a tree from that pattern or
+            match subtrees against it.
+            </remarks>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.TreeWizard.TreePattern">
+            <summary>
+            When using %label:TOKENNAME in a tree for parse(), we must track the label.
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.TreeWizard.TreePatternTreeAdaptor">
+            <summary>
+            This adaptor creates TreePattern objects for use during scan()
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeWizard.ComputeTokenTypes(System.String[])">
+            <summary>
+            Compute a Map&lt;String, Integer&gt; that is an inverted index of
+            tokenNames (which maps int token types to names).
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeWizard.GetTokenType(System.String)">
+            <summary>
+            Using the map of token names to token types, return the type.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeWizard.Index(System.Object)">
+            <summary>
+            Walk the entire tree and make a node name to nodes mapping.
+            </summary>
+            <remarks>
+            For now, use recursion but later nonrecursive version may be
+            more efficient.  Returns Map&lt;Integer, List&gt; where the List is
+            of your AST node type.  The Integer is the token type of the node.
+            TODO: save this index so that find and visit are faster
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeWizard._Index(System.Object,System.Collections.IDictionary)">
+            <summary>Do the work for index</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeWizard.Find(System.Object,System.Int32)">
+            <summary>Return a List of tree nodes with token type ttype</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeWizard.Find(System.Object,System.String)">
+            <summary>Return a List of subtrees matching pattern</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeWizard.Visit(System.Object,System.Int32,Antlr.Runtime.Tree.TreeWizard.ContextVisitor)">
+            <summary>
+            Visit every ttype node in t, invoking the visitor.
+            </summary>
+            <remarks>
+            This is a quicker
+            version of the general visit(t, pattern) method.  The labels arg
+            of the visitor action method is never set (it's null) since using
+            a token type rather than a pattern doesn't let us set a label.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeWizard._Visit(System.Object,System.Object,System.Int32,System.Int32,Antlr.Runtime.Tree.TreeWizard.ContextVisitor)">
+            <summary>Do the recursive work for visit</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeWizard.Visit(System.Object,System.String,Antlr.Runtime.Tree.TreeWizard.ContextVisitor)">
+            <summary>
+            For all subtrees that match the pattern, execute the visit action.
+            </summary>
+            <remarks>
+            The implementation uses the root node of the pattern in combination
+            with visit(t, ttype, visitor) so nil-rooted patterns are not allowed.
+            Patterns with wildcard roots are also not allowed.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeWizard.Parse(System.Object,System.String,System.Collections.IDictionary)">
+            <summary>
+            Given a pattern like (ASSIGN %lhs:ID %rhs:.) with optional labels
+            on the various nodes and '.' (dot) as the node/subtree wildcard,
+            return true if the pattern matches and fill the labels Map with
+            the labels pointing at the appropriate nodes.  Return false if
+            the pattern is malformed or the tree does not match.
+            </summary>
+            <remarks>
+            If a node specifies a text arg in pattern, then that must match
+            for that node in t.
+            TODO: what's a better way to indicate bad pattern? Exceptions are a hassle
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeWizard._Parse(System.Object,Antlr.Runtime.Tree.TreeWizard.TreePattern,System.Collections.IDictionary)">
+            <summary>
+            Do the work for Parse(). Check to see if the t2 pattern fits the
+            structure and token types in t1.  Check text if the pattern has
+            text arguments on nodes.  Fill labels map with pointers to nodes
+            in tree matched against nodes in pattern with labels.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeWizard.Create(System.String)">
+            <summary>
+            Create a tree or node from the indicated tree pattern that closely
+            follows ANTLR tree grammar tree element syntax:
+            		(root child1 ... child2).
+            </summary>
+            <remarks>
+            You can also just pass in a node: ID
+            Any node can have a text argument: ID[foo]
+            (notice there are no quotes around foo--it's clear it's a string).
+            nil is a special name meaning "give me a nil node".  Useful for
+            making lists: (nil A B C) is a list of A B C.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeWizard.Equals(System.Object,System.Object,Antlr.Runtime.Tree.ITreeAdaptor)">
+            <summary>
+            Compare t1 and t2; return true if token types/text, structure match exactly.
+            The trees are examined in their entirety so that (A B) does not match
+            (A B C) nor (A (B C)).
+            </summary>
+            <remarks>
+            TODO: allow them to pass in a comparator
+            TODO: have a version that is nonstatic so it can use instance adaptor
+            I cannot rely on the tree node's equals() implementation as I make
+            no constraints at all on the node types nor interface etc...
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeWizard.Equals(System.Object,System.Object)">
+            <summary>
+            Compare type, structure, and text of two trees, assuming adaptor in
+            this instance of a TreeWizard.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.TreePatternLexer.pattern">
+            <summary>The tree pattern to lex like "(A B C)"</summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.TreePatternLexer.p">
+            <summary>Index into input string</summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.TreePatternLexer.c">
+            <summary>Current char</summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.TreePatternLexer.n">
+            <summary>How long is the pattern in char?</summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.TreePatternLexer.sval">
+            <summary>
+            Set when token type is ID or ARG (name mimics Java's StreamTokenizer)
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.RewriteRuleNodeStream">
+            <summary>
+            Queues up nodes matched on left side of -&gt; in a tree parser. This is
+            the analog of RewriteRuleTokenStream for normal parsers.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleNodeStream.#ctor(Antlr.Runtime.Tree.ITreeAdaptor,System.String,System.Object)">
+            <summary>Create a stream with one element</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleNodeStream.#ctor(Antlr.Runtime.Tree.ITreeAdaptor,System.String,System.Collections.Generic.IList{System.Object})">
+            <summary>Create a stream, but feed off an existing list</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleNodeStream.#ctor(Antlr.Runtime.Tree.ITreeAdaptor,System.String,System.Collections.IList)">
+            <summary>Create a stream, but feed off an existing list</summary>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.RewriteCardinalityException">
+            <summary>Base class for all exceptions thrown during AST rewrite construction.</summary>
+            <remarks>
+            This signifies a case where the cardinality of two or more elements
+            in a subrule are different: (ID INT)+ where |ID|!=|INT|
+            </remarks>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.RewriteCardinalityException.Message">
+            <summary>
+            Returns the line at which the error occurred (for lexers)
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.RewriteEarlyExitException">
+            <summary>
+            No elements within a (...)+ in a rewrite rule
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.RewriteEmptyStreamException">
+            <summary>
+            Ref to ID or expr but no tokens in ID stream or subtrees in expr stream
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.RewriteRuleElementStream`1">
+            <summary>
+            A generic list of elements tracked in an alternative to be used in
+            a -&gt; rewrite rule.  We need to subclass to fill in the next() method,
+            which returns either an AST node wrapped around a token payload or
+            an existing subtree.
+            Once you start next()ing, do not try to add more elements.  It will
+            break the cursor tracking I believe.
+            <see cref="T:Antlr.Runtime.Tree.RewriteRuleSubtreeStream" /><see cref="T:Antlr.Runtime.Tree.RewriteRuleTokenStream" />
+            TODO: add mechanism to detect/puke on modification after reading from stream
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleElementStream`1.#ctor(Antlr.Runtime.Tree.ITreeAdaptor,System.String,`0)">
+            <summary>
+            Create a stream with one element
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleElementStream`1.#ctor(Antlr.Runtime.Tree.ITreeAdaptor,System.String,System.Collections.Generic.IList{`0})">
+            <summary>
+            Create a stream, but feed off an existing list
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleElementStream`1.#ctor(Antlr.Runtime.Tree.ITreeAdaptor,System.String,System.Collections.IList)">
+            <summary>
+            Create a stream, but feed off an existing list
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.RewriteRuleElementStream`1.cursor">
+            <summary>
+            Cursor 0..n-1.  If singleElement!=null, cursor is 0 until you next(),
+            which bumps it to 1 meaning no more elements.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.RewriteRuleElementStream`1.singleElement">
+            <summary>
+            Track single elements w/o creating a list.  Upon 2nd add, alloc list
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.RewriteRuleElementStream`1.elements">
+            <summary>
+            The list of tokens or subtrees we are tracking
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.RewriteRuleElementStream`1.dirty">
+            <summary>
+            Tracks whether a node or subtree has been used in a stream
+            </summary>
+            <remarks>
+            Once a node or subtree has been used in a stream, it must be dup'd
+            from then on.  Streams are reset after subrules so that the streams
+            can be reused in future subrules.  So, reset must set a dirty bit.
+            If dirty, then next() always returns a dup.
+            </remarks>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.RewriteRuleElementStream`1.elementDescription">
+            <summary>
+            The element or stream description; usually has name of the token or
+            rule reference that this list tracks.  Can include rulename too, but
+            the exception would track that info.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleElementStream`1.Reset">
+            <summary>
+            Reset the condition of this stream so that it appears we have
+            not consumed any of its elements.  Elements themselves are untouched.
+            </summary>
+            <remarks>
+            Once we reset the stream, any future use will need duplicates.  Set
+            the dirty bit.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleElementStream`1.NextTree">
+            <summary>
+            Return the next element in the stream.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleElementStream`1._Next">
+            <summary>
+            Do the work of getting the next element, making sure that
+            it's a tree node or subtree.
+            </summary>
+            <remarks>
+            Deal with the optimization of single-element list versus
+            list of size &gt; 1.  Throw an exception if the stream is
+            empty or we're out of elements and size&gt;1.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleElementStream`1.ToTree(`0)">
+            <summary>
+            Ensure stream emits trees; tokens must be converted to AST nodes.
+            AST nodes can be passed through unmolested.
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.RewriteRuleSubtreeStream">
+            <summary>
+            </summary>
+            <remarks>
+            </remarks>
+            <example>
+            </example>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleSubtreeStream.#ctor(Antlr.Runtime.Tree.ITreeAdaptor,System.String,System.Object)">
+            <summary>
+            Create a stream with one element
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleSubtreeStream.#ctor(Antlr.Runtime.Tree.ITreeAdaptor,System.String,System.Collections.Generic.IList{System.Object})">
+            <summary>Create a stream, but feed off an existing list</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleSubtreeStream.#ctor(Antlr.Runtime.Tree.ITreeAdaptor,System.String,System.Collections.IList)">
+            <summary>Create a stream, but feed off an existing list</summary>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.RewriteRuleSubtreeStream.ProcessHandler">
+            <summary>
+            This delegate is used to allow the outfactoring of some common code.
+            </summary>
+            <param name="o">The to be processed object</param>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleSubtreeStream.NextNode">
+            <summary>
+            Treat next element as a single node even if it's a subtree.
+            </summary>
+            <remarks>
+            This is used instead of next() when the result has to be a
+            tree root node.  Also prevents us from duplicating recently-added
+            children; e.g., ^(type ID)+ adds ID to type and then 2nd iteration
+            must dup the type node, but ID has been added.
+            Referencing a rule result twice is ok; dup entire tree as
+            we can't be adding trees as root; e.g., expr expr.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleSubtreeStream.FetchObject(Antlr.Runtime.Tree.RewriteRuleSubtreeStream.ProcessHandler)">
+            <summary>
+            This method has the common code of two other methods, which differed in only one
+            function call.
+            </summary>
+            <param name="ph">The delegate, which has the chosen function</param>
+            <returns>The required object</returns>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleSubtreeStream.RequiresDuplication">
+            <summary>
+            Tests, if the to be returned object requires duplication
+            </summary>
+            <returns>
+                <code>true</code>, if positive, <code>false</code>, if negative.</returns>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleSubtreeStream.NextTree">
+            <summary>
+            Return the next element in the stream.
+            </summary>
+            <remarks>
+            If out of elements, throw an exception unless Count==1.
+            If Count is 1, then return elements[0].
+            Return a duplicate node/subtree if stream is out of
+            elements and Count==1.
+            If we've already used the element, dup (dirty bit set).
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleSubtreeStream.Dup(System.Object)">
+            <summary>
+            When constructing trees, sometimes we need to dup a token or AST
+            subtree. Dup'ing a token means just creating another AST node
+            around it. For trees, you must call the adaptor.dupTree()
+            unless the element is for a tree root; then it must be a node dup
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.RewriteRuleTokenStream">
+            <summary>
+            </summary>
+            <remarks>
+            </remarks>
+            <example>
+            </example>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleTokenStream.#ctor(Antlr.Runtime.Tree.ITreeAdaptor,System.String,Antlr.Runtime.IToken)">
+            <summary>
+            Create a stream with one element
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleTokenStream.#ctor(Antlr.Runtime.Tree.ITreeAdaptor,System.String,System.Collections.Generic.IList{Antlr.Runtime.IToken})">
+            <summary>Create a stream, but feed off an existing list</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleTokenStream.#ctor(Antlr.Runtime.Tree.ITreeAdaptor,System.String,System.Collections.IList)">
+            <summary>Create a stream, but feed off an existing list</summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleTokenStream.NextNode">
+            <summary>
+            Get next token from stream and make a node for it.
+            </summary>
+            <remarks>
+            ITreeAdaptor.Create() returns an object, so no further restrictions possible.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.RewriteRuleTokenStream.ToTree(Antlr.Runtime.IToken)">
+            <summary>
+            Don't convert to a tree unless they explicitly call NextTree().
+            This way we can do hetero tree nodes in rewrite.
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.UnBufferedTreeNodeStream">
+            <summary>
+            A stream of tree nodes, accessing nodes from a tree of ANY kind.
+            </summary>
+            <remarks>
+            No new nodes should be created in tree during the walk.  A small buffer
+            of tokens is kept to efficiently and easily handle LT(i) calls, though
+            the lookahead mechanism is fairly complicated.
+            For tree rewriting during tree parsing, this must also be able
+            to replace a set of children without "losing its place".
+            That part is not yet implemented.  Will permit a rule to return
+            a different tree and have it stitched into the output tree probably.
+            <see cref="T:Antlr.Runtime.Tree.CommonTreeNodeStream" /></remarks>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.TreeWalkState">
+            <summary>
+            When walking ahead with cyclic DFA or for syntactic predicates,
+            we need to record the state of the tree node stream.  This
+            class wraps up the current state of the UnBufferedTreeNodeStream.
+            Calling Mark() will push another of these on the markers stack.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.TreeWalkState.nodeStackSize">
+            <summary>Record state of the nodeStack</summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.TreeWalkState.indexStackSize">
+            <summary>Record state of the indexStack</summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.uniqueNavigationNodes">
+            <summary>Reuse same DOWN, UP navigation nodes unless this is true</summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.root">
+            <summary>Pull nodes from which tree? </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.tokens">
+            <summary>IF this tree (root) was created from a token stream, track it.</summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.adaptor">
+            <summary>What tree adaptor was used to build these trees</summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.nodeStack">
+            <summary>
+            As we walk down the nodes, we must track parent nodes so we know
+            where to go after walking the last child of a node.  When visiting
+            a child, push current node and current index.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.indexStack">
+            <summary>
+            Track which child index you are visiting for each node we push.
+            TODO: pretty inefficient...use int[] when you have time
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.currentNode">
+            <summary>Which node are we currently visiting? </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.previousNode">
+            <summary>Which node did we visit last?  Used for LT(-1) calls. </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.currentChildIndex">
+            <summary>
+            Which child are we currently visiting?  If -1 we have not visited
+            this node yet; next Consume() request will set currentIndex to 0.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.absoluteNodeIndex">
+            <summary>
+            What node index did we just consume?  i=0..n-1 for n node trees.
+            IntStream.next is hence 1 + this value.  Size will be same.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.lookahead">
+            <summary>
+            Buffer tree node stream for use with LT(i).  This list grows
+            to fit new lookahead depths, but Consume() wraps like a circular
+            buffer.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.head">
+            <summary>lookahead[head] is the first symbol of lookahead, LT(1). </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.tail">
+            <summary>
+            Add new lookahead at lookahead[tail].  tail wraps around at the
+            end of the lookahead buffer so tail could be less than head.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.markers">
+            <summary>
+            Calls to Mark() may be nested so we have to track a stack of them.
+            The marker is an index into this stack. This is a List&lt;TreeWalkState&gt;.
+            Indexed from 1..markDepth. A null is kept at index 0. It is created
+            upon first call to Mark().
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.markDepth">
+            <summary>
+            tracks how deep Mark() calls are nested
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.lastMarker">
+            <summary>
+            Track the last Mark() call result value for use in Rewind().
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.TreeSource">
+            <summary>
+            Where is this stream pulling nodes from?  This is not the name, but
+            the object that provides node objects.
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.Count">
+            <summary>
+            Expensive to compute; recursively walk tree to find size;
+            include navigation nodes and EOF.  Reuse functionality
+            in CommonTreeNodeStream as we only really use this
+            for testing.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.MoveNext">
+            <summary>
+            Navigates to the next node found during a depth-first walk of root.
+            Also, adds these nodes and DOWN/UP imaginary nodes into the lokoahead
+            buffer as a side-effect.  Normally side-effects are bad, but because
+            we can Emit many tokens for every MoveNext() call, it's pretty hard to
+            use a single return value for that.  We must add these tokens to
+            the lookahead buffer.
+            This routine does *not* cause the 'Current' property to ever return the
+            DOWN/UP nodes; those are only returned by the LT() method.
+            Ugh.  This mechanism is much more complicated than a recursive
+            solution, but it's the only way to provide nodes on-demand instead
+            of walking once completely through and buffering up the nodes. :(
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.LT(System.Int32)">
+            <summary>
+            Get tree node at current input pointer + i ahead where i=1 is next node.
+            i &lt; 0 indicates nodes in the past.  So -1 is previous node and -2 is
+            two nodes ago. LT(0) is undefined.  For i&gt;=n, return null.
+            Return null for LT(0) and any index that results in an absolute address
+            that is negative.
+            This is analogus to the LT() method of the TokenStream, but this
+            returns a tree node instead of a token.  Makes code gen identical
+            for both parser and tree grammars. :)
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.fill(System.Int32)">
+            <summary>Make sure we have at least k symbols in lookahead buffer </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.AddLookahead(System.Object)">
+            <summary>
+            Add a node to the lookahead buffer.  Add at lookahead[tail].
+            If you tail+1 == head, then we must create a bigger buffer
+            and copy all the nodes over plus reset head, tail.  After
+            this method, LT(1) will be lookahead[0].
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.Mark">
+            <summary>
+            Record the current state of the tree walk which includes
+            the current node and stack state as well as the lookahead
+            buffer.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.Rewind(System.Int32)">
+            <summary>
+            Rewind the current state of the tree walk to the state it
+            was in when Mark() was called and it returned marker.  Also,
+            wipe out the lookahead which will force reloading a few nodes
+            but it is better than making a copy of the lookahead buffer
+            upon Mark().
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.Seek(System.Int32)">
+            <summary>
+            Consume() ahead until we hit index.  Can't just jump ahead--must
+            spit out the navigation nodes.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.Size">
+            <summary>
+            Expensive to compute; recursively walk tree to find size;
+            include navigation nodes and EOF.  Reuse functionality
+            in CommonTreeNodeStream as we only really use this
+            for testing.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.AddNavigationNode(System.Int32)">
+            <summary>
+            As we flatten the tree, we use UP, DOWN nodes to represent
+            the tree structure.  When debugging we need unique nodes
+            so instantiate new ones when uniqueNavigationNodes is true.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.WalkBackToMostRecentNodeWithUnvisitedChildren">
+            <summary>
+            Walk upwards looking for a node with more children to walk.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.ToString">
+            <summary>
+            Print out the entire tree including DOWN/UP nodes.  Uses
+            a recursive walk.  Mostly useful for testing as it yields
+            the token types not text.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.UnBufferedTreeNodeStream.ToString(System.Object,System.Object)">
+            <summary>TODO: not sure this is what we want for trees. </summary>
+        </member>
+        <member name="T:Antlr.Runtime.ANTLRInputStream">
+            <summary>
+            A character stream - an <see cref="T:Antlr.Runtime.ICharStream" /> - that loads
+            and caches the contents of it's underlying
+            <see cref="T:System.IO.Stream" /> fully during object construction
+            </summary>
+            <remarks>
+            Useful for reading from stdin and, for specifying file encodings etc...
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRInputStream.#ctor">
+            <summary>
+            Initializes a new instance of the ANTLRInputStream class
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRInputStream.#ctor(System.IO.Stream)">
+            <summary>
+            Initializes a new instance of the ANTLRInputStream class for the
+            specified stream
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRInputStream.#ctor(System.IO.Stream,System.Text.Encoding)">
+            <summary>
+            Initializes a new instance of the ANTLRInputStream class for the
+            specified stream and encoding
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRInputStream.#ctor(System.IO.Stream,System.Int32)">
+            <summary>
+            Initializes a new instance of the ANTLRInputStream class for the
+            specified stream and initial data buffer size
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRInputStream.#ctor(System.IO.Stream,System.Int32,System.Text.Encoding)">
+            <summary>
+            Initializes a new instance of the ANTLRInputStream class for the
+            specified stream, encoding and initial data buffer size
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRInputStream.#ctor(System.IO.Stream,System.Int32,System.Int32,System.Text.Encoding)">
+            <summary>
+            Initializes a new instance of the ANTLRInputStream class for the
+            specified stream, encoding, initial data buffer size and, using
+            a read buffer of the specified size
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.ANTLRReaderStream">
+            <summary>
+            An ANTLRStringStream that caches all the input from a TextReader. It
+            behaves just like a plain ANTLRStringStream
+            </summary>
+            <remarks>
+            Manages the buffer manually to avoid unnecessary data copying.
+            If you need encoding, use ANTLRInputStream.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRReaderStream.#ctor">
+            <summary>
+            Initializes a new instance of the ANTLRReaderStream class
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRReaderStream.#ctor(System.IO.TextReader)">
+            <summary>
+            Initializes a new instance of the ANTLRReaderStream class for the
+            specified TextReader
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRReaderStream.#ctor(System.IO.TextReader,System.Int32)">
+            <summary>
+            Initializes a new instance of the ANTLRReaderStream class for the
+            specified TextReader and initial data buffer size
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRReaderStream.#ctor(System.IO.TextReader,System.Int32,System.Int32)">
+            <summary>
+            Initializes a new instance of the ANTLRReaderStream class for the
+            specified TextReader, initial data buffer size and, using
+            a read buffer of the specified size
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.ANTLRReaderStream.READ_BUFFER_SIZE">
+            <summary>Default size (in characters) of the buffer used for IO reads</summary>
+        </member>
+        <member name="F:Antlr.Runtime.ANTLRReaderStream.INITIAL_BUFFER_SIZE">
+            <summary>Initial size (in characters) of the data cache</summary>
+        </member>
+        <member name="M:Antlr.Runtime.ANTLRReaderStream.Load(System.IO.TextReader,System.Int32,System.Int32)">
+            <summary>
+            Loads and buffers the contents of the specified reader to be
+            used as this ANTLRReaderStream's source
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.BaseRecognizer">
+            <summary>
+            A generic recognizer that can handle recognizers generated from
+            lexer, parser, and tree grammars.  This is all the parsing
+            support code essentially; most of it is error recovery stuff and
+            backtracking.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.BaseRecognizer.state">
+            <summary>
+            An externalized representation of the - shareable - internal state of
+            this lexer, parser or tree parser.
+            </summary>
+            <remarks>
+            The state of a lexer, parser, or tree parser are collected into
+            external state objects so that the state can be shared. This sharing
+            is needed to have one grammar import others and share same error
+            variables and other state variables.  It's a kind of explicit multiple
+            inheritance via delegation of methods and shared state.
+            </remarks>
+        </member>
+        <member name="P:Antlr.Runtime.BaseRecognizer.NumberOfSyntaxErrors">
+            <summary>
+            Get number of recognition errors (lexer, parser, tree parser).  Each
+            recognizer tracks its own number.  So parser and lexer each have
+            separate count.  Does not count the spurious errors found between
+            an error and next valid token match
+            See also ReportError()
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.BaseRecognizer.GrammarFileName">
+            <summary>
+            For debugging and other purposes, might want the grammar name.
+            Have ANTLR generate an implementation for this property.
+            </summary>
+            <returns>
+            </returns>
+        </member>
+        <member name="P:Antlr.Runtime.BaseRecognizer.SourceName">
+            <summary>
+            For debugging and other purposes, might want the source name.
+            Have ANTLR provide a hook for this property.
+            </summary>
+            <returns>The source name</returns>
+        </member>
+        <member name="P:Antlr.Runtime.BaseRecognizer.TokenNames">
+            <summary>
+            Used to print out token names like ID during debugging and
+            error reporting.  The generated parsers implement a method
+            that overrides this to point to their string[] tokenNames.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.Failed">
+             Return whether or not a backtracking attempt failed.</member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.Reset">
+            <summary>Reset the parser's state. Subclasses must rewind the input stream.</summary>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.Match(Antlr.Runtime.IIntStream,System.Int32,Antlr.Runtime.BitSet)">
+            <summary>
+            Match current input symbol against ttype.  Attempt
+            single token insertion or deletion error recovery.  If
+            that fails, throw MismatchedTokenException.
+            </summary>
+            <remarks>
+            To turn off single token insertion or deletion error
+            recovery, override RecoverFromMismatchedToken() and have it call
+            pthrow an exception. See TreeParser.RecoverFromMismatchedToken().
+            This way any error in a rule will cause an exception and
+            immediate exit from rule.  Rule would recover by resynchronizing
+            to the set of symbols that can follow rule ref.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.MatchAny(Antlr.Runtime.IIntStream)">
+            <summary> Match the wildcard: in a symbol</summary>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.ReportError(Antlr.Runtime.RecognitionException)">
+            <summary>
+            Report a recognition problem.
+            </summary>
+            <remarks>
+            This method sets errorRecovery to indicate the parser is recovering
+            not parsing.  Once in recovery mode, no errors are generated.
+            To get out of recovery mode, the parser must successfully Match
+            a token (after a resync).  So it will go:
+            1. error occurs
+            2. enter recovery mode, report error
+            3. consume until token found in resynch set
+            4. try to resume parsing
+            5. next Match() will reset errorRecovery mode
+            If you override, make sure to update syntaxErrors if you care about that.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.GetErrorMessage(Antlr.Runtime.RecognitionException,System.String[])">
+            <summary>
+            What error message should be generated for the various exception types?
+            Not very object-oriented code, but I like having all error message generation
+            within one method rather than spread among all of the exception classes. This
+            also makes it much easier for the exception handling because the exception
+            classes do not have to have pointers back to this object to access utility
+            routines and so on. Also, changing the message for an exception type would be
+            difficult because you would have to subclassing exception, but then somehow get
+            ANTLR to make those kinds of exception objects instead of the default.
+            This looks weird, but trust me--it makes the most sense in terms of flexibility.
+            For grammar debugging, you will want to override this to add more information
+            such as the stack frame with GetRuleInvocationStack(e, this.GetType().Fullname)
+            and, for no viable alts, the decision description and state etc...
+            Override this to change the message generated for one or more exception types.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.GetErrorHeader(Antlr.Runtime.RecognitionException)">
+            <summary>
+            What is the error header, normally line/character position information?
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.GetTokenErrorDisplay(Antlr.Runtime.IToken)">
+            <summary>
+            How should a token be displayed in an error message? The default
+            is to display just the text, but during development you might
+            want to have a lot of information spit out.  Override in that case
+            to use t.ToString() (which, for CommonToken, dumps everything about
+            the token). This is better than forcing you to override a method in
+            your token objects because you don't have to go modify your lexer
+            so that it creates a new type.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.EmitErrorMessage(System.String)">
+            <summary>
+            Override this method to change where error messages go
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.Recover(Antlr.Runtime.IIntStream,Antlr.Runtime.RecognitionException)">
+            <summary>
+            Recover from an error found on the input stream.  This is
+            for NoViableAlt and mismatched symbol exceptions.  If you enable
+            single token insertion and deletion, this will usually not
+            handle mismatched symbol exceptions but there could be a mismatched
+            token that the Match() routine could not recover from.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.BeginResync">
+            <summary>A hook to listen in on the token consumption during error recovery.
+            The DebugParser subclasses this to fire events to the listenter.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.RecoverFromMismatchedToken(Antlr.Runtime.IIntStream,System.Int32,Antlr.Runtime.BitSet)">
+            <summary>
+            Attempt to Recover from a single missing or extra token.
+            </summary>
+            <remarks>
+            EXTRA TOKEN
+            LA(1) is not what we are looking for.  If LA(2) has the right token,
+            however, then assume LA(1) is some extra spurious token.  Delete it
+            and LA(2) as if we were doing a normal Match(), which advances the
+            input.
+            MISSING TOKEN
+            If current token is consistent with what could come after
+            ttype then it is ok to "insert" the missing token, else throw
+            exception For example, Input "i=(3;" is clearly missing the
+            ')'.  When the parser returns from the nested call to expr, it
+            will have call chain:
+            stat -&gt; expr -&gt; atom
+            and it will be trying to Match the ')' at this point in the
+            derivation:
+            =&gt; ID '=' '(' INT ')' ('+' atom)* ';'
+            ^
+            Match() will see that ';' doesn't Match ')' and report a
+            mismatched token error.  To Recover, it sees that LA(1)==';'
+            is in the set of tokens that can follow the ')' token
+            reference in rule atom.  It can assume that you forgot the ')'.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.RecoverFromMismatchedSet(Antlr.Runtime.IIntStream,Antlr.Runtime.RecognitionException,Antlr.Runtime.BitSet)">
+             Not currently used</member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.ConsumeUntil(Antlr.Runtime.IIntStream,Antlr.Runtime.BitSet)">
+            <summary>Consume tokens until one matches the given token set </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.GetRuleInvocationStack">
+            <summary>
+            Returns List &lt;String&gt; of the rules in your parser instance
+            leading up to a call to this method.  You could override if
+            you want more details such as the file/line info of where
+            in the parser source code a rule is invoked.
+            </summary>
+            <remarks>
+            This is very useful for error messages and for context-sensitive
+            error recovery.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.GetRuleInvocationStack(System.Exception,System.String)">
+            <summary>
+            A more general version of GetRuleInvocationStack where you can
+            pass in, for example, a RecognitionException to get it's rule
+            stack trace.  This routine is shared with all recognizers, hence,
+            static.
+            TODO: move to a utility class or something; weird having lexer call this
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.ToStrings(System.Collections.IList)">
+            <summary>A convenience method for use most often with template rewrites.
+            Convert a List&lt;Token&gt; to List&lt;String&gt;
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.GetRuleMemoization(System.Int32,System.Int32)">
+            <summary>
+            Given a rule number and a start token index number, return
+            MEMO_RULE_UNKNOWN if the rule has not parsed input starting from
+            start index.  If this rule has parsed input starting from the
+            start index before, then return where the rule stopped parsing.
+            It returns the index of the last token matched by the rule.
+            </summary>
+            <remarks>
+            For now we use a hashtable and just the slow Object-based one.
+            Later, we can make a special one for ints and also one that
+            tosses out data after we commit past input position i.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.AlreadyParsedRule(Antlr.Runtime.IIntStream,System.Int32)">
+            <summary>
+            Has this rule already parsed input at the current index in the
+            input stream?  Return the stop token index or MEMO_RULE_UNKNOWN.
+            If we attempted but failed to parse properly before, return
+            MEMO_RULE_FAILED.
+            This method has a side-effect: if we have seen this input for
+            this rule and successfully parsed before, then seek ahead to
+            1 past the stop token matched for this rule last time.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.Memoize(Antlr.Runtime.IIntStream,System.Int32,System.Int32)">
+            <summary>
+            Record whether or not this rule parsed the input at this position
+            successfully.  Use a standard hashtable for now.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.GetRuleMemoizationCacheSize">
+            <summary>
+            Return how many rule/input-index pairs there are in total.
+            TODO: this includes synpreds. :(
+            </summary>
+            <returns>
+            </returns>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.ComputeErrorRecoverySet">
+            <summary>
+            Factor out what to do upon token mismatch so tree parsers can behave
+            differently.  Override and call RecoverFromMismatchedToken()
+            to get single token insertion and deletion. Use this to turn off
+            single token insertion and deletion. Override mismatchRecover
+            to call this instead.
+            TODO: fix this comment, mismatchRecover doesn't exist, for example
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.ComputeContextSensitiveRuleFOLLOW">
+            <summary>Compute the context-sensitive FOLLOW set for current rule.
+            This is set of token types that can follow a specific rule
+            reference given a specific call chain.  You get the set of
+            viable tokens that can possibly come next (lookahead depth 1)
+            given the current call chain.  Contrast this with the
+            definition of plain FOLLOW for rule r:
+            FOLLOW(r)={x | S=&gt;*alpha r beta in G and x in FIRST(beta)}
+            where x in T* and alpha, beta in V*; T is set of terminals and
+            V is the set of terminals and nonterminals.  In other words,
+            FOLLOW(r) is the set of all tokens that can possibly follow
+            references to r in *any* sentential form (context).  At
+            runtime, however, we know precisely which context applies as
+            we have the call chain.  We may compute the exact (rather
+            than covering superset) set of following tokens.
+            For example, consider grammar:
+            stat : ID '=' expr ';'      // FOLLOW(stat)=={EOF}
+            | "return" expr '.'
+            ;
+            expr : atom ('+' atom)* ;   // FOLLOW(expr)=={';','.',')'}
+            atom : INT                  // FOLLOW(atom)=={'+',')',';','.'}
+            | '(' expr ')'
+            ;
+            The FOLLOW sets are all inclusive whereas context-sensitive
+            FOLLOW sets are precisely what could follow a rule reference.
+            For input input "i=(3);", here is the derivation:
+            stat =&gt; ID '=' expr ';'
+            =&gt; ID '=' atom ('+' atom)* ';'
+            =&gt; ID '=' '(' expr ')' ('+' atom)* ';'
+            =&gt; ID '=' '(' atom ')' ('+' atom)* ';'
+            =&gt; ID '=' '(' INT ')' ('+' atom)* ';'
+            =&gt; ID '=' '(' INT ')' ';'
+            At the "3" token, you'd have a call chain of
+            stat -&gt; expr -&gt; atom -&gt; expr -&gt; atom
+            What can follow that specific nested ref to atom?  Exactly ')'
+            as you can see by looking at the derivation of this specific
+            input.  Contrast this with the FOLLOW(atom)={'+',')',';','.'}.
+            You want the exact viable token set when recovering from a
+            token mismatch.  Upon token mismatch, if LA(1) is member of
+            the viable next token set, then you know there is most likely
+            a missing token in the input stream.  "Insert" one by just not
+            throwing an exception.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.GetCurrentInputSymbol(Antlr.Runtime.IIntStream)">
+            <summary>
+            Match needs to return the current input symbol, which gets put
+            into the label for the associated token ref; e.g., x=ID.  Token
+            and tree parsers need to return different objects. Rather than test
+            for input stream type or change the IntStream interface, I use
+            a simple method to ask the recognizer to tell me what the current
+            input symbol is.
+            </summary>
+            <remarks>This is ignored for lexers.</remarks>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.GetMissingSymbol(Antlr.Runtime.IIntStream,Antlr.Runtime.RecognitionException,System.Int32,Antlr.Runtime.BitSet)">
+            <summary>
+            Conjure up a missing token during error recovery.
+            </summary>
+            <remarks>
+            The recognizer attempts to recover from single missing
+            symbols. But, actions might refer to that missing symbol.
+            For example, x=ID {f($x);}. The action clearly assumes
+            that there has been an identifier matched previously and that
+            $x points at that token. If that token is missing, but
+            the next token in the stream is what we want we assume that
+            this token is missing and we keep going. Because we
+            have to return some token to replace the missing token,
+            we have to conjure one up. This method gives the user control
+            over the tokens returned for missing tokens. Mostly,
+            you will want to create something special for identifier
+            tokens. For literals such as '{' and ',', the default
+            action in the parser or tree parser works. It simply creates
+            a CommonToken of the appropriate type. The text will be the token.
+            If you change what tokens must be created by the lexer,
+            override this method to create the appropriate tokens.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.BaseRecognizer.PushFollow(Antlr.Runtime.BitSet)">
+            <summary>
+            Push a rule's follow set using our own hardcoded stack
+            </summary>
+            <param name="fset">
+            </param>
+        </member>
+        <member name="T:Antlr.Runtime.CommonTokenStream">
+            <summary>
+            The most common stream of tokens is one where every token is buffered up
+            and tokens are prefiltered for a certain channel (the parser will only
+            see these tokens and cannot change the filter channel number during the
+            parse).
+            TODO: how to access the full token stream?  How to track all tokens matched per rule?
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.CommonTokenStream.tokens">
+            <summary>Record every single token pulled from the source so we can reproduce
+            chunks of it later.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.CommonTokenStream.channelOverrideMap">
+            <summary><![CDATA[Map<tokentype, channel>]]> to override some Tokens' channel numbers </summary>
+        </member>
+        <member name="F:Antlr.Runtime.CommonTokenStream.discardSet">
+            <summary><![CDATA[Set<tokentype>;]]> discard any tokens with this type </summary>
+        </member>
+        <member name="F:Antlr.Runtime.CommonTokenStream.channel">
+            <summary>Skip tokens on any channel but this one; this is how we skip whitespace... </summary>
+        </member>
+        <member name="F:Antlr.Runtime.CommonTokenStream.discardOffChannelTokens">
+            <summary>By default, track all incoming tokens </summary>
+        </member>
+        <member name="F:Antlr.Runtime.CommonTokenStream.lastMarker">
+            <summary>Track the last Mark() call result value for use in Rewind().</summary>
+        </member>
+        <member name="F:Antlr.Runtime.CommonTokenStream.p">
+            <summary>
+            The index into the tokens list of the current token (next token
+            to consume).  p==-1 indicates that the tokens list is empty
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.CommonTokenStream.TokenSource">
+            <summary>
+            Gets or sets the token source for this stream (i.e. the source
+            that supplies the stream with Token objects).
+            </summary>
+            <remarks>
+            Setting the token source resets the stream.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.CommonTokenStream.LT(System.Int32)">
+            <summary>Get the ith token from the current position 1..n where k=1 is the
+            first symbol of lookahead.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.CommonTokenStream.Get(System.Int32)">
+            <summary>Return absolute token i; ignore which channel the tokens are on;
+            that is, count all tokens not just on-channel tokens.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.CommonTokenStream.Consume">
+            <summary>Move the input pointer to the next incoming token.  The stream
+            must become active with LT(1) available.  Consume() simply
+            moves the input pointer so that LT(1) points at the next
+            input symbol. Consume at least one token.
+            Walk past any token not on the channel the parser is listening to.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.CommonTokenStream.FillBuffer">
+            <summary>Load all tokens from the token source and put in tokens.
+            This is done upon first LT request because you might want to
+            set some token type / channel overrides before filling buffer.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.CommonTokenStream.SkipOffTokenChannels(System.Int32)">
+            <summary>Given a starting index, return the index of the first on-channel
+            token.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.CommonTokenStream.SetTokenTypeChannel(System.Int32,System.Int32)">
+            <summary>
+            A simple filter mechanism whereby you can tell this token stream
+            to force all tokens of type ttype to be on channel.
+            </summary>
+            <remarks>
+            For example,
+            when interpreting, we cannot exec actions so we need to tell
+            the stream to force all WS and NEWLINE to be a different, ignored
+            channel.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.CommonTokenStream.GetTokens(System.Int32,System.Int32,Antlr.Runtime.BitSet)">
+            <summary>Given a start and stop index, return a List of all tokens in
+            the token type BitSet.  Return null if no tokens were found.  This
+            method looks at both on and off channel tokens.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.CommonTokenStream.LB(System.Int32)">
+            <summary>Look backwards k tokens on-channel tokens </summary>
+        </member>
+        <member name="T:Antlr.Runtime.RecognizerSharedState">
+            <summary>
+            The set of fields needed by an abstract recognizer to recognize input
+            and recover from errors
+            </summary>
+            <remarks>
+            As a separate state object, it can be shared among multiple grammars;
+            e.g., when one grammar imports another.
+            These fields are publicly visible but the actual state pointer per
+            parser is protected.
+            </remarks>
+        </member>
+        <member name="F:Antlr.Runtime.RecognizerSharedState.following">
+            <summary>
+            Tracks the set of token types that can follow any rule invocation.
+            Stack grows upwards.  When it hits the max, it grows 2x in size
+            and keeps going.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.RecognizerSharedState.errorRecovery">
+            <summary>
+            This is true when we see an error and before having successfully
+            matched a token.  Prevents generation of more than one error message
+            per error.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.RecognizerSharedState.lastErrorIndex">
+            <summary>
+            The index into the input stream where the last error occurred.
+            </summary>
+            <remarks>
+            This is used to prevent infinite loops where an error is found
+            but no token is consumed during recovery...another error is found,
+            ad naseum.  This is a failsafe mechanism to guarantee that at least
+            one token/tree node is consumed for two errors.
+            </remarks>
+        </member>
+        <member name="F:Antlr.Runtime.RecognizerSharedState.failed">
+            <summary>
+            In lieu of a return value, this indicates that a rule or token
+            has failed to match.  Reset to false upon valid token match.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.RecognizerSharedState.syntaxErrors">
+            <summary>
+            Did the recognizer encounter a syntax error?  Track how many.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.RecognizerSharedState.backtracking">
+            <summary>
+            If 0, no backtracking is going on.  Safe to exec actions etc...
+            If &gt;0 then it's the level of backtracking.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.RecognizerSharedState.ruleMemo">
+            <summary>
+            An array[size num rules] of Map&lt;Integer,Integer&gt; that tracks
+            the stop token index for each rule.
+            </summary>
+            <remarks>
+            ruleMemo[ruleIndex] is the memoization table for ruleIndex.
+            For key ruleStartIndex, you get back the stop token for
+            associated rule or MEMO_RULE_FAILED.
+            This is only used if rule memoization is on (which it is by default).
+            </remarks>
+        </member>
+        <member name="F:Antlr.Runtime.RecognizerSharedState.token">
+            <summary>
+            Token object normally returned by NextToken() after matching lexer rules.
+            </summary>
+            <remarks>
+            The goal of all lexer rules/methods is to create a token object.
+            This is an instance variable as multiple rules may collaborate to
+            create a single token.  nextToken will return this object after
+            matching lexer rule(s).  If you subclass to allow multiple token
+            emissions, then set this to the last token to be matched or
+            something nonnull so that the auto token emit mechanism will not
+            emit another token.
+            </remarks>
+        </member>
+        <member name="F:Antlr.Runtime.RecognizerSharedState.tokenStartCharIndex">
+            <summary>
+            What character index in the stream did the current token start at?
+            </summary>
+            <remarks>
+            Needed, for example, to get the text for current token.  Set at
+            the start of nextToken.
+            </remarks>
+        </member>
+        <member name="F:Antlr.Runtime.RecognizerSharedState.tokenStartLine">
+            <summary>
+            The line on which the first character of the token resides
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.RecognizerSharedState.tokenStartCharPositionInLine">
+            <summary>The character position of first character within the line</summary>
+        </member>
+        <member name="F:Antlr.Runtime.RecognizerSharedState.channel">
+            <summary>The channel number for the current token</summary>
+        </member>
+        <member name="F:Antlr.Runtime.RecognizerSharedState.type">
+            <summary>The token type for the current token</summary>
+        </member>
+        <member name="F:Antlr.Runtime.RecognizerSharedState.text">
+            <summary>
+            You can set the text for the current token to override what is in
+            the input char buffer.  Use setText() or can set this instance var.
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.IToken.Line">
+            <summary>The line number on which this token was matched; line=1..n</summary>
+        </member>
+        <member name="P:Antlr.Runtime.IToken.CharPositionInLine">
+            <summary>
+            The index of the first character relative to the beginning of the line 0..n-1
+            </summary>
+        </member>
+        <member name="P:Antlr.Runtime.IToken.TokenIndex">
+            <summary>
+            An index from 0..n-1 of the token object in the input stream
+            </summary>
+            <remarks>
+            This must be valid in order to use the ANTLRWorks debugger.
+            </remarks>
+        </member>
+        <member name="P:Antlr.Runtime.IToken.Text">
+            <summary>The text of the token</summary>
+            <remarks>
+            When setting the text, it might be a NOP such as for the CommonToken,
+            which doesn't have string pointers, just indexes into a char buffer.
+            </remarks>
+        </member>
+        <member name="T:Antlr.Runtime.ITokenStream">
+            <summary>A stream of tokens accessing tokens from a TokenSource </summary>
+        </member>
+        <member name="P:Antlr.Runtime.ITokenStream.TokenSource">
+            <summary>Where is this stream pulling tokens from?  This is not the name, but
+            the object that provides Token objects.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ITokenStream.LT(System.Int32)">
+            <summary>
+            Get Token at current input pointer + i ahead (where i=1 is next
+            Token).
+            i &lt; 0 indicates tokens in the past.  So -1 is previous token and -2 is
+            two tokens ago. LT(0) is undefined.  For i&gt;=n, return Token.EOFToken.
+            Return null for LT(0) and any index that results in an absolute address
+            that is negative.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ITokenStream.Get(System.Int32)">
+            <summary>
+            Get a token at an absolute index i; 0..n-1.  This is really only
+            needed for profiling and debugging and token stream rewriting.
+            If you don't want to buffer up tokens, then this method makes no
+            sense for you.  Naturally you can't use the rewrite stream feature.
+            I believe DebugTokenStream can easily be altered to not use
+            this method, removing the dependency.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ITokenStream.ToString(System.Int32,System.Int32)">
+            <summary>Return the text of all tokens from start to stop, inclusive.
+            If the stream does not buffer all the tokens then it can just
+            return "" or null;  Users should not access $ruleLabel.text in
+            an action of course in that case.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.ITokenStream.ToString(Antlr.Runtime.IToken,Antlr.Runtime.IToken)">
+            <summary>Because the user is not required to use a token with an index stored
+            in it, we must provide a means for two token objects themselves to
+            indicate the start/end location.  Most often this will just delegate
+            to the other toString(int,int).  This is also parallel with
+            the TreeNodeStream.toString(Object,Object).
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Lexer">
+            <summary>
+            A lexer is recognizer that draws input symbols from a character stream.
+            lexer grammars result in a subclass of this object. A Lexer object
+            uses simplified Match() and error recovery mechanisms in the interest
+            of speed.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.Lexer.input">
+            <summary>Where is the lexer drawing characters from? </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Lexer.CharStream">
+            <summary>Set the char stream and reset the lexer </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Lexer.CharIndex">
+            <summary>What is the index of the current character of lookahead? </summary>
+        </member>
+        <member name="P:Antlr.Runtime.Lexer.Text">
+            <summary>
+            Gets or sets the 'lexeme' for the current token.
+            </summary>
+            <remarks>
+                <para>
+            The getter returns the text matched so far for the current token or any
+            text override.
+            </para>
+                <para>
+            The setter sets the complete text of this token. It overrides/wipes any
+            previous changes to the text.
+            </para>
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Lexer.NextToken">
+            <summary>
+            Return a token from this source; i.e., Match a token on the char stream.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Lexer.Skip">
+            <summary>
+            Instruct the lexer to skip creating a token for current lexer rule and
+            look for another token.  NextToken() knows to keep looking when a lexer
+            rule finishes with token set to SKIP_TOKEN.  Recall that if token==null
+            at end of any token rule, it creates one for you and emits it.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Lexer.mTokens">
+            <summary>This is the lexer entry point that sets instance var 'token' </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Lexer.Emit(Antlr.Runtime.IToken)">
+            <summary>
+            Currently does not support multiple emits per nextToken invocation
+            for efficiency reasons.  Subclass and override this method and
+            nextToken (to push tokens into a list and pull from that list rather
+            than a single variable as this implementation does).
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Lexer.Emit">
+            <summary>
+            The standard method called to automatically emit a token at the
+            outermost lexical rule.  The token object should point into the
+            char buffer start..stop.  If there is a text override in 'text',
+            use that to set the token's text.
+            </summary>
+            <remarks>
+                <para>Override this method to emit custom Token objects.</para>
+                <para>If you are building trees, then you should also override
+            Parser or TreeParser.getMissingSymbol().</para>
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.Lexer.Recover(Antlr.Runtime.RecognitionException)">
+            <summary>
+            Lexers can normally Match any char in it's vocabulary after matching
+            a token, so do the easy thing and just kill a character and hope
+            it all works out.  You can instead use the rule invocation stack
+            to do sophisticated error recovery if you are in a Fragment rule.
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.TokenRewriteStream">
+            <summary>Useful for dumping out the input stream after doing some
+            augmentation or other manipulations.
+            </summary>
+            <remarks>
+            You can insert stuff, Replace, and delete chunks.  Note that the
+            operations are done lazily--only if you convert the buffer to a
+            String.  This is very efficient because you are not moving data around
+            all the time.  As the buffer of tokens is converted to strings, the
+            ToString() method(s) check to see if there is an operation at the
+            current index.  If so, the operation is done and then normal String
+            rendering continues on the buffer.  This is like having multiple Turing
+            machine instruction streams (programs) operating on a single input tape. :)
+            Since the operations are done lazily at ToString-time, operations do not
+            screw up the token index values.  That is, an insert operation at token
+            index i does not change the index values for tokens i+1..n-1.
+            Because operations never actually alter the buffer, you may always get
+            the original token stream back without undoing anything.  Since
+            the instructions are queued up, you can easily simulate transactions and
+            roll back any changes if there is an error just by removing instructions.
+            For example,
+            CharStream input = new ANTLRFileStream("input");
+            TLexer lex = new TLexer(input);
+            TokenRewriteStream tokens = new TokenRewriteStream(lex);
+            T parser = new T(tokens);
+            parser.startRule();
+            Then in the rules, you can execute
+            IToken t,u;
+            ...
+            input.InsertAfter(t, "text to put after t");}
+            input.InsertAfter(u, "text after u");}
+            System.out.println(tokens.ToString());
+            Actually, you have to cast the 'input' to a TokenRewriteStream. :(
+            You can also have multiple "instruction streams" and get multiple
+            rewrites from a single pass over the input.  Just name the instruction
+            streams and use that name again when printing the buffer.  This could be
+            useful for generating a C file and also its header file--all from the
+            same buffer:
+            tokens.InsertAfter("pass1", t, "text to put after t");}
+            tokens.InsertAfter("pass2", u, "text after u");}
+            System.out.println(tokens.ToString("pass1"));
+            System.out.println(tokens.ToString("pass2"));
+            If you don't use named rewrite streams, a "default" stream is used as
+            the first example shows.
+            </remarks>
+        </member>
+        <member name="F:Antlr.Runtime.TokenRewriteStream.RewriteOperation.instructionIndex">
+             What index into rewrites List are we?</member>
+        <member name="F:Antlr.Runtime.TokenRewriteStream.RewriteOperation.index">
+             Token buffer index.</member>
+        <member name="M:Antlr.Runtime.TokenRewriteStream.RewriteOperation.Execute(System.Text.StringBuilder)">
+            <summary>Execute the rewrite operation by possibly adding to the buffer.
+            Return the index of the next token to operate on.
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.TokenRewriteStream.ReplaceOp">
+            <summary>I'm going to try replacing range from x..y with (y-x)+1 ReplaceOp
+            instructions.
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.TokenRewriteStream.programs">
+            <summary>You may have multiple, named streams of rewrite operations.
+            I'm calling these things "programs."
+            Maps String (name) -&gt; rewrite (IList)
+            </summary>
+        </member>
+        <member name="F:Antlr.Runtime.TokenRewriteStream.lastRewriteTokenIndexes">
+            <summary>Map String (program name) -&gt; Integer index </summary>
+        </member>
+        <member name="M:Antlr.Runtime.TokenRewriteStream.Rollback(System.String,System.Int32)">
+            <summary>Rollback the instruction stream for a program so that
+            the indicated instruction (via instructionIndex) is no
+            longer in the stream.  UNTESTED!
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.TokenRewriteStream.DeleteProgram(System.String)">
+            <summary>Reset the program so that no instructions exist </summary>
+        </member>
+        <member name="M:Antlr.Runtime.TokenRewriteStream.ReduceToSingleOperationPerIndex(System.Collections.IList)">
+            <summary>
+            Return a map from token index to operation.
+            </summary>
+            <remarks>We need to combine operations and report invalid operations (like
+            overlapping replaces that are not completed nested).  Inserts to
+            same index need to be combined etc...   Here are the cases:
+            I.i.u I.j.v								leave alone, nonoverlapping
+            I.i.u I.i.v								combine: Iivu
+            R.i-j.u R.x-y.v	| i-j in x-y			delete first R
+            R.i-j.u R.i-j.v							delete first R
+            R.i-j.u R.x-y.v	| x-y in i-j			ERROR
+            R.i-j.u R.x-y.v	| boundaries overlap	ERROR
+            I.i.u R.x-y.v | i in x-y				delete I
+            I.i.u R.x-y.v | i not in x-y			leave alone, nonoverlapping
+            R.x-y.v I.i.u | i in x-y				ERROR
+            R.x-y.v I.x.u 							R.x-y.uv (combine, delete I)
+            R.x-y.v I.i.u | i not in x-y			leave alone, nonoverlapping
+            I.i.u = insert u before op @ index i
+            R.x-y.u = replace x-y indexed tokens with u
+            First we need to examine replaces.  For any replace op:
+            		1. wipe out any insertions before op within that range.
+            		2. Drop any replace op before that is contained completely within
+            that range.
+            		3. Throw exception upon boundary overlap with any previous replace.
+            Then we can deal with inserts:
+            		1. for any inserts to same index, combine even if not adjacent.
+            		2. for any prior replace with same left boundary, combine this
+            insert with replace and delete this replace.
+            		3. throw exception if index in same range as previous replace
+            Don't actually delete; make op null in list. Easier to walk list.
+            Later we can throw as we add to index -&gt; op map.
+            Note that I.2 R.2-2 will wipe out I.2 even though, technically, the
+            inserted stuff would be before the replace range.  But, if you
+            add tokens in front of a method body '{' and then delete the method
+            body, I think the stuff before the '{' you added should disappear too.
+            </remarks>
+        </member>
+        <member name="M:Antlr.Runtime.TokenRewriteStream.GetKindOfOps(System.Collections.IList,System.Type,System.Int32)">
+            <summary>
+            Get all operations before an index of a particular kind
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.ITreeVisitorAction">
+            <summary>
+            How to execute code for node t when a visitor visits node t.  Execute
+            Pre() before visiting children and execute Post() after visiting children.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeVisitorAction.Pre(System.Object)">
+            <summary>
+            Execute an action before visiting children of t.  Return t or
+            a rewritten t.  Children of returned value will be visited.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.ITreeVisitorAction.Post(System.Object)">
+            <summary>
+            Execute an action after visiting children of t. Return t or
+            a rewritten t. It is up to the visitor to decide what to do
+            with the return value.
+            </summary>
+        </member>
+        <member name="T:Antlr.Runtime.Tree.TreeVisitor">
+            <summary>
+            Do a depth first walk of a tree, applying pre() and post() actions
+            as we discover and finish nodes.
+            </summary>
+        </member>
+        <member name="M:Antlr.Runtime.Tree.TreeVisitor.Visit(System.Object,Antlr.Runtime.Tree.ITreeVisitorAction)">
+            <summary>
+            Visit every node in tree t and trigger an action for each node
+            before/after having visited all of its children.
+            Execute both actions even if t has no children.
+            If a child visit yields a new child, it can update its
+            parent's child list or just return the new child.  The
+            child update code works even if the child visit alters its parent
+            and returns the new tree.
+            Return result of applying post action to this node.
+            </summary>
+        </member>
+    </members>
+</doc>
Index: branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Utility (2).XML
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Utility (2).XML	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Utility (2).XML	(revision 3)
@@ -0,0 +1,61 @@
+<?xml version="1.0"?>
+<doc>
+    <assembly>
+        <name>Antlr3.Utility</name>
+    </assembly>
+    <members>
+        <member name="T:Antlr.Utility.Tree.DOTTreeGenerator">
+             <summary>
+             A utility class to generate DOT diagrams (graphviz) from
+             arbitrary trees.  You can pass in your own templates and
+             can pass in any kind of tree or use Tree interface method.
+             I wanted this separator so that you don't have to include
+             ST just to use the org.antlr.runtime.tree.* package.
+             This is a set of non-static methods so you can subclass
+             to override.  For example, here is an invocation:
+            
+                 CharStream input = new ANTLRInputStream(Console.In);
+                 TLexer lex = new TLexer(input);
+                 CommonTokenStream tokens = new CommonTokenStream(lex);
+                 TParser parser = new TParser(tokens);
+                 TParser.e_return r = parser.e();
+                 Tree t = (Tree)r.tree;
+                 Console.Out.WriteLine(t.ToStringTree());
+                 DOTTreeGenerator gen = new DOTTreeGenerator();
+                 StringTemplate st = gen.ToDOT(t);
+                 Console.Out.WriteLine(st);
+                 
+             </summary>
+        </member>
+        <member name="F:Antlr.Utility.Tree.DOTTreeGenerator.nodeToNumberMap">
+            <summary>
+            Track node to number mapping so we can get proper node name back
+            </summary>
+        </member>
+        <member name="F:Antlr.Utility.Tree.DOTTreeGenerator.nodeNumber">
+            <summary>
+            Track node number so we can get unique node names
+            </summary>
+        </member>
+        <member name="M:Antlr.Utility.Tree.DOTTreeGenerator.ToDOT(Antlr.Runtime.Tree.ITree)">
+             <summary>
+             Generate DOT (graphviz) for a whole tree not just a node.
+             For example, 3+4*5 should generate:
+            
+             digraph {
+               node [shape=plaintext, fixedsize=true, fontsize=11, fontname="Courier",
+                     width=.4, height=.2];
+               edge [arrowsize=.7]
+               "+"->3
+               "+"->"*"
+               "*"->4
+               "*"->5
+             }
+            
+             Return the ST not a string in case people want to alter.
+            
+             Takes a Tree interface object.
+             </summary>
+        </member>
+    </members>
+</doc>
Index: branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Utility.dll
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Utility.dll
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Utility.dll	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Utility.dll	(revision 3)

Property changes on: branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Utility.dll
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Utility.dll.mdb
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Utility.dll.mdb
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Utility.dll.mdb	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Utility.dll.mdb	(revision 3)

Property changes on: branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Utility.dll.mdb
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Utility.xml
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Utility.xml	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/Antlr3.Utility.xml	(revision 3)
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+<doc>
+    <assembly>
+        <name>/home/verequus/Arbeit/ANTLR/code/antlr/main/runtime/CSharp/Sources/Antlr3.Utility/bin/Debug/net-2.0/Antlr3.Utility</name>
+    </assembly>
+    <members>
+        <member name="T:Antlr.Utility.Tree.DOTTreeGenerator">
+            <summary>
+            A utility class to generate DOT diagrams (graphviz) from
+            arbitrary trees.  You can pass in your own templates and
+            can pass in any kind of tree or use Tree interface method.
+            I wanted this separator so that you don't have to include
+            ST just to use the org.antlr.runtime.tree.* package.
+            This is a set of non-static methods so you can subclass
+            to override.  For example, here is an invocation:
+            CharStream input = new ANTLRInputStream(Console.In);
+            TLexer lex = new TLexer(input);
+            CommonTokenStream tokens = new CommonTokenStream(lex);
+            TParser parser = new TParser(tokens);
+            TParser.e_return r = parser.e();
+            Tree t = (Tree)r.tree;
+            Console.Out.WriteLine(t.ToStringTree());
+            DOTTreeGenerator gen = new DOTTreeGenerator();
+            StringTemplate st = gen.ToDOT(t);
+            Console.Out.WriteLine(st);
+            </summary>
+        </member>
+        <member name="F:Antlr.Utility.Tree.DOTTreeGenerator.nodeToNumberMap">
+            <summary>
+            Track node to number mapping so we can get proper node name back
+            </summary>
+        </member>
+        <member name="F:Antlr.Utility.Tree.DOTTreeGenerator.nodeNumber">
+            <summary>
+            Track node number so we can get unique node names
+            </summary>
+        </member>
+        <member name="M:Antlr.Utility.Tree.DOTTreeGenerator.ToDOT(Antlr.Runtime.Tree.ITree)">
+            <summary>
+            Generate DOT (graphviz) for a whole tree not just a node.
+            For example, 3+4*5 should generate:
+            digraph {
+            node [shape=plaintext, fixedsize=true, fontsize=11, fontname="Courier",
+            width=.4, height=.2];
+            edge [arrowsize=.7]
+            "+"-&gt;3
+            "+"-&gt;"*"
+            "*"-&gt;4
+            "*"-&gt;5
+            }
+            Return the ST not a string in case people want to alter.
+            Takes a Tree interface object.
+            </summary>
+        </member>
+    </members>
+</doc>
Index: branches/compiler/cSharp/ooasCompiler/src/libs/StringTemplate.dll
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: branches/compiler/cSharp/ooasCompiler/src/libs/StringTemplate.dll
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/StringTemplate.dll	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/StringTemplate.dll	(revision 3)

Property changes on: branches/compiler/cSharp/ooasCompiler/src/libs/StringTemplate.dll
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: branches/compiler/cSharp/ooasCompiler/src/libs/antlr.runtime.dll
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: branches/compiler/cSharp/ooasCompiler/src/libs/antlr.runtime.dll
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/libs/antlr.runtime.dll	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/libs/antlr.runtime.dll	(revision 3)

Property changes on: branches/compiler/cSharp/ooasCompiler/src/libs/antlr.runtime.dll
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: branches/compiler/cSharp/ooasCompiler/src/math/Operations.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/math/Operations.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/math/Operations.cs	(revision 3)
@@ -0,0 +1,357 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TUG.Mogentes
+{
+    public abstract class AbstractOperations
+    {
+        public abstract AbstractRange GenericArithmeticCover(AbstractRange type1, AbstractRange type2, ExpressionKind op);
+    }
+
+    public class Operations<T> : AbstractOperations
+    {
+        public delegate T opUnary(T input);
+        public delegate T opBinary(T inputA, T inputB);
+        public delegate bool opBinRel(T inputA, T intputB);
+
+        public opUnary unaryNotImplemented = p => { throw new NotImplementedException(); };
+        public opBinary binaryNotImplemented = (a, b) => { throw new NotImplementedException(); };
+        public opBinRel binrelNotImplemented = (a, b) => { throw new NotImplementedException(); };
+
+        // not all operations may be defined, then there needs to be some excpetion..
+        public opUnary unMinus;
+        public opBinary minus;
+        public opBinary plus;
+        public opBinary div;
+        public opBinary pow;
+        public opBinary prod;
+        public opBinary mod;
+        public opBinRel equal;
+        public opBinRel smaller;
+        public opBinRel greater;
+
+        public override AbstractRange GenericArithmeticCover(AbstractRange type1, AbstractRange type2, ExpressionKind op)
+        {
+            Range<T> a = type1 as Range<T>;
+            Range<T> b = type2 as Range<T>;
+
+            if (a == null || b == null)
+                throw new ArgumentException();
+
+            return GenericArithmeticCover(a, b, op);
+        }
+
+        public Range<T> GenericArithmeticCover(Range<T> type1, Range<T> type2, ExpressionKind op)
+        {
+            Range<T> result = type1.Create(default(T), default(T));
+            Operations<T> o = this; // remove this if method remains in this class..
+
+            switch (op)
+            {
+                case ExpressionKind.unminus:
+                    result.min = o.unMinus(type1.max);
+                    result.max = o.unMinus(type1.min);
+                    break;
+                case ExpressionKind.unplus:
+                    break;
+
+                case ExpressionKind.minus:
+                    System.Diagnostics.Debug.Assert(type2 != null);
+                    // we do some sort of resulttype = type1 - type2
+                    // hence, do the unminus stuff with type 2
+                    T spare = type2.max;
+                    type2.max = o.unMinus(type2.min);
+                    type2.min = o.unMinus(spare);
+                    // now it's the same with sum.. but c# does not let us fall through..
+                    result.min = o.plus(type1.min, type2.min);
+                    result.max = o.plus(type1.max, type2.max);
+                    break;
+                case ExpressionKind.sum:
+                    System.Diagnostics.Debug.Assert(type2 != null);
+                    result.min = o.plus(type1.min, type2.min);
+                    result.max = o.plus(type1.max, type2.max);
+                    break;
+                case ExpressionKind.idiv:
+                case ExpressionKind.div:
+                    System.Diagnostics.Debug.Assert(type2 != null);
+                    type2.min = o.equal(type2.min, default(T)) ? o.unMinus(type2.precision) : type2.min;
+                    type2.max = o.equal(type2.max, default(T)) ? type2.precision : type2.max;
+                    // hmm, brute force.. is there some formula?
+                    result.max = o.div(type1.min, type2.min);
+                    result.min = result.max;
+
+                    T tmp = o.div(type1.max, type2.min);
+                    result.max = o.smaller(result.max, tmp) ? tmp : result.max;
+                    result.min = o.greater(result.min, tmp) ? tmp : result.min;
+
+                    tmp = o.div(type1.min, type2.max);
+                    result.max = o.smaller(result.max, tmp) ? tmp : result.max;
+                    result.min = o.greater(result.min, tmp) ? tmp : result.min;
+
+                    tmp = o.div(type1.max, type2.max);
+                    result.max = o.smaller(result.max, tmp) ? tmp : result.max;
+                    result.min = o.greater(result.min, tmp) ? tmp : result.min;
+                    break;
+                case ExpressionKind.mod:
+                    throw new ArgumentException(); // do this one level up
+                case ExpressionKind.pow:
+                    // ok, this is bad. - just give up here
+                    result.max = result.typemax;
+                    result.min = result.typemin;
+                    break;
+                case ExpressionKind.prod:
+                    // hmm, brute force.. is there some formula?
+                    result.max = o.prod(type1.min, type2.min);
+                    result.min = result.max;
+
+                    tmp = o.prod(type1.max, type2.min);
+                    result.max = o.smaller(result.max, tmp) ? tmp : result.max;
+                    result.min = o.greater(result.min, tmp) ? tmp : result.min;
+
+                    tmp = o.prod(type1.min, type2.max);
+                    result.max = o.smaller(result.max, tmp) ? tmp : result.max;
+                    result.min = o.greater(result.min, tmp) ? tmp : result.min;
+
+                    tmp = o.prod(type1.max, type2.max);
+                    result.max = o.smaller(result.max, tmp) ? tmp : result.max;
+                    result.min = o.greater(result.min, tmp) ? tmp : result.min;
+                    break;
+
+                default:
+                    throw new NotImplementedException();
+            }
+            return result;
+        }
+
+
+        public Operations()
+        {
+            unMinus = unaryNotImplemented;
+            minus = binaryNotImplemented;
+            plus = binaryNotImplemented;
+            div = binaryNotImplemented;
+            pow = binaryNotImplemented;
+            prod = binaryNotImplemented;
+            mod = binaryNotImplemented;
+            equal = binrelNotImplemented;
+            smaller = binrelNotImplemented;
+            greater = binrelNotImplemented;
+        }
+
+        public Operations(opUnary aUnMinus,
+            opBinary aMinus,
+            opBinary aPlus,
+            opBinary aDiv,
+            opBinary aPow,
+            opBinary aProd,
+            opBinary aMod,
+            opBinRel aEquality,
+            opBinRel aSmaller,
+            opBinRel aGreater)
+        {
+            unMinus = aUnMinus;
+            minus = aMinus;
+            plus = aPlus;
+            div = aDiv;
+            pow = aPow;
+            prod = aProd;
+            mod = aMod;
+            equal = aEquality;
+            smaller = aSmaller;
+            greater = aGreater;
+        }
+    }
+
+
+    public sealed class IntegerOperations : Operations<int>
+    {
+        public IntegerOperations()
+            : base(p => -p,
+            (a, b) => a - b,
+            (a, b) => a + b,
+            (a, b) => a / b,
+            (a, b) => (int)Math.Pow(a, b),
+            (a, b) => a * b,
+            (a, b) => a % b,
+            (a, b) => a == b,
+            (a, b) => a < b,
+            (a, b) => a > b)
+        { }
+    }
+
+
+    public sealed class CheckedIntegerOperations : Operations<int>
+    {
+        public CheckedIntegerOperations()
+            : base(p => { checked { return -p; } },
+            (a, b) => { checked { return a - b; } },
+            (a, b) => { checked { return a + b; } },
+            (a, b) => { checked { return a / b; } },
+            (a, b) => { checked { return (int)Math.Pow(a, b); } },
+            (a, b) => { checked { return a * b; } },
+            (a, b) => a % b,
+            (a, b) => a == b,
+            (a, b) => a < b,
+            (a, b) => a > b)
+        { }
+    }
+
+
+    public sealed class SaturatedIntegerOperations : Operations<int>
+    {
+        private static int SatUnMinus(int input)
+        {
+            return input == int.MinValue ? int.MaxValue : -input;
+        }
+
+        private static int Subtraction(int a, int b)
+        {
+            if (b < 0)
+                return (a > int.MaxValue + b) ? int.MaxValue : a - b;
+            else
+                return (a < int.MinValue + b) ? int.MinValue : a - b;
+        }
+
+        private static int Addition(int a, int b)
+        {
+            if (b < 0)
+                return (a < int.MinValue - b) ? int.MinValue : a + b;
+            else
+                return (a > int.MaxValue - b) ? int.MaxValue : a + b;
+        }
+
+        private static int Division(int a, int b)
+        {
+            checked { return a / b; };
+        }
+
+        private static int Power(int a, int b)
+        {
+            Int64 tmp = (Int64)Math.Pow(a, b);
+            if (tmp < int.MinValue) return int.MinValue;
+            else if (tmp > int.MaxValue) return int.MaxValue;
+            else return (int)tmp;
+        }
+
+        private static int Multiplication(int a, int b)
+        {
+            Int64 tmp = Math.BigMul(a, b);
+            if (tmp < int.MinValue) return int.MinValue;
+            else if (tmp > int.MaxValue) return int.MaxValue;
+            else return (int)tmp;
+        }
+
+        public SaturatedIntegerOperations()
+            : base(SatUnMinus, Subtraction, Addition, Division, Power, Multiplication,
+            (a, b) => a % b,
+            (a, b) => a == b,
+            (a, b) => a < b,
+            (a, b) => a > b)
+        { }
+    }
+
+
+
+    public sealed class DoubleOperations : Operations<double>
+    {
+        public DoubleOperations()
+            : base(p => -p,
+            (a, b) => a - b,
+            (a, b) => a + b,
+            (a, b) => a / b,
+            (a, b) => Math.Pow(a, b),
+            (a, b) => a * b,
+            (a, b) => a % b,
+            (a, b) => a == b,
+            (a, b) => a < b,
+            (a, b) => a > b)
+        { }
+    }
+
+
+
+    public sealed class SaturatedDoubleOperations : Operations<double>
+    {
+
+        private static double checkRange(double aValue)
+        {
+            if (aValue == double.PositiveInfinity)
+                return double.MaxValue;
+            else if (aValue == double.NegativeInfinity)
+                return double.MinValue;
+            else
+                return aValue;
+        }
+
+        private static double SatUnMinus(double input)
+        {
+            return checkRange(-input);
+        }
+
+        private static double Subtraction(double a, double b)
+        {
+            return checkRange(a - b);
+        }
+
+        private static double Addition(double a, double b)
+        {
+            return checkRange(a + b);
+        }
+
+        private static double Division(double a, double b)
+        {
+            return checkRange(a / b);
+        }
+
+        private static double Power(double a, double b)
+        {
+            return checkRange(Math.Pow(a, b));
+        }
+
+        private static double Multiplication(double a, double b)
+        {
+
+            return checkRange(a * b);
+        }
+
+        private static double Reminder(double a, double b)
+        {
+            return checkRange(a % b);
+        }
+
+        public SaturatedDoubleOperations()
+            : base(SatUnMinus,
+            Subtraction,
+            Addition,
+            Division,
+            Power,
+            Multiplication,
+            Reminder,
+            (a, b) => a == b,
+            (a, b) => a < b,
+            (a, b) => a > b)
+        { }
+    }
+
+
+
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/math/Range.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/math/Range.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/math/Range.cs	(revision 3)
@@ -0,0 +1,72 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TUG.Mogentes
+{
+
+    public delegate Range<T> RangeConstructor<T>(T max, T min);
+
+    public abstract class AbstractRange
+    {
+    }
+
+    public class Range<T> : AbstractRange
+    {
+        protected RangeConstructor<T> m_constructor;
+
+        public T max;
+        public T min;
+        public T precision;
+        public T typemax;
+        public T typemin;
+
+        public Range<T> Create(T amax, T amin)
+        {
+            return m_constructor(amax, amin);
+        }
+
+        public Range(T amax, T amin, T aprecision, T atypemax, T atypemin, RangeConstructor<T> aconstr)
+        {
+            max = amax;
+            min = amin;
+            precision = aprecision;
+            typemax = atypemax;
+            typemin = atypemin;
+            m_constructor = aconstr;
+        }
+
+    }
+
+    public sealed class IntegerRange : Range<int>
+    {
+        public IntegerRange(int max, int min)
+            : base(max, min, 1, int.MaxValue, int.MinValue, (a, b) => new IntegerRange(a, b))
+        { }
+    }
+
+    public sealed class DoubleRange : Range<double>
+    {
+        public DoubleRange(double max, double min)
+            : base(max, min, double.Epsilon, double.MaxValue, double.MinValue, (a, b) => new DoubleRange(a, b))
+        { }
+    }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/output/ooa.tokens
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/output/ooa.tokens	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/output/ooa.tokens	(revision 3)
@@ -0,0 +1,136 @@
+T_FLOATNUMBER=29
+T_SYSTEM=6
+T_ELSE=87
+T_LPAREN=12
+T_DUNION=102
+T_BOOL=25
+T_METHODS=35
+T_INDS=105
+T_OR=69
+T_OD=38
+T_AND=75
+T_OF=18
+T_STRINGLITERAL=93
+T_SET=66
+T_SKIP=52
+T_WITH=57
+T_DOM=108
+T_WS=111
+T_VAR=34
+T_SUM=47
+T_REQUIRES=45
+T_DINTER=101
+T_HEAD=104
+T_AUTOCONS=33
+T_END=43
+T_TRUE=90
+T_LSQPAREN=15
+T_PRIMED=97
+T_MAPS=96
+T_NIL=92
+T_INFTY=24
+T_IF=85
+LINE_COMMENT=113
+T_THEN=86
+T_FLOAT=28
+T_TAIL=107
+T_SELF=55
+T_MERGE=110
+T_DIFF=48
+T_FOLDRL=51
+T_QUANTITY=22
+T_IN=65
+T_MUNION=82
+T__126=126
+T__125=125
+T_INTER=74
+T_SEMICOLON=7
+T_FOLDLR=50
+T_CARD=99
+T_FALSE=91
+T_CONT=44
+T_SUBSET=68
+T_COMMA=19
+T_RANGETO=27
+T_MINUS=23
+T_CONC=77
+T_IDIV=71
+T_FORALL=88
+T_DERIV=46
+T_CONSTS=4
+T_TYPES=5
+T_GREATEREQUAL=60
+T__118=118
+T_RNG=109
+T__119=119
+T_MOD=72
+T__117=117
+T_SEQMOD_MAPOVERRIDE=83
+T__124=124
+T__123=123
+T_ELEMS=103
+T__122=122
+T__121=121
+T_IMPLIES=64
+T__120=120
+T_EXISTS=89
+T_POW=76
+T_COMMENT=112
+T_RPAREN=13
+T_PRIO=10
+T_RNGRESBY=80
+T_ABS=98
+T_DIV=70
+T_LIST=14
+T_CBRL=31
+T_DCONC=100
+T_ABORT=53
+T_CHAR=30
+T_POINT=84
+T_STATIC=39
+T_CBRR=32
+T_INT=26
+T_COLON=42
+T_PROD=49
+T_ACTIONS=36
+T_DIGIT=114
+T_LESS=61
+T_BAR=95
+T_TO=21
+T_NONDET=11
+T_DOMRESBY=78
+T_DOMRESTO=79
+T_EQUAL=9
+T_GREATER=59
+T_KILL=54
+T_RNGRESTO=81
+T_RSQPAREN=17
+T_NEW=94
+T_INTNUMBER=16
+T_UNION=73
+T_OBS=40
+T_BIIMPLIES=58
+T_NOTEQUAL=63
+T_IDENTIFIER=8
+T_DO=37
+FLOAT_OR_INT_OR_RANGE=115
+T_LEN=106
+T_NOT=67
+T_ASSIGNMENT=56
+T_LETTER=116
+T_MAP=20
+T_LESSEQUAL=62
+T_CTRL=41
+']|'=118
+'begin'=119
+'as'=121
+'dec'=125
+'|['=117
+'qval'=122
+'('=12
+'-'=23
+'::'=126
+')'=13
+'&'=120
+'steady'=123
+'inc'=124
Index: branches/compiler/cSharp/ooasCompiler/src/output/ooaLexer.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/output/ooaLexer.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/output/ooaLexer.cs	(revision 3)
@@ -0,0 +1,5236 @@
+// $ANTLR 3.2 Sep 23, 2009 12:02:23 C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g 2011-02-10 11:21:05
+
+// The variable 'variable' is assigned but its value is never used.
+#pragma warning disable 168, 219
+// Unreachable code detected.
+#pragma warning disable 162
+
+
+/*
+    Ulysses OO-Action System Parser
+
+    Copyright Willibald Krenn 2009
+
+ */
+
+
+using System;
+using Antlr.Runtime;
+using IList 		= System.Collections.IList;
+using ArrayList 	= System.Collections.ArrayList;
+using Stack 		= Antlr.Runtime.Collections.StackList;
+
+using IDictionary	= System.Collections.IDictionary;
+using Hashtable 	= System.Collections.Hashtable;
+namespace  TUG.Mogentes 
+{
+public partial class ooaLexer : Lexer {
+    public const int T_FLOATNUMBER = 29;
+    public const int T_SYSTEM = 6;
+    public const int T_ELSE = 87;
+    public const int T_LPAREN = 12;
+    public const int T_DUNION = 102;
+    public const int T_BOOL = 25;
+    public const int T_METHODS = 35;
+    public const int T_INDS = 105;
+    public const int T_OR = 69;
+    public const int EOF = -1;
+    public const int T_OD = 38;
+    public const int T_AND = 75;
+    public const int T_OF = 18;
+    public const int T_STRINGLITERAL = 93;
+    public const int T_SET = 66;
+    public const int T_SKIP = 52;
+    public const int T_WITH = 57;
+    public const int T_DOM = 108;
+    public const int T_WS = 111;
+    public const int T_VAR = 34;
+    public const int T_SUM = 47;
+    public const int T_REQUIRES = 45;
+    public const int T_DINTER = 101;
+    public const int T_AUTOCONS = 33;
+    public const int T_HEAD = 104;
+    public const int T_END = 43;
+    public const int T_TRUE = 90;
+    public const int T_LSQPAREN = 15;
+    public const int T_MAPS = 96;
+    public const int T_PRIMED = 97;
+    public const int T_INFTY = 24;
+    public const int T_NIL = 92;
+    public const int T_IF = 85;
+    public const int LINE_COMMENT = 113;
+    public const int T_THEN = 86;
+    public const int T_FLOAT = 28;
+    public const int T_SELF = 55;
+    public const int T_TAIL = 107;
+    public const int T_DIFF = 48;
+    public const int T_MERGE = 110;
+    public const int T_FOLDRL = 51;
+    public const int T_QUANTITY = 22;
+    public const int T_IN = 65;
+    public const int T_MUNION = 82;
+    public const int T__126 = 126;
+    public const int T__125 = 125;
+    public const int T_INTER = 74;
+    public const int T_SEMICOLON = 7;
+    public const int T_FOLDLR = 50;
+    public const int T_CARD = 99;
+    public const int T_FALSE = 91;
+    public const int T_CONT = 44;
+    public const int T_SUBSET = 68;
+    public const int T_COMMA = 19;
+    public const int T_RANGETO = 27;
+    public const int T_MINUS = 23;
+    public const int T_CONC = 77;
+    public const int T_IDIV = 71;
+    public const int T_FORALL = 88;
+    public const int T_DERIV = 46;
+    public const int T_CONSTS = 4;
+    public const int T_TYPES = 5;
+    public const int T_GREATEREQUAL = 60;
+    public const int T__118 = 118;
+    public const int T_RNG = 109;
+    public const int T__119 = 119;
+    public const int T_MOD = 72;
+    public const int T__117 = 117;
+    public const int T_SEQMOD_MAPOVERRIDE = 83;
+    public const int T__124 = 124;
+    public const int T__123 = 123;
+    public const int T_ELEMS = 103;
+    public const int T__122 = 122;
+    public const int T__121 = 121;
+    public const int T_IMPLIES = 64;
+    public const int T__120 = 120;
+    public const int T_EXISTS = 89;
+    public const int T_POW = 76;
+    public const int T_COMMENT = 112;
+    public const int T_RPAREN = 13;
+    public const int T_PRIO = 10;
+    public const int T_RNGRESBY = 80;
+    public const int T_ABS = 98;
+    public const int T_DIV = 70;
+    public const int T_LIST = 14;
+    public const int T_CBRL = 31;
+    public const int T_DCONC = 100;
+    public const int T_ABORT = 53;
+    public const int T_CHAR = 30;
+    public const int T_STATIC = 39;
+    public const int T_POINT = 84;
+    public const int T_INT = 26;
+    public const int T_CBRR = 32;
+    public const int T_PROD = 49;
+    public const int T_COLON = 42;
+    public const int T_ACTIONS = 36;
+    public const int T_LESS = 61;
+    public const int T_DIGIT = 114;
+    public const int T_BAR = 95;
+    public const int T_TO = 21;
+    public const int T_NONDET = 11;
+    public const int T_DOMRESBY = 78;
+    public const int T_DOMRESTO = 79;
+    public const int T_EQUAL = 9;
+    public const int T_GREATER = 59;
+    public const int T_KILL = 54;
+    public const int T_RNGRESTO = 81;
+    public const int T_RSQPAREN = 17;
+    public const int T_NEW = 94;
+    public const int T_INTNUMBER = 16;
+    public const int T_UNION = 73;
+    public const int T_OBS = 40;
+    public const int T_BIIMPLIES = 58;
+    public const int T_NOTEQUAL = 63;
+    public const int T_IDENTIFIER = 8;
+    public const int T_DO = 37;
+    public const int FLOAT_OR_INT_OR_RANGE = 115;
+    public const int T_NOT = 67;
+    public const int T_LEN = 106;
+    public const int T_ASSIGNMENT = 56;
+    public const int T_LETTER = 116;
+    public const int T_LESSEQUAL = 62;
+    public const int T_MAP = 20;
+    public const int T_CTRL = 41;
+
+    // delegates
+    // delegators
+
+    public ooaLexer() 
+    {
+		InitializeCyclicDFAs();
+    }
+    public ooaLexer(ICharStream input)
+		: this(input, null) {
+    }
+    public ooaLexer(ICharStream input, RecognizerSharedState state)
+		: base(input, state) {
+		InitializeCyclicDFAs(); 
+
+    }
+    
+    override public string GrammarFileName
+    {
+    	get { return "C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g";} 
+    }
+
+    // $ANTLR start "T__117"
+    public void mT__117() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__117;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:17:8: ( '|[' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:17:10: '|['
+            {
+            	Match("|["); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__117"
+
+    // $ANTLR start "T__118"
+    public void mT__118() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__118;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:18:8: ( ']|' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:18:10: ']|'
+            {
+            	Match("]|"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__118"
+
+    // $ANTLR start "T__119"
+    public void mT__119() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__119;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:19:8: ( 'begin' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:19:10: 'begin'
+            {
+            	Match("begin"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__119"
+
+    // $ANTLR start "T__120"
+    public void mT__120() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__120;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:20:8: ( '&' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:20:10: '&'
+            {
+            	Match('&'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__120"
+
+    // $ANTLR start "T__121"
+    public void mT__121() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__121;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:21:8: ( 'as' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:21:10: 'as'
+            {
+            	Match("as"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__121"
+
+    // $ANTLR start "T__122"
+    public void mT__122() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__122;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:22:8: ( 'qval' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:22:10: 'qval'
+            {
+            	Match("qval"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__122"
+
+    // $ANTLR start "T__123"
+    public void mT__123() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__123;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:23:8: ( 'steady' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:23:10: 'steady'
+            {
+            	Match("steady"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__123"
+
+    // $ANTLR start "T__124"
+    public void mT__124() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__124;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:24:8: ( 'inc' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:24:10: 'inc'
+            {
+            	Match("inc"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__124"
+
+    // $ANTLR start "T__125"
+    public void mT__125() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__125;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:25:8: ( 'dec' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:25:10: 'dec'
+            {
+            	Match("dec"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__125"
+
+    // $ANTLR start "T__126"
+    public void mT__126() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__126;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:26:8: ( '::' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:26:10: '::'
+            {
+            	Match("::"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__126"
+
+    // $ANTLR start "T_WS"
+    public void mT_WS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_WS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:989:8: ( ( ' ' | '\\r' | '\\t' | '\\u000C' | '\\n' ) )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:989:10: ( ' ' | '\\r' | '\\t' | '\\u000C' | '\\n' )
+            {
+            	if ( (input.LA(1) >= '\t' && input.LA(1) <= '\n') || (input.LA(1) >= '\f' && input.LA(1) <= '\r') || input.LA(1) == ' ' ) 
+            	{
+            	    input.Consume();
+            	state.failed = false;
+            	}
+            	else 
+            	{
+            	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+            	    MismatchedSetException mse = new MismatchedSetException(null,input);
+            	    Recover(mse);
+            	    throw mse;}
+
+            	if ( (state.backtracking==0) )
+            	{
+            	  _channel=HIDDEN;
+            	}
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_WS"
+
+    // $ANTLR start "T_COMMENT"
+    public void mT_COMMENT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_COMMENT;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:993:6: ( '/*' ( . )* '*/' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:993:8: '/*' ( . )* '*/'
+            {
+            	Match("/*"); if (state.failed) return ;
+
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:993:13: ( . )*
+            	do 
+            	{
+            	    int alt1 = 2;
+            	    int LA1_0 = input.LA(1);
+
+            	    if ( (LA1_0 == '*') )
+            	    {
+            	        int LA1_1 = input.LA(2);
+
+            	        if ( (LA1_1 == '/') )
+            	        {
+            	            alt1 = 2;
+            	        }
+            	        else if ( ((LA1_1 >= '\u0000' && LA1_1 <= '.') || (LA1_1 >= '0' && LA1_1 <= '\uFFFF')) )
+            	        {
+            	            alt1 = 1;
+            	        }
+
+
+            	    }
+            	    else if ( ((LA1_0 >= '\u0000' && LA1_0 <= ')') || (LA1_0 >= '+' && LA1_0 <= '\uFFFF')) )
+            	    {
+            	        alt1 = 1;
+            	    }
+
+
+            	    switch (alt1) 
+            		{
+            			case 1 :
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:993:13: .
+            			    {
+            			    	MatchAny(); if (state.failed) return ;
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop1;
+            	    }
+            	} while (true);
+
+            	loop1:
+            		;	// Stops C# compiler whining that label 'loop1' has no statements
+
+            	Match("*/"); if (state.failed) return ;
+
+            	if ( (state.backtracking==0) )
+            	{
+            	  _channel=HIDDEN;
+            	}
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_COMMENT"
+
+    // $ANTLR start "LINE_COMMENT"
+    public void mLINE_COMMENT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = LINE_COMMENT;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:997:6: ( '#' (~ ( '\\n' | '\\r' ) )* ( '\\r' )? '\\n' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:997:8: '#' (~ ( '\\n' | '\\r' ) )* ( '\\r' )? '\\n'
+            {
+            	Match('#'); if (state.failed) return ;
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:997:12: (~ ( '\\n' | '\\r' ) )*
+            	do 
+            	{
+            	    int alt2 = 2;
+            	    int LA2_0 = input.LA(1);
+
+            	    if ( ((LA2_0 >= '\u0000' && LA2_0 <= '\t') || (LA2_0 >= '\u000B' && LA2_0 <= '\f') || (LA2_0 >= '\u000E' && LA2_0 <= '\uFFFF')) )
+            	    {
+            	        alt2 = 1;
+            	    }
+
+
+            	    switch (alt2) 
+            		{
+            			case 1 :
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:997:12: ~ ( '\\n' | '\\r' )
+            			    {
+            			    	if ( (input.LA(1) >= '\u0000' && input.LA(1) <= '\t') || (input.LA(1) >= '\u000B' && input.LA(1) <= '\f') || (input.LA(1) >= '\u000E' && input.LA(1) <= '\uFFFF') ) 
+            			    	{
+            			    	    input.Consume();
+            			    	state.failed = false;
+            			    	}
+            			    	else 
+            			    	{
+            			    	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+            			    	    MismatchedSetException mse = new MismatchedSetException(null,input);
+            			    	    Recover(mse);
+            			    	    throw mse;}
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop2;
+            	    }
+            	} while (true);
+
+            	loop2:
+            		;	// Stops C# compiler whining that label 'loop2' has no statements
+
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:997:26: ( '\\r' )?
+            	int alt3 = 2;
+            	int LA3_0 = input.LA(1);
+
+            	if ( (LA3_0 == '\r') )
+            	{
+            	    alt3 = 1;
+            	}
+            	switch (alt3) 
+            	{
+            	    case 1 :
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:997:26: '\\r'
+            	        {
+            	        	Match('\r'); if (state.failed) return ;
+
+            	        }
+            	        break;
+
+            	}
+
+            	Match('\n'); if (state.failed) return ;
+            	if ( (state.backtracking==0) )
+            	{
+            	  _channel=HIDDEN;
+            	}
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "LINE_COMMENT"
+
+    // $ANTLR start "T_PRIMED"
+    public void mT_PRIMED() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_PRIMED;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1001:2: ( '\\'' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1001:4: '\\''
+            {
+            	Match('\''); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_PRIMED"
+
+    // $ANTLR start "T_STRINGLITERAL"
+    public void mT_STRINGLITERAL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_STRINGLITERAL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1004:2: ( '\"' ( ( '\"' '\"' )=> '\"' | ~ '\"' )* '\"' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1004:4: '\"' ( ( '\"' '\"' )=> '\"' | ~ '\"' )* '\"'
+            {
+            	Match('\"'); if (state.failed) return ;
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1005:3: ( ( '\"' '\"' )=> '\"' | ~ '\"' )*
+            	do 
+            	{
+            	    int alt4 = 3;
+            	    int LA4_0 = input.LA(1);
+
+            	    if ( (LA4_0 == '\"') )
+            	    {
+            	        int LA4_1 = input.LA(2);
+
+            	        if ( (LA4_1 == '\"') && (synpred1_ooa()) )
+            	        {
+            	            alt4 = 1;
+            	        }
+            	        else if ( ((LA4_1 >= '\u0000' && LA4_1 <= '!') || (LA4_1 >= '#' && LA4_1 <= '\uFFFF')) && (synpred1_ooa()) )
+            	        {
+            	            alt4 = 1;
+            	        }
+
+
+            	    }
+            	    else if ( ((LA4_0 >= '\u0000' && LA4_0 <= '!') || (LA4_0 >= '#' && LA4_0 <= '\uFFFF')) )
+            	    {
+            	        alt4 = 2;
+            	    }
+
+
+            	    switch (alt4) 
+            		{
+            			case 1 :
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1006:9: ( '\"' '\"' )=> '\"'
+            			    {
+            			    	Match('\"'); if (state.failed) return ;
+
+            			    }
+            			    break;
+            			case 2 :
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1007:13: ~ '\"'
+            			    {
+            			    	if ( (input.LA(1) >= '\u0000' && input.LA(1) <= '!') || (input.LA(1) >= '#' && input.LA(1) <= '\uFFFF') ) 
+            			    	{
+            			    	    input.Consume();
+            			    	state.failed = false;
+            			    	}
+            			    	else 
+            			    	{
+            			    	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+            			    	    MismatchedSetException mse = new MismatchedSetException(null,input);
+            			    	    Recover(mse);
+            			    	    throw mse;}
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop4;
+            	    }
+            	} while (true);
+
+            	loop4:
+            		;	// Stops C# compiler whining that label 'loop4' has no statements
+
+            	Match('\"'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_STRINGLITERAL"
+
+    // $ANTLR start "T_ABORT"
+    public void mT_ABORT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_ABORT;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1013:9: ( 'abort' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1013:11: 'abort'
+            {
+            	Match("abort"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_ABORT"
+
+    // $ANTLR start "T_ACTIONS"
+    public void mT_ACTIONS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_ACTIONS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1015:2: ( 'actions' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1015:4: 'actions'
+            {
+            	Match("actions"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_ACTIONS"
+
+    // $ANTLR start "T_ASSIGNMENT"
+    public void mT_ASSIGNMENT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_ASSIGNMENT;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1017:2: ( ':=' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1017:4: ':='
+            {
+            	Match(":="); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_ASSIGNMENT"
+
+    // $ANTLR start "T_AUTOCONS"
+    public void mT_AUTOCONS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_AUTOCONS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1018:11: ( 'autocons' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1018:13: 'autocons'
+            {
+            	Match("autocons"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_AUTOCONS"
+
+    // $ANTLR start "T_BAR"
+    public void mT_BAR() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_BAR;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1019:7: ( '|' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1019:9: '|'
+            {
+            	Match('|'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_BAR"
+
+    // $ANTLR start "T_BOOL"
+    public void mT_BOOL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_BOOL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1020:8: ( 'bool' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1020:10: 'bool'
+            {
+            	Match("bool"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_BOOL"
+
+    // $ANTLR start "T_CBRL"
+    public void mT_CBRL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_CBRL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1021:8: ( '{' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1021:10: '{'
+            {
+            	Match('{'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_CBRL"
+
+    // $ANTLR start "T_CBRR"
+    public void mT_CBRR() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_CBRR;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1022:8: ( '}' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1022:10: '}'
+            {
+            	Match('}'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_CBRR"
+
+    // $ANTLR start "T_COLON"
+    public void mT_COLON() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_COLON;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1023:9: ( ':' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1023:11: ':'
+            {
+            	Match(':'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_COLON"
+
+    // $ANTLR start "T_COMMA"
+    public void mT_COMMA() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_COMMA;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1024:9: ( ',' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1024:11: ','
+            {
+            	Match(','); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_COMMA"
+
+    // $ANTLR start "T_CONT"
+    public void mT_CONT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_CONT;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1025:8: ( 'qual' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1025:10: 'qual'
+            {
+            	Match("qual"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_CONT"
+
+    // $ANTLR start "T_CHAR"
+    public void mT_CHAR() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_CHAR;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1026:8: ( 'char' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1026:10: 'char'
+            {
+            	Match("char"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_CHAR"
+
+    // $ANTLR start "T_CTRL"
+    public void mT_CTRL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_CTRL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1027:9: ( 'ctr' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1027:11: 'ctr'
+            {
+            	Match("ctr"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_CTRL"
+
+    // $ANTLR start "T_SYSTEM"
+    public void mT_SYSTEM() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_SYSTEM;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1029:2: ( 'system' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1029:4: 'system'
+            {
+            	Match("system"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_SYSTEM"
+
+    // $ANTLR start "T_DO"
+    public void mT_DO() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DO;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1030:6: ( 'do' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1030:8: 'do'
+            {
+            	Match("do"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DO"
+
+    // $ANTLR start "T_ELSE"
+    public void mT_ELSE() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_ELSE;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1031:8: ( 'else' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1031:10: 'else'
+            {
+            	Match("else"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_ELSE"
+
+    // $ANTLR start "T_END"
+    public void mT_END() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_END;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1032:7: ( 'end' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1032:9: 'end'
+            {
+            	Match("end"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_END"
+
+    // $ANTLR start "T_EQUAL"
+    public void mT_EQUAL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_EQUAL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1033:9: ( '=' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1033:11: '='
+            {
+            	Match('='); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_EQUAL"
+
+    // $ANTLR start "T_EXISTS"
+    public void mT_EXISTS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_EXISTS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1034:9: ( 'exists' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1034:11: 'exists'
+            {
+            	Match("exists"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_EXISTS"
+
+    // $ANTLR start "T_FLOAT"
+    public void mT_FLOAT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_FLOAT;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1035:9: ( 'float' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1035:11: 'float'
+            {
+            	Match("float"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_FLOAT"
+
+    // $ANTLR start "T_FORALL"
+    public void mT_FORALL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_FORALL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1036:9: ( 'forall' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1036:11: 'forall'
+            {
+            	Match("forall"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_FORALL"
+
+    // $ANTLR start "T_FALSE"
+    public void mT_FALSE() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_FALSE;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1037:9: ( 'false' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1037:11: 'false'
+            {
+            	Match("false"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_FALSE"
+
+    // $ANTLR start "T_IF"
+    public void mT_IF() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_IF;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1038:6: ( 'if' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1038:8: 'if'
+            {
+            	Match("if"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_IF"
+
+    // $ANTLR start "T_IN"
+    public void mT_IN() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_IN;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1039:6: ( 'in' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1039:8: 'in'
+            {
+            	Match("in"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_IN"
+
+    // $ANTLR start "T_INT"
+    public void mT_INT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_INT;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1040:7: ( 'int' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1040:9: 'int'
+            {
+            	Match("int"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_INT"
+
+    // $ANTLR start "T_KILL"
+    public void mT_KILL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_KILL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1041:8: ( 'kill' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1041:10: 'kill'
+            {
+            	Match("kill"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_KILL"
+
+    // $ANTLR start "T_LIST"
+    public void mT_LIST() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_LIST;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1042:8: ( 'list' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1042:10: 'list'
+            {
+            	Match("list"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_LIST"
+
+    // $ANTLR start "T_LPAREN"
+    public void mT_LPAREN() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_LPAREN;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1043:9: ( '(' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1043:11: '('
+            {
+            	Match('('); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_LPAREN"
+
+    // $ANTLR start "T_LSQPAREN"
+    public void mT_LSQPAREN() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_LSQPAREN;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1044:11: ( '[' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1044:13: '['
+            {
+            	Match('['); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_LSQPAREN"
+
+    // $ANTLR start "T_MAP"
+    public void mT_MAP() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_MAP;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1045:7: ( 'map' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1045:9: 'map'
+            {
+            	Match("map"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_MAP"
+
+    // $ANTLR start "T_MAPS"
+    public void mT_MAPS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_MAPS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1046:8: ( '->' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1046:10: '->'
+            {
+            	Match("->"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_MAPS"
+
+    // $ANTLR start "T_METHODS"
+    public void mT_METHODS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_METHODS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1048:2: ( 'methods' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1048:4: 'methods'
+            {
+            	Match("methods"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_METHODS"
+
+    // $ANTLR start "T_NEW"
+    public void mT_NEW() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_NEW;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1049:7: ( 'new' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1049:9: 'new'
+            {
+            	Match("new"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_NEW"
+
+    // $ANTLR start "T_NIL"
+    public void mT_NIL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_NIL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1050:7: ( 'nil' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1050:9: 'nil'
+            {
+            	Match("nil"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_NIL"
+
+    // $ANTLR start "T_NONDET"
+    public void mT_NONDET() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_NONDET;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1051:9: ( '[]' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1051:11: '[]'
+            {
+            	Match("[]"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_NONDET"
+
+    // $ANTLR start "T_OBS"
+    public void mT_OBS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_OBS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1052:7: ( 'obs' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1052:9: 'obs'
+            {
+            	Match("obs"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_OBS"
+
+    // $ANTLR start "T_OD"
+    public void mT_OD() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_OD;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1053:6: ( 'od' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1053:8: 'od'
+            {
+            	Match("od"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_OD"
+
+    // $ANTLR start "T_OF"
+    public void mT_OF() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_OF;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1054:6: ( 'of' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1054:8: 'of'
+            {
+            	Match("of"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_OF"
+
+    // $ANTLR start "T_PRIO"
+    public void mT_PRIO() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_PRIO;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1055:8: ( '//' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1055:10: '//'
+            {
+            	Match("//"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_PRIO"
+
+    // $ANTLR start "T_REQUIRES"
+    public void mT_REQUIRES() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_REQUIRES;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1057:2: ( 'requires' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1057:4: 'requires'
+            {
+            	Match("requires"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_REQUIRES"
+
+    // $ANTLR start "T_RPAREN"
+    public void mT_RPAREN() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_RPAREN;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1058:9: ( ')' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1058:11: ')'
+            {
+            	Match(')'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_RPAREN"
+
+    // $ANTLR start "T_RSQPAREN"
+    public void mT_RSQPAREN() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_RSQPAREN;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1059:11: ( ']' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1059:13: ']'
+            {
+            	Match(']'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_RSQPAREN"
+
+    // $ANTLR start "T_QUANTITY"
+    public void mT_QUANTITY() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_QUANTITY;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1061:2: ( 'qspace' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1061:4: 'qspace'
+            {
+            	Match("qspace"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_QUANTITY"
+
+    // $ANTLR start "T_SELF"
+    public void mT_SELF() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_SELF;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1062:8: ( 'self' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1062:10: 'self'
+            {
+            	Match("self"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_SELF"
+
+    // $ANTLR start "T_SET"
+    public void mT_SET() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_SET;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1063:8: ( 'set' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1063:10: 'set'
+            {
+            	Match("set"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_SET"
+
+    // $ANTLR start "T_SEMICOLON"
+    public void mT_SEMICOLON() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_SEMICOLON;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1065:2: ( ';' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1065:4: ';'
+            {
+            	Match(';'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_SEMICOLON"
+
+    // $ANTLR start "T_STATIC"
+    public void mT_STATIC() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_STATIC;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1066:9: ( 'static' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1066:11: 'static'
+            {
+            	Match("static"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_STATIC"
+
+    // $ANTLR start "T_SKIP"
+    public void mT_SKIP() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_SKIP;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1067:8: ( 'skip' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1067:10: 'skip'
+            {
+            	Match("skip"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_SKIP"
+
+    // $ANTLR start "T_THEN"
+    public void mT_THEN() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_THEN;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1068:8: ( 'then' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1068:10: 'then'
+            {
+            	Match("then"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_THEN"
+
+    // $ANTLR start "T_TRUE"
+    public void mT_TRUE() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_TRUE;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1069:9: ( 'true' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1069:11: 'true'
+            {
+            	Match("true"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_TRUE"
+
+    // $ANTLR start "T_TO"
+    public void mT_TO() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_TO;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1070:6: ( 'to' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1070:8: 'to'
+            {
+            	Match("to"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_TO"
+
+    // $ANTLR start "T_TYPES"
+    public void mT_TYPES() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_TYPES;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1071:9: ( 'types' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1071:11: 'types'
+            {
+            	Match("types"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_TYPES"
+
+    // $ANTLR start "T_VAR"
+    public void mT_VAR() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_VAR;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1072:7: ( 'var' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1072:9: 'var'
+            {
+            	Match("var"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_VAR"
+
+    // $ANTLR start "T_WITH"
+    public void mT_WITH() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_WITH;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1073:8: ( 'with' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1073:10: 'with'
+            {
+            	Match("with"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_WITH"
+
+    // $ANTLR start "T_AND"
+    public void mT_AND() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_AND;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1079:7: ( 'and' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1079:9: 'and'
+            {
+            	Match("and"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_AND"
+
+    // $ANTLR start "T_BIIMPLIES"
+    public void mT_BIIMPLIES() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_BIIMPLIES;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1081:2: ( '<=>' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1081:4: '<=>'
+            {
+            	Match("<=>"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_BIIMPLIES"
+
+    // $ANTLR start "T_IMPLIES"
+    public void mT_IMPLIES() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_IMPLIES;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1083:2: ( '=>' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1083:4: '=>'
+            {
+            	Match("=>"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_IMPLIES"
+
+    // $ANTLR start "T_NOT"
+    public void mT_NOT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_NOT;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1084:7: ( 'not' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1084:9: 'not'
+            {
+            	Match("not"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_NOT"
+
+    // $ANTLR start "T_NOTEQUAL"
+    public void mT_NOTEQUAL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_NOTEQUAL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1085:11: ( '<>' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1085:13: '<>'
+            {
+            	Match("<>"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_NOTEQUAL"
+
+    // $ANTLR start "T_OR"
+    public void mT_OR() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_OR;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1086:6: ( 'or' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1086:8: 'or'
+            {
+            	Match("or"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_OR"
+
+    // $ANTLR start "T_ABS"
+    public void mT_ABS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_ABS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1089:7: ( 'abs' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1089:9: 'abs'
+            {
+            	Match("abs"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_ABS"
+
+    // $ANTLR start "T_DIV"
+    public void mT_DIV() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DIV;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1090:7: ( '/' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1090:9: '/'
+            {
+            	Match('/'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DIV"
+
+    // $ANTLR start "T_GREATER"
+    public void mT_GREATER() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_GREATER;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1092:2: ( '>' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1092:4: '>'
+            {
+            	Match('>'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_GREATER"
+
+    // $ANTLR start "T_GREATEREQUAL"
+    public void mT_GREATEREQUAL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_GREATEREQUAL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1094:2: ( '>=' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1094:4: '>='
+            {
+            	Match(">="); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_GREATEREQUAL"
+
+    // $ANTLR start "T_IDIV"
+    public void mT_IDIV() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_IDIV;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1095:8: ( 'div' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1095:10: 'div'
+            {
+            	Match("div"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_IDIV"
+
+    // $ANTLR start "T_LESS"
+    public void mT_LESS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_LESS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1096:8: ( '<' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1096:10: '<'
+            {
+            	Match('<'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_LESS"
+
+    // $ANTLR start "T_LESSEQUAL"
+    public void mT_LESSEQUAL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_LESSEQUAL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1098:2: ( '<=' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1098:4: '<='
+            {
+            	Match("<="); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_LESSEQUAL"
+
+    // $ANTLR start "T_MOD"
+    public void mT_MOD() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_MOD;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1099:7: ( 'mod' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1099:9: 'mod'
+            {
+            	Match("mod"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_MOD"
+
+    // $ANTLR start "T_POW"
+    public void mT_POW() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_POW;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1100:7: ( '**' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1100:9: '**'
+            {
+            	Match("**"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_POW"
+
+    // $ANTLR start "T_PROD"
+    public void mT_PROD() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_PROD;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1101:8: ( '*' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1101:10: '*'
+            {
+            	Match('*'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_PROD"
+
+    // $ANTLR start "T_DERIV"
+    public void mT_DERIV() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DERIV;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1102:9: ( 'dt' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1102:11: 'dt'
+            {
+            	Match("dt"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DERIV"
+
+    // $ANTLR start "T_CARD"
+    public void mT_CARD() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_CARD;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1105:8: ( 'card' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1105:10: 'card'
+            {
+            	Match("card"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_CARD"
+
+    // $ANTLR start "T_CONC"
+    public void mT_CONC() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_CONC;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1106:8: ( '^' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1106:10: '^'
+            {
+            	Match('^'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_CONC"
+
+    // $ANTLR start "T_DCONC"
+    public void mT_DCONC() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DCONC;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1107:9: ( 'conc' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1107:11: 'conc'
+            {
+            	Match("conc"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DCONC"
+
+    // $ANTLR start "T_DIFF"
+    public void mT_DIFF() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DIFF;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1108:8: ( '\\\\' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1108:10: '\\\\'
+            {
+            	Match('\\'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DIFF"
+
+    // $ANTLR start "T_DINTER"
+    public void mT_DINTER() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DINTER;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1109:9: ( 'dinter' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1109:11: 'dinter'
+            {
+            	Match("dinter"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DINTER"
+
+    // $ANTLR start "T_DUNION"
+    public void mT_DUNION() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DUNION;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1110:9: ( 'dunion' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1110:11: 'dunion'
+            {
+            	Match("dunion"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DUNION"
+
+    // $ANTLR start "T_ELEMS"
+    public void mT_ELEMS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_ELEMS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1111:9: ( 'elems' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1111:11: 'elems'
+            {
+            	Match("elems"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_ELEMS"
+
+    // $ANTLR start "T_HEAD"
+    public void mT_HEAD() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_HEAD;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1112:8: ( 'hd' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1112:10: 'hd'
+            {
+            	Match("hd"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_HEAD"
+
+    // $ANTLR start "T_INDS"
+    public void mT_INDS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_INDS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1113:8: ( 'inds' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1113:10: 'inds'
+            {
+            	Match("inds"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_INDS"
+
+    // $ANTLR start "T_INTER"
+    public void mT_INTER() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_INTER;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1114:9: ( 'inter' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1114:11: 'inter'
+            {
+            	Match("inter"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_INTER"
+
+    // $ANTLR start "T_LEN"
+    public void mT_LEN() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_LEN;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1115:7: ( 'len' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1115:9: 'len'
+            {
+            	Match("len"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_LEN"
+
+    // $ANTLR start "T_SEQMOD_MAPOVERRIDE"
+    public void mT_SEQMOD_MAPOVERRIDE() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_SEQMOD_MAPOVERRIDE;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1117:2: ( '++' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1117:4: '++'
+            {
+            	Match("++"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_SEQMOD_MAPOVERRIDE"
+
+    // $ANTLR start "T_SUBSET"
+    public void mT_SUBSET() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_SUBSET;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1118:9: ( 'subset' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1118:11: 'subset'
+            {
+            	Match("subset"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_SUBSET"
+
+    // $ANTLR start "T_TAIL"
+    public void mT_TAIL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_TAIL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1119:8: ( 'tl' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1119:10: 'tl'
+            {
+            	Match("tl"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_TAIL"
+
+    // $ANTLR start "T_UNION"
+    public void mT_UNION() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_UNION;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1120:9: ( 'union' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1120:11: 'union'
+            {
+            	Match("union"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_UNION"
+
+    // $ANTLR start "T_FOLDLR"
+    public void mT_FOLDLR() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_FOLDLR;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1122:2: ( ':>:' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1122:4: ':>:'
+            {
+            	Match(":>:"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_FOLDLR"
+
+    // $ANTLR start "T_FOLDRL"
+    public void mT_FOLDRL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_FOLDRL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1124:2: ( ':<:' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1124:4: ':<:'
+            {
+            	Match(":<:"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_FOLDRL"
+
+    // $ANTLR start "T_DOM"
+    public void mT_DOM() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DOM;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1128:7: ( 'dom' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1128:9: 'dom'
+            {
+            	Match("dom"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DOM"
+
+    // $ANTLR start "T_DOMRESBY"
+    public void mT_DOMRESBY() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DOMRESBY;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1130:2: ( '<-:' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1130:4: '<-:'
+            {
+            	Match("<-:"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DOMRESBY"
+
+    // $ANTLR start "T_DOMRESTO"
+    public void mT_DOMRESTO() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DOMRESTO;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1132:2: ( '<:' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1132:4: '<:'
+            {
+            	Match("<:"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DOMRESTO"
+
+    // $ANTLR start "T_RNG"
+    public void mT_RNG() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_RNG;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1133:7: ( 'rng' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1133:9: 'rng'
+            {
+            	Match("rng"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_RNG"
+
+    // $ANTLR start "T_RNGRESBY"
+    public void mT_RNGRESBY() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_RNGRESBY;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1135:2: ( ':->' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1135:4: ':->'
+            {
+            	Match(":->"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_RNGRESBY"
+
+    // $ANTLR start "T_RNGRESTO"
+    public void mT_RNGRESTO() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_RNGRESTO;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1137:2: ( ':>' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1137:4: ':>'
+            {
+            	Match(":>"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_RNGRESTO"
+
+    // $ANTLR start "T_MERGE"
+    public void mT_MERGE() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_MERGE;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1138:9: ( 'merge' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1138:11: 'merge'
+            {
+            	Match("merge"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_MERGE"
+
+    // $ANTLR start "T_MUNION"
+    public void mT_MUNION() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_MUNION;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1139:9: ( 'munion' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1139:11: 'munion'
+            {
+            	Match("munion"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_MUNION"
+
+    // $ANTLR start "T_CONSTS"
+    public void mT_CONSTS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_CONSTS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1141:9: ( 'consts' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1141:11: 'consts'
+            {
+            	Match("consts"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_CONSTS"
+
+    // $ANTLR start "T_INFTY"
+    public void mT_INFTY() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_INFTY;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1145:9: ( ( T_MINUS | T_SUM )? 'inf' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1145:11: ( T_MINUS | T_SUM )? 'inf'
+            {
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1145:11: ( T_MINUS | T_SUM )?
+            	int alt5 = 2;
+            	int LA5_0 = input.LA(1);
+
+            	if ( (LA5_0 == '+' || LA5_0 == '-') )
+            	{
+            	    alt5 = 1;
+            	}
+            	switch (alt5) 
+            	{
+            	    case 1 :
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:
+            	        {
+            	        	if ( input.LA(1) == '+' || input.LA(1) == '-' ) 
+            	        	{
+            	        	    input.Consume();
+            	        	state.failed = false;
+            	        	}
+            	        	else 
+            	        	{
+            	        	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+            	        	    MismatchedSetException mse = new MismatchedSetException(null,input);
+            	        	    Recover(mse);
+            	        	    throw mse;}
+
+
+            	        }
+            	        break;
+
+            	}
+
+            	Match("inf"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_INFTY"
+
+    // $ANTLR start "T_INTNUMBER"
+    public void mT_INTNUMBER() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1152:2: ()
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1152:4: 
+            {
+            }
+
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_INTNUMBER"
+
+    // $ANTLR start "T_FLOATNUMBER"
+    public void mT_FLOATNUMBER() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1154:2: ()
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1154:4: 
+            {
+            }
+
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_FLOATNUMBER"
+
+    // $ANTLR start "T_RANGETO"
+    public void mT_RANGETO() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1156:2: ()
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1156:4: 
+            {
+            }
+
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_RANGETO"
+
+    // $ANTLR start "FLOAT_OR_INT_OR_RANGE"
+    public void mFLOAT_OR_INT_OR_RANGE() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = FLOAT_OR_INT_OR_RANGE;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1159:2: ( ( T_MINUS | T_SUM )? ( T_DIGIT )+ ( ( T_POINT T_POINT )=> | ( T_POINT T_DIGIT )=> T_POINT ( T_DIGIT )+ ( ( 'e' | 'E' ) ( T_MINUS | T_SUM )? ( T_DIGIT )+ )? | ) | T_POINT ( T_POINT | ) | T_MINUS | T_SUM )
+            int alt14 = 4;
+            switch ( input.LA(1) ) 
+            {
+            case '-':
+            	{
+                int LA14_1 = input.LA(2);
+
+                if ( ((LA14_1 >= '0' && LA14_1 <= '9')) )
+                {
+                    alt14 = 1;
+                }
+                else 
+                {
+                    alt14 = 3;}
+                }
+                break;
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            	{
+                alt14 = 1;
+                }
+                break;
+            case '.':
+            	{
+                alt14 = 2;
+                }
+                break;
+            case '+':
+            	{
+                int LA14_4 = input.LA(2);
+
+                if ( ((LA14_4 >= '0' && LA14_4 <= '9')) )
+                {
+                    alt14 = 1;
+                }
+                else 
+                {
+                    alt14 = 4;}
+                }
+                break;
+            	default:
+            	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+            	    NoViableAltException nvae_d14s0 =
+            	        new NoViableAltException("", 14, 0, input);
+
+            	    throw nvae_d14s0;
+            }
+
+            switch (alt14) 
+            {
+                case 1 :
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1159:5: ( T_MINUS | T_SUM )? ( T_DIGIT )+ ( ( T_POINT T_POINT )=> | ( T_POINT T_DIGIT )=> T_POINT ( T_DIGIT )+ ( ( 'e' | 'E' ) ( T_MINUS | T_SUM )? ( T_DIGIT )+ )? | )
+                    {
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1159:5: ( T_MINUS | T_SUM )?
+                    	int alt6 = 2;
+                    	int LA6_0 = input.LA(1);
+
+                    	if ( (LA6_0 == '+' || LA6_0 == '-') )
+                    	{
+                    	    alt6 = 1;
+                    	}
+                    	switch (alt6) 
+                    	{
+                    	    case 1 :
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:
+                    	        {
+                    	        	if ( input.LA(1) == '+' || input.LA(1) == '-' ) 
+                    	        	{
+                    	        	    input.Consume();
+                    	        	state.failed = false;
+                    	        	}
+                    	        	else 
+                    	        	{
+                    	        	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+                    	        	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	        	    Recover(mse);
+                    	        	    throw mse;}
+
+
+                    	        }
+                    	        break;
+
+                    	}
+
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1159:22: ( T_DIGIT )+
+                    	int cnt7 = 0;
+                    	do 
+                    	{
+                    	    int alt7 = 2;
+                    	    int LA7_0 = input.LA(1);
+
+                    	    if ( ((LA7_0 >= '0' && LA7_0 <= '9')) )
+                    	    {
+                    	        alt7 = 1;
+                    	    }
+
+
+                    	    switch (alt7) 
+                    		{
+                    			case 1 :
+                    			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1159:22: T_DIGIT
+                    			    {
+                    			    	mT_DIGIT(); if (state.failed) return ;
+
+                    			    }
+                    			    break;
+
+                    			default:
+                    			    if ( cnt7 >= 1 ) goto loop7;
+                    			    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+                    		            EarlyExitException eee7 =
+                    		                new EarlyExitException(7, input);
+                    		            throw eee7;
+                    	    }
+                    	    cnt7++;
+                    	} while (true);
+
+                    	loop7:
+                    		;	// Stops C# compiler whining that label 'loop7' has no statements
+
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1160:3: ( ( T_POINT T_POINT )=> | ( T_POINT T_DIGIT )=> T_POINT ( T_DIGIT )+ ( ( 'e' | 'E' ) ( T_MINUS | T_SUM )? ( T_DIGIT )+ )? | )
+                    	int alt12 = 3;
+                    	int LA12_0 = input.LA(1);
+
+                    	if ( (LA12_0 == '.') && (synpred3_ooa()) )
+                    	{
+                    	    alt12 = 2;
+                    	}
+                    	else if ( (synpred2_ooa()) )
+                    	{
+                    	    alt12 = 1;
+                    	}
+                    	else if ( (true) )
+                    	{
+                    	    alt12 = 3;
+                    	}
+                    	else 
+                    	{
+                    	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+                    	    NoViableAltException nvae_d12s0 =
+                    	        new NoViableAltException("", 12, 0, input);
+
+                    	    throw nvae_d12s0;
+                    	}
+                    	switch (alt12) 
+                    	{
+                    	    case 1 :
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1161:5: ( T_POINT T_POINT )=>
+                    	        {
+                    	        	if ( (state.backtracking==0) )
+                    	        	{
+                    	        	  _type=T_INTNUMBER;
+                    	        	}
+
+                    	        }
+                    	        break;
+                    	    case 2 :
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1162:6: ( T_POINT T_DIGIT )=> T_POINT ( T_DIGIT )+ ( ( 'e' | 'E' ) ( T_MINUS | T_SUM )? ( T_DIGIT )+ )?
+                    	        {
+                    	        	mT_POINT(); if (state.failed) return ;
+                    	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1162:35: ( T_DIGIT )+
+                    	        	int cnt8 = 0;
+                    	        	do 
+                    	        	{
+                    	        	    int alt8 = 2;
+                    	        	    int LA8_0 = input.LA(1);
+
+                    	        	    if ( ((LA8_0 >= '0' && LA8_0 <= '9')) )
+                    	        	    {
+                    	        	        alt8 = 1;
+                    	        	    }
+
+
+                    	        	    switch (alt8) 
+                    	        		{
+                    	        			case 1 :
+                    	        			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1162:35: T_DIGIT
+                    	        			    {
+                    	        			    	mT_DIGIT(); if (state.failed) return ;
+
+                    	        			    }
+                    	        			    break;
+
+                    	        			default:
+                    	        			    if ( cnt8 >= 1 ) goto loop8;
+                    	        			    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+                    	        		            EarlyExitException eee8 =
+                    	        		                new EarlyExitException(8, input);
+                    	        		            throw eee8;
+                    	        	    }
+                    	        	    cnt8++;
+                    	        	} while (true);
+
+                    	        	loop8:
+                    	        		;	// Stops C# compiler whining that label 'loop8' has no statements
+
+                    	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1162:44: ( ( 'e' | 'E' ) ( T_MINUS | T_SUM )? ( T_DIGIT )+ )?
+                    	        	int alt11 = 2;
+                    	        	int LA11_0 = input.LA(1);
+
+                    	        	if ( (LA11_0 == 'E' || LA11_0 == 'e') )
+                    	        	{
+                    	        	    alt11 = 1;
+                    	        	}
+                    	        	switch (alt11) 
+                    	        	{
+                    	        	    case 1 :
+                    	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1162:45: ( 'e' | 'E' ) ( T_MINUS | T_SUM )? ( T_DIGIT )+
+                    	        	        {
+                    	        	        	if ( input.LA(1) == 'E' || input.LA(1) == 'e' ) 
+                    	        	        	{
+                    	        	        	    input.Consume();
+                    	        	        	state.failed = false;
+                    	        	        	}
+                    	        	        	else 
+                    	        	        	{
+                    	        	        	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+                    	        	        	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	        	        	    Recover(mse);
+                    	        	        	    throw mse;}
+
+                    	        	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1162:55: ( T_MINUS | T_SUM )?
+                    	        	        	int alt9 = 2;
+                    	        	        	int LA9_0 = input.LA(1);
+
+                    	        	        	if ( (LA9_0 == '+' || LA9_0 == '-') )
+                    	        	        	{
+                    	        	        	    alt9 = 1;
+                    	        	        	}
+                    	        	        	switch (alt9) 
+                    	        	        	{
+                    	        	        	    case 1 :
+                    	        	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:
+                    	        	        	        {
+                    	        	        	        	if ( input.LA(1) == '+' || input.LA(1) == '-' ) 
+                    	        	        	        	{
+                    	        	        	        	    input.Consume();
+                    	        	        	        	state.failed = false;
+                    	        	        	        	}
+                    	        	        	        	else 
+                    	        	        	        	{
+                    	        	        	        	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+                    	        	        	        	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	        	        	        	    Recover(mse);
+                    	        	        	        	    throw mse;}
+
+
+                    	        	        	        }
+                    	        	        	        break;
+
+                    	        	        	}
+
+                    	        	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1162:72: ( T_DIGIT )+
+                    	        	        	int cnt10 = 0;
+                    	        	        	do 
+                    	        	        	{
+                    	        	        	    int alt10 = 2;
+                    	        	        	    int LA10_0 = input.LA(1);
+
+                    	        	        	    if ( ((LA10_0 >= '0' && LA10_0 <= '9')) )
+                    	        	        	    {
+                    	        	        	        alt10 = 1;
+                    	        	        	    }
+
+
+                    	        	        	    switch (alt10) 
+                    	        	        		{
+                    	        	        			case 1 :
+                    	        	        			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1162:72: T_DIGIT
+                    	        	        			    {
+                    	        	        			    	mT_DIGIT(); if (state.failed) return ;
+
+                    	        	        			    }
+                    	        	        			    break;
+
+                    	        	        			default:
+                    	        	        			    if ( cnt10 >= 1 ) goto loop10;
+                    	        	        			    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+                    	        	        		            EarlyExitException eee10 =
+                    	        	        		                new EarlyExitException(10, input);
+                    	        	        		            throw eee10;
+                    	        	        	    }
+                    	        	        	    cnt10++;
+                    	        	        	} while (true);
+
+                    	        	        	loop10:
+                    	        	        		;	// Stops C# compiler whining that label 'loop10' has no statements
+
+
+                    	        	        }
+                    	        	        break;
+
+                    	        	}
+
+                    	        	if ( (state.backtracking==0) )
+                    	        	{
+                    	        	  _type=T_FLOATNUMBER;
+                    	        	}
+
+                    	        }
+                    	        break;
+                    	    case 3 :
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1163:6: 
+                    	        {
+                    	        	if ( (state.backtracking==0) )
+                    	        	{
+                    	        	  _type=T_INTNUMBER;
+                    	        	}
+
+                    	        }
+                    	        break;
+
+                    	}
+
+
+                    }
+                    break;
+                case 2 :
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1165:4: T_POINT ( T_POINT | )
+                    {
+                    	mT_POINT(); if (state.failed) return ;
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1166:3: ( T_POINT | )
+                    	int alt13 = 2;
+                    	int LA13_0 = input.LA(1);
+
+                    	if ( (LA13_0 == '.') )
+                    	{
+                    	    alt13 = 1;
+                    	}
+                    	else 
+                    	{
+                    	    alt13 = 2;}
+                    	switch (alt13) 
+                    	{
+                    	    case 1 :
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1167:5: T_POINT
+                    	        {
+                    	        	mT_POINT(); if (state.failed) return ;
+                    	        	if ( (state.backtracking==0) )
+                    	        	{
+                    	        	  _type=T_RANGETO;
+                    	        	}
+
+                    	        }
+                    	        break;
+                    	    case 2 :
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1168:13: 
+                    	        {
+                    	        	if ( (state.backtracking==0) )
+                    	        	{
+                    	        	  _type=T_POINT;
+                    	        	}
+
+                    	        }
+                    	        break;
+
+                    	}
+
+
+                    }
+                    break;
+                case 3 :
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1170:4: T_MINUS
+                    {
+                    	mT_MINUS(); if (state.failed) return ;
+                    	if ( (state.backtracking==0) )
+                    	{
+                    	  _type=T_MINUS;
+                    	}
+
+                    }
+                    break;
+                case 4 :
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1171:4: T_SUM
+                    {
+                    	mT_SUM(); if (state.failed) return ;
+                    	if ( (state.backtracking==0) )
+                    	{
+                    	  _type=T_SUM;
+                    	}
+
+                    }
+                    break;
+
+            }
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "FLOAT_OR_INT_OR_RANGE"
+
+    // $ANTLR start "T_MINUS"
+    public void mT_MINUS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1176:17: ( '-' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1176:19: '-'
+            {
+            	Match('-'); if (state.failed) return ;
+
+            }
+
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_MINUS"
+
+    // $ANTLR start "T_SUM"
+    public void mT_SUM() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1177:16: ( '+' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1177:18: '+'
+            {
+            	Match('+'); if (state.failed) return ;
+
+            }
+
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_SUM"
+
+    // $ANTLR start "T_POINT"
+    public void mT_POINT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1178:17: ( '.' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1178:19: '.'
+            {
+            	Match('.'); if (state.failed) return ;
+
+            }
+
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_POINT"
+
+    // $ANTLR start "T_IDENTIFIER"
+    public void mT_IDENTIFIER() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_IDENTIFIER;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1184:2: ( T_LETTER ( T_LETTER | T_DIGIT )* )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1184:4: T_LETTER ( T_LETTER | T_DIGIT )*
+            {
+            	mT_LETTER(); if (state.failed) return ;
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1184:13: ( T_LETTER | T_DIGIT )*
+            	do 
+            	{
+            	    int alt15 = 2;
+            	    int LA15_0 = input.LA(1);
+
+            	    if ( (LA15_0 == '$' || (LA15_0 >= '0' && LA15_0 <= '9') || (LA15_0 >= 'A' && LA15_0 <= 'Z') || LA15_0 == '_' || (LA15_0 >= 'a' && LA15_0 <= 'z')) )
+            	    {
+            	        alt15 = 1;
+            	    }
+
+
+            	    switch (alt15) 
+            		{
+            			case 1 :
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:
+            			    {
+            			    	if ( input.LA(1) == '$' || (input.LA(1) >= '0' && input.LA(1) <= '9') || (input.LA(1) >= 'A' && input.LA(1) <= 'Z') || input.LA(1) == '_' || (input.LA(1) >= 'a' && input.LA(1) <= 'z') ) 
+            			    	{
+            			    	    input.Consume();
+            			    	state.failed = false;
+            			    	}
+            			    	else 
+            			    	{
+            			    	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+            			    	    MismatchedSetException mse = new MismatchedSetException(null,input);
+            			    	    Recover(mse);
+            			    	    throw mse;}
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop15;
+            	    }
+            	} while (true);
+
+            	loop15:
+            		;	// Stops C# compiler whining that label 'loop15' has no statements
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_IDENTIFIER"
+
+    // $ANTLR start "T_LETTER"
+    public void mT_LETTER() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1192:2: ( '$' | 'A' .. 'Z' | 'a' .. 'z' | '_' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:
+            {
+            	if ( input.LA(1) == '$' || (input.LA(1) >= 'A' && input.LA(1) <= 'Z') || input.LA(1) == '_' || (input.LA(1) >= 'a' && input.LA(1) <= 'z') ) 
+            	{
+            	    input.Consume();
+            	state.failed = false;
+            	}
+            	else 
+            	{
+            	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+            	    MismatchedSetException mse = new MismatchedSetException(null,input);
+            	    Recover(mse);
+            	    throw mse;}
+
+
+            }
+
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_LETTER"
+
+    // $ANTLR start "T_DIGIT"
+    public void mT_DIGIT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1199:8: ( '0' .. '9' )
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1199:10: '0' .. '9'
+            {
+            	MatchRange('0','9'); if (state.failed) return ;
+
+            }
+
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DIGIT"
+
+    override public void mTokens() // throws RecognitionException 
+    {
+        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:8: ( T__117 | T__118 | T__119 | T__120 | T__121 | T__122 | T__123 | T__124 | T__125 | T__126 | T_WS | T_COMMENT | LINE_COMMENT | T_PRIMED | T_STRINGLITERAL | T_ABORT | T_ACTIONS | T_ASSIGNMENT | T_AUTOCONS | T_BAR | T_BOOL | T_CBRL | T_CBRR | T_COLON | T_COMMA | T_CONT | T_CHAR | T_CTRL | T_SYSTEM | T_DO | T_ELSE | T_END | T_EQUAL | T_EXISTS | T_FLOAT | T_FORALL | T_FALSE | T_IF | T_IN | T_INT | T_KILL | T_LIST | T_LPAREN | T_LSQPAREN | T_MAP | T_MAPS | T_METHODS | T_NEW | T_NIL | T_NONDET | T_OBS | T_OD | T_OF | T_PRIO | T_REQUIRES | T_RPAREN | T_RSQPAREN | T_QUANTITY | T_SELF | T_SET | T_SEMICOLON | T_STATIC | T_SKIP | T_THEN | T_TRUE | T_TO | T_TYPES | T_VAR | T_WITH | T_AND | T_BIIMPLIES | T_IMPLIES | T_NOT | T_NOTEQUAL | T_OR | T_ABS | T_DIV | T_GREATER | T_GREATEREQUAL | T_IDIV | T_LESS | T_LESSEQUAL | T_MOD | T_POW | T_PROD | T_DERIV | T_CARD | T_CONC | T_DCONC | T_DIFF | T_DINTER | T_DUNION | T_ELEMS | T_HEAD | T_INDS | T_INTER | T_LEN | T_SEQMOD_MAPOVERRIDE | T_SUBSET | T_TAIL | T_UNION | T_FOLDLR | T_FOLDRL | T_DOM | T_DOMRESBY | T_DOMRESTO | T_RNG | T_RNGRESBY | T_RNGRESTO | T_MERGE | T_MUNION | T_CONSTS | T_INFTY | FLOAT_OR_INT_OR_RANGE | T_IDENTIFIER )
+        int alt16 = 115;
+        alt16 = dfa16.Predict(input);
+        switch (alt16) 
+        {
+            case 1 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:10: T__117
+                {
+                	mT__117(); if (state.failed) return ;
+
+                }
+                break;
+            case 2 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:17: T__118
+                {
+                	mT__118(); if (state.failed) return ;
+
+                }
+                break;
+            case 3 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:24: T__119
+                {
+                	mT__119(); if (state.failed) return ;
+
+                }
+                break;
+            case 4 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:31: T__120
+                {
+                	mT__120(); if (state.failed) return ;
+
+                }
+                break;
+            case 5 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:38: T__121
+                {
+                	mT__121(); if (state.failed) return ;
+
+                }
+                break;
+            case 6 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:45: T__122
+                {
+                	mT__122(); if (state.failed) return ;
+
+                }
+                break;
+            case 7 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:52: T__123
+                {
+                	mT__123(); if (state.failed) return ;
+
+                }
+                break;
+            case 8 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:59: T__124
+                {
+                	mT__124(); if (state.failed) return ;
+
+                }
+                break;
+            case 9 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:66: T__125
+                {
+                	mT__125(); if (state.failed) return ;
+
+                }
+                break;
+            case 10 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:73: T__126
+                {
+                	mT__126(); if (state.failed) return ;
+
+                }
+                break;
+            case 11 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:80: T_WS
+                {
+                	mT_WS(); if (state.failed) return ;
+
+                }
+                break;
+            case 12 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:85: T_COMMENT
+                {
+                	mT_COMMENT(); if (state.failed) return ;
+
+                }
+                break;
+            case 13 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:95: LINE_COMMENT
+                {
+                	mLINE_COMMENT(); if (state.failed) return ;
+
+                }
+                break;
+            case 14 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:108: T_PRIMED
+                {
+                	mT_PRIMED(); if (state.failed) return ;
+
+                }
+                break;
+            case 15 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:117: T_STRINGLITERAL
+                {
+                	mT_STRINGLITERAL(); if (state.failed) return ;
+
+                }
+                break;
+            case 16 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:133: T_ABORT
+                {
+                	mT_ABORT(); if (state.failed) return ;
+
+                }
+                break;
+            case 17 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:141: T_ACTIONS
+                {
+                	mT_ACTIONS(); if (state.failed) return ;
+
+                }
+                break;
+            case 18 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:151: T_ASSIGNMENT
+                {
+                	mT_ASSIGNMENT(); if (state.failed) return ;
+
+                }
+                break;
+            case 19 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:164: T_AUTOCONS
+                {
+                	mT_AUTOCONS(); if (state.failed) return ;
+
+                }
+                break;
+            case 20 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:175: T_BAR
+                {
+                	mT_BAR(); if (state.failed) return ;
+
+                }
+                break;
+            case 21 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:181: T_BOOL
+                {
+                	mT_BOOL(); if (state.failed) return ;
+
+                }
+                break;
+            case 22 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:188: T_CBRL
+                {
+                	mT_CBRL(); if (state.failed) return ;
+
+                }
+                break;
+            case 23 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:195: T_CBRR
+                {
+                	mT_CBRR(); if (state.failed) return ;
+
+                }
+                break;
+            case 24 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:202: T_COLON
+                {
+                	mT_COLON(); if (state.failed) return ;
+
+                }
+                break;
+            case 25 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:210: T_COMMA
+                {
+                	mT_COMMA(); if (state.failed) return ;
+
+                }
+                break;
+            case 26 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:218: T_CONT
+                {
+                	mT_CONT(); if (state.failed) return ;
+
+                }
+                break;
+            case 27 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:225: T_CHAR
+                {
+                	mT_CHAR(); if (state.failed) return ;
+
+                }
+                break;
+            case 28 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:232: T_CTRL
+                {
+                	mT_CTRL(); if (state.failed) return ;
+
+                }
+                break;
+            case 29 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:239: T_SYSTEM
+                {
+                	mT_SYSTEM(); if (state.failed) return ;
+
+                }
+                break;
+            case 30 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:248: T_DO
+                {
+                	mT_DO(); if (state.failed) return ;
+
+                }
+                break;
+            case 31 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:253: T_ELSE
+                {
+                	mT_ELSE(); if (state.failed) return ;
+
+                }
+                break;
+            case 32 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:260: T_END
+                {
+                	mT_END(); if (state.failed) return ;
+
+                }
+                break;
+            case 33 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:266: T_EQUAL
+                {
+                	mT_EQUAL(); if (state.failed) return ;
+
+                }
+                break;
+            case 34 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:274: T_EXISTS
+                {
+                	mT_EXISTS(); if (state.failed) return ;
+
+                }
+                break;
+            case 35 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:283: T_FLOAT
+                {
+                	mT_FLOAT(); if (state.failed) return ;
+
+                }
+                break;
+            case 36 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:291: T_FORALL
+                {
+                	mT_FORALL(); if (state.failed) return ;
+
+                }
+                break;
+            case 37 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:300: T_FALSE
+                {
+                	mT_FALSE(); if (state.failed) return ;
+
+                }
+                break;
+            case 38 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:308: T_IF
+                {
+                	mT_IF(); if (state.failed) return ;
+
+                }
+                break;
+            case 39 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:313: T_IN
+                {
+                	mT_IN(); if (state.failed) return ;
+
+                }
+                break;
+            case 40 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:318: T_INT
+                {
+                	mT_INT(); if (state.failed) return ;
+
+                }
+                break;
+            case 41 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:324: T_KILL
+                {
+                	mT_KILL(); if (state.failed) return ;
+
+                }
+                break;
+            case 42 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:331: T_LIST
+                {
+                	mT_LIST(); if (state.failed) return ;
+
+                }
+                break;
+            case 43 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:338: T_LPAREN
+                {
+                	mT_LPAREN(); if (state.failed) return ;
+
+                }
+                break;
+            case 44 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:347: T_LSQPAREN
+                {
+                	mT_LSQPAREN(); if (state.failed) return ;
+
+                }
+                break;
+            case 45 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:358: T_MAP
+                {
+                	mT_MAP(); if (state.failed) return ;
+
+                }
+                break;
+            case 46 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:364: T_MAPS
+                {
+                	mT_MAPS(); if (state.failed) return ;
+
+                }
+                break;
+            case 47 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:371: T_METHODS
+                {
+                	mT_METHODS(); if (state.failed) return ;
+
+                }
+                break;
+            case 48 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:381: T_NEW
+                {
+                	mT_NEW(); if (state.failed) return ;
+
+                }
+                break;
+            case 49 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:387: T_NIL
+                {
+                	mT_NIL(); if (state.failed) return ;
+
+                }
+                break;
+            case 50 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:393: T_NONDET
+                {
+                	mT_NONDET(); if (state.failed) return ;
+
+                }
+                break;
+            case 51 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:402: T_OBS
+                {
+                	mT_OBS(); if (state.failed) return ;
+
+                }
+                break;
+            case 52 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:408: T_OD
+                {
+                	mT_OD(); if (state.failed) return ;
+
+                }
+                break;
+            case 53 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:413: T_OF
+                {
+                	mT_OF(); if (state.failed) return ;
+
+                }
+                break;
+            case 54 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:418: T_PRIO
+                {
+                	mT_PRIO(); if (state.failed) return ;
+
+                }
+                break;
+            case 55 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:425: T_REQUIRES
+                {
+                	mT_REQUIRES(); if (state.failed) return ;
+
+                }
+                break;
+            case 56 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:436: T_RPAREN
+                {
+                	mT_RPAREN(); if (state.failed) return ;
+
+                }
+                break;
+            case 57 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:445: T_RSQPAREN
+                {
+                	mT_RSQPAREN(); if (state.failed) return ;
+
+                }
+                break;
+            case 58 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:456: T_QUANTITY
+                {
+                	mT_QUANTITY(); if (state.failed) return ;
+
+                }
+                break;
+            case 59 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:467: T_SELF
+                {
+                	mT_SELF(); if (state.failed) return ;
+
+                }
+                break;
+            case 60 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:474: T_SET
+                {
+                	mT_SET(); if (state.failed) return ;
+
+                }
+                break;
+            case 61 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:480: T_SEMICOLON
+                {
+                	mT_SEMICOLON(); if (state.failed) return ;
+
+                }
+                break;
+            case 62 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:492: T_STATIC
+                {
+                	mT_STATIC(); if (state.failed) return ;
+
+                }
+                break;
+            case 63 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:501: T_SKIP
+                {
+                	mT_SKIP(); if (state.failed) return ;
+
+                }
+                break;
+            case 64 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:508: T_THEN
+                {
+                	mT_THEN(); if (state.failed) return ;
+
+                }
+                break;
+            case 65 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:515: T_TRUE
+                {
+                	mT_TRUE(); if (state.failed) return ;
+
+                }
+                break;
+            case 66 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:522: T_TO
+                {
+                	mT_TO(); if (state.failed) return ;
+
+                }
+                break;
+            case 67 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:527: T_TYPES
+                {
+                	mT_TYPES(); if (state.failed) return ;
+
+                }
+                break;
+            case 68 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:535: T_VAR
+                {
+                	mT_VAR(); if (state.failed) return ;
+
+                }
+                break;
+            case 69 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:541: T_WITH
+                {
+                	mT_WITH(); if (state.failed) return ;
+
+                }
+                break;
+            case 70 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:548: T_AND
+                {
+                	mT_AND(); if (state.failed) return ;
+
+                }
+                break;
+            case 71 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:554: T_BIIMPLIES
+                {
+                	mT_BIIMPLIES(); if (state.failed) return ;
+
+                }
+                break;
+            case 72 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:566: T_IMPLIES
+                {
+                	mT_IMPLIES(); if (state.failed) return ;
+
+                }
+                break;
+            case 73 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:576: T_NOT
+                {
+                	mT_NOT(); if (state.failed) return ;
+
+                }
+                break;
+            case 74 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:582: T_NOTEQUAL
+                {
+                	mT_NOTEQUAL(); if (state.failed) return ;
+
+                }
+                break;
+            case 75 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:593: T_OR
+                {
+                	mT_OR(); if (state.failed) return ;
+
+                }
+                break;
+            case 76 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:598: T_ABS
+                {
+                	mT_ABS(); if (state.failed) return ;
+
+                }
+                break;
+            case 77 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:604: T_DIV
+                {
+                	mT_DIV(); if (state.failed) return ;
+
+                }
+                break;
+            case 78 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:610: T_GREATER
+                {
+                	mT_GREATER(); if (state.failed) return ;
+
+                }
+                break;
+            case 79 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:620: T_GREATEREQUAL
+                {
+                	mT_GREATEREQUAL(); if (state.failed) return ;
+
+                }
+                break;
+            case 80 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:635: T_IDIV
+                {
+                	mT_IDIV(); if (state.failed) return ;
+
+                }
+                break;
+            case 81 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:642: T_LESS
+                {
+                	mT_LESS(); if (state.failed) return ;
+
+                }
+                break;
+            case 82 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:649: T_LESSEQUAL
+                {
+                	mT_LESSEQUAL(); if (state.failed) return ;
+
+                }
+                break;
+            case 83 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:661: T_MOD
+                {
+                	mT_MOD(); if (state.failed) return ;
+
+                }
+                break;
+            case 84 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:667: T_POW
+                {
+                	mT_POW(); if (state.failed) return ;
+
+                }
+                break;
+            case 85 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:673: T_PROD
+                {
+                	mT_PROD(); if (state.failed) return ;
+
+                }
+                break;
+            case 86 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:680: T_DERIV
+                {
+                	mT_DERIV(); if (state.failed) return ;
+
+                }
+                break;
+            case 87 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:688: T_CARD
+                {
+                	mT_CARD(); if (state.failed) return ;
+
+                }
+                break;
+            case 88 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:695: T_CONC
+                {
+                	mT_CONC(); if (state.failed) return ;
+
+                }
+                break;
+            case 89 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:702: T_DCONC
+                {
+                	mT_DCONC(); if (state.failed) return ;
+
+                }
+                break;
+            case 90 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:710: T_DIFF
+                {
+                	mT_DIFF(); if (state.failed) return ;
+
+                }
+                break;
+            case 91 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:717: T_DINTER
+                {
+                	mT_DINTER(); if (state.failed) return ;
+
+                }
+                break;
+            case 92 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:726: T_DUNION
+                {
+                	mT_DUNION(); if (state.failed) return ;
+
+                }
+                break;
+            case 93 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:735: T_ELEMS
+                {
+                	mT_ELEMS(); if (state.failed) return ;
+
+                }
+                break;
+            case 94 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:743: T_HEAD
+                {
+                	mT_HEAD(); if (state.failed) return ;
+
+                }
+                break;
+            case 95 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:750: T_INDS
+                {
+                	mT_INDS(); if (state.failed) return ;
+
+                }
+                break;
+            case 96 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:757: T_INTER
+                {
+                	mT_INTER(); if (state.failed) return ;
+
+                }
+                break;
+            case 97 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:765: T_LEN
+                {
+                	mT_LEN(); if (state.failed) return ;
+
+                }
+                break;
+            case 98 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:771: T_SEQMOD_MAPOVERRIDE
+                {
+                	mT_SEQMOD_MAPOVERRIDE(); if (state.failed) return ;
+
+                }
+                break;
+            case 99 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:792: T_SUBSET
+                {
+                	mT_SUBSET(); if (state.failed) return ;
+
+                }
+                break;
+            case 100 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:801: T_TAIL
+                {
+                	mT_TAIL(); if (state.failed) return ;
+
+                }
+                break;
+            case 101 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:808: T_UNION
+                {
+                	mT_UNION(); if (state.failed) return ;
+
+                }
+                break;
+            case 102 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:816: T_FOLDLR
+                {
+                	mT_FOLDLR(); if (state.failed) return ;
+
+                }
+                break;
+            case 103 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:825: T_FOLDRL
+                {
+                	mT_FOLDRL(); if (state.failed) return ;
+
+                }
+                break;
+            case 104 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:834: T_DOM
+                {
+                	mT_DOM(); if (state.failed) return ;
+
+                }
+                break;
+            case 105 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:840: T_DOMRESBY
+                {
+                	mT_DOMRESBY(); if (state.failed) return ;
+
+                }
+                break;
+            case 106 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:851: T_DOMRESTO
+                {
+                	mT_DOMRESTO(); if (state.failed) return ;
+
+                }
+                break;
+            case 107 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:862: T_RNG
+                {
+                	mT_RNG(); if (state.failed) return ;
+
+                }
+                break;
+            case 108 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:868: T_RNGRESBY
+                {
+                	mT_RNGRESBY(); if (state.failed) return ;
+
+                }
+                break;
+            case 109 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:879: T_RNGRESTO
+                {
+                	mT_RNGRESTO(); if (state.failed) return ;
+
+                }
+                break;
+            case 110 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:890: T_MERGE
+                {
+                	mT_MERGE(); if (state.failed) return ;
+
+                }
+                break;
+            case 111 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:898: T_MUNION
+                {
+                	mT_MUNION(); if (state.failed) return ;
+
+                }
+                break;
+            case 112 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:907: T_CONSTS
+                {
+                	mT_CONSTS(); if (state.failed) return ;
+
+                }
+                break;
+            case 113 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:916: T_INFTY
+                {
+                	mT_INFTY(); if (state.failed) return ;
+
+                }
+                break;
+            case 114 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:924: FLOAT_OR_INT_OR_RANGE
+                {
+                	mFLOAT_OR_INT_OR_RANGE(); if (state.failed) return ;
+
+                }
+                break;
+            case 115 :
+                // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1:946: T_IDENTIFIER
+                {
+                	mT_IDENTIFIER(); if (state.failed) return ;
+
+                }
+                break;
+
+        }
+
+    }
+
+    // $ANTLR start "synpred1_ooa"
+    public void synpred1_ooa_fragment() {
+        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1006:9: ( '\"' '\"' )
+        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1006:11: '\"' '\"'
+        {
+        	Match('\"'); if (state.failed) return ;
+        	Match('\"'); if (state.failed) return ;
+
+        }
+    }
+    // $ANTLR end "synpred1_ooa"
+
+    // $ANTLR start "synpred2_ooa"
+    public void synpred2_ooa_fragment() {
+        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1161:5: ( T_POINT T_POINT )
+        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1161:6: T_POINT T_POINT
+        {
+        	mT_POINT(); if (state.failed) return ;
+        	mT_POINT(); if (state.failed) return ;
+
+        }
+    }
+    // $ANTLR end "synpred2_ooa"
+
+    // $ANTLR start "synpred3_ooa"
+    public void synpred3_ooa_fragment() {
+        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1162:6: ( T_POINT T_DIGIT )
+        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:1162:7: T_POINT T_DIGIT
+        {
+        	mT_POINT(); if (state.failed) return ;
+        	mT_DIGIT(); if (state.failed) return ;
+
+        }
+    }
+    // $ANTLR end "synpred3_ooa"
+
+   	public bool synpred2_ooa() 
+   	{
+   	    state.backtracking++;
+   	    int start = input.Mark();
+   	    try 
+   	    {
+   	        synpred2_ooa_fragment(); // can never throw exception
+   	    }
+   	    catch (RecognitionException re) 
+   	    {
+   	        Console.Error.WriteLine("impossible: "+re);
+   	    }
+   	    bool success = !state.failed;
+   	    input.Rewind(start);
+   	    state.backtracking--;
+   	    state.failed = false;
+   	    return success;
+   	}
+   	public bool synpred1_ooa() 
+   	{
+   	    state.backtracking++;
+   	    int start = input.Mark();
+   	    try 
+   	    {
+   	        synpred1_ooa_fragment(); // can never throw exception
+   	    }
+   	    catch (RecognitionException re) 
+   	    {
+   	        Console.Error.WriteLine("impossible: "+re);
+   	    }
+   	    bool success = !state.failed;
+   	    input.Rewind(start);
+   	    state.backtracking--;
+   	    state.failed = false;
+   	    return success;
+   	}
+   	public bool synpred3_ooa() 
+   	{
+   	    state.backtracking++;
+   	    int start = input.Mark();
+   	    try 
+   	    {
+   	        synpred3_ooa_fragment(); // can never throw exception
+   	    }
+   	    catch (RecognitionException re) 
+   	    {
+   	        Console.Error.WriteLine("impossible: "+re);
+   	    }
+   	    bool success = !state.failed;
+   	    input.Rewind(start);
+   	    state.backtracking--;
+   	    state.failed = false;
+   	    return success;
+   	}
+
+
+    protected DFA16 dfa16;
+	private void InitializeCyclicDFAs()
+	{
+	    this.dfa16 = new DFA16(this);
+	}
+
+    const string DFA16_eotS =
+        "\x01\uffff\x01\x30\x01\x32\x01\x2e\x01\uffff\x05\x2e\x01\x4e\x01"+
+        "\uffff\x01\x51\x06\uffff\x02\x2e\x01\x5a\x03\x2e\x01\uffff\x01\x62"+
+        "\x01\x2e\x01\x2d\x03\x2e\x02\uffff\x03\x2e\x01\x7d\x01\x7f\x01\u0081"+
+        "\x02\uffff\x01\x2e\x01\x2d\x01\x2e\x06\uffff\x02\x2e\x01\u0087\x0c"+
+        "\x2e\x01\u009b\x01\u009c\x01\x2e\x01\u009f\x01\x2e\x01\u00a2\x01"+
+        "\x2e\x02\uffff\x01\u00a5\x06\uffff\x07\x2e\x02\uffff\x06\x2e\x02"+
+        "\uffff\x04\x2e\x02\uffff\x04\x2e\x01\u00bd\x01\u00be\x01\u00bf\x04"+
+        "\x2e\x01\u00c4\x01\x2e\x01\u00c6\x02\x2e\x01\u00ca\x08\uffff\x01"+
+        "\u00cb\x01\uffff\x03\x2e\x01\uffff\x01\x2e\x01\u00d0\x02\x2e\x01"+
+        "\u00d3\x07\x2e\x01\u00db\x02\x2e\x01\u00de\x01\u00e0\x01\x2e\x01"+
+        "\x68\x02\uffff\x01\u00e2\x01\u00e3\x01\uffff\x01\u00e4\x01\x2e\x01"+
+        "\uffff\x01\x2e\x02\uffff\x01\x2e\x01\u00e8\x04\x2e\x01\u00ee\x06"+
+        "\x2e\x01\u00f5\x01\u00f6\x02\x2e\x01\u00f9\x01\x2e\x01\u00fb\x01"+
+        "\u00fc\x01\u00fd\x01\u00fe\x03\uffff\x01\x2e\x01\u0100\x02\x2e\x01"+
+        "\uffff\x01\x2e\x01\uffff\x01\u0104\x01\x2e\x03\uffff\x02\x2e\x01"+
+        "\u0108\x01\x2e\x01\uffff\x02\x2e\x01\uffff\x01\u010c\x01\u010d\x04"+
+        "\x2e\x01\u0112\x01\uffff\x01\u0113\x01\x2e\x01\uffff\x01\x2e\x01"+
+        "\uffff\x01\u0116\x03\uffff\x02\x2e\x01\u0119\x01\uffff\x01\u011a"+
+        "\x01\u011b\x01\x2e\x01\u011d\x01\x2e\x01\uffff\x04\x2e\x01\u0123"+
+        "\x01\u0124\x02\uffff\x02\x2e\x01\uffff\x01\x2e\x04\uffff\x01\x2e"+
+        "\x01\uffff\x01\u0129\x01\u012a\x01\x2e\x01\uffff\x01\u012c\x01\x2e"+
+        "\x01\u012e\x01\uffff\x01\u012f\x02\x2e\x02\uffff\x04\x2e\x02\uffff"+
+        "\x01\x2e\x01\u0137\x01\uffff\x02\x2e\x03\uffff\x01\x2e\x01\uffff"+
+        "\x01\u013b\x01\x2e\x01\u013d\x01\x2e\x01\u013f\x02\uffff\x01\x2e"+
+        "\x01\u0141\x02\x2e\x02\uffff\x01\u0144\x01\uffff\x01\u0145\x02\uffff"+
+        "\x02\x2e\x01\u0148\x01\u0149\x01\u014a\x01\u014b\x01\u014c\x01\uffff"+
+        "\x01\u014d\x01\u014e\x01\u014f\x01\uffff\x01\u0150\x01\uffff\x01"+
+        "\u0151\x01\uffff\x01\x2e\x01\uffff\x01\u0153\x01\x2e\x02\uffff\x01"+
+        "\u0155\x01\x2e\x0a\uffff\x01\u0157\x01\uffff\x01\x2e\x01\uffff\x01"+
+        "\u0159\x01\uffff\x01\u015a\x02\uffff";
+    const string DFA16_eofS =
+        "\u015b\uffff";
+    const string DFA16_minS =
+        "\x01\x09\x01\x5b\x01\x7c\x01\x65\x01\uffff\x01\x62\x01\x73\x01"+
+        "\x65\x01\x66\x01\x65\x01\x2d\x01\uffff\x01\x2a\x06\uffff\x01\x61"+
+        "\x01\x6c\x01\x3e\x01\x61\x01\x69\x01\x65\x01\uffff\x01\x5d\x01\x61"+
+        "\x01\x3e\x01\x65\x01\x62\x01\x65\x02\uffff\x01\x68\x01\x61\x01\x69"+
+        "\x01\x2d\x01\x3d\x01\x2a\x02\uffff\x01\x64\x01\x2b\x01\x6e\x06\uffff"+
+        "\x01\x67\x01\x6f\x01\x24\x01\x6f\x02\x74\x01\x64\x02\x61\x01\x70"+
+        "\x01\x61\x01\x73\x01\x6c\x01\x69\x01\x62\x02\x24\x01\x63\x01\x24"+
+        "\x01\x6e\x01\x24\x01\x6e\x02\uffff\x01\x3a\x06\uffff\x01\x61\x02"+
+        "\x72\x01\x6e\x01\x65\x01\x64\x01\x69\x02\uffff\x01\x6f\x01\x72\x02"+
+        "\x6c\x01\x73\x01\x6e\x02\uffff\x01\x70\x01\x72\x01\x64\x01\x6e\x02"+
+        "\uffff\x01\x77\x01\x6c\x01\x74\x01\x73\x03\x24\x01\x71\x01\x67\x01"+
+        "\x65\x01\x75\x01\x24\x01\x70\x01\x24\x01\x72\x01\x74\x01\x3e\x08"+
+        "\uffff\x01\x24\x01\uffff\x02\x69\x01\x6c\x01\uffff\x01\x72\x01\x24"+
+        "\x01\x69\x01\x6f\x01\x24\x02\x6c\x02\x61\x02\x74\x01\x66\x01\x24"+
+        "\x01\x70\x01\x73\x02\x24\x01\x73\x01\x24\x02\uffff\x02\x24\x01\uffff"+
+        "\x01\x24\x01\x74\x01\uffff\x01\x69\x02\uffff\x01\x72\x01\x24\x01"+
+        "\x64\x01\x63\x01\x65\x01\x6d\x01\x24\x01\x73\x02\x61\x01\x73\x01"+
+        "\x6c\x01\x74\x02\x24\x01\x68\x01\x67\x01\x24\x01\x69\x04\x24\x03"+
+        "\uffff\x01\x75\x01\x24\x01\x6e\x01\x65\x01\uffff\x01\x65\x01\uffff"+
+        "\x01\x24\x01\x68\x03\uffff\x01\x6f\x01\x6e\x01\x24\x01\x74\x01\uffff"+
+        "\x01\x6f\x01\x63\x01\uffff\x02\x24\x01\x63\x01\x64\x01\x69\x01\x65"+
+        "\x01\x24\x01\uffff\x01\x24\x01\x65\x01\uffff\x01\x72\x01\uffff\x01"+
+        "\x24\x03\uffff\x01\x65\x01\x6f\x01\x24\x01\uffff\x02\x24\x01\x74"+
+        "\x01\x24\x01\x73\x01\uffff\x02\x74\x01\x6c\x01\x65\x02\x24\x02\uffff"+
+        "\x01\x6f\x01\x65\x01\uffff\x01\x6f\x04\uffff\x01\x69\x01\uffff\x02"+
+        "\x24\x01\x73\x01\uffff\x01\x24\x01\x6e\x01\x24\x01\uffff\x01\x24"+
+        "\x01\x6e\x01\x6f\x02\uffff\x01\x65\x01\x79\x01\x63\x01\x6d\x02\uffff"+
+        "\x01\x74\x01\x24\x01\uffff\x01\x72\x01\x6e\x03\uffff\x01\x73\x01"+
+        "\uffff\x01\x24\x01\x73\x01\x24\x01\x6c\x01\x24\x02\uffff\x01\x64"+
+        "\x01\x24\x01\x6e\x01\x72\x02\uffff\x01\x24\x01\uffff\x01\x24\x02"+
+        "\uffff\x01\x73\x01\x6e\x05\x24\x01\uffff\x03\x24\x01\uffff\x01\x24"+
+        "\x01\uffff\x01\x24\x01\uffff\x01\x73\x01\uffff\x01\x24\x01\x65\x02"+
+        "\uffff\x01\x24\x01\x73\x0a\uffff\x01\x24\x01\uffff\x01\x73\x01\uffff"+
+        "\x01\x24\x01\uffff\x01\x24\x02\uffff";
+    const string DFA16_maxS =
+        "\x01\x7d\x01\x5b\x01\x7c\x01\x6f\x01\uffff\x01\x75\x01\x76\x01"+
+        "\x79\x01\x6e\x01\x75\x01\x3e\x01\uffff\x01\x2f\x06\uffff\x01\x74"+
+        "\x01\x78\x01\x3e\x01\x6f\x02\x69\x01\uffff\x01\x5d\x01\x75\x01\x69"+
+        "\x01\x6f\x01\x72\x01\x6e\x02\uffff\x01\x79\x01\x61\x01\x69\x01\x3e"+
+        "\x01\x3d\x01\x2a\x02\uffff\x01\x64\x01\x69\x01\x6e\x06\uffff\x01"+
+        "\x67\x01\x6f\x01\x7a\x01\x73\x02\x74\x01\x64\x02\x61\x01\x70\x01"+
+        "\x65\x01\x73\x01\x74\x01\x69\x01\x62\x02\x7a\x01\x63\x01\x7a\x01"+
+        "\x76\x01\x7a\x01\x6e\x02\uffff\x01\x3a\x06\uffff\x01\x61\x02\x72"+
+        "\x01\x6e\x01\x73\x01\x64\x01\x69\x02\uffff\x01\x6f\x01\x72\x02\x6c"+
+        "\x01\x73\x01\x6e\x02\uffff\x01\x70\x01\x74\x01\x64\x01\x6e\x02\uffff"+
+        "\x01\x77\x01\x6c\x01\x74\x01\x73\x03\x7a\x01\x71\x01\x67\x01\x65"+
+        "\x01\x75\x01\x7a\x01\x70\x01\x7a\x01\x72\x01\x74\x01\x3e\x08\uffff"+
+        "\x01\x7a\x01\uffff\x02\x69\x01\x6c\x01\uffff\x01\x72\x01\x7a\x01"+
+        "\x69\x01\x6f\x01\x7a\x02\x6c\x02\x61\x02\x74\x01\x66\x01\x7a\x01"+
+        "\x70\x01\x73\x02\x7a\x01\x73\x01\x7a\x02\uffff\x02\x7a\x01\uffff"+
+        "\x01\x7a\x01\x74\x01\uffff\x01\x69\x02\uffff\x01\x72\x01\x7a\x01"+
+        "\x64\x01\x73\x01\x65\x01\x6d\x01\x7a\x01\x73\x02\x61\x01\x73\x01"+
+        "\x6c\x01\x74\x02\x7a\x01\x68\x01\x67\x01\x7a\x01\x69\x04\x7a\x03"+
+        "\uffff\x01\x75\x01\x7a\x01\x6e\x01\x65\x01\uffff\x01\x65\x01\uffff"+
+        "\x01\x7a\x01\x68\x03\uffff\x01\x6f\x01\x6e\x01\x7a\x01\x74\x01\uffff"+
+        "\x01\x6f\x01\x63\x01\uffff\x02\x7a\x01\x63\x01\x64\x01\x69\x01\x65"+
+        "\x01\x7a\x01\uffff\x01\x7a\x01\x65\x01\uffff\x01\x72\x01\uffff\x01"+
+        "\x7a\x03\uffff\x01\x65\x01\x6f\x01\x7a\x01\uffff\x02\x7a\x01\x74"+
+        "\x01\x7a\x01\x73\x01\uffff\x02\x74\x01\x6c\x01\x65\x02\x7a\x02\uffff"+
+        "\x01\x6f\x01\x65\x01\uffff\x01\x6f\x04\uffff\x01\x69\x01\uffff\x02"+
+        "\x7a\x01\x73\x01\uffff\x01\x7a\x01\x6e\x01\x7a\x01\uffff\x01\x7a"+
+        "\x01\x6e\x01\x6f\x02\uffff\x01\x65\x01\x79\x01\x63\x01\x6d\x02\uffff"+
+        "\x01\x74\x01\x7a\x01\uffff\x01\x72\x01\x6e\x03\uffff\x01\x73\x01"+
+        "\uffff\x01\x7a\x01\x73\x01\x7a\x01\x6c\x01\x7a\x02\uffff\x01\x64"+
+        "\x01\x7a\x01\x6e\x01\x72\x02\uffff\x01\x7a\x01\uffff\x01\x7a\x02"+
+        "\uffff\x01\x73\x01\x6e\x05\x7a\x01\uffff\x03\x7a\x01\uffff\x01\x7a"+
+        "\x01\uffff\x01\x7a\x01\uffff\x01\x73\x01\uffff\x01\x7a\x01\x65\x02"+
+        "\uffff\x01\x7a\x01\x73\x0a\uffff\x01\x7a\x01\uffff\x01\x73\x01\uffff"+
+        "\x01\x7a\x01\uffff\x01\x7a\x02\uffff";
+    const string DFA16_acceptS =
+        "\x04\uffff\x01\x04\x06\uffff\x01\x0b\x01\uffff\x01\x0d\x01\x0e"+
+        "\x01\x0f\x01\x16\x01\x17\x01\x19\x06\uffff\x01\x2b\x06\uffff\x01"+
+        "\x38\x01\x3d\x06\uffff\x01\x58\x01\x5a\x03\uffff\x01\x72\x01\x73"+
+        "\x01\x01\x01\x14\x01\x02\x01\x39\x16\uffff\x01\x0a\x01\x12\x01\uffff"+
+        "\x01\x67\x01\x6c\x01\x18\x01\x0c\x01\x36\x01\x4d\x07\uffff\x01\x48"+
+        "\x01\x21\x06\uffff\x01\x32\x01\x2c\x04\uffff\x01\x2e\x01\x71\x11"+
+        "\uffff\x01\x4a\x01\x69\x01\x6a\x01\x51\x01\x4f\x01\x4e\x01\x54\x01"+
+        "\x55\x01\uffff\x01\x62\x03\uffff\x01\x05\x13\uffff\x01\x27\x01\x26"+
+        "\x02\uffff\x01\x1e\x02\uffff\x01\x56\x01\uffff\x01\x66\x01\x6d\x17"+
+        "\uffff\x01\x34\x01\x35\x01\x4b\x04\uffff\x01\x42\x01\uffff\x01\x64"+
+        "\x02\uffff\x01\x47\x01\x52\x01\x5e\x04\uffff\x01\x4c\x02\uffff\x01"+
+        "\x46\x07\uffff\x01\x3c\x02\uffff\x01\x08\x01\uffff\x01\x28\x01\uffff"+
+        "\x01\x09\x01\x68\x01\x50\x03\uffff\x01\x1c\x05\uffff\x01\x20\x06"+
+        "\uffff\x01\x61\x01\x2d\x02\uffff\x01\x53\x01\uffff\x01\x30\x01\x31"+
+        "\x01\x49\x01\x33\x01\uffff\x01\x6b\x03\uffff\x01\x44\x03\uffff\x01"+
+        "\x15\x03\uffff\x01\x06\x01\x1a\x04\uffff\x01\x3b\x01\x3f\x02\uffff"+
+        "\x01\x5f\x02\uffff\x01\x1b\x01\x57\x01\x59\x01\uffff\x01\x1f\x05"+
+        "\uffff\x01\x29\x01\x2a\x04\uffff\x01\x40\x01\x41\x01\uffff\x01\x45"+
+        "\x01\uffff\x01\x03\x01\x10\x07\uffff\x01\x60\x03\uffff\x01\x5d\x01"+
+        "\uffff\x01\x23\x01\uffff\x01\x25\x01\uffff\x01\x6e\x02\uffff\x01"+
+        "\x43\x01\x65\x02\uffff\x01\x3a\x01\x07\x01\x3e\x01\x1d\x01\x63\x01"+
+        "\x5b\x01\x5c\x01\x70\x01\x22\x01\x24\x01\uffff\x01\x6f\x01\uffff"+
+        "\x01\x11\x01\uffff\x01\x2f\x01\uffff\x01\x13\x01\x37";
+    const string DFA16_specialS =
+        "\u015b\uffff}>";
+    static readonly string[] DFA16_transitionS = {
+            "\x02\x0b\x01\uffff\x02\x0b\x12\uffff\x01\x0b\x01\uffff\x01"+
+            "\x0f\x01\x0d\x01\x2e\x01\uffff\x01\x04\x01\x0e\x01\x19\x01\x20"+
+            "\x01\x27\x01\x2b\x01\x12\x01\x1c\x01\x2d\x01\x0c\x0a\x2d\x01"+
+            "\x0a\x01\x21\x01\x25\x01\x15\x01\x26\x02\uffff\x1a\x2e\x01\x1a"+
+            "\x01\x29\x01\x02\x01\x28\x01\x2e\x01\uffff\x01\x05\x01\x03\x01"+
+            "\x13\x01\x09\x01\x14\x01\x16\x01\x2e\x01\x2a\x01\x08\x01\x2e"+
+            "\x01\x17\x01\x18\x01\x1b\x01\x1d\x01\x1e\x01\x2e\x01\x06\x01"+
+            "\x1f\x01\x07\x01\x22\x01\x2c\x01\x23\x01\x24\x03\x2e\x01\x10"+
+            "\x01\x01\x01\x11",
+            "\x01\x2f",
+            "\x01\x31",
+            "\x01\x33\x09\uffff\x01\x34",
+            "",
+            "\x01\x36\x01\x37\x0a\uffff\x01\x39\x04\uffff\x01\x35\x01\uffff"+
+            "\x01\x38",
+            "\x01\x3c\x01\uffff\x01\x3b\x01\x3a",
+            "\x01\x3f\x05\uffff\x01\x40\x08\uffff\x01\x3d\x01\x41\x03\uffff"+
+            "\x01\x3e",
+            "\x01\x43\x07\uffff\x01\x42",
+            "\x01\x44\x03\uffff\x01\x46\x05\uffff\x01\x45\x04\uffff\x01"+
+            "\x47\x01\x48",
+            "\x01\x4d\x0c\uffff\x01\x49\x01\uffff\x01\x4c\x01\x4a\x01\x4b",
+            "",
+            "\x01\x4f\x04\uffff\x01\x50",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "\x01\x54\x06\uffff\x01\x52\x06\uffff\x01\x55\x04\uffff\x01"+
+            "\x53",
+            "\x01\x56\x01\uffff\x01\x57\x09\uffff\x01\x58",
+            "\x01\x59",
+            "\x01\x5d\x0a\uffff\x01\x5b\x02\uffff\x01\x5c",
+            "\x01\x5e",
+            "\x01\x60\x03\uffff\x01\x5f",
+            "",
+            "\x01\x61",
+            "\x01\x63\x03\uffff\x01\x64\x09\uffff\x01\x65\x05\uffff\x01"+
+            "\x66",
+            "\x01\x67\x2a\uffff\x01\x68",
+            "\x01\x69\x03\uffff\x01\x6a\x05\uffff\x01\x6b",
+            "\x01\x6c\x01\uffff\x01\x6d\x01\uffff\x01\x6e\x0b\uffff\x01"+
+            "\x6f",
+            "\x01\x70\x08\uffff\x01\x71",
+            "",
+            "",
+            "\x01\x72\x03\uffff\x01\x76\x02\uffff\x01\x74\x02\uffff\x01"+
+            "\x73\x06\uffff\x01\x75",
+            "\x01\x77",
+            "\x01\x78",
+            "\x01\x7b\x0c\uffff\x01\x7c\x02\uffff\x01\x79\x01\x7a",
+            "\x01\x7e",
+            "\x01\u0080",
+            "",
+            "",
+            "\x01\u0082",
+            "\x01\u0083\x3d\uffff\x01\x68",
+            "\x01\u0084",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "\x01\u0085",
+            "\x01\u0086",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u0088\x03\uffff\x01\u0089",
+            "\x01\u008a",
+            "\x01\u008b",
+            "\x01\u008c",
+            "\x01\u008d",
+            "\x01\u008e",
+            "\x01\u008f",
+            "\x01\u0091\x03\uffff\x01\u0090",
+            "\x01\u0092",
+            "\x01\u0093\x07\uffff\x01\u0094",
+            "\x01\u0095",
+            "\x01\u0096",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x02\x2e\x01\u0097\x01\u0099\x01\x2e\x01\u009a"+
+            "\x0d\x2e\x01\u0098\x06\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u009d",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x0c\x2e\x01\u009e\x0d\x2e",
+            "\x01\u00a1\x07\uffff\x01\u00a0",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00a3",
+            "",
+            "",
+            "\x01\u00a4",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "\x01\u00a6",
+            "\x01\u00a7",
+            "\x01\u00a8",
+            "\x01\u00a9",
+            "\x01\u00ab\x0d\uffff\x01\u00aa",
+            "\x01\u00ac",
+            "\x01\u00ad",
+            "",
+            "",
+            "\x01\u00ae",
+            "\x01\u00af",
+            "\x01\u00b0",
+            "\x01\u00b1",
+            "\x01\u00b2",
+            "\x01\u00b3",
+            "",
+            "",
+            "\x01\u00b4",
+            "\x01\u00b6\x01\uffff\x01\u00b5",
+            "\x01\u00b7",
+            "\x01\u00b8",
+            "",
+            "",
+            "\x01\u00b9",
+            "\x01\u00ba",
+            "\x01\u00bb",
+            "\x01\u00bc",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00c0",
+            "\x01\u00c1",
+            "\x01\u00c2",
+            "\x01\u00c3",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00c5",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00c7",
+            "\x01\u00c8",
+            "\x01\u00c9",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\u00cc",
+            "\x01\u00cd",
+            "\x01\u00ce",
+            "",
+            "\x01\u00cf",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00d1",
+            "\x01\u00d2",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00d4",
+            "\x01\u00d5",
+            "\x01\u00d6",
+            "\x01\u00d7",
+            "\x01\u00d8",
+            "\x01\u00d9",
+            "\x01\u00da",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00dc",
+            "\x01\u00dd",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x04\x2e\x01\u00df\x15\x2e",
+            "\x01\u00e1",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00e5",
+            "",
+            "\x01\u00e6",
+            "",
+            "",
+            "\x01\u00e7",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00e9",
+            "\x01\u00ea\x0f\uffff\x01\u00eb",
+            "\x01\u00ec",
+            "\x01\u00ed",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00ef",
+            "\x01\u00f0",
+            "\x01\u00f1",
+            "\x01\u00f2",
+            "\x01\u00f3",
+            "\x01\u00f4",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00f7",
+            "\x01\u00f8",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00fa",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "",
+            "",
+            "\x01\u00ff",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u0101",
+            "\x01\u0102",
+            "",
+            "\x01\u0103",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u0105",
+            "",
+            "",
+            "",
+            "\x01\u0106",
+            "\x01\u0107",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u0109",
+            "",
+            "\x01\u010a",
+            "\x01\u010b",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u010e",
+            "\x01\u010f",
+            "\x01\u0110",
+            "\x01\u0111",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u0114",
+            "",
+            "\x01\u0115",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "",
+            "",
+            "\x01\u0117",
+            "\x01\u0118",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u011c",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u011e",
+            "",
+            "\x01\u011f",
+            "\x01\u0120",
+            "\x01\u0121",
+            "\x01\u0122",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "",
+            "\x01\u0125",
+            "\x01\u0126",
+            "",
+            "\x01\u0127",
+            "",
+            "",
+            "",
+            "",
+            "\x01\u0128",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u012b",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u012d",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u0130",
+            "\x01\u0131",
+            "",
+            "",
+            "\x01\u0132",
+            "\x01\u0133",
+            "\x01\u0134",
+            "\x01\u0135",
+            "",
+            "",
+            "\x01\u0136",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\u0138",
+            "\x01\u0139",
+            "",
+            "",
+            "",
+            "\x01\u013a",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u013c",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u013e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "",
+            "\x01\u0140",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u0142",
+            "\x01\u0143",
+            "",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "",
+            "\x01\u0146",
+            "\x01\u0147",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\u0152",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u0154",
+            "",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u0156",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\u0158",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA16_eot = DFA.UnpackEncodedString(DFA16_eotS);
+    static readonly short[] DFA16_eof = DFA.UnpackEncodedString(DFA16_eofS);
+    static readonly char[] DFA16_min = DFA.UnpackEncodedStringToUnsignedChars(DFA16_minS);
+    static readonly char[] DFA16_max = DFA.UnpackEncodedStringToUnsignedChars(DFA16_maxS);
+    static readonly short[] DFA16_accept = DFA.UnpackEncodedString(DFA16_acceptS);
+    static readonly short[] DFA16_special = DFA.UnpackEncodedString(DFA16_specialS);
+    static readonly short[][] DFA16_transition = DFA.UnpackEncodedStringArray(DFA16_transitionS);
+
+    protected class DFA16 : DFA
+    {
+        public DFA16(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 16;
+            this.eot = DFA16_eot;
+            this.eof = DFA16_eof;
+            this.min = DFA16_min;
+            this.max = DFA16_max;
+            this.accept = DFA16_accept;
+            this.special = DFA16_special;
+            this.transition = DFA16_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "1:1: Tokens : ( T__117 | T__118 | T__119 | T__120 | T__121 | T__122 | T__123 | T__124 | T__125 | T__126 | T_WS | T_COMMENT | LINE_COMMENT | T_PRIMED | T_STRINGLITERAL | T_ABORT | T_ACTIONS | T_ASSIGNMENT | T_AUTOCONS | T_BAR | T_BOOL | T_CBRL | T_CBRR | T_COLON | T_COMMA | T_CONT | T_CHAR | T_CTRL | T_SYSTEM | T_DO | T_ELSE | T_END | T_EQUAL | T_EXISTS | T_FLOAT | T_FORALL | T_FALSE | T_IF | T_IN | T_INT | T_KILL | T_LIST | T_LPAREN | T_LSQPAREN | T_MAP | T_MAPS | T_METHODS | T_NEW | T_NIL | T_NONDET | T_OBS | T_OD | T_OF | T_PRIO | T_REQUIRES | T_RPAREN | T_RSQPAREN | T_QUANTITY | T_SELF | T_SET | T_SEMICOLON | T_STATIC | T_SKIP | T_THEN | T_TRUE | T_TO | T_TYPES | T_VAR | T_WITH | T_AND | T_BIIMPLIES | T_IMPLIES | T_NOT | T_NOTEQUAL | T_OR | T_ABS | T_DIV | T_GREATER | T_GREATEREQUAL | T_IDIV | T_LESS | T_LESSEQUAL | T_MOD | T_POW | T_PROD | T_DERIV | T_CARD | T_CONC | T_DCONC | T_DIFF | T_DINTER | T_DUNION | T_ELEMS | T_HEAD | T_INDS | T_INTER | T_LEN | T_SEQMOD_MAPOVERRIDE | T_SUBSET | T_TAIL | T_UNION | T_FOLDLR | T_FOLDRL | T_DOM | T_DOMRESBY | T_DOMRESTO | T_RNG | T_RNGRESBY | T_RNGRESTO | T_MERGE | T_MUNION | T_CONSTS | T_INFTY | FLOAT_OR_INT_OR_RANGE | T_IDENTIFIER );"; }
+        }
+
+    }
+
+ 
+    
+}
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/output/ooaParser.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/output/ooaParser.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/output/ooaParser.cs	(revision 3)
@@ -0,0 +1,13024 @@
+// $ANTLR 3.2 Sep 23, 2009 12:02:23 C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g 2011-02-10 11:21:04
+
+#define ANTLR_DEBUG
+// The variable 'variable' is assigned but its value is never used.
+#pragma warning disable 168, 219
+// Unreachable code detected.
+#pragma warning disable 162
+
+
+/*
+    Ulysses OO-Action System Parser
+
+    Copyright Willibald Krenn 2009
+
+ */
+
+
+using System;
+using Antlr.Runtime;
+using IList 		= System.Collections.IList;
+using ArrayList 	= System.Collections.ArrayList;
+using Stack 		= Antlr.Runtime.Collections.StackList;
+
+
+using Antlr.Runtime.Debug;
+using IOException = System.IO.IOException;
+namespace  TUG.Mogentes 
+{
+public partial class ooaParser : DebugParser
+{
+    public static readonly string[] tokenNames = new string[] 
+	{
+        "<invalid>", 
+		"<EOR>", 
+		"<DOWN>", 
+		"<UP>", 
+		"T_CONSTS", 
+		"T_TYPES", 
+		"T_SYSTEM", 
+		"T_SEMICOLON", 
+		"T_IDENTIFIER", 
+		"T_EQUAL", 
+		"T_PRIO", 
+		"T_NONDET", 
+		"T_LPAREN", 
+		"T_RPAREN", 
+		"T_LIST", 
+		"T_LSQPAREN", 
+		"T_INTNUMBER", 
+		"T_RSQPAREN", 
+		"T_OF", 
+		"T_COMMA", 
+		"T_MAP", 
+		"T_TO", 
+		"T_QUANTITY", 
+		"T_MINUS", 
+		"T_INFTY", 
+		"T_BOOL", 
+		"T_INT", 
+		"T_RANGETO", 
+		"T_FLOAT", 
+		"T_FLOATNUMBER", 
+		"T_CHAR", 
+		"T_CBRL", 
+		"T_CBRR", 
+		"T_AUTOCONS", 
+		"T_VAR", 
+		"T_METHODS", 
+		"T_ACTIONS", 
+		"T_DO", 
+		"T_OD", 
+		"T_STATIC", 
+		"T_OBS", 
+		"T_CTRL", 
+		"T_COLON", 
+		"T_END", 
+		"T_CONT", 
+		"T_REQUIRES", 
+		"T_DERIV", 
+		"T_SUM", 
+		"T_DIFF", 
+		"T_PROD", 
+		"T_FOLDLR", 
+		"T_FOLDRL", 
+		"T_SKIP", 
+		"T_ABORT", 
+		"T_KILL", 
+		"T_SELF", 
+		"T_ASSIGNMENT", 
+		"T_WITH", 
+		"T_BIIMPLIES", 
+		"T_GREATER", 
+		"T_GREATEREQUAL", 
+		"T_LESS", 
+		"T_LESSEQUAL", 
+		"T_NOTEQUAL", 
+		"T_IMPLIES", 
+		"T_IN", 
+		"T_SET", 
+		"T_NOT", 
+		"T_SUBSET", 
+		"T_OR", 
+		"T_DIV", 
+		"T_IDIV", 
+		"T_MOD", 
+		"T_UNION", 
+		"T_INTER", 
+		"T_AND", 
+		"T_POW", 
+		"T_CONC", 
+		"T_DOMRESBY", 
+		"T_DOMRESTO", 
+		"T_RNGRESBY", 
+		"T_RNGRESTO", 
+		"T_MUNION", 
+		"T_SEQMOD_MAPOVERRIDE", 
+		"T_POINT", 
+		"T_IF", 
+		"T_THEN", 
+		"T_ELSE", 
+		"T_FORALL", 
+		"T_EXISTS", 
+		"T_TRUE", 
+		"T_FALSE", 
+		"T_NIL", 
+		"T_STRINGLITERAL", 
+		"T_NEW", 
+		"T_BAR", 
+		"T_MAPS", 
+		"T_PRIMED", 
+		"T_ABS", 
+		"T_CARD", 
+		"T_DCONC", 
+		"T_DINTER", 
+		"T_DUNION", 
+		"T_ELEMS", 
+		"T_HEAD", 
+		"T_INDS", 
+		"T_LEN", 
+		"T_TAIL", 
+		"T_DOM", 
+		"T_RNG", 
+		"T_MERGE", 
+		"T_WS", 
+		"T_COMMENT", 
+		"LINE_COMMENT", 
+		"T_DIGIT", 
+		"FLOAT_OR_INT_OR_RANGE", 
+		"T_LETTER", 
+		"'|['", 
+		"']|'", 
+		"'begin'", 
+		"'&'", 
+		"'as'", 
+		"'qval'", 
+		"'steady'", 
+		"'inc'", 
+		"'dec'", 
+		"'::'"
+    };
+
+    public const int T_FLOATNUMBER = 29;
+    public const int T_SYSTEM = 6;
+    public const int T_ELSE = 87;
+    public const int T_LPAREN = 12;
+    public const int T_DUNION = 102;
+    public const int T_BOOL = 25;
+    public const int T_METHODS = 35;
+    public const int T_INDS = 105;
+    public const int T_OR = 69;
+    public const int EOF = -1;
+    public const int T_OD = 38;
+    public const int T_AND = 75;
+    public const int T_OF = 18;
+    public const int T_STRINGLITERAL = 93;
+    public const int T_SET = 66;
+    public const int T_SKIP = 52;
+    public const int T_WITH = 57;
+    public const int T_DOM = 108;
+    public const int T_WS = 111;
+    public const int T_VAR = 34;
+    public const int T_SUM = 47;
+    public const int T_REQUIRES = 45;
+    public const int T_DINTER = 101;
+    public const int T_HEAD = 104;
+    public const int T_AUTOCONS = 33;
+    public const int T_END = 43;
+    public const int T_TRUE = 90;
+    public const int T_LSQPAREN = 15;
+    public const int T_PRIMED = 97;
+    public const int T_MAPS = 96;
+    public const int T_NIL = 92;
+    public const int T_INFTY = 24;
+    public const int T_IF = 85;
+    public const int LINE_COMMENT = 113;
+    public const int T_THEN = 86;
+    public const int T_FLOAT = 28;
+    public const int T_TAIL = 107;
+    public const int T_SELF = 55;
+    public const int T_MERGE = 110;
+    public const int T_DIFF = 48;
+    public const int T_FOLDRL = 51;
+    public const int T_QUANTITY = 22;
+    public const int T_IN = 65;
+    public const int T_MUNION = 82;
+    public const int T__126 = 126;
+    public const int T__125 = 125;
+    public const int T_INTER = 74;
+    public const int T_SEMICOLON = 7;
+    public const int T_FOLDLR = 50;
+    public const int T_CARD = 99;
+    public const int T_FALSE = 91;
+    public const int T_CONT = 44;
+    public const int T_SUBSET = 68;
+    public const int T_COMMA = 19;
+    public const int T_RANGETO = 27;
+    public const int T_MINUS = 23;
+    public const int T_CONC = 77;
+    public const int T_IDIV = 71;
+    public const int T_FORALL = 88;
+    public const int T_DERIV = 46;
+    public const int T_CONSTS = 4;
+    public const int T_TYPES = 5;
+    public const int T_GREATEREQUAL = 60;
+    public const int T__118 = 118;
+    public const int T_RNG = 109;
+    public const int T__119 = 119;
+    public const int T_MOD = 72;
+    public const int T__117 = 117;
+    public const int T_SEQMOD_MAPOVERRIDE = 83;
+    public const int T__124 = 124;
+    public const int T__123 = 123;
+    public const int T_ELEMS = 103;
+    public const int T__122 = 122;
+    public const int T__121 = 121;
+    public const int T_IMPLIES = 64;
+    public const int T__120 = 120;
+    public const int T_EXISTS = 89;
+    public const int T_POW = 76;
+    public const int T_COMMENT = 112;
+    public const int T_RPAREN = 13;
+    public const int T_PRIO = 10;
+    public const int T_RNGRESBY = 80;
+    public const int T_ABS = 98;
+    public const int T_DIV = 70;
+    public const int T_LIST = 14;
+    public const int T_CBRL = 31;
+    public const int T_DCONC = 100;
+    public const int T_ABORT = 53;
+    public const int T_CHAR = 30;
+    public const int T_POINT = 84;
+    public const int T_STATIC = 39;
+    public const int T_CBRR = 32;
+    public const int T_INT = 26;
+    public const int T_COLON = 42;
+    public const int T_PROD = 49;
+    public const int T_ACTIONS = 36;
+    public const int T_DIGIT = 114;
+    public const int T_LESS = 61;
+    public const int T_BAR = 95;
+    public const int T_TO = 21;
+    public const int T_NONDET = 11;
+    public const int T_DOMRESBY = 78;
+    public const int T_DOMRESTO = 79;
+    public const int T_EQUAL = 9;
+    public const int T_GREATER = 59;
+    public const int T_KILL = 54;
+    public const int T_RNGRESTO = 81;
+    public const int T_RSQPAREN = 17;
+    public const int T_NEW = 94;
+    public const int T_INTNUMBER = 16;
+    public const int T_UNION = 73;
+    public const int T_OBS = 40;
+    public const int T_BIIMPLIES = 58;
+    public const int T_NOTEQUAL = 63;
+    public const int T_IDENTIFIER = 8;
+    public const int T_DO = 37;
+    public const int FLOAT_OR_INT_OR_RANGE = 115;
+    public const int T_LEN = 106;
+    public const int T_NOT = 67;
+    public const int T_ASSIGNMENT = 56;
+    public const int T_LETTER = 116;
+    public const int T_MAP = 20;
+    public const int T_LESSEQUAL = 62;
+    public const int T_CTRL = 41;
+
+    // delegates
+    // delegators
+
+    public static readonly string[] ruleNames = new string[] {
+        "invalidRule", "statement", "op_un_set_list", "actionBodyParallel", 
+        "atomExpression", "initializedListType", "anonymousAction", "asTypeCompositionParallel", 
+        "actionBodySequential", "listComprehension", "methodCallParams", 
+        "constant", "qvalExpression", "namedTypeList", "map", "namedConst", 
+        "initializedSetType", "qualifiedIdentifier", "op_un", "actionBlockParen", 
+        "ooActionSystems", "blockvarlist", "setComprehension", "binoperator", 
+        "asTypeCompositionBlockParen", "localActionVars", "simpleType", 
+        "namedAction", "identifierExpression", "asTypeComposition", "expression", 
+        "reference", "namedActionList", "ooActionSystem", "actionBlockParallel", 
+        "complexType", "actionBody", "attrList", "initializedComplexType", 
+        "continuousActionBody", "methodParameterList", "methodList", "qualConstraint", 
+        "namedConstList", "actionBlock", "actionBlockSequential", "initializedSet", 
+        "accessExpression", "asTypeCompositionSequential", "method", "namedType", 
+        "actionBodyParen", "discreteActionBody", "quantifierExpression", 
+        "attr", "op_un_map", "blockvar", "anonymousOrNamedAction", "qualConstraintList"
+    };
+     
+        private int ruleLevel = 0;
+        public int RuleLevel {
+    	get { return ruleLevel; }
+        }
+        public void IncRuleLevel() { ruleLevel++; }
+        public void DecRuleLevel() { ruleLevel--; }
+        public ooaParser(ITokenStream input)
+            : this(input, DebugEventSocketProxy.DEFAULT_DEBUGGER_PORT, new RecognizerSharedState()) {
+        }
+
+        public ooaParser(ITokenStream input, int port, RecognizerSharedState state)
+            : base(input, state) {
+            DebugEventSocketProxy dbg = new DebugEventSocketProxy(this, port, null);DebugListener = dbg;
+            try
+            {
+                dbg.Handshake();
+            }
+            catch (IOException ioe)
+            {
+                ReportError(ioe);
+            }
+            InitializeCyclicDFAs(dbg);
+
+        }
+    public ooaParser(ITokenStream input, IDebugEventListener dbg)
+        : base(input, dbg, new RecognizerSharedState()) {
+        InitializeCyclicDFAs(dbg);
+
+    }
+    protected bool EvalPredicate(bool result, string predicate) 
+    {
+        dbg.SemanticPredicate(result, predicate);
+        return result;
+    }
+
+
+    override public string[] TokenNames {
+		get { return ooaParser.tokenNames; }
+    }
+
+    override public string GrammarFileName {
+		get { return "C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g"; }
+    }
+
+
+
+    // $ANTLR start "ooActionSystems"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:135:1: ooActionSystems : ( T_CONSTS namedConstList )? T_TYPES namedTypeList T_SYSTEM comp= asTypeComposition[null] ;
+    public void ooActionSystems() // throws RecognitionException [1]
+    {   
+        IdentifierList comp = default(IdentifierList);
+
+
+        try {
+        	dbg.EnterRule(GrammarFileName, "ooActionSystems");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(135, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:136:2: ( ( T_CONSTS namedConstList )? T_TYPES namedTypeList T_SYSTEM comp= asTypeComposition[null] )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:136:4: ( T_CONSTS namedConstList )? T_TYPES namedTypeList T_SYSTEM comp= asTypeComposition[null]
+            {
+            	dbg.Location(136,4);
+            	initializeTopLevelParserState();
+            	dbg.Location(138,11);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:138:11: ( T_CONSTS namedConstList )?
+            	int alt1 = 2;
+            	try { dbg.EnterSubRule(1);
+            	try { dbg.EnterDecision(1);
+
+            	int LA1_0 = input.LA(1);
+
+            	if ( (LA1_0 == T_CONSTS) )
+            	{
+            	    alt1 = 1;
+            	}
+            	} finally { dbg.ExitDecision(1); }
+
+            	switch (alt1) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:138:12: T_CONSTS namedConstList
+            	        {
+            	        	dbg.Location(138,12);
+            	        	Match(input,T_CONSTS,FOLLOW_T_CONSTS_in_ooActionSystems93); 
+            	        	dbg.Location(138,21);
+            	        	PushFollow(FOLLOW_namedConstList_in_ooActionSystems95);
+            	        	namedConstList();
+            	        	state.followingStackPointer--;
+
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(1); }
+
+            	dbg.Location(140,4);
+            	Match(input,T_TYPES,FOLLOW_T_TYPES_in_ooActionSystems105); 
+            	dbg.Location(141,6);
+            	PushFollow(FOLLOW_namedTypeList_in_ooActionSystems113);
+            	namedTypeList();
+            	state.followingStackPointer--;
+
+            	dbg.Location(142,4);
+            	Match(input,T_SYSTEM,FOLLOW_T_SYSTEM_in_ooActionSystems118); 
+            	dbg.Location(143,8);
+            	PushFollow(FOLLOW_asTypeComposition_in_ooActionSystems125);
+            	comp = asTypeComposition(null);
+            	state.followingStackPointer--;
+
+            	dbg.Location(144,4);
+            	fixUpRun(comp);
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(145, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "ooActionSystems");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "ooActionSystems"
+
+
+    // $ANTLR start "namedConstList"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:153:1: namedConstList : namedConst ( T_SEMICOLON namedConst )* ;
+    public void namedConstList() // throws RecognitionException [1]
+    {   
+        try {
+        	dbg.EnterRule(GrammarFileName, "namedConstList");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(153, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:154:2: ( namedConst ( T_SEMICOLON namedConst )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:154:4: namedConst ( T_SEMICOLON namedConst )*
+            {
+            	dbg.Location(154,4);
+            	PushFollow(FOLLOW_namedConst_in_namedConstList148);
+            	namedConst();
+            	state.followingStackPointer--;
+
+            	dbg.Location(154,15);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:154:15: ( T_SEMICOLON namedConst )*
+            	try { dbg.EnterSubRule(2);
+
+            	do 
+            	{
+            	    int alt2 = 2;
+            	    try { dbg.EnterDecision(2);
+
+            	    int LA2_0 = input.LA(1);
+
+            	    if ( (LA2_0 == T_SEMICOLON) )
+            	    {
+            	        alt2 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(2); }
+
+            	    switch (alt2) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:154:16: T_SEMICOLON namedConst
+            			    {
+            			    	dbg.Location(154,16);
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_namedConstList151); 
+            			    	dbg.Location(154,28);
+            			    	PushFollow(FOLLOW_namedConst_in_namedConstList153);
+            			    	namedConst();
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop2;
+            	    }
+            	} while (true);
+
+            	loop2:
+            		;	// Stops C# compiler whining that label 'loop2' has no statements
+            	} finally { dbg.ExitSubRule(2); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(155, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "namedConstList");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "namedConstList"
+
+
+    // $ANTLR start "namedConst"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:157:1: namedConst : aName= T_IDENTIFIER T_EQUAL anExpr= expression ;
+    public void namedConst() // throws RecognitionException [1]
+    {   
+        IToken aName = null;
+        Expression anExpr = default(Expression);
+
+
+        try {
+        	dbg.EnterRule(GrammarFileName, "namedConst");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(157, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:158:2: (aName= T_IDENTIFIER T_EQUAL anExpr= expression )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:158:4: aName= T_IDENTIFIER T_EQUAL anExpr= expression
+            {
+            	dbg.Location(158,9);
+            	aName=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_namedConst169); 
+            	dbg.Location(159,3);
+            	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_namedConst173); 
+            	dbg.Location(160,9);
+            	PushFollow(FOLLOW_expression_in_namedConst179);
+            	anExpr = expression();
+            	state.followingStackPointer--;
+
+            	dbg.Location(161,3);
+            	addNamedConst(aName,anExpr);
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(162, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "namedConst");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "namedConst"
+
+
+    // $ANTLR start "namedTypeList"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:168:1: namedTypeList : namedType ( T_SEMICOLON namedType )* ;
+    public void namedTypeList() // throws RecognitionException [1]
+    {   
+        try {
+        	dbg.EnterRule(GrammarFileName, "namedTypeList");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(168, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:169:2: ( namedType ( T_SEMICOLON namedType )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:169:4: namedType ( T_SEMICOLON namedType )*
+            {
+            	dbg.Location(169,4);
+            	PushFollow(FOLLOW_namedType_in_namedTypeList199);
+            	namedType();
+            	state.followingStackPointer--;
+
+            	dbg.Location(169,14);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:169:14: ( T_SEMICOLON namedType )*
+            	try { dbg.EnterSubRule(3);
+
+            	do 
+            	{
+            	    int alt3 = 2;
+            	    try { dbg.EnterDecision(3);
+
+            	    int LA3_0 = input.LA(1);
+
+            	    if ( (LA3_0 == T_SEMICOLON) )
+            	    {
+            	        alt3 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(3); }
+
+            	    switch (alt3) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:169:15: T_SEMICOLON namedType
+            			    {
+            			    	dbg.Location(169,15);
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_namedTypeList202); 
+            			    	dbg.Location(169,27);
+            			    	PushFollow(FOLLOW_namedType_in_namedTypeList204);
+            			    	namedType();
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop3;
+            	    }
+            	} while (true);
+
+            	loop3:
+            		;	// Stops C# compiler whining that label 'loop3' has no statements
+            	} finally { dbg.ExitSubRule(3); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(170, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "namedTypeList");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "namedTypeList"
+
+
+    // $ANTLR start "namedType"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:172:1: namedType : aName= T_IDENTIFIER T_EQUAL (aType= complexType | anOoaType= ooActionSystem ) ;
+    public void namedType() // throws RecognitionException [1]
+    {   
+        IToken aName = null;
+        UlyssesType aType = default(UlyssesType);
+
+        OoActionSystemType anOoaType = default(OoActionSystemType);
+
+
+        try {
+        	dbg.EnterRule(GrammarFileName, "namedType");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(172, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:173:2: (aName= T_IDENTIFIER T_EQUAL (aType= complexType | anOoaType= ooActionSystem ) )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:173:4: aName= T_IDENTIFIER T_EQUAL (aType= complexType | anOoaType= ooActionSystem )
+            {
+            	dbg.Location(173,9);
+            	aName=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_namedType220); 
+            	dbg.Location(174,3);
+            	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_namedType225); 
+            	dbg.Location(175,3);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:175:3: (aType= complexType | anOoaType= ooActionSystem )
+            	int alt4 = 2;
+            	try { dbg.EnterSubRule(4);
+            	try { dbg.EnterDecision(4);
+
+            	try 
+            	{
+            	    isCyclicDecision = true;
+            	    alt4 = dfa4.Predict(input);
+            	}
+            	catch (NoViableAltException nvae) 
+            	{
+            	    dbg.RecognitionException(nvae);
+            	    throw nvae;
+            	}
+            	} finally { dbg.ExitDecision(4); }
+
+            	switch (alt4) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:176:4: aType= complexType
+            	        {
+            	        	dbg.Location(176,9);
+            	        	PushFollow(FOLLOW_complexType_in_namedType237);
+            	        	aType = complexType();
+            	        	state.followingStackPointer--;
+
+            	        	dbg.Location(176,24);
+            	        	createNamedType(aName,aType);
+
+            	        }
+            	        break;
+            	    case 2 :
+            	        dbg.EnterAlt(2);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:177:5: anOoaType= ooActionSystem
+            	        {
+            	        	dbg.Location(177,14);
+            	        	PushFollow(FOLLOW_ooActionSystem_in_namedType249);
+            	        	anOoaType = ooActionSystem();
+            	        	state.followingStackPointer--;
+
+            	        	dbg.Location(177,30);
+            	        	createNamedType(aName,anOoaType);
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(4); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(180, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "namedType");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "namedType"
+
+
+    // $ANTLR start "asTypeComposition"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:183:1: asTypeComposition[IdentifierList top] returns [IdentifierList prioList] : asTypeCompositionParallel[prioList] ( T_PRIO asTypeCompositionParallel[prioList] )* ;
+    public IdentifierList asTypeComposition(IdentifierList top) // throws RecognitionException [1]
+    {   
+        IdentifierList prioList = default(IdentifierList);
+
+        try {
+        	dbg.EnterRule(GrammarFileName, "asTypeComposition");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(183, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:185:2: ( asTypeCompositionParallel[prioList] ( T_PRIO asTypeCompositionParallel[prioList] )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:185:6: asTypeCompositionParallel[prioList] ( T_PRIO asTypeCompositionParallel[prioList] )*
+            {
+            	dbg.Location(185,6);
+            	prioList = new PrioIdentifierList(top);
+            	dbg.Location(186,3);
+            	PushFollow(FOLLOW_asTypeCompositionParallel_in_asTypeComposition285);
+            	asTypeCompositionParallel(prioList);
+            	state.followingStackPointer--;
+
+            	dbg.Location(186,40);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:186:40: ( T_PRIO asTypeCompositionParallel[prioList] )*
+            	try { dbg.EnterSubRule(5);
+
+            	do 
+            	{
+            	    int alt5 = 2;
+            	    try { dbg.EnterDecision(5);
+
+            	    int LA5_0 = input.LA(1);
+
+            	    if ( (LA5_0 == T_PRIO) )
+            	    {
+            	        alt5 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(5); }
+
+            	    switch (alt5) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:186:41: T_PRIO asTypeCompositionParallel[prioList]
+            			    {
+            			    	dbg.Location(186,41);
+            			    	Match(input,T_PRIO,FOLLOW_T_PRIO_in_asTypeComposition290); 
+            			    	dbg.Location(186,48);
+            			    	PushFollow(FOLLOW_asTypeCompositionParallel_in_asTypeComposition292);
+            			    	asTypeCompositionParallel(prioList);
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop5;
+            	    }
+            	} while (true);
+
+            	loop5:
+            		;	// Stops C# compiler whining that label 'loop5' has no statements
+            	} finally { dbg.ExitSubRule(5); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(187, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "asTypeComposition");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return prioList;
+    }
+    // $ANTLR end "asTypeComposition"
+
+
+    // $ANTLR start "asTypeCompositionParallel"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:189:1: asTypeCompositionParallel[IdentifierList top] : asTypeCompositionSequential[parList] ( T_NONDET asTypeCompositionSequential[parList] )* ;
+    public void asTypeCompositionParallel(IdentifierList top) // throws RecognitionException [1]
+    {   
+        try {
+        	dbg.EnterRule(GrammarFileName, "asTypeCompositionParallel");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(189, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:190:2: ( asTypeCompositionSequential[parList] ( T_NONDET asTypeCompositionSequential[parList] )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:190:6: asTypeCompositionSequential[parList] ( T_NONDET asTypeCompositionSequential[parList] )*
+            {
+            	dbg.Location(190,6);
+            	IdentifierList parList = new NondetIdentifierList(top);
+            	dbg.Location(191,3);
+            	PushFollow(FOLLOW_asTypeCompositionSequential_in_asTypeCompositionParallel315);
+            	asTypeCompositionSequential(parList);
+            	state.followingStackPointer--;
+
+            	dbg.Location(191,40);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:191:40: ( T_NONDET asTypeCompositionSequential[parList] )*
+            	try { dbg.EnterSubRule(6);
+
+            	do 
+            	{
+            	    int alt6 = 2;
+            	    try { dbg.EnterDecision(6);
+
+            	    int LA6_0 = input.LA(1);
+
+            	    if ( (LA6_0 == T_NONDET) )
+            	    {
+            	        alt6 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(6); }
+
+            	    switch (alt6) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:191:41: T_NONDET asTypeCompositionSequential[parList]
+            			    {
+            			    	dbg.Location(191,41);
+            			    	Match(input,T_NONDET,FOLLOW_T_NONDET_in_asTypeCompositionParallel319); 
+            			    	dbg.Location(191,50);
+            			    	PushFollow(FOLLOW_asTypeCompositionSequential_in_asTypeCompositionParallel321);
+            			    	asTypeCompositionSequential(parList);
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop6;
+            	    }
+            	} while (true);
+
+            	loop6:
+            		;	// Stops C# compiler whining that label 'loop6' has no statements
+            	} finally { dbg.ExitSubRule(6); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(192, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "asTypeCompositionParallel");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "asTypeCompositionParallel"
+
+
+    // $ANTLR start "asTypeCompositionSequential"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:194:1: asTypeCompositionSequential[IdentifierList top] : asTypeCompositionBlockParen[seqList] ;
+    public void asTypeCompositionSequential(IdentifierList top) // throws RecognitionException [1]
+    {   
+        try {
+        	dbg.EnterRule(GrammarFileName, "asTypeCompositionSequential");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(194, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:195:2: ( asTypeCompositionBlockParen[seqList] )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:195:6: asTypeCompositionBlockParen[seqList]
+            {
+            	dbg.Location(195,6);
+            	IdentifierList seqList = new SeqIdentifierList(top);
+            	dbg.Location(196,3);
+            	PushFollow(FOLLOW_asTypeCompositionBlockParen_in_asTypeCompositionSequential343);
+            	asTypeCompositionBlockParen(seqList);
+            	state.followingStackPointer--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(197, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "asTypeCompositionSequential");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "asTypeCompositionSequential"
+
+
+    // $ANTLR start "asTypeCompositionBlockParen"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:199:1: asTypeCompositionBlockParen[IdentifierList top] : ( T_LPAREN asTypeComposition[top] T_RPAREN | aName= T_IDENTIFIER );
+    public void asTypeCompositionBlockParen(IdentifierList top) // throws RecognitionException [1]
+    {   
+        IToken aName = null;
+
+        try {
+        	dbg.EnterRule(GrammarFileName, "asTypeCompositionBlockParen");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(199, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:200:2: ( T_LPAREN asTypeComposition[top] T_RPAREN | aName= T_IDENTIFIER )
+            int alt7 = 2;
+            try { dbg.EnterDecision(7);
+
+            int LA7_0 = input.LA(1);
+
+            if ( (LA7_0 == T_LPAREN) )
+            {
+                alt7 = 1;
+            }
+            else if ( (LA7_0 == T_IDENTIFIER) )
+            {
+                alt7 = 2;
+            }
+            else 
+            {
+                NoViableAltException nvae_d7s0 =
+                    new NoViableAltException("", 7, 0, input);
+
+                dbg.RecognitionException(nvae_d7s0);
+                throw nvae_d7s0;
+            }
+            } finally { dbg.ExitDecision(7); }
+
+            switch (alt7) 
+            {
+                case 1 :
+                    dbg.EnterAlt(1);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:200:4: T_LPAREN asTypeComposition[top] T_RPAREN
+                    {
+                    	dbg.Location(200,4);
+                    	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_asTypeCompositionBlockParen358); 
+                    	dbg.Location(200,13);
+                    	PushFollow(FOLLOW_asTypeComposition_in_asTypeCompositionBlockParen360);
+                    	asTypeComposition(top);
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(200,36);
+                    	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_asTypeCompositionBlockParen363); 
+
+                    }
+                    break;
+                case 2 :
+                    dbg.EnterAlt(2);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:201:4: aName= T_IDENTIFIER
+                    {
+                    	dbg.Location(201,9);
+                    	aName=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_asTypeCompositionBlockParen370); 
+                    	dbg.Location(201,23);
+                    	addToIdentifierList(top,aName);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(202, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "asTypeCompositionBlockParen");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "asTypeCompositionBlockParen"
+
+
+    // $ANTLR start "complexType"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:209:1: complexType returns [UlyssesType aTypeSymbol] : ( T_LIST T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN T_OF innertype= complexType | T_LSQPAREN alistelem= T_IDENTIFIER ( T_COMMA otherlistelem= T_IDENTIFIER )* T_RSQPAREN | T_MAP ( T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN )? mapfromtype= simpleType T_TO maptotype= complexType | T_QUANTITY T_OF T_LSQPAREN (alandmark= T_IDENTIFIER | alandmark= T_MINUS T_INFTY ) ( T_COMMA (otherlandmark= T_IDENTIFIER | otherlandmark= T_INFTY ) )* T_RSQPAREN | T_LPAREN aType= complexType ( T_COMMA anotherType= complexType )* T_RPAREN | r= simpleType );
+    public UlyssesType complexType() // throws RecognitionException [1]
+    {   
+        UlyssesType aTypeSymbol = default(UlyssesType);
+
+        IToken numOfElements = null;
+        IToken alistelem = null;
+        IToken otherlistelem = null;
+        IToken alandmark = null;
+        IToken otherlandmark = null;
+        UlyssesType innertype = default(UlyssesType);
+
+        UlyssesType mapfromtype = default(UlyssesType);
+
+        UlyssesType maptotype = default(UlyssesType);
+
+        UlyssesType aType = default(UlyssesType);
+
+        UlyssesType anotherType = default(UlyssesType);
+
+        UlyssesType r = default(UlyssesType);
+
+
+         
+        		aTypeSymbol = null;
+        		alandmark = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "complexType");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(209, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:215:2: ( T_LIST T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN T_OF innertype= complexType | T_LSQPAREN alistelem= T_IDENTIFIER ( T_COMMA otherlistelem= T_IDENTIFIER )* T_RSQPAREN | T_MAP ( T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN )? mapfromtype= simpleType T_TO maptotype= complexType | T_QUANTITY T_OF T_LSQPAREN (alandmark= T_IDENTIFIER | alandmark= T_MINUS T_INFTY ) ( T_COMMA (otherlandmark= T_IDENTIFIER | otherlandmark= T_INFTY ) )* T_RSQPAREN | T_LPAREN aType= complexType ( T_COMMA anotherType= complexType )* T_RPAREN | r= simpleType )
+            int alt14 = 6;
+            try { dbg.EnterDecision(14);
+
+            try 
+            {
+                isCyclicDecision = true;
+                alt14 = dfa14.Predict(input);
+            }
+            catch (NoViableAltException nvae) 
+            {
+                dbg.RecognitionException(nvae);
+                throw nvae;
+            }
+            } finally { dbg.ExitDecision(14); }
+
+            switch (alt14) 
+            {
+                case 1 :
+                    dbg.EnterAlt(1);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:215:4: T_LIST T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN T_OF innertype= complexType
+                    {
+                    	dbg.Location(215,4);
+                    	Match(input,T_LIST,FOLLOW_T_LIST_in_complexType401); 
+                    	dbg.Location(215,12);
+                    	Match(input,T_LSQPAREN,FOLLOW_T_LSQPAREN_in_complexType404); 
+                    	dbg.Location(215,36);
+                    	numOfElements = (IToken)input.LT(1);
+                    	if ( input.LA(1) == T_IDENTIFIER || input.LA(1) == T_INTNUMBER ) 
+                    	{
+                    	    input.Consume();
+                    	    state.errorRecovery = false;
+                    	}
+                    	else 
+                    	{
+                    	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	    dbg.RecognitionException(mse);
+                    	    throw mse;
+                    	}
+
+                    	dbg.Location(215,64);
+                    	Match(input,T_RSQPAREN,FOLLOW_T_RSQPAREN_in_complexType414); 
+                    	dbg.Location(215,75);
+                    	Match(input,T_OF,FOLLOW_T_OF_in_complexType416); 
+                    	dbg.Location(215,90);
+                    	PushFollow(FOLLOW_complexType_in_complexType421);
+                    	innertype = complexType();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(216,4);
+                    	aTypeSymbol = createListType(numOfElements,innertype);
+
+                    }
+                    break;
+                case 2 :
+                    dbg.EnterAlt(2);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:219:4: T_LSQPAREN alistelem= T_IDENTIFIER ( T_COMMA otherlistelem= T_IDENTIFIER )* T_RSQPAREN
+                    {
+                    	dbg.Location(219,4);
+                    	Match(input,T_LSQPAREN,FOLLOW_T_LSQPAREN_in_complexType436); 
+                    	dbg.Location(219,24);
+                    	alistelem=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_complexType440); 
+                    	dbg.Location(219,38);
+                    	aTypeSymbol = createListEnumType(alistelem);
+                    	dbg.Location(220,4);
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:220:4: ( T_COMMA otherlistelem= T_IDENTIFIER )*
+                    	try { dbg.EnterSubRule(8);
+
+                    	do 
+                    	{
+                    	    int alt8 = 2;
+                    	    try { dbg.EnterDecision(8);
+
+                    	    int LA8_0 = input.LA(1);
+
+                    	    if ( (LA8_0 == T_COMMA) )
+                    	    {
+                    	        alt8 = 1;
+                    	    }
+
+
+                    	    } finally { dbg.ExitDecision(8); }
+
+                    	    switch (alt8) 
+                    		{
+                    			case 1 :
+                    			    dbg.EnterAlt(1);
+
+                    			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:220:5: T_COMMA otherlistelem= T_IDENTIFIER
+                    			    {
+                    			    	dbg.Location(220,5);
+                    			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_complexType449); 
+                    			    	dbg.Location(220,26);
+                    			    	otherlistelem=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_complexType453); 
+                    			    	dbg.Location(220,40);
+                    			    	addToListEnumType(aTypeSymbol,otherlistelem);
+
+                    			    }
+                    			    break;
+
+                    			default:
+                    			    goto loop8;
+                    	    }
+                    	} while (true);
+
+                    	loop8:
+                    		;	// Stops C# compiler whining that label 'loop8' has no statements
+                    	} finally { dbg.ExitSubRule(8); }
+
+                    	dbg.Location(220,90);
+                    	Match(input,T_RSQPAREN,FOLLOW_T_RSQPAREN_in_complexType459); 
+
+                    }
+                    break;
+                case 3 :
+                    dbg.EnterAlt(3);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:223:4: T_MAP ( T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN )? mapfromtype= simpleType T_TO maptotype= complexType
+                    {
+                    	dbg.Location(223,4);
+                    	Match(input,T_MAP,FOLLOW_T_MAP_in_complexType469); 
+                    	dbg.Location(223,12);
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:223:12: ( T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN )?
+                    	int alt9 = 2;
+                    	try { dbg.EnterSubRule(9);
+                    	try { dbg.EnterDecision(9);
+
+                    	int LA9_0 = input.LA(1);
+
+                    	if ( (LA9_0 == T_LSQPAREN) )
+                    	{
+                    	    alt9 = 1;
+                    	}
+                    	} finally { dbg.ExitDecision(9); }
+
+                    	switch (alt9) 
+                    	{
+                    	    case 1 :
+                    	        dbg.EnterAlt(1);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:223:13: T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN
+                    	        {
+                    	        	dbg.Location(223,13);
+                    	        	Match(input,T_LSQPAREN,FOLLOW_T_LSQPAREN_in_complexType474); 
+                    	        	dbg.Location(223,37);
+                    	        	numOfElements = (IToken)input.LT(1);
+                    	        	if ( input.LA(1) == T_IDENTIFIER || input.LA(1) == T_INTNUMBER ) 
+                    	        	{
+                    	        	    input.Consume();
+                    	        	    state.errorRecovery = false;
+                    	        	}
+                    	        	else 
+                    	        	{
+                    	        	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	        	    dbg.RecognitionException(mse);
+                    	        	    throw mse;
+                    	        	}
+
+                    	        	dbg.Location(223,65);
+                    	        	Match(input,T_RSQPAREN,FOLLOW_T_RSQPAREN_in_complexType484); 
+
+                    	        }
+                    	        break;
+
+                    	}
+                    	} finally { dbg.ExitSubRule(9); }
+
+                    	dbg.Location(223,89);
+                    	PushFollow(FOLLOW_simpleType_in_complexType490);
+                    	mapfromtype = simpleType();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(223,101);
+                    	Match(input,T_TO,FOLLOW_T_TO_in_complexType492); 
+                    	dbg.Location(223,115);
+                    	PushFollow(FOLLOW_complexType_in_complexType496);
+                    	maptotype = complexType();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(224,4);
+                    	aTypeSymbol = createMapType(numOfElements,mapfromtype,maptotype);
+
+                    }
+                    break;
+                case 4 :
+                    dbg.EnterAlt(4);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:226:4: T_QUANTITY T_OF T_LSQPAREN (alandmark= T_IDENTIFIER | alandmark= T_MINUS T_INFTY ) ( T_COMMA (otherlandmark= T_IDENTIFIER | otherlandmark= T_INFTY ) )* T_RSQPAREN
+                    {
+                    	dbg.Location(226,4);
+                    	Match(input,T_QUANTITY,FOLLOW_T_QUANTITY_in_complexType510); 
+                    	dbg.Location(226,15);
+                    	Match(input,T_OF,FOLLOW_T_OF_in_complexType512); 
+                    	dbg.Location(226,20);
+                    	Match(input,T_LSQPAREN,FOLLOW_T_LSQPAREN_in_complexType514); 
+                    	dbg.Location(226,31);
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:226:31: (alandmark= T_IDENTIFIER | alandmark= T_MINUS T_INFTY )
+                    	int alt10 = 2;
+                    	try { dbg.EnterSubRule(10);
+                    	try { dbg.EnterDecision(10);
+
+                    	int LA10_0 = input.LA(1);
+
+                    	if ( (LA10_0 == T_IDENTIFIER) )
+                    	{
+                    	    alt10 = 1;
+                    	}
+                    	else if ( (LA10_0 == T_MINUS) )
+                    	{
+                    	    alt10 = 2;
+                    	}
+                    	else 
+                    	{
+                    	    NoViableAltException nvae_d10s0 =
+                    	        new NoViableAltException("", 10, 0, input);
+
+                    	    dbg.RecognitionException(nvae_d10s0);
+                    	    throw nvae_d10s0;
+                    	}
+                    	} finally { dbg.ExitDecision(10); }
+
+                    	switch (alt10) 
+                    	{
+                    	    case 1 :
+                    	        dbg.EnterAlt(1);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:226:32: alandmark= T_IDENTIFIER
+                    	        {
+                    	        	dbg.Location(226,41);
+                    	        	alandmark=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_complexType519); 
+
+                    	        }
+                    	        break;
+                    	    case 2 :
+                    	        dbg.EnterAlt(2);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:226:56: alandmark= T_MINUS T_INFTY
+                    	        {
+                    	        	dbg.Location(226,65);
+                    	        	alandmark=(IToken)Match(input,T_MINUS,FOLLOW_T_MINUS_in_complexType524); 
+                    	        	dbg.Location(226,74);
+                    	        	Match(input,T_INFTY,FOLLOW_T_INFTY_in_complexType526); 
+
+                    	        }
+                    	        break;
+
+                    	}
+                    	} finally { dbg.ExitSubRule(10); }
+
+                    	dbg.Location(226,83);
+                    	aTypeSymbol = createQrType(alandmark);
+                    	dbg.Location(227,4);
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:227:4: ( T_COMMA (otherlandmark= T_IDENTIFIER | otherlandmark= T_INFTY ) )*
+                    	try { dbg.EnterSubRule(12);
+
+                    	do 
+                    	{
+                    	    int alt12 = 2;
+                    	    try { dbg.EnterDecision(12);
+
+                    	    int LA12_0 = input.LA(1);
+
+                    	    if ( (LA12_0 == T_COMMA) )
+                    	    {
+                    	        alt12 = 1;
+                    	    }
+
+
+                    	    } finally { dbg.ExitDecision(12); }
+
+                    	    switch (alt12) 
+                    		{
+                    			case 1 :
+                    			    dbg.EnterAlt(1);
+
+                    			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:227:5: T_COMMA (otherlandmark= T_IDENTIFIER | otherlandmark= T_INFTY )
+                    			    {
+                    			    	dbg.Location(227,5);
+                    			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_complexType536); 
+                    			    	dbg.Location(227,13);
+                    			    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:227:13: (otherlandmark= T_IDENTIFIER | otherlandmark= T_INFTY )
+                    			    	int alt11 = 2;
+                    			    	try { dbg.EnterSubRule(11);
+                    			    	try { dbg.EnterDecision(11);
+
+                    			    	int LA11_0 = input.LA(1);
+
+                    			    	if ( (LA11_0 == T_IDENTIFIER) )
+                    			    	{
+                    			    	    alt11 = 1;
+                    			    	}
+                    			    	else if ( (LA11_0 == T_INFTY) )
+                    			    	{
+                    			    	    alt11 = 2;
+                    			    	}
+                    			    	else 
+                    			    	{
+                    			    	    NoViableAltException nvae_d11s0 =
+                    			    	        new NoViableAltException("", 11, 0, input);
+
+                    			    	    dbg.RecognitionException(nvae_d11s0);
+                    			    	    throw nvae_d11s0;
+                    			    	}
+                    			    	} finally { dbg.ExitDecision(11); }
+
+                    			    	switch (alt11) 
+                    			    	{
+                    			    	    case 1 :
+                    			    	        dbg.EnterAlt(1);
+
+                    			    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:227:14: otherlandmark= T_IDENTIFIER
+                    			    	        {
+                    			    	        	dbg.Location(227,27);
+                    			    	        	otherlandmark=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_complexType541); 
+
+                    			    	        }
+                    			    	        break;
+                    			    	    case 2 :
+                    			    	        dbg.EnterAlt(2);
+
+                    			    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:227:41: otherlandmark= T_INFTY
+                    			    	        {
+                    			    	        	dbg.Location(227,54);
+                    			    	        	otherlandmark=(IToken)Match(input,T_INFTY,FOLLOW_T_INFTY_in_complexType545); 
+
+                    			    	        }
+                    			    	        break;
+
+                    			    	}
+                    			    	} finally { dbg.ExitSubRule(11); }
+
+                    			    	dbg.Location(227,64);
+                    			    	addToQrType(aTypeSymbol,otherlandmark);
+
+                    			    }
+                    			    break;
+
+                    			default:
+                    			    goto loop12;
+                    	    }
+                    	} while (true);
+
+                    	loop12:
+                    		;	// Stops C# compiler whining that label 'loop12' has no statements
+                    	} finally { dbg.ExitSubRule(12); }
+
+                    	dbg.Location(227,108);
+                    	Match(input,T_RSQPAREN,FOLLOW_T_RSQPAREN_in_complexType552); 
+
+                    }
+                    break;
+                case 5 :
+                    dbg.EnterAlt(5);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:229:5: T_LPAREN aType= complexType ( T_COMMA anotherType= complexType )* T_RPAREN
+                    {
+                    	dbg.Location(229,5);
+                    	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_complexType562); 
+                    	dbg.Location(229,19);
+                    	PushFollow(FOLLOW_complexType_in_complexType566);
+                    	aType = complexType();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(229,32);
+                    	aTypeSymbol = createTupleType(aType);
+                    	dbg.Location(230,4);
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:230:4: ( T_COMMA anotherType= complexType )*
+                    	try { dbg.EnterSubRule(13);
+
+                    	do 
+                    	{
+                    	    int alt13 = 2;
+                    	    try { dbg.EnterDecision(13);
+
+                    	    int LA13_0 = input.LA(1);
+
+                    	    if ( (LA13_0 == T_COMMA) )
+                    	    {
+                    	        alt13 = 1;
+                    	    }
+
+
+                    	    } finally { dbg.ExitDecision(13); }
+
+                    	    switch (alt13) 
+                    		{
+                    			case 1 :
+                    			    dbg.EnterAlt(1);
+
+                    			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:230:5: T_COMMA anotherType= complexType
+                    			    {
+                    			    	dbg.Location(230,5);
+                    			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_complexType575); 
+                    			    	dbg.Location(230,24);
+                    			    	PushFollow(FOLLOW_complexType_in_complexType579);
+                    			    	anotherType = complexType();
+                    			    	state.followingStackPointer--;
+
+                    			    	dbg.Location(230,37);
+                    			    	addToTupleType(aTypeSymbol,anotherType);
+
+                    			    }
+                    			    break;
+
+                    			default:
+                    			    goto loop13;
+                    	    }
+                    	} while (true);
+
+                    	loop13:
+                    		;	// Stops C# compiler whining that label 'loop13' has no statements
+                    	} finally { dbg.ExitSubRule(13); }
+
+                    	dbg.Location(230,83);
+                    	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_complexType586); 
+
+                    }
+                    break;
+                case 6 :
+                    dbg.EnterAlt(6);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:233:4: r= simpleType
+                    {
+                    	dbg.Location(233,5);
+                    	PushFollow(FOLLOW_simpleType_in_complexType599);
+                    	r = simpleType();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(233,17);
+                    	aTypeSymbol = r;
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            fixupComplexType(aTypeSymbol);
+        }
+        dbg.Location(234, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "complexType");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return aTypeSymbol;
+    }
+    // $ANTLR end "complexType"
+
+
+    // $ANTLR start "simpleType"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:239:1: simpleType returns [UlyssesType aTypeSymbol] : ( T_BOOL | T_INT T_LSQPAREN rangeLow= ( T_INTNUMBER | T_INFTY | T_IDENTIFIER ) T_RANGETO rangeHigh= ( T_INTNUMBER | T_INFTY | T_IDENTIFIER ) T_RSQPAREN | T_FLOAT T_LSQPAREN rangeLow= ( T_FLOATNUMBER | T_INFTY | T_IDENTIFIER ) T_RANGETO rangeHigh= ( T_FLOATNUMBER | T_INFTY | T_IDENTIFIER ) T_RSQPAREN | T_CHAR | T_CBRL aRangeValue= T_IDENTIFIER ( T_EQUAL optVal= T_INTNUMBER )? ( T_COMMA otherRangeValue= T_IDENTIFIER ( T_EQUAL otherOptVal= T_INTNUMBER )? )* T_CBRR | aType= T_IDENTIFIER );
+    public UlyssesType simpleType() // throws RecognitionException [1]
+    {   
+        UlyssesType aTypeSymbol = default(UlyssesType);
+
+        IToken rangeLow = null;
+        IToken rangeHigh = null;
+        IToken aRangeValue = null;
+        IToken optVal = null;
+        IToken otherRangeValue = null;
+        IToken otherOptVal = null;
+        IToken aType = null;
+
+         
+        		aTypeSymbol = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "simpleType");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(239, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:244:2: ( T_BOOL | T_INT T_LSQPAREN rangeLow= ( T_INTNUMBER | T_INFTY | T_IDENTIFIER ) T_RANGETO rangeHigh= ( T_INTNUMBER | T_INFTY | T_IDENTIFIER ) T_RSQPAREN | T_FLOAT T_LSQPAREN rangeLow= ( T_FLOATNUMBER | T_INFTY | T_IDENTIFIER ) T_RANGETO rangeHigh= ( T_FLOATNUMBER | T_INFTY | T_IDENTIFIER ) T_RSQPAREN | T_CHAR | T_CBRL aRangeValue= T_IDENTIFIER ( T_EQUAL optVal= T_INTNUMBER )? ( T_COMMA otherRangeValue= T_IDENTIFIER ( T_EQUAL otherOptVal= T_INTNUMBER )? )* T_CBRR | aType= T_IDENTIFIER )
+            int alt18 = 6;
+            try { dbg.EnterDecision(18);
+
+            switch ( input.LA(1) ) 
+            {
+            case T_BOOL:
+            	{
+                alt18 = 1;
+                }
+                break;
+            case T_INT:
+            	{
+                alt18 = 2;
+                }
+                break;
+            case T_FLOAT:
+            	{
+                alt18 = 3;
+                }
+                break;
+            case T_CHAR:
+            	{
+                alt18 = 4;
+                }
+                break;
+            case T_CBRL:
+            	{
+                alt18 = 5;
+                }
+                break;
+            case T_IDENTIFIER:
+            	{
+                alt18 = 6;
+                }
+                break;
+            	default:
+            	    NoViableAltException nvae_d18s0 =
+            	        new NoViableAltException("", 18, 0, input);
+
+            	    dbg.RecognitionException(nvae_d18s0);
+            	    throw nvae_d18s0;
+            }
+
+            } finally { dbg.ExitDecision(18); }
+
+            switch (alt18) 
+            {
+                case 1 :
+                    dbg.EnterAlt(1);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:244:4: T_BOOL
+                    {
+                    	dbg.Location(244,4);
+                    	Match(input,T_BOOL,FOLLOW_T_BOOL_in_simpleType632); 
+                    	dbg.Location(244,12);
+                    	aTypeSymbol = createBoolType();
+
+                    }
+                    break;
+                case 2 :
+                    dbg.EnterAlt(2);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:247:4: T_INT T_LSQPAREN rangeLow= ( T_INTNUMBER | T_INFTY | T_IDENTIFIER ) T_RANGETO rangeHigh= ( T_INTNUMBER | T_INFTY | T_IDENTIFIER ) T_RSQPAREN
+                    {
+                    	dbg.Location(247,4);
+                    	Match(input,T_INT,FOLLOW_T_INT_in_simpleType645); 
+                    	dbg.Location(247,10);
+                    	Match(input,T_LSQPAREN,FOLLOW_T_LSQPAREN_in_simpleType647); 
+                    	dbg.Location(247,29);
+                    	rangeLow = (IToken)input.LT(1);
+                    	if ( input.LA(1) == T_IDENTIFIER || input.LA(1) == T_INTNUMBER || input.LA(1) == T_INFTY ) 
+                    	{
+                    	    input.Consume();
+                    	    state.errorRecovery = false;
+                    	}
+                    	else 
+                    	{
+                    	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	    dbg.RecognitionException(mse);
+                    	    throw mse;
+                    	}
+
+                    	dbg.Location(247,65);
+                    	Match(input,T_RANGETO,FOLLOW_T_RANGETO_in_simpleType659); 
+                    	dbg.Location(247,84);
+                    	rangeHigh = (IToken)input.LT(1);
+                    	if ( input.LA(1) == T_IDENTIFIER || input.LA(1) == T_INTNUMBER || input.LA(1) == T_INFTY ) 
+                    	{
+                    	    input.Consume();
+                    	    state.errorRecovery = false;
+                    	}
+                    	else 
+                    	{
+                    	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	    dbg.RecognitionException(mse);
+                    	    throw mse;
+                    	}
+
+                    	dbg.Location(247,120);
+                    	Match(input,T_RSQPAREN,FOLLOW_T_RSQPAREN_in_simpleType671); 
+                    	dbg.Location(248,4);
+                    	aTypeSymbol = createIntType(rangeLow,rangeHigh);
+
+                    }
+                    break;
+                case 3 :
+                    dbg.EnterAlt(3);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:251:4: T_FLOAT T_LSQPAREN rangeLow= ( T_FLOATNUMBER | T_INFTY | T_IDENTIFIER ) T_RANGETO rangeHigh= ( T_FLOATNUMBER | T_INFTY | T_IDENTIFIER ) T_RSQPAREN
+                    {
+                    	dbg.Location(251,4);
+                    	Match(input,T_FLOAT,FOLLOW_T_FLOAT_in_simpleType690); 
+                    	dbg.Location(251,13);
+                    	Match(input,T_LSQPAREN,FOLLOW_T_LSQPAREN_in_simpleType693); 
+                    	dbg.Location(251,32);
+                    	rangeLow = (IToken)input.LT(1);
+                    	if ( input.LA(1) == T_IDENTIFIER || input.LA(1) == T_INFTY || input.LA(1) == T_FLOATNUMBER ) 
+                    	{
+                    	    input.Consume();
+                    	    state.errorRecovery = false;
+                    	}
+                    	else 
+                    	{
+                    	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	    dbg.RecognitionException(mse);
+                    	    throw mse;
+                    	}
+
+                    	dbg.Location(251,70);
+                    	Match(input,T_RANGETO,FOLLOW_T_RANGETO_in_simpleType705); 
+                    	dbg.Location(251,89);
+                    	rangeHigh = (IToken)input.LT(1);
+                    	if ( input.LA(1) == T_IDENTIFIER || input.LA(1) == T_INFTY || input.LA(1) == T_FLOATNUMBER ) 
+                    	{
+                    	    input.Consume();
+                    	    state.errorRecovery = false;
+                    	}
+                    	else 
+                    	{
+                    	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	    dbg.RecognitionException(mse);
+                    	    throw mse;
+                    	}
+
+                    	dbg.Location(251,127);
+                    	Match(input,T_RSQPAREN,FOLLOW_T_RSQPAREN_in_simpleType717); 
+                    	dbg.Location(252,4);
+                    	aTypeSymbol = createFloatType(rangeLow,rangeHigh);
+
+                    }
+                    break;
+                case 4 :
+                    dbg.EnterAlt(4);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:255:4: T_CHAR
+                    {
+                    	dbg.Location(255,4);
+                    	Match(input,T_CHAR,FOLLOW_T_CHAR_in_simpleType735); 
+                    	dbg.Location(255,11);
+                    	aTypeSymbol = createCharType();
+
+                    }
+                    break;
+                case 5 :
+                    dbg.EnterAlt(5);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:259:4: T_CBRL aRangeValue= T_IDENTIFIER ( T_EQUAL optVal= T_INTNUMBER )? ( T_COMMA otherRangeValue= T_IDENTIFIER ( T_EQUAL otherOptVal= T_INTNUMBER )? )* T_CBRR
+                    {
+                    	dbg.Location(259,4);
+                    	Match(input,T_CBRL,FOLLOW_T_CBRL_in_simpleType751); 
+                    	dbg.Location(259,22);
+                    	aRangeValue=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_simpleType755); 
+                    	dbg.Location(259,36);
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:259:36: ( T_EQUAL optVal= T_INTNUMBER )?
+                    	int alt15 = 2;
+                    	try { dbg.EnterSubRule(15);
+                    	try { dbg.EnterDecision(15);
+
+                    	int LA15_0 = input.LA(1);
+
+                    	if ( (LA15_0 == T_EQUAL) )
+                    	{
+                    	    alt15 = 1;
+                    	}
+                    	} finally { dbg.ExitDecision(15); }
+
+                    	switch (alt15) 
+                    	{
+                    	    case 1 :
+                    	        dbg.EnterAlt(1);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:259:37: T_EQUAL optVal= T_INTNUMBER
+                    	        {
+                    	        	dbg.Location(259,37);
+                    	        	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_simpleType758); 
+                    	        	dbg.Location(259,51);
+                    	        	optVal=(IToken)Match(input,T_INTNUMBER,FOLLOW_T_INTNUMBER_in_simpleType762); 
+
+                    	        }
+                    	        break;
+
+                    	}
+                    	} finally { dbg.ExitSubRule(15); }
+
+                    	dbg.Location(259,66);
+                    	aTypeSymbol = createEnumType(aRangeValue, optVal);
+                    	dbg.Location(260,4);
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:260:4: ( T_COMMA otherRangeValue= T_IDENTIFIER ( T_EQUAL otherOptVal= T_INTNUMBER )? )*
+                    	try { dbg.EnterSubRule(17);
+
+                    	do 
+                    	{
+                    	    int alt17 = 2;
+                    	    try { dbg.EnterDecision(17);
+
+                    	    int LA17_0 = input.LA(1);
+
+                    	    if ( (LA17_0 == T_COMMA) )
+                    	    {
+                    	        alt17 = 1;
+                    	    }
+
+
+                    	    } finally { dbg.ExitDecision(17); }
+
+                    	    switch (alt17) 
+                    		{
+                    			case 1 :
+                    			    dbg.EnterAlt(1);
+
+                    			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:260:5: T_COMMA otherRangeValue= T_IDENTIFIER ( T_EQUAL otherOptVal= T_INTNUMBER )?
+                    			    {
+                    			    	dbg.Location(260,5);
+                    			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_simpleType773); 
+                    			    	dbg.Location(260,28);
+                    			    	otherRangeValue=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_simpleType777); 
+                    			    	dbg.Location(260,42);
+                    			    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:260:42: ( T_EQUAL otherOptVal= T_INTNUMBER )?
+                    			    	int alt16 = 2;
+                    			    	try { dbg.EnterSubRule(16);
+                    			    	try { dbg.EnterDecision(16);
+
+                    			    	int LA16_0 = input.LA(1);
+
+                    			    	if ( (LA16_0 == T_EQUAL) )
+                    			    	{
+                    			    	    alt16 = 1;
+                    			    	}
+                    			    	} finally { dbg.ExitDecision(16); }
+
+                    			    	switch (alt16) 
+                    			    	{
+                    			    	    case 1 :
+                    			    	        dbg.EnterAlt(1);
+
+                    			    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:260:43: T_EQUAL otherOptVal= T_INTNUMBER
+                    			    	        {
+                    			    	        	dbg.Location(260,43);
+                    			    	        	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_simpleType780); 
+                    			    	        	dbg.Location(260,62);
+                    			    	        	otherOptVal=(IToken)Match(input,T_INTNUMBER,FOLLOW_T_INTNUMBER_in_simpleType784); 
+
+                    			    	        }
+                    			    	        break;
+
+                    			    	}
+                    			    	} finally { dbg.ExitSubRule(16); }
+
+                    			    	dbg.Location(260,77);
+                    			    	addToEnumType(aTypeSymbol,otherRangeValue,otherOptVal); otherOptVal=null;
+
+                    			    }
+                    			    break;
+
+                    			default:
+                    			    goto loop17;
+                    	    }
+                    	} while (true);
+
+                    	loop17:
+                    		;	// Stops C# compiler whining that label 'loop17' has no statements
+                    	} finally { dbg.ExitSubRule(17); }
+
+                    	dbg.Location(260,155);
+                    	Match(input,T_CBRR,FOLLOW_T_CBRR_in_simpleType792); 
+
+                    }
+                    break;
+                case 6 :
+                    dbg.EnterAlt(6);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:262:4: aType= T_IDENTIFIER
+                    {
+                    	dbg.Location(262,9);
+                    	aType=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_simpleType803); 
+                    	dbg.Location(262,23);
+                    	aTypeSymbol = getNamedType(aType);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            fixupSimpleType(aTypeSymbol);
+        }
+        dbg.Location(263, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "simpleType");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return aTypeSymbol;
+    }
+    // $ANTLR end "simpleType"
+
+
+    // $ANTLR start "ooActionSystem"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:272:1: ooActionSystem returns [OoActionSystemType aTypeSymbol] : ( T_AUTOCONS )? T_SYSTEM ( T_LPAREN refinesSystemName= T_IDENTIFIER T_RPAREN )? '|[' ( T_VAR attrList )? ( T_METHODS methodList )? ( T_ACTIONS namedActionList )? ( T_DO (bl= actionBlock[null] )? T_OD )? ']|' ;
+    public OoActionSystemType ooActionSystem() // throws RecognitionException [1]
+    {   
+        OoActionSystemType aTypeSymbol = default(OoActionSystemType);
+
+        IToken refinesSystemName = null;
+        Block bl = default(Block);
+
+
+         
+        		bool autoCons = false; 
+        		aTypeSymbol = null;
+        		refinesSystemName = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "ooActionSystem");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(272, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:279:2: ( ( T_AUTOCONS )? T_SYSTEM ( T_LPAREN refinesSystemName= T_IDENTIFIER T_RPAREN )? '|[' ( T_VAR attrList )? ( T_METHODS methodList )? ( T_ACTIONS namedActionList )? ( T_DO (bl= actionBlock[null] )? T_OD )? ']|' )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:279:9: ( T_AUTOCONS )? T_SYSTEM ( T_LPAREN refinesSystemName= T_IDENTIFIER T_RPAREN )? '|[' ( T_VAR attrList )? ( T_METHODS methodList )? ( T_ACTIONS namedActionList )? ( T_DO (bl= actionBlock[null] )? T_OD )? ']|'
+            {
+            	dbg.Location(279,9);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:279:9: ( T_AUTOCONS )?
+            	int alt19 = 2;
+            	try { dbg.EnterSubRule(19);
+            	try { dbg.EnterDecision(19);
+
+            	int LA19_0 = input.LA(1);
+
+            	if ( (LA19_0 == T_AUTOCONS) )
+            	{
+            	    alt19 = 1;
+            	}
+            	} finally { dbg.ExitDecision(19); }
+
+            	switch (alt19) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:279:10: T_AUTOCONS
+            	        {
+            	        	dbg.Location(279,10);
+            	        	Match(input,T_AUTOCONS,FOLLOW_T_AUTOCONS_in_ooActionSystem846); 
+            	        	dbg.Location(279,21);
+            	        	autoCons = true;
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(19); }
+
+            	dbg.Location(280,3);
+            	Match(input,T_SYSTEM,FOLLOW_T_SYSTEM_in_ooActionSystem855); 
+            	dbg.Location(280,12);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:280:12: ( T_LPAREN refinesSystemName= T_IDENTIFIER T_RPAREN )?
+            	int alt20 = 2;
+            	try { dbg.EnterSubRule(20);
+            	try { dbg.EnterDecision(20);
+
+            	int LA20_0 = input.LA(1);
+
+            	if ( (LA20_0 == T_LPAREN) )
+            	{
+            	    alt20 = 1;
+            	}
+            	} finally { dbg.ExitDecision(20); }
+
+            	switch (alt20) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:280:13: T_LPAREN refinesSystemName= T_IDENTIFIER T_RPAREN
+            	        {
+            	        	dbg.Location(280,13);
+            	        	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_ooActionSystem858); 
+            	        	dbg.Location(280,39);
+            	        	refinesSystemName=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_ooActionSystem862); 
+            	        	dbg.Location(280,53);
+            	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_ooActionSystem864); 
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(20); }
+
+            	dbg.Location(281,3);
+            	aTypeSymbol = createOoaType(refinesSystemName,autoCons);
+            	dbg.Location(282,3);
+            	Match(input,117,FOLLOW_117_in_ooActionSystem877); 
+            	dbg.Location(283,4);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:283:4: ( T_VAR attrList )?
+            	int alt21 = 2;
+            	try { dbg.EnterSubRule(21);
+            	try { dbg.EnterDecision(21);
+
+            	int LA21_0 = input.LA(1);
+
+            	if ( (LA21_0 == T_VAR) )
+            	{
+            	    alt21 = 1;
+            	}
+            	} finally { dbg.ExitDecision(21); }
+
+            	switch (alt21) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:283:5: T_VAR attrList
+            	        {
+            	        	dbg.Location(283,5);
+            	        	Match(input,T_VAR,FOLLOW_T_VAR_in_ooActionSystem883); 
+            	        	dbg.Location(283,11);
+            	        	PushFollow(FOLLOW_attrList_in_ooActionSystem885);
+            	        	attrList();
+            	        	state.followingStackPointer--;
+
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(21); }
+
+            	dbg.Location(284,4);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:284:4: ( T_METHODS methodList )?
+            	int alt22 = 2;
+            	try { dbg.EnterSubRule(22);
+            	try { dbg.EnterDecision(22);
+
+            	int LA22_0 = input.LA(1);
+
+            	if ( (LA22_0 == T_METHODS) )
+            	{
+            	    alt22 = 1;
+            	}
+            	} finally { dbg.ExitDecision(22); }
+
+            	switch (alt22) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:284:5: T_METHODS methodList
+            	        {
+            	        	dbg.Location(284,5);
+            	        	Match(input,T_METHODS,FOLLOW_T_METHODS_in_ooActionSystem893); 
+            	        	dbg.Location(284,15);
+            	        	PushFollow(FOLLOW_methodList_in_ooActionSystem895);
+            	        	methodList();
+            	        	state.followingStackPointer--;
+
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(22); }
+
+            	dbg.Location(285,4);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:285:4: ( T_ACTIONS namedActionList )?
+            	int alt23 = 2;
+            	try { dbg.EnterSubRule(23);
+            	try { dbg.EnterDecision(23);
+
+            	int LA23_0 = input.LA(1);
+
+            	if ( (LA23_0 == T_ACTIONS) )
+            	{
+            	    alt23 = 1;
+            	}
+            	} finally { dbg.ExitDecision(23); }
+
+            	switch (alt23) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:285:5: T_ACTIONS namedActionList
+            	        {
+            	        	dbg.Location(285,5);
+            	        	Match(input,T_ACTIONS,FOLLOW_T_ACTIONS_in_ooActionSystem903); 
+            	        	dbg.Location(285,15);
+            	        	PushFollow(FOLLOW_namedActionList_in_ooActionSystem905);
+            	        	namedActionList();
+            	        	state.followingStackPointer--;
+
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(23); }
+
+            	dbg.Location(286,4);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:286:4: ( T_DO (bl= actionBlock[null] )? T_OD )?
+            	int alt25 = 2;
+            	try { dbg.EnterSubRule(25);
+            	try { dbg.EnterDecision(25);
+
+            	int LA25_0 = input.LA(1);
+
+            	if ( (LA25_0 == T_DO) )
+            	{
+            	    alt25 = 1;
+            	}
+            	} finally { dbg.ExitDecision(25); }
+
+            	switch (alt25) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:286:5: T_DO (bl= actionBlock[null] )? T_OD
+            	        {
+            	        	dbg.Location(286,5);
+            	        	Match(input,T_DO,FOLLOW_T_DO_in_ooActionSystem913); 
+            	        	dbg.Location(286,10);
+            	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:286:10: (bl= actionBlock[null] )?
+            	        	int alt24 = 2;
+            	        	try { dbg.EnterSubRule(24);
+            	        	try { dbg.EnterDecision(24);
+
+            	        	int LA24_0 = input.LA(1);
+
+            	        	if ( (LA24_0 == T_IDENTIFIER || LA24_0 == T_LPAREN || LA24_0 == T_VAR || (LA24_0 >= T_CONT && LA24_0 <= T_REQUIRES) || LA24_0 == T_SKIP) )
+            	        	{
+            	        	    alt24 = 1;
+            	        	}
+            	        	} finally { dbg.ExitDecision(24); }
+
+            	        	switch (alt24) 
+            	        	{
+            	        	    case 1 :
+            	        	        dbg.EnterAlt(1);
+
+            	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:286:11: bl= actionBlock[null]
+            	        	        {
+            	        	        	dbg.Location(286,13);
+            	        	        	PushFollow(FOLLOW_actionBlock_in_ooActionSystem918);
+            	        	        	bl = actionBlock(null);
+            	        	        	state.followingStackPointer--;
+
+            	        	        	dbg.Location(286,32);
+            	        	        	addActionBlock(aTypeSymbol,bl);
+
+            	        	        }
+            	        	        break;
+
+            	        	}
+            	        	} finally { dbg.ExitSubRule(24); }
+
+            	        	dbg.Location(286,68);
+            	        	Match(input,T_OD,FOLLOW_T_OD_in_ooActionSystem925); 
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(25); }
+
+            	dbg.Location(287,3);
+            	Match(input,118,FOLLOW_118_in_ooActionSystem931); 
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            fixupOoaType(aTypeSymbol);
+        }
+        dbg.Location(288, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "ooActionSystem");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return aTypeSymbol;
+    }
+    // $ANTLR end "ooActionSystem"
+
+
+    // $ANTLR start "attrList"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:298:1: attrList : attr ( T_SEMICOLON attr )* ;
+    public void attrList() // throws RecognitionException [1]
+    {   
+        try {
+        	dbg.EnterRule(GrammarFileName, "attrList");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(298, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:299:2: ( attr ( T_SEMICOLON attr )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:299:4: attr ( T_SEMICOLON attr )*
+            {
+            	dbg.Location(299,4);
+            	BeginParsingAttributes();
+            	dbg.Location(300,4);
+            	PushFollow(FOLLOW_attr_in_attrList962);
+            	attr();
+            	state.followingStackPointer--;
+
+            	dbg.Location(300,9);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:300:9: ( T_SEMICOLON attr )*
+            	try { dbg.EnterSubRule(26);
+
+            	do 
+            	{
+            	    int alt26 = 2;
+            	    try { dbg.EnterDecision(26);
+
+            	    int LA26_0 = input.LA(1);
+
+            	    if ( (LA26_0 == T_SEMICOLON) )
+            	    {
+            	        alt26 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(26); }
+
+            	    switch (alt26) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:300:10: T_SEMICOLON attr
+            			    {
+            			    	dbg.Location(300,10);
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_attrList965); 
+            			    	dbg.Location(300,22);
+            			    	PushFollow(FOLLOW_attr_in_attrList967);
+            			    	attr();
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop26;
+            	    }
+            	} while (true);
+
+            	loop26:
+            		;	// Stops C# compiler whining that label 'loop26' has no statements
+            	} finally { dbg.ExitSubRule(26); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+
+            		EndParsingAttributes();
+            	
+        }
+        dbg.Location(301, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "attrList");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "attrList"
+
+
+    // $ANTLR start "attr"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:306:1: attr : ( T_STATIC )? ( T_OBS | T_CTRL )? varname= T_IDENTIFIER T_COLON aType= complexType ( T_EQUAL anExpr= expression )? ;
+    public void attr() // throws RecognitionException [1]
+    {   
+        IToken varname = null;
+        UlyssesType aType = default(UlyssesType);
+
+        Expression anExpr = default(Expression);
+
+
+         
+        		bool isStatic = false; 
+        		bool isCtr = false;
+        		bool isObs = false;				
+        		
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "attr");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(306, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:313:2: ( ( T_STATIC )? ( T_OBS | T_CTRL )? varname= T_IDENTIFIER T_COLON aType= complexType ( T_EQUAL anExpr= expression )? )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:313:5: ( T_STATIC )? ( T_OBS | T_CTRL )? varname= T_IDENTIFIER T_COLON aType= complexType ( T_EQUAL anExpr= expression )?
+            {
+            	dbg.Location(313,5);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:313:5: ( T_STATIC )?
+            	int alt27 = 2;
+            	try { dbg.EnterSubRule(27);
+            	try { dbg.EnterDecision(27);
+
+            	int LA27_0 = input.LA(1);
+
+            	if ( (LA27_0 == T_STATIC) )
+            	{
+            	    alt27 = 1;
+            	}
+            	} finally { dbg.ExitDecision(27); }
+
+            	switch (alt27) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:313:6: T_STATIC
+            	        {
+            	        	dbg.Location(313,6);
+            	        	Match(input,T_STATIC,FOLLOW_T_STATIC_in_attr992); 
+            	        	dbg.Location(313,15);
+            	        	isStatic = true;
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(27); }
+
+            	dbg.Location(313,36);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:313:36: ( T_OBS | T_CTRL )?
+            	int alt28 = 3;
+            	try { dbg.EnterSubRule(28);
+            	try { dbg.EnterDecision(28);
+
+            	int LA28_0 = input.LA(1);
+
+            	if ( (LA28_0 == T_OBS) )
+            	{
+            	    alt28 = 1;
+            	}
+            	else if ( (LA28_0 == T_CTRL) )
+            	{
+            	    alt28 = 2;
+            	}
+            	} finally { dbg.ExitDecision(28); }
+
+            	switch (alt28) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:313:37: T_OBS
+            	        {
+            	        	dbg.Location(313,37);
+            	        	Match(input,T_OBS,FOLLOW_T_OBS_in_attr999); 
+            	        	dbg.Location(313,43);
+            	        	isObs = true;
+
+            	        }
+            	        break;
+            	    case 2 :
+            	        dbg.EnterAlt(2);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:313:61: T_CTRL
+            	        {
+            	        	dbg.Location(313,61);
+            	        	Match(input,T_CTRL,FOLLOW_T_CTRL_in_attr1005); 
+            	        	dbg.Location(313,68);
+            	        	isCtr = true;
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(28); }
+
+            	dbg.Location(314,10);
+            	varname=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_attr1016); 
+            	dbg.Location(314,25);
+            	Match(input,T_COLON,FOLLOW_T_COLON_in_attr1019); 
+            	dbg.Location(314,38);
+            	PushFollow(FOLLOW_complexType_in_attr1023);
+            	aType = complexType();
+            	state.followingStackPointer--;
+
+            	dbg.Location(314,51);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:314:51: ( T_EQUAL anExpr= expression )?
+            	int alt29 = 2;
+            	try { dbg.EnterSubRule(29);
+            	try { dbg.EnterDecision(29);
+
+            	int LA29_0 = input.LA(1);
+
+            	if ( (LA29_0 == T_EQUAL) )
+            	{
+            	    alt29 = 1;
+            	}
+            	} finally { dbg.ExitDecision(29); }
+
+            	switch (alt29) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:314:52: T_EQUAL anExpr= expression
+            	        {
+            	        	dbg.Location(314,52);
+            	        	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_attr1026); 
+            	        	dbg.Location(314,66);
+            	        	PushFollow(FOLLOW_expression_in_attr1030);
+            	        	anExpr = expression();
+            	        	state.followingStackPointer--;
+
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(29); }
+
+            	dbg.Location(315,3);
+            	createAttribute(varname, isStatic, isObs, isCtr, aType, anExpr);
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(316, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "attr");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "attr"
+
+
+    // $ANTLR start "methodList"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:321:1: methodList : method ( T_SEMICOLON method )* ;
+    public void methodList() // throws RecognitionException [1]
+    {   
+        try {
+        	dbg.EnterRule(GrammarFileName, "methodList");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(321, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:322:2: ( method ( T_SEMICOLON method )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:322:5: method ( T_SEMICOLON method )*
+            {
+            	dbg.Location(322,5);
+            	PushFollow(FOLLOW_method_in_methodList1052);
+            	method();
+            	state.followingStackPointer--;
+
+            	dbg.Location(322,12);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:322:12: ( T_SEMICOLON method )*
+            	try { dbg.EnterSubRule(30);
+
+            	do 
+            	{
+            	    int alt30 = 2;
+            	    try { dbg.EnterDecision(30);
+
+            	    int LA30_0 = input.LA(1);
+
+            	    if ( (LA30_0 == T_SEMICOLON) )
+            	    {
+            	        alt30 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(30); }
+
+            	    switch (alt30) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:322:13: T_SEMICOLON method
+            			    {
+            			    	dbg.Location(322,13);
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_methodList1055); 
+            			    	dbg.Location(322,25);
+            			    	PushFollow(FOLLOW_method_in_methodList1057);
+            			    	method();
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop30;
+            	    }
+            	} while (true);
+
+            	loop30:
+            		;	// Stops C# compiler whining that label 'loop30' has no statements
+            	} finally { dbg.ExitSubRule(30); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(323, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "methodList");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "methodList"
+
+
+    // $ANTLR start "method"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:325:1: method : mname= T_IDENTIFIER ( T_LPAREN methodParameterList[newMethod] T_RPAREN )? ( T_COLON rt= complexType )? T_EQUAL ( T_VAR localActionVars[newMethod] 'begin' )? statements= actionBody[null] T_END ;
+    public void method() // throws RecognitionException [1]
+    {   
+        IToken mname = null;
+        UlyssesType rt = default(UlyssesType);
+
+        Block statements = default(Block);
+
+
+        	
+        		FunctionIdentifier newMethod = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "method");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(325, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:329:2: (mname= T_IDENTIFIER ( T_LPAREN methodParameterList[newMethod] T_RPAREN )? ( T_COLON rt= complexType )? T_EQUAL ( T_VAR localActionVars[newMethod] 'begin' )? statements= actionBody[null] T_END )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:329:4: mname= T_IDENTIFIER ( T_LPAREN methodParameterList[newMethod] T_RPAREN )? ( T_COLON rt= complexType )? T_EQUAL ( T_VAR localActionVars[newMethod] 'begin' )? statements= actionBody[null] T_END
+            {
+            	dbg.Location(329,9);
+            	mname=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_method1079); 
+            	dbg.Location(329,24);
+            	newMethod = createMethodSymbol(mname);
+            	dbg.Location(330,3);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:330:3: ( T_LPAREN methodParameterList[newMethod] T_RPAREN )?
+            	int alt31 = 2;
+            	try { dbg.EnterSubRule(31);
+            	try { dbg.EnterDecision(31);
+
+            	int LA31_0 = input.LA(1);
+
+            	if ( (LA31_0 == T_LPAREN) )
+            	{
+            	    alt31 = 1;
+            	}
+            	} finally { dbg.ExitDecision(31); }
+
+            	switch (alt31) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:330:4: T_LPAREN methodParameterList[newMethod] T_RPAREN
+            	        {
+            	        	dbg.Location(330,4);
+            	        	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_method1087); 
+            	        	dbg.Location(330,13);
+            	        	PushFollow(FOLLOW_methodParameterList_in_method1089);
+            	        	methodParameterList(newMethod);
+            	        	state.followingStackPointer--;
+
+            	        	dbg.Location(330,45);
+            	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_method1093); 
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(31); }
+
+            	dbg.Location(331,3);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:331:3: ( T_COLON rt= complexType )?
+            	int alt32 = 2;
+            	try { dbg.EnterSubRule(32);
+            	try { dbg.EnterDecision(32);
+
+            	int LA32_0 = input.LA(1);
+
+            	if ( (LA32_0 == T_COLON) )
+            	{
+            	    alt32 = 1;
+            	}
+            	} finally { dbg.ExitDecision(32); }
+
+            	switch (alt32) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:331:4: T_COLON rt= complexType
+            	        {
+            	        	dbg.Location(331,4);
+            	        	Match(input,T_COLON,FOLLOW_T_COLON_in_method1101); 
+            	        	dbg.Location(331,14);
+            	        	PushFollow(FOLLOW_complexType_in_method1105);
+            	        	rt = complexType();
+            	        	state.followingStackPointer--;
+
+            	        	dbg.Location(331,27);
+            	        	setMethodReturnType(newMethod,rt);
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(32); }
+
+            	dbg.Location(332,4);
+            	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_method1115); 
+            	dbg.Location(333,4);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:333:4: ( T_VAR localActionVars[newMethod] 'begin' )?
+            	int alt33 = 2;
+            	try { dbg.EnterSubRule(33);
+            	try { dbg.EnterDecision(33);
+
+            	int LA33_0 = input.LA(1);
+
+            	if ( (LA33_0 == T_VAR) )
+            	{
+            	    alt33 = 1;
+            	}
+            	} finally { dbg.ExitDecision(33); }
+
+            	switch (alt33) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:333:5: T_VAR localActionVars[newMethod] 'begin'
+            	        {
+            	        	dbg.Location(333,5);
+            	        	Match(input,T_VAR,FOLLOW_T_VAR_in_method1122); 
+            	        	dbg.Location(333,11);
+            	        	PushFollow(FOLLOW_localActionVars_in_method1124);
+            	        	localActionVars(newMethod);
+            	        	state.followingStackPointer--;
+
+            	        	dbg.Location(333,38);
+            	        	Match(input,119,FOLLOW_119_in_method1127); 
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(33); }
+
+            	dbg.Location(334,13);
+            	PushFollow(FOLLOW_actionBody_in_method1136);
+            	statements = actionBody(null);
+            	state.followingStackPointer--;
+
+            	dbg.Location(334,31);
+            	addMethodBody(newMethod,statements);
+            	dbg.Location(335,3);
+            	Match(input,T_END,FOLLOW_T_END_in_method1144); 
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            popResolveStack(newMethod);
+        }
+        dbg.Location(336, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "method");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "method"
+
+
+    // $ANTLR start "methodParameterList"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:340:1: methodParameterList[FunctionIdentifier newMethod] : paramName= T_IDENTIFIER T_COLON atype= complexType ( T_COMMA otherparam= T_IDENTIFIER T_COLON othertype= complexType )* ;
+    public void methodParameterList(FunctionIdentifier newMethod) // throws RecognitionException [1]
+    {   
+        IToken paramName = null;
+        IToken otherparam = null;
+        UlyssesType atype = default(UlyssesType);
+
+        UlyssesType othertype = default(UlyssesType);
+
+
+        try {
+        	dbg.EnterRule(GrammarFileName, "methodParameterList");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(340, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:341:2: (paramName= T_IDENTIFIER T_COLON atype= complexType ( T_COMMA otherparam= T_IDENTIFIER T_COLON othertype= complexType )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:341:5: paramName= T_IDENTIFIER T_COLON atype= complexType ( T_COMMA otherparam= T_IDENTIFIER T_COLON othertype= complexType )*
+            {
+            	dbg.Location(341,14);
+            	paramName=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_methodParameterList1168); 
+            	dbg.Location(341,28);
+            	Match(input,T_COLON,FOLLOW_T_COLON_in_methodParameterList1170); 
+            	dbg.Location(341,41);
+            	PushFollow(FOLLOW_complexType_in_methodParameterList1174);
+            	atype = complexType();
+            	state.followingStackPointer--;
+
+            	dbg.Location(341,54);
+            	addMethodParameter(newMethod,paramName,atype);
+            	dbg.Location(342,4);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:342:4: ( T_COMMA otherparam= T_IDENTIFIER T_COLON othertype= complexType )*
+            	try { dbg.EnterSubRule(34);
+
+            	do 
+            	{
+            	    int alt34 = 2;
+            	    try { dbg.EnterDecision(34);
+
+            	    int LA34_0 = input.LA(1);
+
+            	    if ( (LA34_0 == T_COMMA) )
+            	    {
+            	        alt34 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(34); }
+
+            	    switch (alt34) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:342:5: T_COMMA otherparam= T_IDENTIFIER T_COLON othertype= complexType
+            			    {
+            			    	dbg.Location(342,5);
+            			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_methodParameterList1182); 
+            			    	dbg.Location(342,23);
+            			    	otherparam=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_methodParameterList1186); 
+            			    	dbg.Location(342,37);
+            			    	Match(input,T_COLON,FOLLOW_T_COLON_in_methodParameterList1188); 
+            			    	dbg.Location(342,54);
+            			    	PushFollow(FOLLOW_complexType_in_methodParameterList1192);
+            			    	othertype = complexType();
+            			    	state.followingStackPointer--;
+
+            			    	dbg.Location(343,4);
+            			    	addMethodParameter(newMethod,otherparam,othertype);
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop34;
+            	    }
+            	} while (true);
+
+            	loop34:
+            		;	// Stops C# compiler whining that label 'loop34' has no statements
+            	} finally { dbg.ExitSubRule(34); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(344, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "methodParameterList");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "methodParameterList"
+
+
+    // $ANTLR start "namedActionList"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:351:1: namedActionList : namedAction ( T_SEMICOLON namedAction )* ;
+    public void namedActionList() // throws RecognitionException [1]
+    {   
+        try {
+        	dbg.EnterRule(GrammarFileName, "namedActionList");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(351, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:352:2: ( namedAction ( T_SEMICOLON namedAction )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:352:4: namedAction ( T_SEMICOLON namedAction )*
+            {
+            	dbg.Location(352,4);
+            	PushFollow(FOLLOW_namedAction_in_namedActionList1219);
+            	namedAction();
+            	state.followingStackPointer--;
+
+            	dbg.Location(352,16);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:352:16: ( T_SEMICOLON namedAction )*
+            	try { dbg.EnterSubRule(35);
+
+            	do 
+            	{
+            	    int alt35 = 2;
+            	    try { dbg.EnterDecision(35);
+
+            	    int LA35_0 = input.LA(1);
+
+            	    if ( (LA35_0 == T_SEMICOLON) )
+            	    {
+            	        alt35 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(35); }
+
+            	    switch (alt35) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:352:17: T_SEMICOLON namedAction
+            			    {
+            			    	dbg.Location(352,17);
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_namedActionList1222); 
+            			    	dbg.Location(352,29);
+            			    	PushFollow(FOLLOW_namedAction_in_namedActionList1224);
+            			    	namedAction();
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop35;
+            	    }
+            	} while (true);
+
+            	loop35:
+            		;	// Stops C# compiler whining that label 'loop35' has no statements
+            	} finally { dbg.ExitSubRule(35); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(353, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "namedActionList");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "namedActionList"
+
+
+    // $ANTLR start "namedAction"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:355:1: namedAction : ( T_CONT cactionname= T_IDENTIFIER ( T_LPAREN methodParameterList[newAction] T_RPAREN )? T_EQUAL constraints= continuousActionBody | ( T_CTRL | T_OBS | ) actionname= T_IDENTIFIER ( T_LPAREN methodParameterList[newAction] T_RPAREN )? T_EQUAL ( T_VAR localActionVars[newAction] )? body= discreteActionBody );
+    public void namedAction() // throws RecognitionException [1]
+    {   
+        IToken cactionname = null;
+        IToken actionname = null;
+        GuardedCommand constraints = default(GuardedCommand);
+
+        GuardedCommand body = default(GuardedCommand);
+
+
+
+        		FunctionTypeEnum actionType;
+        		FunctionIdentifier newAction = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "namedAction");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(355, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:360:2: ( T_CONT cactionname= T_IDENTIFIER ( T_LPAREN methodParameterList[newAction] T_RPAREN )? T_EQUAL constraints= continuousActionBody | ( T_CTRL | T_OBS | ) actionname= T_IDENTIFIER ( T_LPAREN methodParameterList[newAction] T_RPAREN )? T_EQUAL ( T_VAR localActionVars[newAction] )? body= discreteActionBody )
+            int alt40 = 2;
+            try { dbg.EnterDecision(40);
+
+            int LA40_0 = input.LA(1);
+
+            if ( (LA40_0 == T_CONT) )
+            {
+                alt40 = 1;
+            }
+            else if ( (LA40_0 == T_IDENTIFIER || (LA40_0 >= T_OBS && LA40_0 <= T_CTRL)) )
+            {
+                alt40 = 2;
+            }
+            else 
+            {
+                NoViableAltException nvae_d40s0 =
+                    new NoViableAltException("", 40, 0, input);
+
+                dbg.RecognitionException(nvae_d40s0);
+                throw nvae_d40s0;
+            }
+            } finally { dbg.ExitDecision(40); }
+
+            switch (alt40) 
+            {
+                case 1 :
+                    dbg.EnterAlt(1);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:360:4: T_CONT cactionname= T_IDENTIFIER ( T_LPAREN methodParameterList[newAction] T_RPAREN )? T_EQUAL constraints= continuousActionBody
+                    {
+                    	dbg.Location(360,4);
+                    	Match(input,T_CONT,FOLLOW_T_CONT_in_namedAction1244); 
+                    	dbg.Location(360,22);
+                    	cactionname=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_namedAction1248); 
+                    	dbg.Location(360,37);
+                    	newAction = createNamedContinuousAction(cactionname, FunctionTypeEnum.Continuous);
+                    	dbg.Location(361,3);
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:361:3: ( T_LPAREN methodParameterList[newAction] T_RPAREN )?
+                    	int alt36 = 2;
+                    	try { dbg.EnterSubRule(36);
+                    	try { dbg.EnterDecision(36);
+
+                    	int LA36_0 = input.LA(1);
+
+                    	if ( (LA36_0 == T_LPAREN) )
+                    	{
+                    	    alt36 = 1;
+                    	}
+                    	} finally { dbg.ExitDecision(36); }
+
+                    	switch (alt36) 
+                    	{
+                    	    case 1 :
+                    	        dbg.EnterAlt(1);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:361:4: T_LPAREN methodParameterList[newAction] T_RPAREN
+                    	        {
+                    	        	dbg.Location(361,4);
+                    	        	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_namedAction1256); 
+                    	        	dbg.Location(361,13);
+                    	        	PushFollow(FOLLOW_methodParameterList_in_namedAction1258);
+                    	        	methodParameterList(newAction);
+                    	        	state.followingStackPointer--;
+
+                    	        	dbg.Location(361,45);
+                    	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_namedAction1262); 
+
+                    	        }
+                    	        break;
+
+                    	}
+                    	} finally { dbg.ExitSubRule(36); }
+
+                    	dbg.Location(362,3);
+                    	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_namedAction1269); 
+                    	dbg.Location(362,22);
+                    	PushFollow(FOLLOW_continuousActionBody_in_namedAction1273);
+                    	constraints = continuousActionBody();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(362,44);
+                    	addContinuousActionBody(newAction,constraints);
+
+                    }
+                    break;
+                case 2 :
+                    dbg.EnterAlt(2);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:364:4: ( T_CTRL | T_OBS | ) actionname= T_IDENTIFIER ( T_LPAREN methodParameterList[newAction] T_RPAREN )? T_EQUAL ( T_VAR localActionVars[newAction] )? body= discreteActionBody
+                    {
+                    	dbg.Location(364,4);
+                    	actionType = FunctionTypeEnum.Internal;
+                    	dbg.Location(365,3);
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:365:3: ( T_CTRL | T_OBS | )
+                    	int alt37 = 3;
+                    	try { dbg.EnterSubRule(37);
+                    	try { dbg.EnterDecision(37);
+
+                    	switch ( input.LA(1) ) 
+                    	{
+                    	case T_CTRL:
+                    		{
+                    	    alt37 = 1;
+                    	    }
+                    	    break;
+                    	case T_OBS:
+                    		{
+                    	    alt37 = 2;
+                    	    }
+                    	    break;
+                    	case T_IDENTIFIER:
+                    		{
+                    	    alt37 = 3;
+                    	    }
+                    	    break;
+                    		default:
+                    		    NoViableAltException nvae_d37s0 =
+                    		        new NoViableAltException("", 37, 0, input);
+
+                    		    dbg.RecognitionException(nvae_d37s0);
+                    		    throw nvae_d37s0;
+                    	}
+
+                    	} finally { dbg.ExitDecision(37); }
+
+                    	switch (alt37) 
+                    	{
+                    	    case 1 :
+                    	        dbg.EnterAlt(1);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:365:4: T_CTRL
+                    	        {
+                    	        	dbg.Location(365,4);
+                    	        	Match(input,T_CTRL,FOLLOW_T_CTRL_in_namedAction1288); 
+                    	        	dbg.Location(365,11);
+                    	        	actionType = FunctionTypeEnum.Controllable;
+
+                    	        }
+                    	        break;
+                    	    case 2 :
+                    	        dbg.EnterAlt(2);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:365:58: T_OBS
+                    	        {
+                    	        	dbg.Location(365,58);
+                    	        	Match(input,T_OBS,FOLLOW_T_OBS_in_namedAction1293); 
+                    	        	dbg.Location(365,64);
+                    	        	actionType = FunctionTypeEnum.Observable;
+
+                    	        }
+                    	        break;
+                    	    case 3 :
+                    	        dbg.EnterAlt(3);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:365:109: 
+                    	        {
+                    	        }
+                    	        break;
+
+                    	}
+                    	} finally { dbg.ExitSubRule(37); }
+
+                    	dbg.Location(366,14);
+                    	actionname=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_namedAction1305); 
+                    	dbg.Location(366,29);
+                    	newAction = createNamedAction(actionname,actionType);
+                    	dbg.Location(367,3);
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:367:3: ( T_LPAREN methodParameterList[newAction] T_RPAREN )?
+                    	int alt38 = 2;
+                    	try { dbg.EnterSubRule(38);
+                    	try { dbg.EnterDecision(38);
+
+                    	int LA38_0 = input.LA(1);
+
+                    	if ( (LA38_0 == T_LPAREN) )
+                    	{
+                    	    alt38 = 1;
+                    	}
+                    	} finally { dbg.ExitDecision(38); }
+
+                    	switch (alt38) 
+                    	{
+                    	    case 1 :
+                    	        dbg.EnterAlt(1);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:367:4: T_LPAREN methodParameterList[newAction] T_RPAREN
+                    	        {
+                    	        	dbg.Location(367,4);
+                    	        	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_namedAction1313); 
+                    	        	dbg.Location(367,13);
+                    	        	PushFollow(FOLLOW_methodParameterList_in_namedAction1315);
+                    	        	methodParameterList(newAction);
+                    	        	state.followingStackPointer--;
+
+                    	        	dbg.Location(367,45);
+                    	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_namedAction1319); 
+
+                    	        }
+                    	        break;
+
+                    	}
+                    	} finally { dbg.ExitSubRule(38); }
+
+                    	dbg.Location(368,3);
+                    	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_namedAction1326); 
+                    	dbg.Location(369,3);
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:369:3: ( T_VAR localActionVars[newAction] )?
+                    	int alt39 = 2;
+                    	try { dbg.EnterSubRule(39);
+                    	try { dbg.EnterDecision(39);
+
+                    	int LA39_0 = input.LA(1);
+
+                    	if ( (LA39_0 == T_VAR) )
+                    	{
+                    	    alt39 = 1;
+                    	}
+                    	} finally { dbg.ExitDecision(39); }
+
+                    	switch (alt39) 
+                    	{
+                    	    case 1 :
+                    	        dbg.EnterAlt(1);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:369:4: T_VAR localActionVars[newAction]
+                    	        {
+                    	        	dbg.Location(369,4);
+                    	        	Match(input,T_VAR,FOLLOW_T_VAR_in_namedAction1332); 
+                    	        	dbg.Location(369,10);
+                    	        	PushFollow(FOLLOW_localActionVars_in_namedAction1334);
+                    	        	localActionVars(newAction);
+                    	        	state.followingStackPointer--;
+
+
+                    	        }
+                    	        break;
+
+                    	}
+                    	} finally { dbg.ExitSubRule(39); }
+
+                    	dbg.Location(370,7);
+                    	PushFollow(FOLLOW_discreteActionBody_in_namedAction1345);
+                    	body = discreteActionBody();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(371,3);
+                    	addActionBody(newAction,body);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            popResolveStack(newAction);
+        }
+        dbg.Location(372, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "namedAction");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "namedAction"
+
+
+    // $ANTLR start "localActionVars"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:377:1: localActionVars[FunctionIdentifier newMethod] : id1= T_IDENTIFIER T_COLON t1= complexType ( T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType )* ;
+    public void localActionVars(FunctionIdentifier newMethod) // throws RecognitionException [1]
+    {   
+        IToken id1 = null;
+        IToken id2 = null;
+        UlyssesType t1 = default(UlyssesType);
+
+        UlyssesType t2 = default(UlyssesType);
+
+
+        try {
+        	dbg.EnterRule(GrammarFileName, "localActionVars");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(377, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:378:2: (id1= T_IDENTIFIER T_COLON t1= complexType ( T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:379:3: id1= T_IDENTIFIER T_COLON t1= complexType ( T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType )*
+            {
+            	dbg.Location(379,6);
+            	id1=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_localActionVars1377); 
+            	dbg.Location(379,20);
+            	Match(input,T_COLON,FOLLOW_T_COLON_in_localActionVars1379); 
+            	dbg.Location(379,30);
+            	PushFollow(FOLLOW_complexType_in_localActionVars1383);
+            	t1 = complexType();
+            	state.followingStackPointer--;
+
+            	dbg.Location(379,44);
+            	addLocalVariableToNamedAction(newMethod,id1,t1);
+            	dbg.Location(380,4);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:380:4: ( T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType )*
+            	try { dbg.EnterSubRule(41);
+
+            	do 
+            	{
+            	    int alt41 = 2;
+            	    try { dbg.EnterDecision(41);
+
+            	    int LA41_0 = input.LA(1);
+
+            	    if ( (LA41_0 == T_SEMICOLON) )
+            	    {
+            	        alt41 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(41); }
+
+            	    switch (alt41) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:380:5: T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType
+            			    {
+            			    	dbg.Location(380,5);
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_localActionVars1392); 
+            			    	dbg.Location(380,20);
+            			    	id2=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_localActionVars1396); 
+            			    	dbg.Location(380,34);
+            			    	Match(input,T_COLON,FOLLOW_T_COLON_in_localActionVars1398); 
+            			    	dbg.Location(380,44);
+            			    	PushFollow(FOLLOW_complexType_in_localActionVars1402);
+            			    	t2 = complexType();
+            			    	state.followingStackPointer--;
+
+            			    	dbg.Location(381,4);
+            			    	addLocalVariableToNamedAction(newMethod,id2,t2);
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop41;
+            	    }
+            	} while (true);
+
+            	loop41:
+            		;	// Stops C# compiler whining that label 'loop41' has no statements
+            	} finally { dbg.ExitSubRule(41); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(382, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "localActionVars");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "localActionVars"
+
+
+    // $ANTLR start "anonymousAction"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:386:1: anonymousAction returns [GuardedCommand result] : (a= continuousActionBody | b= discreteActionBody );
+    public GuardedCommand anonymousAction() // throws RecognitionException [1]
+    {   
+        GuardedCommand result = default(GuardedCommand);
+
+        GuardedCommand a = default(GuardedCommand);
+
+        GuardedCommand b = default(GuardedCommand);
+
+
+        try {
+        	dbg.EnterRule(GrammarFileName, "anonymousAction");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(386, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:388:2: (a= continuousActionBody | b= discreteActionBody )
+            int alt42 = 2;
+            try { dbg.EnterDecision(42);
+
+            int LA42_0 = input.LA(1);
+
+            if ( (LA42_0 == T_CONT) )
+            {
+                alt42 = 1;
+            }
+            else if ( (LA42_0 == T_REQUIRES) )
+            {
+                alt42 = 2;
+            }
+            else 
+            {
+                NoViableAltException nvae_d42s0 =
+                    new NoViableAltException("", 42, 0, input);
+
+                dbg.RecognitionException(nvae_d42s0);
+                throw nvae_d42s0;
+            }
+            } finally { dbg.ExitDecision(42); }
+
+            switch (alt42) 
+            {
+                case 1 :
+                    dbg.EnterAlt(1);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:388:4: a= continuousActionBody
+                    {
+                    	dbg.Location(388,5);
+                    	PushFollow(FOLLOW_continuousActionBody_in_anonymousAction1432);
+                    	a = continuousActionBody();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(388,27);
+                    	result = a;
+
+                    }
+                    break;
+                case 2 :
+                    dbg.EnterAlt(2);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:389:4: b= discreteActionBody
+                    {
+                    	dbg.Location(389,5);
+                    	PushFollow(FOLLOW_discreteActionBody_in_anonymousAction1441);
+                    	b = discreteActionBody();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(389,25);
+                    	result = b;
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(390, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "anonymousAction");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "anonymousAction"
+
+
+    // $ANTLR start "continuousActionBody"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:392:1: continuousActionBody returns [GuardedCommand result] : T_CONT T_REQUIRES expr= expression T_COLON bdy= qualConstraintList T_END ;
+    public GuardedCommand continuousActionBody() // throws RecognitionException [1]
+    {   
+        GuardedCommand result = default(GuardedCommand);
+
+        Expression expr = default(Expression);
+
+        Block bdy = default(Block);
+
+
+
+        		result = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "continuousActionBody");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(392, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:397:2: ( T_CONT T_REQUIRES expr= expression T_COLON bdy= qualConstraintList T_END )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:397:4: T_CONT T_REQUIRES expr= expression T_COLON bdy= qualConstraintList T_END
+            {
+            	dbg.Location(397,4);
+            	Match(input,T_CONT,FOLLOW_T_CONT_in_continuousActionBody1466); 
+            	dbg.Location(397,11);
+            	Match(input,T_REQUIRES,FOLLOW_T_REQUIRES_in_continuousActionBody1468); 
+            	dbg.Location(397,26);
+            	PushFollow(FOLLOW_expression_in_continuousActionBody1472);
+            	expr = expression();
+            	state.followingStackPointer--;
+
+            	dbg.Location(397,38);
+            	Match(input,T_COLON,FOLLOW_T_COLON_in_continuousActionBody1474); 
+            	dbg.Location(398,7);
+            	PushFollow(FOLLOW_qualConstraintList_in_continuousActionBody1481);
+            	bdy = qualConstraintList();
+            	state.followingStackPointer--;
+
+            	dbg.Location(399,3);
+            	Match(input,T_END,FOLLOW_T_END_in_continuousActionBody1486); 
+            	dbg.Location(400,3);
+            	result = createGuardedCommandStatement(expr,bdy,true);
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(401, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "continuousActionBody");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "continuousActionBody"
+
+
+    // $ANTLR start "qualConstraintList"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:403:1: qualConstraintList returns [Block result] : stmt= qualConstraint ( T_COMMA ostmt= qualConstraint )* ;
+    public Block qualConstraintList() // throws RecognitionException [1]
+    {   
+        Block result = default(Block);
+
+        QualitativeConstraintStatement stmt = default(QualitativeConstraintStatement);
+
+        QualitativeConstraintStatement ostmt = default(QualitativeConstraintStatement);
+
+
+
+        		result = createSeqBlock(null);
+        		pushBlockToResolveStack(result);
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "qualConstraintList");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(403, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:409:2: (stmt= qualConstraint ( T_COMMA ostmt= qualConstraint )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:409:4: stmt= qualConstraint ( T_COMMA ostmt= qualConstraint )*
+            {
+            	dbg.Location(409,8);
+            	PushFollow(FOLLOW_qualConstraint_in_qualConstraintList1514);
+            	stmt = qualConstraint();
+            	state.followingStackPointer--;
+
+            	dbg.Location(409,24);
+            	addToBlockList(result,stmt);
+            	dbg.Location(410,3);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:410:3: ( T_COMMA ostmt= qualConstraint )*
+            	try { dbg.EnterSubRule(43);
+
+            	do 
+            	{
+            	    int alt43 = 2;
+            	    try { dbg.EnterDecision(43);
+
+            	    int LA43_0 = input.LA(1);
+
+            	    if ( (LA43_0 == T_COMMA) )
+            	    {
+            	        alt43 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(43); }
+
+            	    switch (alt43) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:410:4: T_COMMA ostmt= qualConstraint
+            			    {
+            			    	dbg.Location(410,4);
+            			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_qualConstraintList1521); 
+            			    	dbg.Location(410,17);
+            			    	PushFollow(FOLLOW_qualConstraint_in_qualConstraintList1525);
+            			    	ostmt = qualConstraint();
+            			    	state.followingStackPointer--;
+
+            			    	dbg.Location(410,33);
+            			    	addToBlockList(result,ostmt);
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop43;
+            	    }
+            	} while (true);
+
+            	loop43:
+            		;	// Stops C# compiler whining that label 'loop43' has no statements
+            	} finally { dbg.ExitSubRule(43); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            popBlockFromResolveStack(result);
+        }
+        dbg.Location(411, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "qualConstraintList");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "qualConstraintList"
+
+
+    // $ANTLR start "qualConstraint"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:417:1: qualConstraint returns [QualitativeConstraintStatement result] : id1= T_IDENTIFIER T_EQUAL ( T_DERIV derivid= T_IDENTIFIER | id2= T_IDENTIFIER ( (op= T_SUM | op= T_DIFF | op= T_PROD ) id3= T_IDENTIFIER | ) ) ;
+    public QualitativeConstraintStatement qualConstraint() // throws RecognitionException [1]
+    {   
+        QualitativeConstraintStatement result = default(QualitativeConstraintStatement);
+
+        IToken id1 = null;
+        IToken derivid = null;
+        IToken id2 = null;
+        IToken op = null;
+        IToken id3 = null;
+
+        try {
+        	dbg.EnterRule(GrammarFileName, "qualConstraint");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(417, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:419:2: (id1= T_IDENTIFIER T_EQUAL ( T_DERIV derivid= T_IDENTIFIER | id2= T_IDENTIFIER ( (op= T_SUM | op= T_DIFF | op= T_PROD ) id3= T_IDENTIFIER | ) ) )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:419:4: id1= T_IDENTIFIER T_EQUAL ( T_DERIV derivid= T_IDENTIFIER | id2= T_IDENTIFIER ( (op= T_SUM | op= T_DIFF | op= T_PROD ) id3= T_IDENTIFIER | ) )
+            {
+            	dbg.Location(419,7);
+            	id1=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_qualConstraint1556); 
+            	dbg.Location(419,21);
+            	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_qualConstraint1558); 
+            	dbg.Location(420,3);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:420:3: ( T_DERIV derivid= T_IDENTIFIER | id2= T_IDENTIFIER ( (op= T_SUM | op= T_DIFF | op= T_PROD ) id3= T_IDENTIFIER | ) )
+            	int alt46 = 2;
+            	try { dbg.EnterSubRule(46);
+            	try { dbg.EnterDecision(46);
+
+            	int LA46_0 = input.LA(1);
+
+            	if ( (LA46_0 == T_DERIV) )
+            	{
+            	    alt46 = 1;
+            	}
+            	else if ( (LA46_0 == T_IDENTIFIER) )
+            	{
+            	    alt46 = 2;
+            	}
+            	else 
+            	{
+            	    NoViableAltException nvae_d46s0 =
+            	        new NoViableAltException("", 46, 0, input);
+
+            	    dbg.RecognitionException(nvae_d46s0);
+            	    throw nvae_d46s0;
+            	}
+            	} finally { dbg.ExitDecision(46); }
+
+            	switch (alt46) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:420:5: T_DERIV derivid= T_IDENTIFIER
+            	        {
+            	        	dbg.Location(420,5);
+            	        	Match(input,T_DERIV,FOLLOW_T_DERIV_in_qualConstraint1565); 
+            	        	dbg.Location(420,20);
+            	        	derivid=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_qualConstraint1569); 
+            	        	dbg.Location(421,4);
+            	        	result = createQualDerivConstraintStatement(id1,derivid);
+
+            	        }
+            	        break;
+            	    case 2 :
+            	        dbg.EnterAlt(2);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:424:11: id2= T_IDENTIFIER ( (op= T_SUM | op= T_DIFF | op= T_PROD ) id3= T_IDENTIFIER | )
+            	        {
+            	        	dbg.Location(424,14);
+            	        	id2=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_qualConstraint1604); 
+            	        	dbg.Location(425,11);
+            	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:425:11: ( (op= T_SUM | op= T_DIFF | op= T_PROD ) id3= T_IDENTIFIER | )
+            	        	int alt45 = 2;
+            	        	try { dbg.EnterSubRule(45);
+            	        	try { dbg.EnterDecision(45);
+
+            	        	int LA45_0 = input.LA(1);
+
+            	        	if ( ((LA45_0 >= T_SUM && LA45_0 <= T_PROD)) )
+            	        	{
+            	        	    alt45 = 1;
+            	        	}
+            	        	else if ( (LA45_0 == T_COMMA || LA45_0 == T_END) )
+            	        	{
+            	        	    alt45 = 2;
+            	        	}
+            	        	else 
+            	        	{
+            	        	    NoViableAltException nvae_d45s0 =
+            	        	        new NoViableAltException("", 45, 0, input);
+
+            	        	    dbg.RecognitionException(nvae_d45s0);
+            	        	    throw nvae_d45s0;
+            	        	}
+            	        	} finally { dbg.ExitDecision(45); }
+
+            	        	switch (alt45) 
+            	        	{
+            	        	    case 1 :
+            	        	        dbg.EnterAlt(1);
+
+            	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:426:12: (op= T_SUM | op= T_DIFF | op= T_PROD ) id3= T_IDENTIFIER
+            	        	        {
+            	        	        	dbg.Location(426,12);
+            	        	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:426:12: (op= T_SUM | op= T_DIFF | op= T_PROD )
+            	        	        	int alt44 = 3;
+            	        	        	try { dbg.EnterSubRule(44);
+            	        	        	try { dbg.EnterDecision(44);
+
+            	        	        	switch ( input.LA(1) ) 
+            	        	        	{
+            	        	        	case T_SUM:
+            	        	        		{
+            	        	        	    alt44 = 1;
+            	        	        	    }
+            	        	        	    break;
+            	        	        	case T_DIFF:
+            	        	        		{
+            	        	        	    alt44 = 2;
+            	        	        	    }
+            	        	        	    break;
+            	        	        	case T_PROD:
+            	        	        		{
+            	        	        	    alt44 = 3;
+            	        	        	    }
+            	        	        	    break;
+            	        	        		default:
+            	        	        		    NoViableAltException nvae_d44s0 =
+            	        	        		        new NoViableAltException("", 44, 0, input);
+
+            	        	        		    dbg.RecognitionException(nvae_d44s0);
+            	        	        		    throw nvae_d44s0;
+            	        	        	}
+
+            	        	        	} finally { dbg.ExitDecision(44); }
+
+            	        	        	switch (alt44) 
+            	        	        	{
+            	        	        	    case 1 :
+            	        	        	        dbg.EnterAlt(1);
+
+            	        	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:426:14: op= T_SUM
+            	        	        	        {
+            	        	        	        	dbg.Location(426,16);
+            	        	        	        	op=(IToken)Match(input,T_SUM,FOLLOW_T_SUM_in_qualConstraint1635); 
+
+            	        	        	        }
+            	        	        	        break;
+            	        	        	    case 2 :
+            	        	        	        dbg.EnterAlt(2);
+
+            	        	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:427:14: op= T_DIFF
+            	        	        	        {
+            	        	        	        	dbg.Location(427,16);
+            	        	        	        	op=(IToken)Match(input,T_DIFF,FOLLOW_T_DIFF_in_qualConstraint1652); 
+
+            	        	        	        }
+            	        	        	        break;
+            	        	        	    case 3 :
+            	        	        	        dbg.EnterAlt(3);
+
+            	        	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:428:14: op= T_PROD
+            	        	        	        {
+            	        	        	        	dbg.Location(428,16);
+            	        	        	        	op=(IToken)Match(input,T_PROD,FOLLOW_T_PROD_in_qualConstraint1669); 
+
+            	        	        	        }
+            	        	        	        break;
+
+            	        	        	}
+            	        	        	} finally { dbg.ExitSubRule(44); }
+
+            	        	        	dbg.Location(430,15);
+            	        	        	id3=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_qualConstraint1698); 
+            	        	        	dbg.Location(431,12);
+            	        	        	result = createQualArithConstraintStatement(id1,id2,id3,op);
+
+            	        	        }
+            	        	        break;
+            	        	    case 2 :
+            	        	        dbg.EnterAlt(2);
+
+            	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:433:12: 
+            	        	        {
+            	        	        	dbg.Location(433,12);
+            	        	        	result = createQualEqualConstraintStatement(id1,id2);
+
+            	        	        }
+            	        	        break;
+
+            	        	}
+            	        	} finally { dbg.ExitSubRule(45); }
+
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(46); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(436, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "qualConstraint");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "qualConstraint"
+
+
+    // $ANTLR start "discreteActionBody"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:441:1: discreteActionBody returns [GuardedCommand result] : T_REQUIRES expr= expression T_COLON bdy= actionBody[null] T_END ;
+    public GuardedCommand discreteActionBody() // throws RecognitionException [1]
+    {   
+        GuardedCommand result = default(GuardedCommand);
+
+        Expression expr = default(Expression);
+
+        Block bdy = default(Block);
+
+
+
+        		result = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "discreteActionBody");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(441, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:446:2: ( T_REQUIRES expr= expression T_COLON bdy= actionBody[null] T_END )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:447:3: T_REQUIRES expr= expression T_COLON bdy= actionBody[null] T_END
+            {
+            	dbg.Location(447,3);
+            	Match(input,T_REQUIRES,FOLLOW_T_REQUIRES_in_discreteActionBody1788); 
+            	dbg.Location(447,18);
+            	PushFollow(FOLLOW_expression_in_discreteActionBody1792);
+            	expr = expression();
+            	state.followingStackPointer--;
+
+            	dbg.Location(447,30);
+            	Match(input,T_COLON,FOLLOW_T_COLON_in_discreteActionBody1794); 
+            	dbg.Location(448,7);
+            	PushFollow(FOLLOW_actionBody_in_discreteActionBody1801);
+            	bdy = actionBody(null);
+            	state.followingStackPointer--;
+
+            	dbg.Location(449,3);
+            	Match(input,T_END,FOLLOW_T_END_in_discreteActionBody1806); 
+            	dbg.Location(450,3);
+            	result = createGuardedCommandStatement(expr,bdy);
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(451, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "discreteActionBody");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "discreteActionBody"
+
+
+    // $ANTLR start "actionBlock"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:458:1: actionBlock[Block top] returns [Block prioList] : actionBlockParallel[prioList] ( T_PRIO actionBlockParallel[prioList] )* ;
+    public Block actionBlock(Block top) // throws RecognitionException [1]
+    {   
+        Block prioList = default(Block);
+
+        try {
+        	dbg.EnterRule(GrammarFileName, "actionBlock");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(458, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:460:2: ( actionBlockParallel[prioList] ( T_PRIO actionBlockParallel[prioList] )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:460:6: actionBlockParallel[prioList] ( T_PRIO actionBlockParallel[prioList] )*
+            {
+            	dbg.Location(460,6);
+            	prioList = createPrioBlock(top);
+            	dbg.Location(461,4);
+            	PushFollow(FOLLOW_actionBlockParallel_in_actionBlock1842);
+            	actionBlockParallel(prioList);
+            	state.followingStackPointer--;
+
+            	dbg.Location(461,34);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:461:34: ( T_PRIO actionBlockParallel[prioList] )*
+            	try { dbg.EnterSubRule(47);
+
+            	do 
+            	{
+            	    int alt47 = 2;
+            	    try { dbg.EnterDecision(47);
+
+            	    int LA47_0 = input.LA(1);
+
+            	    if ( (LA47_0 == T_PRIO) )
+            	    {
+            	        alt47 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(47); }
+
+            	    switch (alt47) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:461:35: T_PRIO actionBlockParallel[prioList]
+            			    {
+            			    	dbg.Location(461,35);
+            			    	Match(input,T_PRIO,FOLLOW_T_PRIO_in_actionBlock1846); 
+            			    	dbg.Location(461,42);
+            			    	PushFollow(FOLLOW_actionBlockParallel_in_actionBlock1848);
+            			    	actionBlockParallel(prioList);
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop47;
+            	    }
+            	} while (true);
+
+            	loop47:
+            		;	// Stops C# compiler whining that label 'loop47' has no statements
+            	} finally { dbg.ExitSubRule(47); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(462, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "actionBlock");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return prioList;
+    }
+    // $ANTLR end "actionBlock"
+
+
+    // $ANTLR start "actionBlockParallel"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:464:1: actionBlockParallel[Block top] : actionBlockSequential[parList] ( T_NONDET actionBlockSequential[parList] )* ;
+    public void actionBlockParallel(Block top) // throws RecognitionException [1]
+    {   
+        try {
+        	dbg.EnterRule(GrammarFileName, "actionBlockParallel");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(464, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:465:2: ( actionBlockSequential[parList] ( T_NONDET actionBlockSequential[parList] )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:465:6: actionBlockSequential[parList] ( T_NONDET actionBlockSequential[parList] )*
+            {
+            	dbg.Location(465,6);
+            	Block parList = createNondetBlock(top);
+            	dbg.Location(466,3);
+            	PushFollow(FOLLOW_actionBlockSequential_in_actionBlockParallel1873);
+            	actionBlockSequential(parList);
+            	state.followingStackPointer--;
+
+            	dbg.Location(466,34);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:466:34: ( T_NONDET actionBlockSequential[parList] )*
+            	try { dbg.EnterSubRule(48);
+
+            	do 
+            	{
+            	    int alt48 = 2;
+            	    try { dbg.EnterDecision(48);
+
+            	    int LA48_0 = input.LA(1);
+
+            	    if ( (LA48_0 == T_NONDET) )
+            	    {
+            	        alt48 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(48); }
+
+            	    switch (alt48) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:466:35: T_NONDET actionBlockSequential[parList]
+            			    {
+            			    	dbg.Location(466,35);
+            			    	Match(input,T_NONDET,FOLLOW_T_NONDET_in_actionBlockParallel1877); 
+            			    	dbg.Location(466,44);
+            			    	PushFollow(FOLLOW_actionBlockSequential_in_actionBlockParallel1879);
+            			    	actionBlockSequential(parList);
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop48;
+            	    }
+            	} while (true);
+
+            	loop48:
+            		;	// Stops C# compiler whining that label 'loop48' has no statements
+            	} finally { dbg.ExitSubRule(48); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(467, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "actionBlockParallel");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "actionBlockParallel"
+
+
+    // $ANTLR start "actionBlockSequential"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:470:1: actionBlockSequential[Block top] : ( T_VAR syms= blockvarlist[seqList] ( '&' sexpr= expression )? T_COLON )? actionBlockParen[seqList] ( T_SEMICOLON actionBlockParen[seqList] )* ;
+    public void actionBlockSequential(Block top) // throws RecognitionException [1]
+    {   
+        Expression sexpr = default(Expression);
+
+
+
+        			Block seqList = createSeqBlock(top);
+        			pushBlockToResolveStack(seqList);
+        		
+        try {
+        	dbg.EnterRule(GrammarFileName, "actionBlockSequential");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(470, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:475:2: ( ( T_VAR syms= blockvarlist[seqList] ( '&' sexpr= expression )? T_COLON )? actionBlockParen[seqList] ( T_SEMICOLON actionBlockParen[seqList] )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:475:5: ( T_VAR syms= blockvarlist[seqList] ( '&' sexpr= expression )? T_COLON )? actionBlockParen[seqList] ( T_SEMICOLON actionBlockParen[seqList] )*
+            {
+            	dbg.Location(475,5);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:475:5: ( T_VAR syms= blockvarlist[seqList] ( '&' sexpr= expression )? T_COLON )?
+            	int alt50 = 2;
+            	try { dbg.EnterSubRule(50);
+            	try { dbg.EnterDecision(50);
+
+            	int LA50_0 = input.LA(1);
+
+            	if ( (LA50_0 == T_VAR) )
+            	{
+            	    alt50 = 1;
+            	}
+            	} finally { dbg.ExitDecision(50); }
+
+            	switch (alt50) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:475:6: T_VAR syms= blockvarlist[seqList] ( '&' sexpr= expression )? T_COLON
+            	        {
+            	        	dbg.Location(475,6);
+            	        	Match(input,T_VAR,FOLLOW_T_VAR_in_actionBlockSequential1908); 
+            	        	dbg.Location(475,16);
+            	        	PushFollow(FOLLOW_blockvarlist_in_actionBlockSequential1912);
+            	        	blockvarlist(seqList);
+            	        	state.followingStackPointer--;
+
+            	        	dbg.Location(475,39);
+            	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:475:39: ( '&' sexpr= expression )?
+            	        	int alt49 = 2;
+            	        	try { dbg.EnterSubRule(49);
+            	        	try { dbg.EnterDecision(49);
+
+            	        	int LA49_0 = input.LA(1);
+
+            	        	if ( (LA49_0 == 120) )
+            	        	{
+            	        	    alt49 = 1;
+            	        	}
+            	        	} finally { dbg.ExitDecision(49); }
+
+            	        	switch (alt49) 
+            	        	{
+            	        	    case 1 :
+            	        	        dbg.EnterAlt(1);
+
+            	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:475:40: '&' sexpr= expression
+            	        	        {
+            	        	        	dbg.Location(475,40);
+            	        	        	Match(input,120,FOLLOW_120_in_actionBlockSequential1916); 
+            	        	        	dbg.Location(475,49);
+            	        	        	PushFollow(FOLLOW_expression_in_actionBlockSequential1920);
+            	        	        	sexpr = expression();
+            	        	        	state.followingStackPointer--;
+
+            	        	        	dbg.Location(475,61);
+            	        	        	addSeqBlockExpression(seqList,sexpr);
+
+            	        	        }
+            	        	        break;
+
+            	        	}
+            	        	} finally { dbg.ExitSubRule(49); }
+
+            	        	dbg.Location(475,104);
+            	        	Match(input,T_COLON,FOLLOW_T_COLON_in_actionBlockSequential1927); 
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(50); }
+
+            	dbg.Location(476,4);
+            	PushFollow(FOLLOW_actionBlockParen_in_actionBlockSequential1936);
+            	actionBlockParen(seqList);
+            	state.followingStackPointer--;
+
+            	dbg.Location(476,30);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:476:30: ( T_SEMICOLON actionBlockParen[seqList] )*
+            	try { dbg.EnterSubRule(51);
+
+            	do 
+            	{
+            	    int alt51 = 2;
+            	    try { dbg.EnterDecision(51);
+
+            	    int LA51_0 = input.LA(1);
+
+            	    if ( (LA51_0 == T_SEMICOLON) )
+            	    {
+            	        alt51 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(51); }
+
+            	    switch (alt51) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:476:31: T_SEMICOLON actionBlockParen[seqList]
+            			    {
+            			    	dbg.Location(476,31);
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_actionBlockSequential1940); 
+            			    	dbg.Location(476,43);
+            			    	PushFollow(FOLLOW_actionBlockParen_in_actionBlockSequential1942);
+            			    	actionBlockParen(seqList);
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop51;
+            	    }
+            	} while (true);
+
+            	loop51:
+            		;	// Stops C# compiler whining that label 'loop51' has no statements
+            	} finally { dbg.ExitSubRule(51); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            popBlockFromResolveStack(seqList);
+        }
+        dbg.Location(477, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "actionBlockSequential");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "actionBlockSequential"
+
+
+    // $ANTLR start "actionBlockParen"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:481:1: actionBlockParen[Block top] : ( T_LPAREN actionBlock[top] T_RPAREN | anonymousOrNamedAction[top] );
+    public void actionBlockParen(Block top) // throws RecognitionException [1]
+    {   
+        try {
+        	dbg.EnterRule(GrammarFileName, "actionBlockParen");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(481, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:482:2: ( T_LPAREN actionBlock[top] T_RPAREN | anonymousOrNamedAction[top] )
+            int alt52 = 2;
+            try { dbg.EnterDecision(52);
+
+            int LA52_0 = input.LA(1);
+
+            if ( (LA52_0 == T_LPAREN) )
+            {
+                alt52 = 1;
+            }
+            else if ( (LA52_0 == T_IDENTIFIER || (LA52_0 >= T_CONT && LA52_0 <= T_REQUIRES) || LA52_0 == T_SKIP) )
+            {
+                alt52 = 2;
+            }
+            else 
+            {
+                NoViableAltException nvae_d52s0 =
+                    new NoViableAltException("", 52, 0, input);
+
+                dbg.RecognitionException(nvae_d52s0);
+                throw nvae_d52s0;
+            }
+            } finally { dbg.ExitDecision(52); }
+
+            switch (alt52) 
+            {
+                case 1 :
+                    dbg.EnterAlt(1);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:482:4: T_LPAREN actionBlock[top] T_RPAREN
+                    {
+                    	dbg.Location(482,4);
+                    	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_actionBlockParen1966); 
+                    	dbg.Location(482,13);
+                    	PushFollow(FOLLOW_actionBlock_in_actionBlockParen1968);
+                    	actionBlock(top);
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(482,30);
+                    	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_actionBlockParen1971); 
+
+                    }
+                    break;
+                case 2 :
+                    dbg.EnterAlt(2);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:483:4: anonymousOrNamedAction[top]
+                    {
+                    	dbg.Location(483,4);
+                    	PushFollow(FOLLOW_anonymousOrNamedAction_in_actionBlockParen1976);
+                    	anonymousOrNamedAction(top);
+                    	state.followingStackPointer--;
+
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(484, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "actionBlockParen");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "actionBlockParen"
+
+
+    // $ANTLR start "anonymousOrNamedAction"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:486:1: anonymousOrNamedAction[Block top] : (gcmd= anonymousAction | aname= T_IDENTIFIER ( T_LPAREN m_params= methodCallParams T_RPAREN )? (amap= ( T_FOLDLR | T_FOLDRL ) '(' amapexpr= expression ')' )? | T_SKIP );
+    public void anonymousOrNamedAction(Block top) // throws RecognitionException [1]
+    {   
+        IToken aname = null;
+        IToken amap = null;
+        GuardedCommand gcmd = default(GuardedCommand);
+
+        System.Collections.Generic.List<Expression> m_params = default(System.Collections.Generic.List<Expression>);
+
+        Expression amapexpr = default(Expression);
+
+
+        try {
+        	dbg.EnterRule(GrammarFileName, "anonymousOrNamedAction");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(486, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:487:2: (gcmd= anonymousAction | aname= T_IDENTIFIER ( T_LPAREN m_params= methodCallParams T_RPAREN )? (amap= ( T_FOLDLR | T_FOLDRL ) '(' amapexpr= expression ')' )? | T_SKIP )
+            int alt55 = 3;
+            try { dbg.EnterDecision(55);
+
+            switch ( input.LA(1) ) 
+            {
+            case T_CONT:
+            case T_REQUIRES:
+            	{
+                alt55 = 1;
+                }
+                break;
+            case T_IDENTIFIER:
+            	{
+                alt55 = 2;
+                }
+                break;
+            case T_SKIP:
+            	{
+                alt55 = 3;
+                }
+                break;
+            	default:
+            	    NoViableAltException nvae_d55s0 =
+            	        new NoViableAltException("", 55, 0, input);
+
+            	    dbg.RecognitionException(nvae_d55s0);
+            	    throw nvae_d55s0;
+            }
+
+            } finally { dbg.ExitDecision(55); }
+
+            switch (alt55) 
+            {
+                case 1 :
+                    dbg.EnterAlt(1);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:487:4: gcmd= anonymousAction
+                    {
+                    	dbg.Location(487,8);
+                    	PushFollow(FOLLOW_anonymousAction_in_anonymousOrNamedAction1993);
+                    	gcmd = anonymousAction();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(487,25);
+                    	addToBlockList(top,gcmd);
+
+                    }
+                    break;
+                case 2 :
+                    dbg.EnterAlt(2);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:488:4: aname= T_IDENTIFIER ( T_LPAREN m_params= methodCallParams T_RPAREN )? (amap= ( T_FOLDLR | T_FOLDRL ) '(' amapexpr= expression ')' )?
+                    {
+                    	dbg.Location(488,9);
+                    	aname=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_anonymousOrNamedAction2002); 
+                    	dbg.Location(489,11);
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:489:11: ( T_LPAREN m_params= methodCallParams T_RPAREN )?
+                    	int alt53 = 2;
+                    	try { dbg.EnterSubRule(53);
+                    	try { dbg.EnterDecision(53);
+
+                    	int LA53_0 = input.LA(1);
+
+                    	if ( (LA53_0 == T_LPAREN) )
+                    	{
+                    	    alt53 = 1;
+                    	}
+                    	} finally { dbg.ExitDecision(53); }
+
+                    	switch (alt53) 
+                    	{
+                    	    case 1 :
+                    	        dbg.EnterAlt(1);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:489:12: T_LPAREN m_params= methodCallParams T_RPAREN
+                    	        {
+                    	        	dbg.Location(489,12);
+                    	        	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_anonymousOrNamedAction2016); 
+                    	        	dbg.Location(489,30);
+                    	        	PushFollow(FOLLOW_methodCallParams_in_anonymousOrNamedAction2021);
+                    	        	m_params = methodCallParams();
+                    	        	state.followingStackPointer--;
+
+                    	        	dbg.Location(489,48);
+                    	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_anonymousOrNamedAction2023); 
+
+                    	        }
+                    	        break;
+
+                    	}
+                    	} finally { dbg.ExitSubRule(53); }
+
+                    	dbg.Location(490,11);
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:490:11: (amap= ( T_FOLDLR | T_FOLDRL ) '(' amapexpr= expression ')' )?
+                    	int alt54 = 2;
+                    	try { dbg.EnterSubRule(54);
+                    	try { dbg.EnterDecision(54);
+
+                    	int LA54_0 = input.LA(1);
+
+                    	if ( ((LA54_0 >= T_FOLDLR && LA54_0 <= T_FOLDRL)) )
+                    	{
+                    	    alt54 = 1;
+                    	}
+                    	} finally { dbg.ExitDecision(54); }
+
+                    	switch (alt54) 
+                    	{
+                    	    case 1 :
+                    	        dbg.EnterAlt(1);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:490:12: amap= ( T_FOLDLR | T_FOLDRL ) '(' amapexpr= expression ')'
+                    	        {
+                    	        	dbg.Location(490,16);
+                    	        	amap = (IToken)input.LT(1);
+                    	        	if ( (input.LA(1) >= T_FOLDLR && input.LA(1) <= T_FOLDRL) ) 
+                    	        	{
+                    	        	    input.Consume();
+                    	        	    state.errorRecovery = false;
+                    	        	}
+                    	        	else 
+                    	        	{
+                    	        	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	        	    dbg.RecognitionException(mse);
+                    	        	    throw mse;
+                    	        	}
+
+                    	        	dbg.Location(490,37);
+                    	        	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_anonymousOrNamedAction2047); 
+                    	        	dbg.Location(490,49);
+                    	        	PushFollow(FOLLOW_expression_in_anonymousOrNamedAction2051);
+                    	        	amapexpr = expression();
+                    	        	state.followingStackPointer--;
+
+                    	        	dbg.Location(490,61);
+                    	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_anonymousOrNamedAction2053); 
+
+                    	        }
+                    	        break;
+
+                    	}
+                    	} finally { dbg.ExitSubRule(54); }
+
+                    	dbg.Location(491,3);
+                    	addNamedActionCallToBlockList(top,aname,m_params,amap,amapexpr);
+
+                    }
+                    break;
+                case 3 :
+                    dbg.EnterAlt(3);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:492:4: T_SKIP
+                    {
+                    	dbg.Location(492,4);
+                    	Match(input,T_SKIP,FOLLOW_T_SKIP_in_anonymousOrNamedAction2064); 
+                    	dbg.Location(492,11);
+                    	addSkipStatementToBlockList(top);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(493, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "anonymousOrNamedAction");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "anonymousOrNamedAction"
+
+
+    // $ANTLR start "blockvarlist"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:496:1: blockvarlist[Block seqList] : blockvar[seqList] ( T_SEMICOLON blockvar[seqList] )* ;
+    public void blockvarlist(Block seqList) // throws RecognitionException [1]
+    {   
+        try {
+        	dbg.EnterRule(GrammarFileName, "blockvarlist");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(496, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:497:2: ( blockvar[seqList] ( T_SEMICOLON blockvar[seqList] )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:497:4: blockvar[seqList] ( T_SEMICOLON blockvar[seqList] )*
+            {
+            	dbg.Location(497,4);
+            	PushFollow(FOLLOW_blockvar_in_blockvarlist2080);
+            	blockvar(seqList);
+            	state.followingStackPointer--;
+
+            	dbg.Location(497,23);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:497:23: ( T_SEMICOLON blockvar[seqList] )*
+            	try { dbg.EnterSubRule(56);
+
+            	do 
+            	{
+            	    int alt56 = 2;
+            	    try { dbg.EnterDecision(56);
+
+            	    int LA56_0 = input.LA(1);
+
+            	    if ( (LA56_0 == T_SEMICOLON) )
+            	    {
+            	        alt56 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(56); }
+
+            	    switch (alt56) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:497:24: T_SEMICOLON blockvar[seqList]
+            			    {
+            			    	dbg.Location(497,24);
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_blockvarlist2085); 
+            			    	dbg.Location(497,36);
+            			    	PushFollow(FOLLOW_blockvar_in_blockvarlist2087);
+            			    	blockvar(seqList);
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop56;
+            	    }
+            	} while (true);
+
+            	loop56:
+            		;	// Stops C# compiler whining that label 'loop56' has no statements
+            	} finally { dbg.ExitSubRule(56); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(498, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "blockvarlist");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "blockvarlist"
+
+
+    // $ANTLR start "blockvar"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:500:1: blockvar[Block seqList] : varname= T_IDENTIFIER T_COLON aType= complexType ;
+    public void blockvar(Block seqList) // throws RecognitionException [1]
+    {   
+        IToken varname = null;
+        UlyssesType aType = default(UlyssesType);
+
+
+        try {
+        	dbg.EnterRule(GrammarFileName, "blockvar");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(500, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:501:2: (varname= T_IDENTIFIER T_COLON aType= complexType )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:501:5: varname= T_IDENTIFIER T_COLON aType= complexType
+            {
+            	dbg.Location(501,12);
+            	varname=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_blockvar2107); 
+            	dbg.Location(501,27);
+            	Match(input,T_COLON,FOLLOW_T_COLON_in_blockvar2110); 
+            	dbg.Location(501,40);
+            	PushFollow(FOLLOW_complexType_in_blockvar2114);
+            	aType = complexType();
+            	state.followingStackPointer--;
+
+            	dbg.Location(502,3);
+            	addBlockVariable(seqList,varname,aType);
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(503, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "blockvar");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "blockvar"
+
+
+    // $ANTLR start "actionBody"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:511:1: actionBody[Block top] returns [Block result] : actionBodyParallel[result] ( T_PRIO actionBodyParallel[result] )? ;
+    public Block actionBody(Block top) // throws RecognitionException [1]
+    {   
+        Block result = default(Block);
+
+        try {
+        	dbg.EnterRule(GrammarFileName, "actionBody");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(511, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:513:2: ( actionBodyParallel[result] ( T_PRIO actionBodyParallel[result] )? )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:513:4: actionBodyParallel[result] ( T_PRIO actionBodyParallel[result] )?
+            {
+            	dbg.Location(513,4);
+            	result = createPrioBlock(top);
+            	dbg.Location(514,3);
+            	PushFollow(FOLLOW_actionBodyParallel_in_actionBody2149);
+            	actionBodyParallel(result);
+            	state.followingStackPointer--;
+
+            	dbg.Location(514,30);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:514:30: ( T_PRIO actionBodyParallel[result] )?
+            	int alt57 = 2;
+            	try { dbg.EnterSubRule(57);
+            	try { dbg.EnterDecision(57);
+
+            	int LA57_0 = input.LA(1);
+
+            	if ( (LA57_0 == T_PRIO) )
+            	{
+            	    alt57 = 1;
+            	}
+            	} finally { dbg.ExitDecision(57); }
+
+            	switch (alt57) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:514:31: T_PRIO actionBodyParallel[result]
+            	        {
+            	        	dbg.Location(514,31);
+            	        	Match(input,T_PRIO,FOLLOW_T_PRIO_in_actionBody2153); 
+            	        	dbg.Location(514,38);
+            	        	PushFollow(FOLLOW_actionBodyParallel_in_actionBody2155);
+            	        	actionBodyParallel(result);
+            	        	state.followingStackPointer--;
+
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(57); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(515, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "actionBody");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "actionBody"
+
+
+    // $ANTLR start "actionBodyParallel"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:517:1: actionBodyParallel[Block top] returns [Block result] : actionBodySequential[result] ( T_NONDET olst= actionBodySequential[result] )* ;
+    public Block actionBodyParallel(Block top) // throws RecognitionException [1]
+    {   
+        Block result = default(Block);
+
+        Block olst = default(Block);
+
+
+        try {
+        	dbg.EnterRule(GrammarFileName, "actionBodyParallel");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(517, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:519:2: ( actionBodySequential[result] ( T_NONDET olst= actionBodySequential[result] )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:519:4: actionBodySequential[result] ( T_NONDET olst= actionBodySequential[result] )*
+            {
+            	dbg.Location(519,4);
+            	result = createNondetBlock(top);
+            	dbg.Location(520,3);
+            	PushFollow(FOLLOW_actionBodySequential_in_actionBodyParallel2183);
+            	actionBodySequential(result);
+            	state.followingStackPointer--;
+
+            	dbg.Location(521,3);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:521:3: ( T_NONDET olst= actionBodySequential[result] )*
+            	try { dbg.EnterSubRule(58);
+
+            	do 
+            	{
+            	    int alt58 = 2;
+            	    try { dbg.EnterDecision(58);
+
+            	    int LA58_0 = input.LA(1);
+
+            	    if ( (LA58_0 == T_NONDET) )
+            	    {
+            	        alt58 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(58); }
+
+            	    switch (alt58) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:521:4: T_NONDET olst= actionBodySequential[result]
+            			    {
+            			    	dbg.Location(521,4);
+            			    	Match(input,T_NONDET,FOLLOW_T_NONDET_in_actionBodyParallel2189); 
+            			    	dbg.Location(521,17);
+            			    	PushFollow(FOLLOW_actionBodySequential_in_actionBodyParallel2193);
+            			    	olst = actionBodySequential(result);
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop58;
+            	    }
+            	} while (true);
+
+            	loop58:
+            		;	// Stops C# compiler whining that label 'loop58' has no statements
+            	} finally { dbg.ExitSubRule(58); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(522, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "actionBodyParallel");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "actionBodyParallel"
+
+
+    // $ANTLR start "actionBodySequential"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:525:1: actionBodySequential[Block top] returns [Block result] : actionBodyParen[result] ( T_SEMICOLON actionBodyParen[result] )* ;
+    public Block actionBodySequential(Block top) // throws RecognitionException [1]
+    {   
+        Block result = default(Block);
+
+        try {
+        	dbg.EnterRule(GrammarFileName, "actionBodySequential");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(525, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:527:2: ( actionBodyParen[result] ( T_SEMICOLON actionBodyParen[result] )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:527:4: actionBodyParen[result] ( T_SEMICOLON actionBodyParen[result] )*
+            {
+            	dbg.Location(527,4);
+            	result = createSeqBlock(top);
+            	dbg.Location(528,3);
+            	PushFollow(FOLLOW_actionBodyParen_in_actionBodySequential2220);
+            	actionBodyParen(result);
+            	state.followingStackPointer--;
+
+            	dbg.Location(528,27);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:528:27: ( T_SEMICOLON actionBodyParen[result] )*
+            	try { dbg.EnterSubRule(59);
+
+            	do 
+            	{
+            	    int alt59 = 2;
+            	    try { dbg.EnterDecision(59);
+
+            	    int LA59_0 = input.LA(1);
+
+            	    if ( (LA59_0 == T_SEMICOLON) )
+            	    {
+            	        alt59 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(59); }
+
+            	    switch (alt59) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:528:28: T_SEMICOLON actionBodyParen[result]
+            			    {
+            			    	dbg.Location(528,28);
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_actionBodySequential2224); 
+            			    	dbg.Location(528,40);
+            			    	PushFollow(FOLLOW_actionBodyParen_in_actionBodySequential2226);
+            			    	actionBodyParen(result);
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop59;
+            	    }
+            	} while (true);
+
+            	loop59:
+            		;	// Stops C# compiler whining that label 'loop59' has no statements
+            	} finally { dbg.ExitSubRule(59); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(529, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "actionBodySequential");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "actionBodySequential"
+
+
+    // $ANTLR start "actionBodyParen"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:531:1: actionBodyParen[Block top] : ( T_LPAREN actionBody[top] T_RPAREN | stmt= statement );
+    public void actionBodyParen(Block top) // throws RecognitionException [1]
+    {   
+        Statement stmt = default(Statement);
+
+
+        try {
+        	dbg.EnterRule(GrammarFileName, "actionBodyParen");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(531, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:532:2: ( T_LPAREN actionBody[top] T_RPAREN | stmt= statement )
+            int alt60 = 2;
+            try { dbg.EnterDecision(60);
+
+            int LA60_0 = input.LA(1);
+
+            if ( (LA60_0 == T_LPAREN) )
+            {
+                alt60 = 1;
+            }
+            else if ( (LA60_0 == T_IDENTIFIER || LA60_0 == T_REQUIRES || (LA60_0 >= T_SKIP && LA60_0 <= T_SELF)) )
+            {
+                alt60 = 2;
+            }
+            else 
+            {
+                NoViableAltException nvae_d60s0 =
+                    new NoViableAltException("", 60, 0, input);
+
+                dbg.RecognitionException(nvae_d60s0);
+                throw nvae_d60s0;
+            }
+            } finally { dbg.ExitDecision(60); }
+
+            switch (alt60) 
+            {
+                case 1 :
+                    dbg.EnterAlt(1);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:532:4: T_LPAREN actionBody[top] T_RPAREN
+                    {
+                    	dbg.Location(532,4);
+                    	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_actionBodyParen2244); 
+                    	dbg.Location(532,13);
+                    	PushFollow(FOLLOW_actionBody_in_actionBodyParen2246);
+                    	actionBody(top);
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(532,29);
+                    	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_actionBodyParen2249); 
+
+                    }
+                    break;
+                case 2 :
+                    dbg.EnterAlt(2);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:533:4: stmt= statement
+                    {
+                    	dbg.Location(533,8);
+                    	PushFollow(FOLLOW_statement_in_actionBodyParen2256);
+                    	stmt = statement();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(534,3);
+                    	addToStatementList(top,stmt);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(535, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "actionBodyParen");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "actionBodyParen"
+
+
+    // $ANTLR start "statement"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:538:1: statement returns [Statement result] : ( T_ABORT | T_SKIP | T_KILL T_LPAREN aname= ( T_IDENTIFIER | T_SELF ) T_RPAREN | gc= discreteActionBody | aqname= reference ( T_ASSIGNMENT aexp= expression ( T_WITH ndexp= expression )? | ( T_COMMA malhs= reference )+ T_ASSIGNMENT mexp= expression ( T_COMMA mexp2= expression )+ ( T_WITH ndex2= expression )? | ) );
+    public Statement statement() // throws RecognitionException [1]
+    {   
+        Statement result = default(Statement);
+
+        IToken aname = null;
+        GuardedCommand gc = default(GuardedCommand);
+
+        Expression aqname = default(Expression);
+
+        Expression aexp = default(Expression);
+
+        Expression ndexp = default(Expression);
+
+        Expression malhs = default(Expression);
+
+        Expression mexp = default(Expression);
+
+        Expression mexp2 = default(Expression);
+
+        Expression ndex2 = default(Expression);
+
+
+
+        		bool popFromResolveStack = false;
+        		result = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "statement");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(538, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:544:2: ( T_ABORT | T_SKIP | T_KILL T_LPAREN aname= ( T_IDENTIFIER | T_SELF ) T_RPAREN | gc= discreteActionBody | aqname= reference ( T_ASSIGNMENT aexp= expression ( T_WITH ndexp= expression )? | ( T_COMMA malhs= reference )+ T_ASSIGNMENT mexp= expression ( T_COMMA mexp2= expression )+ ( T_WITH ndex2= expression )? | ) )
+            int alt66 = 5;
+            try { dbg.EnterDecision(66);
+
+            switch ( input.LA(1) ) 
+            {
+            case T_ABORT:
+            	{
+                alt66 = 1;
+                }
+                break;
+            case T_SKIP:
+            	{
+                alt66 = 2;
+                }
+                break;
+            case T_KILL:
+            	{
+                alt66 = 3;
+                }
+                break;
+            case T_REQUIRES:
+            	{
+                alt66 = 4;
+                }
+                break;
+            case T_IDENTIFIER:
+            case T_SELF:
+            	{
+                alt66 = 5;
+                }
+                break;
+            	default:
+            	    NoViableAltException nvae_d66s0 =
+            	        new NoViableAltException("", 66, 0, input);
+
+            	    dbg.RecognitionException(nvae_d66s0);
+            	    throw nvae_d66s0;
+            }
+
+            } finally { dbg.ExitDecision(66); }
+
+            switch (alt66) 
+            {
+                case 1 :
+                    dbg.EnterAlt(1);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:544:4: T_ABORT
+                    {
+                    	dbg.Location(544,4);
+                    	Match(input,T_ABORT,FOLLOW_T_ABORT_in_statement2284); 
+                    	dbg.Location(544,12);
+                    	result = createAbortStatement();
+
+                    }
+                    break;
+                case 2 :
+                    dbg.EnterAlt(2);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:545:4: T_SKIP
+                    {
+                    	dbg.Location(545,4);
+                    	Match(input,T_SKIP,FOLLOW_T_SKIP_in_statement2291); 
+                    	dbg.Location(545,11);
+                    	result = createSkipStatement();
+
+                    }
+                    break;
+                case 3 :
+                    dbg.EnterAlt(3);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:546:4: T_KILL T_LPAREN aname= ( T_IDENTIFIER | T_SELF ) T_RPAREN
+                    {
+                    	dbg.Location(546,4);
+                    	Match(input,T_KILL,FOLLOW_T_KILL_in_statement2298); 
+                    	dbg.Location(546,11);
+                    	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_statement2300); 
+                    	dbg.Location(546,25);
+                    	aname = (IToken)input.LT(1);
+                    	if ( input.LA(1) == T_IDENTIFIER || input.LA(1) == T_SELF ) 
+                    	{
+                    	    input.Consume();
+                    	    state.errorRecovery = false;
+                    	}
+                    	else 
+                    	{
+                    	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	    dbg.RecognitionException(mse);
+                    	    throw mse;
+                    	}
+
+                    	dbg.Location(546,50);
+                    	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_statement2312); 
+                    	dbg.Location(546,59);
+                    	result = createKillStatement(aname);
+
+                    }
+                    break;
+                case 4 :
+                    dbg.EnterAlt(4);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:547:5: gc= discreteActionBody
+                    {
+                    	dbg.Location(547,7);
+                    	PushFollow(FOLLOW_discreteActionBody_in_statement2322);
+                    	gc = discreteActionBody();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(547,27);
+                    	result = gc;
+
+                    }
+                    break;
+                case 5 :
+                    dbg.EnterAlt(5);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:548:4: aqname= reference ( T_ASSIGNMENT aexp= expression ( T_WITH ndexp= expression )? | ( T_COMMA malhs= reference )+ T_ASSIGNMENT mexp= expression ( T_COMMA mexp2= expression )+ ( T_WITH ndex2= expression )? | )
+                    {
+                    	dbg.Location(548,10);
+                    	PushFollow(FOLLOW_reference_in_statement2331);
+                    	aqname = reference();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(549,7);
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:549:7: ( T_ASSIGNMENT aexp= expression ( T_WITH ndexp= expression )? | ( T_COMMA malhs= reference )+ T_ASSIGNMENT mexp= expression ( T_COMMA mexp2= expression )+ ( T_WITH ndex2= expression )? | )
+                    	int alt65 = 3;
+                    	try { dbg.EnterSubRule(65);
+                    	try { dbg.EnterDecision(65);
+
+                    	switch ( input.LA(1) ) 
+                    	{
+                    	case T_ASSIGNMENT:
+                    		{
+                    	    alt65 = 1;
+                    	    }
+                    	    break;
+                    	case T_COMMA:
+                    		{
+                    	    alt65 = 2;
+                    	    }
+                    	    break;
+                    	case T_SEMICOLON:
+                    	case T_PRIO:
+                    	case T_NONDET:
+                    	case T_RPAREN:
+                    	case T_END:
+                    		{
+                    	    alt65 = 3;
+                    	    }
+                    	    break;
+                    		default:
+                    		    NoViableAltException nvae_d65s0 =
+                    		        new NoViableAltException("", 65, 0, input);
+
+                    		    dbg.RecognitionException(nvae_d65s0);
+                    		    throw nvae_d65s0;
+                    	}
+
+                    	} finally { dbg.ExitDecision(65); }
+
+                    	switch (alt65) 
+                    	{
+                    	    case 1 :
+                    	        dbg.EnterAlt(1);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:550:12: T_ASSIGNMENT aexp= expression ( T_WITH ndexp= expression )?
+                    	        {
+                    	        	dbg.Location(550,12);
+                    	        	Match(input,T_ASSIGNMENT,FOLLOW_T_ASSIGNMENT_in_statement2359); 
+                    	        	dbg.Location(550,30);
+                    	        	PushFollow(FOLLOW_expression_in_statement2364);
+                    	        	aexp = expression();
+                    	        	state.followingStackPointer--;
+
+                    	        	dbg.Location(550,43);
+                    	        	result = createSingleAssignmentStatement(aqname,aexp);
+                    	        	dbg.Location(551,15);
+                    	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:551:15: ( T_WITH ndexp= expression )?
+                    	        	int alt61 = 2;
+                    	        	try { dbg.EnterSubRule(61);
+                    	        	try { dbg.EnterDecision(61);
+
+                    	        	int LA61_0 = input.LA(1);
+
+                    	        	if ( (LA61_0 == T_WITH) )
+                    	        	{
+                    	        	    alt61 = 1;
+                    	        	}
+                    	        	} finally { dbg.ExitDecision(61); }
+
+                    	        	switch (alt61) 
+                    	        	{
+                    	        	    case 1 :
+                    	        	        dbg.EnterAlt(1);
+
+                    	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:551:16: T_WITH ndexp= expression
+                    	        	        {
+                    	        	        	dbg.Location(551,16);
+                    	        	        	Match(input,T_WITH,FOLLOW_T_WITH_in_statement2384); 
+                    	        	        	dbg.Location(551,28);
+                    	        	        	PushFollow(FOLLOW_expression_in_statement2388);
+                    	        	        	ndexp = expression();
+                    	        	        	state.followingStackPointer--;
+
+                    	        	        	dbg.Location(551,40);
+                    	        	        	addConstraintToAssignment(result,ndexp);
+
+                    	        	        }
+                    	        	        break;
+
+                    	        	}
+                    	        	} finally { dbg.ExitSubRule(61); }
+
+
+                    	        }
+                    	        break;
+                    	    case 2 :
+                    	        dbg.EnterAlt(2);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:554:8: ( T_COMMA malhs= reference )+ T_ASSIGNMENT mexp= expression ( T_COMMA mexp2= expression )+ ( T_WITH ndex2= expression )?
+                    	        {
+                    	        	dbg.Location(554,8);
+                    	        	result = createMultipleAssignmentStatementLHS(aqname);
+                    	        	dbg.Location(555,7);
+                    	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:555:7: ( T_COMMA malhs= reference )+
+                    	        	int cnt62 = 0;
+                    	        	try { dbg.EnterSubRule(62);
+
+                    	        	do 
+                    	        	{
+                    	        	    int alt62 = 2;
+                    	        	    try { dbg.EnterDecision(62);
+
+                    	        	    int LA62_0 = input.LA(1);
+
+                    	        	    if ( (LA62_0 == T_COMMA) )
+                    	        	    {
+                    	        	        alt62 = 1;
+                    	        	    }
+
+
+                    	        	    } finally { dbg.ExitDecision(62); }
+
+                    	        	    switch (alt62) 
+                    	        		{
+                    	        			case 1 :
+                    	        			    dbg.EnterAlt(1);
+
+                    	        			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:555:8: T_COMMA malhs= reference
+                    	        			    {
+                    	        			    	dbg.Location(555,8);
+                    	        			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_statement2441); 
+                    	        			    	dbg.Location(555,21);
+                    	        			    	PushFollow(FOLLOW_reference_in_statement2445);
+                    	        			    	malhs = reference();
+                    	        			    	state.followingStackPointer--;
+
+                    	        			    	dbg.Location(555,33);
+                    	        			    	addMultipleAssignmentStatementLHS(result,malhs);
+
+                    	        			    }
+                    	        			    break;
+
+                    	        			default:
+                    	        			    if ( cnt62 >= 1 ) goto loop62;
+                    	        		            EarlyExitException eee62 =
+                    	        		                new EarlyExitException(62, input);
+                    	        		            dbg.RecognitionException(eee62);
+
+                    	        		            throw eee62;
+                    	        	    }
+                    	        	    cnt62++;
+                    	        	} while (true);
+
+                    	        	loop62:
+                    	        		;	// Stops C# compiler whining that label 'loop62' has no statements
+                    	        	} finally { dbg.ExitSubRule(62); }
+
+                    	        	dbg.Location(556,8);
+                    	        	Match(input,T_ASSIGNMENT,FOLLOW_T_ASSIGNMENT_in_statement2460); 
+                    	        	dbg.Location(557,8);
+                    	        	pushAssignmentOnResolveStack(result); popFromResolveStack = true;
+                    	        	dbg.Location(558,12);
+                    	        	PushFollow(FOLLOW_expression_in_statement2482);
+                    	        	mexp = expression();
+                    	        	state.followingStackPointer--;
+
+                    	        	dbg.Location(559,8);
+                    	        	addMutlipleAssignmentStatementRHS(result,mexp);
+                    	        	dbg.Location(560,8);
+                    	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:560:8: ( T_COMMA mexp2= expression )+
+                    	        	int cnt63 = 0;
+                    	        	try { dbg.EnterSubRule(63);
+
+                    	        	do 
+                    	        	{
+                    	        	    int alt63 = 2;
+                    	        	    try { dbg.EnterDecision(63);
+
+                    	        	    int LA63_0 = input.LA(1);
+
+                    	        	    if ( (LA63_0 == T_COMMA) )
+                    	        	    {
+                    	        	        alt63 = 1;
+                    	        	    }
+
+
+                    	        	    } finally { dbg.ExitDecision(63); }
+
+                    	        	    switch (alt63) 
+                    	        		{
+                    	        			case 1 :
+                    	        			    dbg.EnterAlt(1);
+
+                    	        			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:560:9: T_COMMA mexp2= expression
+                    	        			    {
+                    	        			    	dbg.Location(560,9);
+                    	        			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_statement2501); 
+                    	        			    	dbg.Location(560,22);
+                    	        			    	PushFollow(FOLLOW_expression_in_statement2505);
+                    	        			    	mexp2 = expression();
+                    	        			    	state.followingStackPointer--;
+
+                    	        			    	dbg.Location(560,34);
+                    	        			    	addMutlipleAssignmentStatementRHS(result,mexp2);
+
+                    	        			    }
+                    	        			    break;
+
+                    	        			default:
+                    	        			    if ( cnt63 >= 1 ) goto loop63;
+                    	        		            EarlyExitException eee63 =
+                    	        		                new EarlyExitException(63, input);
+                    	        		            dbg.RecognitionException(eee63);
+
+                    	        		            throw eee63;
+                    	        	    }
+                    	        	    cnt63++;
+                    	        	} while (true);
+
+                    	        	loop63:
+                    	        		;	// Stops C# compiler whining that label 'loop63' has no statements
+                    	        	} finally { dbg.ExitSubRule(63); }
+
+                    	        	dbg.Location(561,8);
+                    	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:561:8: ( T_WITH ndex2= expression )?
+                    	        	int alt64 = 2;
+                    	        	try { dbg.EnterSubRule(64);
+                    	        	try { dbg.EnterDecision(64);
+
+                    	        	int LA64_0 = input.LA(1);
+
+                    	        	if ( (LA64_0 == T_WITH) )
+                    	        	{
+                    	        	    alt64 = 1;
+                    	        	}
+                    	        	} finally { dbg.ExitDecision(64); }
+
+                    	        	switch (alt64) 
+                    	        	{
+                    	        	    case 1 :
+                    	        	        dbg.EnterAlt(1);
+
+                    	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:561:9: T_WITH ndex2= expression
+                    	        	        {
+                    	        	        	dbg.Location(561,9);
+                    	        	        	Match(input,T_WITH,FOLLOW_T_WITH_in_statement2519); 
+                    	        	        	dbg.Location(561,21);
+                    	        	        	PushFollow(FOLLOW_expression_in_statement2523);
+                    	        	        	ndex2 = expression();
+                    	        	        	state.followingStackPointer--;
+
+                    	        	        	dbg.Location(561,33);
+                    	        	        	addConstraintToAssignment(result,ndex2);
+
+                    	        	        }
+                    	        	        break;
+
+                    	        	}
+                    	        	} finally { dbg.ExitSubRule(64); }
+
+
+                    	        }
+                    	        break;
+                    	    case 3 :
+                    	        dbg.EnterAlt(3);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:564:7: 
+                    	        {
+                    	        	dbg.Location(564,7);
+                    	        	result = createCallStatement(aqname);
+
+                    	        }
+                    	        break;
+
+                    	}
+                    	} finally { dbg.ExitSubRule(65); }
+
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+
+            	       if (popFromResolveStack == true)
+            	            popAssignmentOffResolveStack(result);
+            	
+        }
+        dbg.Location(566, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "statement");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "statement"
+
+
+    // $ANTLR start "expression"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:575:1: expression returns [Expression expr] : left= atomExpression (op= binoperator right= atomExpression )* ;
+    public Expression expression() // throws RecognitionException [1]
+    {   
+        Expression expr = default(Expression);
+
+        Expression left = default(Expression);
+
+        BinaryOperator op = default(BinaryOperator);
+
+        Expression right = default(Expression);
+
+
+
+        		System.Collections.Generic.List<BinaryOperator> operators = new System.Collections.Generic.List<BinaryOperator>();
+        		System.Collections.Generic.List<Expression> expressions = new System.Collections.Generic.List<Expression>();		
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "expression");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(575, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:581:2: (left= atomExpression (op= binoperator right= atomExpression )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:581:4: left= atomExpression (op= binoperator right= atomExpression )*
+            {
+            	dbg.Location(581,8);
+            	PushFollow(FOLLOW_atomExpression_in_expression2598);
+            	left = atomExpression();
+            	state.followingStackPointer--;
+
+            	dbg.Location(582,3);
+            	expressions.Add(left);
+            	dbg.Location(583,3);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:583:3: (op= binoperator right= atomExpression )*
+            	try { dbg.EnterSubRule(67);
+
+            	do 
+            	{
+            	    int alt67 = 2;
+            	    try { dbg.EnterDecision(67);
+
+            	    try 
+            	    {
+            	        isCyclicDecision = true;
+            	        alt67 = dfa67.Predict(input);
+            	    }
+            	    catch (NoViableAltException nvae) 
+            	    {
+            	        dbg.RecognitionException(nvae);
+            	        throw nvae;
+            	    }
+            	    } finally { dbg.ExitDecision(67); }
+
+            	    switch (alt67) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:583:5: op= binoperator right= atomExpression
+            			    {
+            			    	dbg.Location(583,7);
+            			    	PushFollow(FOLLOW_binoperator_in_expression2611);
+            			    	op = binoperator();
+            			    	state.followingStackPointer--;
+
+            			    	dbg.Location(584,10);
+            			    	PushFollow(FOLLOW_atomExpression_in_expression2619);
+            			    	right = atomExpression();
+            			    	state.followingStackPointer--;
+
+            			    	dbg.Location(585,5);
+
+            			    			  	operators.Add(op);
+            			    			  	expressions.Add(right);
+            			    			  
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop67;
+            	    }
+            	} while (true);
+
+            	loop67:
+            		;	// Stops C# compiler whining that label 'loop67' has no statements
+            	} finally { dbg.ExitSubRule(67); }
+
+            	dbg.Location(590,3);
+            	expr = createPrecedenceTree(expressions,operators);
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(591, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "expression");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return expr;
+    }
+    // $ANTLR end "expression"
+
+
+    // $ANTLR start "binoperator"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:594:1: binoperator returns [BinaryOperator binop] : ( T_BIIMPLIES | T_GREATER | T_GREATEREQUAL | T_LESS | T_LESSEQUAL | T_EQUAL | T_NOTEQUAL | T_IMPLIES | T_MINUS | T_SUM | T_IN ( T_SET )? | T_NOT T_IN ( T_SET )? | T_SUBSET | T_OR | T_DIV | T_PROD | T_IDIV | T_MOD | T_UNION | T_DIFF | T_INTER | T_AND | T_POW | T_CONC | T_DOMRESBY | T_DOMRESTO | T_RNGRESBY | T_RNGRESTO | T_MUNION | T_SEQMOD_MAPOVERRIDE );
+    public BinaryOperator binoperator() // throws RecognitionException [1]
+    {   
+        BinaryOperator binop = default(BinaryOperator);
+
+        try {
+        	dbg.EnterRule(GrammarFileName, "binoperator");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(594, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:596:2: ( T_BIIMPLIES | T_GREATER | T_GREATEREQUAL | T_LESS | T_LESSEQUAL | T_EQUAL | T_NOTEQUAL | T_IMPLIES | T_MINUS | T_SUM | T_IN ( T_SET )? | T_NOT T_IN ( T_SET )? | T_SUBSET | T_OR | T_DIV | T_PROD | T_IDIV | T_MOD | T_UNION | T_DIFF | T_INTER | T_AND | T_POW | T_CONC | T_DOMRESBY | T_DOMRESTO | T_RNGRESBY | T_RNGRESTO | T_MUNION | T_SEQMOD_MAPOVERRIDE )
+            int alt70 = 30;
+            try { dbg.EnterDecision(70);
+
+            try 
+            {
+                isCyclicDecision = true;
+                alt70 = dfa70.Predict(input);
+            }
+            catch (NoViableAltException nvae) 
+            {
+                dbg.RecognitionException(nvae);
+                throw nvae;
+            }
+            } finally { dbg.ExitDecision(70); }
+
+            switch (alt70) 
+            {
+                case 1 :
+                    dbg.EnterAlt(1);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:596:4: T_BIIMPLIES
+                    {
+                    	dbg.Location(596,4);
+                    	Match(input,T_BIIMPLIES,FOLLOW_T_BIIMPLIES_in_binoperator2652); 
+                    	dbg.Location(597,3);
+                    	binop = createBinaryOperator(ExpressionKind.biimplies);
+
+                    }
+                    break;
+                case 2 :
+                    dbg.EnterAlt(2);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:598:4: T_GREATER
+                    {
+                    	dbg.Location(598,4);
+                    	Match(input,T_GREATER,FOLLOW_T_GREATER_in_binoperator2661); 
+                    	dbg.Location(599,3);
+                    	binop = createBinaryOperator(ExpressionKind.greater);
+
+                    }
+                    break;
+                case 3 :
+                    dbg.EnterAlt(3);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:600:4: T_GREATEREQUAL
+                    {
+                    	dbg.Location(600,4);
+                    	Match(input,T_GREATEREQUAL,FOLLOW_T_GREATEREQUAL_in_binoperator2671); 
+                    	dbg.Location(601,3);
+                    	binop = createBinaryOperator(ExpressionKind.greaterequal);
+
+                    }
+                    break;
+                case 4 :
+                    dbg.EnterAlt(4);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:602:4: T_LESS
+                    {
+                    	dbg.Location(602,4);
+                    	Match(input,T_LESS,FOLLOW_T_LESS_in_binoperator2680); 
+                    	dbg.Location(603,3);
+                    	binop = createBinaryOperator(ExpressionKind.less);
+
+                    }
+                    break;
+                case 5 :
+                    dbg.EnterAlt(5);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:604:4: T_LESSEQUAL
+                    {
+                    	dbg.Location(604,4);
+                    	Match(input,T_LESSEQUAL,FOLLOW_T_LESSEQUAL_in_binoperator2690); 
+                    	dbg.Location(605,3);
+                    	binop = createBinaryOperator(ExpressionKind.lessequal);
+
+                    }
+                    break;
+                case 6 :
+                    dbg.EnterAlt(6);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:606:4: T_EQUAL
+                    {
+                    	dbg.Location(606,4);
+                    	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_binoperator2699); 
+                    	dbg.Location(607,3);
+                    	binop = createBinaryOperator(ExpressionKind.equal);
+
+                    }
+                    break;
+                case 7 :
+                    dbg.EnterAlt(7);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:608:4: T_NOTEQUAL
+                    {
+                    	dbg.Location(608,4);
+                    	Match(input,T_NOTEQUAL,FOLLOW_T_NOTEQUAL_in_binoperator2711); 
+                    	dbg.Location(609,3);
+                    	binop = createBinaryOperator(ExpressionKind.notequal);
+
+                    }
+                    break;
+                case 8 :
+                    dbg.EnterAlt(8);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:610:4: T_IMPLIES
+                    {
+                    	dbg.Location(610,4);
+                    	Match(input,T_IMPLIES,FOLLOW_T_IMPLIES_in_binoperator2722); 
+                    	dbg.Location(611,3);
+                    	binop = createBinaryOperator(ExpressionKind.implies);
+
+                    }
+                    break;
+                case 9 :
+                    dbg.EnterAlt(9);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:612:4: T_MINUS
+                    {
+                    	dbg.Location(612,4);
+                    	Match(input,T_MINUS,FOLLOW_T_MINUS_in_binoperator2731); 
+                    	dbg.Location(613,3);
+                    	binop = createBinaryOperator(ExpressionKind.minus);
+
+                    }
+                    break;
+                case 10 :
+                    dbg.EnterAlt(10);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:614:4: T_SUM
+                    {
+                    	dbg.Location(614,4);
+                    	Match(input,T_SUM,FOLLOW_T_SUM_in_binoperator2741); 
+                    	dbg.Location(615,3);
+                    	binop = createBinaryOperator(ExpressionKind.sum);
+
+                    }
+                    break;
+                case 11 :
+                    dbg.EnterAlt(11);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:616:4: T_IN ( T_SET )?
+                    {
+                    	dbg.Location(616,4);
+                    	Match(input,T_IN,FOLLOW_T_IN_in_binoperator2751); 
+                    	dbg.Location(616,9);
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:616:9: ( T_SET )?
+                    	int alt68 = 2;
+                    	try { dbg.EnterSubRule(68);
+                    	try { dbg.EnterDecision(68);
+
+                    	try 
+                    	{
+                    	    isCyclicDecision = true;
+                    	    alt68 = dfa68.Predict(input);
+                    	}
+                    	catch (NoViableAltException nvae) 
+                    	{
+                    	    dbg.RecognitionException(nvae);
+                    	    throw nvae;
+                    	}
+                    	} finally { dbg.ExitDecision(68); }
+
+                    	switch (alt68) 
+                    	{
+                    	    case 1 :
+                    	        dbg.EnterAlt(1);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:616:9: T_SET
+                    	        {
+                    	        	dbg.Location(616,9);
+                    	        	Match(input,T_SET,FOLLOW_T_SET_in_binoperator2753); 
+
+                    	        }
+                    	        break;
+
+                    	}
+                    	} finally { dbg.ExitSubRule(68); }
+
+                    	dbg.Location(617,3);
+                    	binop = createBinaryOperator(ExpressionKind.elemin);
+
+                    }
+                    break;
+                case 12 :
+                    dbg.EnterAlt(12);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:618:4: T_NOT T_IN ( T_SET )?
+                    {
+                    	dbg.Location(618,4);
+                    	Match(input,T_NOT,FOLLOW_T_NOT_in_binoperator2764); 
+                    	dbg.Location(618,10);
+                    	Match(input,T_IN,FOLLOW_T_IN_in_binoperator2766); 
+                    	dbg.Location(618,15);
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:618:15: ( T_SET )?
+                    	int alt69 = 2;
+                    	try { dbg.EnterSubRule(69);
+                    	try { dbg.EnterDecision(69);
+
+                    	try 
+                    	{
+                    	    isCyclicDecision = true;
+                    	    alt69 = dfa69.Predict(input);
+                    	}
+                    	catch (NoViableAltException nvae) 
+                    	{
+                    	    dbg.RecognitionException(nvae);
+                    	    throw nvae;
+                    	}
+                    	} finally { dbg.ExitDecision(69); }
+
+                    	switch (alt69) 
+                    	{
+                    	    case 1 :
+                    	        dbg.EnterAlt(1);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:618:15: T_SET
+                    	        {
+                    	        	dbg.Location(618,15);
+                    	        	Match(input,T_SET,FOLLOW_T_SET_in_binoperator2768); 
+
+                    	        }
+                    	        break;
+
+                    	}
+                    	} finally { dbg.ExitSubRule(69); }
+
+                    	dbg.Location(619,3);
+                    	binop = createBinaryOperator(ExpressionKind.notelemin);
+
+                    }
+                    break;
+                case 13 :
+                    dbg.EnterAlt(13);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:620:4: T_SUBSET
+                    {
+                    	dbg.Location(620,4);
+                    	Match(input,T_SUBSET,FOLLOW_T_SUBSET_in_binoperator2779); 
+                    	dbg.Location(621,3);
+                    	binop = createBinaryOperator(ExpressionKind.subset);
+
+                    }
+                    break;
+                case 14 :
+                    dbg.EnterAlt(14);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:622:4: T_OR
+                    {
+                    	dbg.Location(622,4);
+                    	Match(input,T_OR,FOLLOW_T_OR_in_binoperator2789); 
+                    	dbg.Location(623,3);
+                    	binop = createBinaryOperator(ExpressionKind.or);
+
+                    }
+                    break;
+                case 15 :
+                    dbg.EnterAlt(15);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:624:4: T_DIV
+                    {
+                    	dbg.Location(624,4);
+                    	Match(input,T_DIV,FOLLOW_T_DIV_in_binoperator2798); 
+                    	dbg.Location(625,3);
+                    	binop = createBinaryOperator(ExpressionKind.div);
+
+                    }
+                    break;
+                case 16 :
+                    dbg.EnterAlt(16);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:626:4: T_PROD
+                    {
+                    	dbg.Location(626,4);
+                    	Match(input,T_PROD,FOLLOW_T_PROD_in_binoperator2807); 
+                    	dbg.Location(627,3);
+                    	binop = createBinaryOperator(ExpressionKind.prod);
+
+                    }
+                    break;
+                case 17 :
+                    dbg.EnterAlt(17);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:628:4: T_IDIV
+                    {
+                    	dbg.Location(628,4);
+                    	Match(input,T_IDIV,FOLLOW_T_IDIV_in_binoperator2817); 
+                    	dbg.Location(629,3);
+                    	binop = createBinaryOperator(ExpressionKind.idiv);
+
+                    }
+                    break;
+                case 18 :
+                    dbg.EnterAlt(18);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:630:4: T_MOD
+                    {
+                    	dbg.Location(630,4);
+                    	Match(input,T_MOD,FOLLOW_T_MOD_in_binoperator2827); 
+                    	dbg.Location(631,3);
+                    	binop = createBinaryOperator(ExpressionKind.mod);
+
+                    }
+                    break;
+                case 19 :
+                    dbg.EnterAlt(19);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:632:4: T_UNION
+                    {
+                    	dbg.Location(632,4);
+                    	Match(input,T_UNION,FOLLOW_T_UNION_in_binoperator2837); 
+                    	dbg.Location(633,3);
+                    	binop = createBinaryOperator(ExpressionKind.union);
+
+                    }
+                    break;
+                case 20 :
+                    dbg.EnterAlt(20);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:634:4: T_DIFF
+                    {
+                    	dbg.Location(634,4);
+                    	Match(input,T_DIFF,FOLLOW_T_DIFF_in_binoperator2848); 
+                    	dbg.Location(635,3);
+                    	binop = createBinaryOperator(ExpressionKind.diff);
+
+                    }
+                    break;
+                case 21 :
+                    dbg.EnterAlt(21);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:636:4: T_INTER
+                    {
+                    	dbg.Location(636,4);
+                    	Match(input,T_INTER,FOLLOW_T_INTER_in_binoperator2859); 
+                    	dbg.Location(637,3);
+                    	binop = createBinaryOperator(ExpressionKind.inter);
+
+                    }
+                    break;
+                case 22 :
+                    dbg.EnterAlt(22);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:638:4: T_AND
+                    {
+                    	dbg.Location(638,4);
+                    	Match(input,T_AND,FOLLOW_T_AND_in_binoperator2870); 
+                    	dbg.Location(639,3);
+                    	binop = createBinaryOperator(ExpressionKind.and);
+
+                    }
+                    break;
+                case 23 :
+                    dbg.EnterAlt(23);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:640:4: T_POW
+                    {
+                    	dbg.Location(640,4);
+                    	Match(input,T_POW,FOLLOW_T_POW_in_binoperator2885); 
+                    	dbg.Location(641,3);
+                    	binop = createBinaryOperator(ExpressionKind.pow);
+
+                    }
+                    break;
+                case 24 :
+                    dbg.EnterAlt(24);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:642:4: T_CONC
+                    {
+                    	dbg.Location(642,4);
+                    	Match(input,T_CONC,FOLLOW_T_CONC_in_binoperator2900); 
+                    	dbg.Location(643,3);
+                    	binop = createBinaryOperator(ExpressionKind.conc);
+
+                    }
+                    break;
+                case 25 :
+                    dbg.EnterAlt(25);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:644:4: T_DOMRESBY
+                    {
+                    	dbg.Location(644,4);
+                    	Match(input,T_DOMRESBY,FOLLOW_T_DOMRESBY_in_binoperator2913); 
+                    	dbg.Location(645,3);
+                    	binop = createBinaryOperator(ExpressionKind.domresby);
+
+                    }
+                    break;
+                case 26 :
+                    dbg.EnterAlt(26);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:646:4: T_DOMRESTO
+                    {
+                    	dbg.Location(646,4);
+                    	Match(input,T_DOMRESTO,FOLLOW_T_DOMRESTO_in_binoperator2923); 
+                    	dbg.Location(647,3);
+                    	binop = createBinaryOperator(ExpressionKind.domresto);
+
+                    }
+                    break;
+                case 27 :
+                    dbg.EnterAlt(27);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:648:4: T_RNGRESBY
+                    {
+                    	dbg.Location(648,4);
+                    	Match(input,T_RNGRESBY,FOLLOW_T_RNGRESBY_in_binoperator2933); 
+                    	dbg.Location(649,3);
+                    	binop = createBinaryOperator(ExpressionKind.rngresby);
+
+                    }
+                    break;
+                case 28 :
+                    dbg.EnterAlt(28);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:650:4: T_RNGRESTO
+                    {
+                    	dbg.Location(650,4);
+                    	Match(input,T_RNGRESTO,FOLLOW_T_RNGRESTO_in_binoperator2943); 
+                    	dbg.Location(651,3);
+                    	binop = createBinaryOperator(ExpressionKind.rngresto);
+
+                    }
+                    break;
+                case 29 :
+                    dbg.EnterAlt(29);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:652:4: T_MUNION
+                    {
+                    	dbg.Location(652,4);
+                    	Match(input,T_MUNION,FOLLOW_T_MUNION_in_binoperator2953); 
+                    	dbg.Location(653,3);
+                    	binop = createBinaryOperator(ExpressionKind.munion);
+
+                    }
+                    break;
+                case 30 :
+                    dbg.EnterAlt(30);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:654:4: T_SEQMOD_MAPOVERRIDE
+                    {
+                    	dbg.Location(654,4);
+                    	Match(input,T_SEQMOD_MAPOVERRIDE,FOLLOW_T_SEQMOD_MAPOVERRIDE_in_binoperator2963); 
+                    	dbg.Location(656,3);
+                    	binop = createBinaryOperator(ExpressionKind.seqmod_mapoverride);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(657, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "binoperator");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return binop;
+    }
+    // $ANTLR end "binoperator"
+
+
+    // $ANTLR start "atomExpression"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:660:1: atomExpression returns [Expression expr] : ( ( (unexpr= op_un )? (e= identifierExpression | e= qvalExpression | e= constant | e= initializedComplexType | e= quantifierExpression | T_LPAREN e= expression T_RPAREN ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )? ) ( 'as' cid= T_IDENTIFIER )? ) | ie= T_IF ce= expression T_THEN te= expression T_ELSE ee= expression T_END );
+    public Expression atomExpression() // throws RecognitionException [1]
+    {   
+        Expression expr = default(Expression);
+
+        IToken idn = null;
+        IToken cid = null;
+        IToken ie = null;
+        UnaryOperator unexpr = default(UnaryOperator);
+
+        Expression e = default(Expression);
+
+        Expression res = default(Expression);
+
+        Expression ce = default(Expression);
+
+        Expression te = default(Expression);
+
+        Expression ee = default(Expression);
+
+
+
+        		expr = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "atomExpression");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(660, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:665:2: ( ( (unexpr= op_un )? (e= identifierExpression | e= qvalExpression | e= constant | e= initializedComplexType | e= quantifierExpression | T_LPAREN e= expression T_RPAREN ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )? ) ( 'as' cid= T_IDENTIFIER )? ) | ie= T_IF ce= expression T_THEN te= expression T_ELSE ee= expression T_END )
+            int alt77 = 2;
+            try { dbg.EnterDecision(77);
+
+            try 
+            {
+                isCyclicDecision = true;
+                alt77 = dfa77.Predict(input);
+            }
+            catch (NoViableAltException nvae) 
+            {
+                dbg.RecognitionException(nvae);
+                throw nvae;
+            }
+            } finally { dbg.ExitDecision(77); }
+
+            switch (alt77) 
+            {
+                case 1 :
+                    dbg.EnterAlt(1);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:665:4: ( (unexpr= op_un )? (e= identifierExpression | e= qvalExpression | e= constant | e= initializedComplexType | e= quantifierExpression | T_LPAREN e= expression T_RPAREN ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )? ) ( 'as' cid= T_IDENTIFIER )? )
+                    {
+                    	dbg.Location(665,4);
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:665:4: ( (unexpr= op_un )? (e= identifierExpression | e= qvalExpression | e= constant | e= initializedComplexType | e= quantifierExpression | T_LPAREN e= expression T_RPAREN ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )? ) ( 'as' cid= T_IDENTIFIER )? )
+                    	dbg.EnterAlt(1);
+
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:665:5: (unexpr= op_un )? (e= identifierExpression | e= qvalExpression | e= constant | e= initializedComplexType | e= quantifierExpression | T_LPAREN e= expression T_RPAREN ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )? ) ( 'as' cid= T_IDENTIFIER )?
+                    	{
+                    		dbg.Location(665,11);
+                    		// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:665:11: (unexpr= op_un )?
+                    		int alt71 = 2;
+                    		try { dbg.EnterSubRule(71);
+                    		try { dbg.EnterDecision(71);
+
+                    		try 
+                    		{
+                    		    isCyclicDecision = true;
+                    		    alt71 = dfa71.Predict(input);
+                    		}
+                    		catch (NoViableAltException nvae) 
+                    		{
+                    		    dbg.RecognitionException(nvae);
+                    		    throw nvae;
+                    		}
+                    		} finally { dbg.ExitDecision(71); }
+
+                    		switch (alt71) 
+                    		{
+                    		    case 1 :
+                    		        dbg.EnterAlt(1);
+
+                    		        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:665:11: unexpr= op_un
+                    		        {
+                    		        	dbg.Location(665,11);
+                    		        	PushFollow(FOLLOW_op_un_in_atomExpression3001);
+                    		        	unexpr = op_un();
+                    		        	state.followingStackPointer--;
+
+
+                    		        }
+                    		        break;
+
+                    		}
+                    		} finally { dbg.ExitSubRule(71); }
+
+                    		dbg.Location(665,19);
+                    		// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:665:19: (e= identifierExpression | e= qvalExpression | e= constant | e= initializedComplexType | e= quantifierExpression | T_LPAREN e= expression T_RPAREN ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )? )
+                    		int alt75 = 6;
+                    		try { dbg.EnterSubRule(75);
+                    		try { dbg.EnterDecision(75);
+
+                    		try 
+                    		{
+                    		    isCyclicDecision = true;
+                    		    alt75 = dfa75.Predict(input);
+                    		}
+                    		catch (NoViableAltException nvae) 
+                    		{
+                    		    dbg.RecognitionException(nvae);
+                    		    throw nvae;
+                    		}
+                    		} finally { dbg.ExitDecision(75); }
+
+                    		switch (alt75) 
+                    		{
+                    		    case 1 :
+                    		        dbg.EnterAlt(1);
+
+                    		        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:666:8: e= identifierExpression
+                    		        {
+                    		        	dbg.Location(666,9);
+                    		        	PushFollow(FOLLOW_identifierExpression_in_atomExpression3018);
+                    		        	e = identifierExpression();
+                    		        	state.followingStackPointer--;
+
+
+                    		        }
+                    		        break;
+                    		    case 2 :
+                    		        dbg.EnterAlt(2);
+
+                    		        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:667:8: e= qvalExpression
+                    		        {
+                    		        	dbg.Location(667,9);
+                    		        	PushFollow(FOLLOW_qvalExpression_in_atomExpression3029);
+                    		        	e = qvalExpression();
+                    		        	state.followingStackPointer--;
+
+
+                    		        }
+                    		        break;
+                    		    case 3 :
+                    		        dbg.EnterAlt(3);
+
+                    		        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:668:8: e= constant
+                    		        {
+                    		        	dbg.Location(668,9);
+                    		        	PushFollow(FOLLOW_constant_in_atomExpression3040);
+                    		        	e = constant();
+                    		        	state.followingStackPointer--;
+
+
+                    		        }
+                    		        break;
+                    		    case 4 :
+                    		        dbg.EnterAlt(4);
+
+                    		        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:669:8: e= initializedComplexType
+                    		        {
+                    		        	dbg.Location(669,9);
+                    		        	PushFollow(FOLLOW_initializedComplexType_in_atomExpression3051);
+                    		        	e = initializedComplexType();
+                    		        	state.followingStackPointer--;
+
+
+                    		        }
+                    		        break;
+                    		    case 5 :
+                    		        dbg.EnterAlt(5);
+
+                    		        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:670:8: e= quantifierExpression
+                    		        {
+                    		        	dbg.Location(670,9);
+                    		        	PushFollow(FOLLOW_quantifierExpression_in_atomExpression3063);
+                    		        	e = quantifierExpression();
+                    		        	state.followingStackPointer--;
+
+
+                    		        }
+                    		        break;
+                    		    case 6 :
+                    		        dbg.EnterAlt(6);
+
+                    		        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:671:8: T_LPAREN e= expression T_RPAREN ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )?
+                    		        {
+                    		        	dbg.Location(671,8);
+                    		        	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_atomExpression3072); 
+                    		        	dbg.Location(671,18);
+                    		        	PushFollow(FOLLOW_expression_in_atomExpression3076);
+                    		        	e = expression();
+                    		        	state.followingStackPointer--;
+
+                    		        	dbg.Location(671,30);
+                    		        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_atomExpression3078); 
+                    		        	dbg.Location(672,8);
+                    		        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:672:8: ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )?
+                    		        	int alt74 = 3;
+                    		        	try { dbg.EnterSubRule(74);
+                    		        	try { dbg.EnterDecision(74);
+
+                    		        	try 
+                    		        	{
+                    		        	    isCyclicDecision = true;
+                    		        	    alt74 = dfa74.Predict(input);
+                    		        	}
+                    		        	catch (NoViableAltException nvae) 
+                    		        	{
+                    		        	    dbg.RecognitionException(nvae);
+                    		        	    throw nvae;
+                    		        	}
+                    		        	} finally { dbg.ExitDecision(74); }
+
+                    		        	switch (alt74) 
+                    		        	{
+                    		        	    case 1 :
+                    		        	        dbg.EnterAlt(1);
+
+                    		        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:673:6: ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )?
+                    		        	        {
+                    		        	        	dbg.Location(673,6);
+                    		        	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:673:6: ( T_POINT idn= T_IDENTIFIER )+
+                    		        	        	int cnt72 = 0;
+                    		        	        	try { dbg.EnterSubRule(72);
+
+                    		        	        	do 
+                    		        	        	{
+                    		        	        	    int alt72 = 2;
+                    		        	        	    try { dbg.EnterDecision(72);
+
+                    		        	        	    try 
+                    		        	        	    {
+                    		        	        	        isCyclicDecision = true;
+                    		        	        	        alt72 = dfa72.Predict(input);
+                    		        	        	    }
+                    		        	        	    catch (NoViableAltException nvae) 
+                    		        	        	    {
+                    		        	        	        dbg.RecognitionException(nvae);
+                    		        	        	        throw nvae;
+                    		        	        	    }
+                    		        	        	    } finally { dbg.ExitDecision(72); }
+
+                    		        	        	    switch (alt72) 
+                    		        	        		{
+                    		        	        			case 1 :
+                    		        	        			    dbg.EnterAlt(1);
+
+                    		        	        			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:673:7: T_POINT idn= T_IDENTIFIER
+                    		        	        			    {
+                    		        	        			    	dbg.Location(673,7);
+                    		        	        			    	Match(input,T_POINT,FOLLOW_T_POINT_in_atomExpression3101); 
+                    		        	        			    	dbg.Location(674,11);
+                    		        	        			    	idn=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_atomExpression3113); 
+                    		        	        			    	dbg.Location(675,8);
+                    		        	        			    	e = addIdentifierAccessExpression(e,idn);
+
+                    		        	        			    }
+                    		        	        			    break;
+
+                    		        	        			default:
+                    		        	        			    if ( cnt72 >= 1 ) goto loop72;
+                    		        	        		            EarlyExitException eee72 =
+                    		        	        		                new EarlyExitException(72, input);
+                    		        	        		            dbg.RecognitionException(eee72);
+
+                    		        	        		            throw eee72;
+                    		        	        	    }
+                    		        	        	    cnt72++;
+                    		        	        	} while (true);
+
+                    		        	        	loop72:
+                    		        	        		;	// Stops C# compiler whining that label 'loop72' has no statements
+                    		        	        	} finally { dbg.ExitSubRule(72); }
+
+                    		        	        	dbg.Location(676,8);
+                    		        	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:676:8: (res= accessExpression[e] )?
+                    		        	        	int alt73 = 2;
+                    		        	        	try { dbg.EnterSubRule(73);
+                    		        	        	try { dbg.EnterDecision(73);
+
+                    		        	        	try 
+                    		        	        	{
+                    		        	        	    isCyclicDecision = true;
+                    		        	        	    alt73 = dfa73.Predict(input);
+                    		        	        	}
+                    		        	        	catch (NoViableAltException nvae) 
+                    		        	        	{
+                    		        	        	    dbg.RecognitionException(nvae);
+                    		        	        	    throw nvae;
+                    		        	        	}
+                    		        	        	} finally { dbg.ExitDecision(73); }
+
+                    		        	        	switch (alt73) 
+                    		        	        	{
+                    		        	        	    case 1 :
+                    		        	        	        dbg.EnterAlt(1);
+
+                    		        	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:676:9: res= accessExpression[e]
+                    		        	        	        {
+                    		        	        	        	dbg.Location(676,12);
+                    		        	        	        	PushFollow(FOLLOW_accessExpression_in_atomExpression3137);
+                    		        	        	        	res = accessExpression(e);
+                    		        	        	        	state.followingStackPointer--;
+
+                    		        	        	        	dbg.Location(676,33);
+                    		        	        	        	e=res;
+
+                    		        	        	        }
+                    		        	        	        break;
+
+                    		        	        	}
+                    		        	        	} finally { dbg.ExitSubRule(73); }
+
+
+                    		        	        }
+                    		        	        break;
+                    		        	    case 2 :
+                    		        	        dbg.EnterAlt(2);
+
+                    		        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:678:6: e= accessExpression[e]
+                    		        	        {
+                    		        	        	dbg.Location(678,7);
+                    		        	        	PushFollow(FOLLOW_accessExpression_in_atomExpression3157);
+                    		        	        	e = accessExpression(e);
+                    		        	        	state.followingStackPointer--;
+
+
+                    		        	        }
+                    		        	        break;
+
+                    		        	}
+                    		        	} finally { dbg.ExitSubRule(74); }
+
+
+                    		        }
+                    		        break;
+
+                    		}
+                    		} finally { dbg.ExitSubRule(75); }
+
+                    		dbg.Location(680,5);
+                    		// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:680:5: ( 'as' cid= T_IDENTIFIER )?
+                    		int alt76 = 2;
+                    		try { dbg.EnterSubRule(76);
+                    		try { dbg.EnterDecision(76);
+
+                    		try 
+                    		{
+                    		    isCyclicDecision = true;
+                    		    alt76 = dfa76.Predict(input);
+                    		}
+                    		catch (NoViableAltException nvae) 
+                    		{
+                    		    dbg.RecognitionException(nvae);
+                    		    throw nvae;
+                    		}
+                    		} finally { dbg.ExitDecision(76); }
+
+                    		switch (alt76) 
+                    		{
+                    		    case 1 :
+                    		        dbg.EnterAlt(1);
+
+                    		        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:680:6: 'as' cid= T_IDENTIFIER
+                    		        {
+                    		        	dbg.Location(680,6);
+                    		        	Match(input,121,FOLLOW_121_in_atomExpression3176); 
+                    		        	dbg.Location(680,14);
+                    		        	cid=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_atomExpression3180); 
+                    		        	dbg.Location(680,28);
+                    		        	e=addCastExpression(e,cid);
+
+                    		        }
+                    		        break;
+
+                    		}
+                    		} finally { dbg.ExitSubRule(76); }
+
+                    		dbg.Location(681,3);
+                    		expr = addUnaryExpression(unexpr,e);
+
+                    	}
+
+
+                    }
+                    break;
+                case 2 :
+                    dbg.EnterAlt(2);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:683:6: ie= T_IF ce= expression T_THEN te= expression T_ELSE ee= expression T_END
+                    {
+                    	dbg.Location(683,8);
+                    	ie=(IToken)Match(input,T_IF,FOLLOW_T_IF_in_atomExpression3201); 
+                    	dbg.Location(683,16);
+                    	PushFollow(FOLLOW_expression_in_atomExpression3205);
+                    	ce = expression();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(683,28);
+                    	Match(input,T_THEN,FOLLOW_T_THEN_in_atomExpression3207); 
+                    	dbg.Location(683,37);
+                    	PushFollow(FOLLOW_expression_in_atomExpression3211);
+                    	te = expression();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(683,49);
+                    	Match(input,T_ELSE,FOLLOW_T_ELSE_in_atomExpression3213); 
+                    	dbg.Location(683,58);
+                    	PushFollow(FOLLOW_expression_in_atomExpression3217);
+                    	ee = expression();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(683,70);
+                    	Match(input,T_END,FOLLOW_T_END_in_atomExpression3219); 
+                    	dbg.Location(684,3);
+                    	expr = createConditionalExpression(ce,te,ee,ie);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(685, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "atomExpression");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return expr;
+    }
+    // $ANTLR end "atomExpression"
+
+
+    // $ANTLR start "quantifierExpression"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:688:1: quantifierExpression returns [Quantifier result] : t= ( T_FORALL | T_EXISTS ) (id= T_IDENTIFIER ( T_COLON id_type= simpleType ) ( T_COMMA id2= T_IDENTIFIER ( T_COLON id_type2= simpleType ) )* ) T_COLON T_LPAREN e= expression T_RPAREN ;
+    public Quantifier quantifierExpression() // throws RecognitionException [1]
+    {   
+        Quantifier result = default(Quantifier);
+
+        IToken t = null;
+        IToken id = null;
+        IToken id2 = null;
+        UlyssesType id_type = default(UlyssesType);
+
+        UlyssesType id_type2 = default(UlyssesType);
+
+        Expression e = default(Expression);
+
+
+
+        		result = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "quantifierExpression");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(688, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:693:2: (t= ( T_FORALL | T_EXISTS ) (id= T_IDENTIFIER ( T_COLON id_type= simpleType ) ( T_COMMA id2= T_IDENTIFIER ( T_COLON id_type2= simpleType ) )* ) T_COLON T_LPAREN e= expression T_RPAREN )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:693:5: t= ( T_FORALL | T_EXISTS ) (id= T_IDENTIFIER ( T_COLON id_type= simpleType ) ( T_COMMA id2= T_IDENTIFIER ( T_COLON id_type2= simpleType ) )* ) T_COLON T_LPAREN e= expression T_RPAREN
+            {
+            	dbg.Location(693,6);
+            	t = (IToken)input.LT(1);
+            	if ( (input.LA(1) >= T_FORALL && input.LA(1) <= T_EXISTS) ) 
+            	{
+            	    input.Consume();
+            	    state.errorRecovery = false;
+            	}
+            	else 
+            	{
+            	    MismatchedSetException mse = new MismatchedSetException(null,input);
+            	    dbg.RecognitionException(mse);
+            	    throw mse;
+            	}
+
+            	dbg.Location(694,3);
+            	result = createQuantifierExpression(t);
+            	dbg.Location(695,3);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:695:3: (id= T_IDENTIFIER ( T_COLON id_type= simpleType ) ( T_COMMA id2= T_IDENTIFIER ( T_COLON id_type2= simpleType ) )* )
+            	dbg.EnterAlt(1);
+
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:695:4: id= T_IDENTIFIER ( T_COLON id_type= simpleType ) ( T_COMMA id2= T_IDENTIFIER ( T_COLON id_type2= simpleType ) )*
+            	{
+            		dbg.Location(695,6);
+            		id=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_quantifierExpression3268); 
+            		dbg.Location(695,20);
+            		// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:695:20: ( T_COLON id_type= simpleType )
+            		dbg.EnterAlt(1);
+
+            		// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:695:21: T_COLON id_type= simpleType
+            		{
+            			dbg.Location(695,21);
+            			Match(input,T_COLON,FOLLOW_T_COLON_in_quantifierExpression3271); 
+            			dbg.Location(695,36);
+            			PushFollow(FOLLOW_simpleType_in_quantifierExpression3275);
+            			id_type = simpleType();
+            			state.followingStackPointer--;
+
+            			dbg.Location(695,48);
+            			addBoundVarToQuantifierExpression(result,id,id_type);
+
+            		}
+
+            		dbg.Location(696,5);
+            		// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:696:5: ( T_COMMA id2= T_IDENTIFIER ( T_COLON id_type2= simpleType ) )*
+            		try { dbg.EnterSubRule(78);
+
+            		do 
+            		{
+            		    int alt78 = 2;
+            		    try { dbg.EnterDecision(78);
+
+            		    int LA78_0 = input.LA(1);
+
+            		    if ( (LA78_0 == T_COMMA) )
+            		    {
+            		        alt78 = 1;
+            		    }
+
+
+            		    } finally { dbg.ExitDecision(78); }
+
+            		    switch (alt78) 
+            			{
+            				case 1 :
+            				    dbg.EnterAlt(1);
+
+            				    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:696:6: T_COMMA id2= T_IDENTIFIER ( T_COLON id_type2= simpleType )
+            				    {
+            				    	dbg.Location(696,6);
+            				    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_quantifierExpression3286); 
+            				    	dbg.Location(696,17);
+            				    	id2=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_quantifierExpression3290); 
+            				    	dbg.Location(696,31);
+            				    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:696:31: ( T_COLON id_type2= simpleType )
+            				    	dbg.EnterAlt(1);
+
+            				    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:696:32: T_COLON id_type2= simpleType
+            				    	{
+            				    		dbg.Location(696,32);
+            				    		Match(input,T_COLON,FOLLOW_T_COLON_in_quantifierExpression3293); 
+            				    		dbg.Location(696,48);
+            				    		PushFollow(FOLLOW_simpleType_in_quantifierExpression3297);
+            				    		id_type2 = simpleType();
+            				    		state.followingStackPointer--;
+
+
+            				    	}
+
+            				    	dbg.Location(696,60);
+            				    	addBoundVarToQuantifierExpression(result,id2,id_type2);
+
+            				    }
+            				    break;
+
+            				default:
+            				    goto loop78;
+            		    }
+            		} while (true);
+
+            		loop78:
+            			;	// Stops C# compiler whining that label 'loop78' has no statements
+            		} finally { dbg.ExitSubRule(78); }
+
+
+            	}
+
+            	dbg.Location(697,3);
+            	Match(input,T_COLON,FOLLOW_T_COLON_in_quantifierExpression3307); 
+            	dbg.Location(697,11);
+            	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_quantifierExpression3309); 
+            	dbg.Location(697,21);
+            	PushFollow(FOLLOW_expression_in_quantifierExpression3313);
+            	e = expression();
+            	state.followingStackPointer--;
+
+            	dbg.Location(697,33);
+            	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_quantifierExpression3315); 
+            	dbg.Location(698,3);
+            	addExpressionToQuantifier(result,e);
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            removeBoundVarsFromResolveStack(result);
+        }
+        dbg.Location(699, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "quantifierExpression");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "quantifierExpression"
+
+
+    // $ANTLR start "constant"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:703:1: constant returns [LeafExpression result] : ( T_TRUE | T_FALSE | T_NIL | T_SELF | t_fl= T_FLOATNUMBER | t_in= T_INTNUMBER | t_l= T_STRINGLITERAL );
+    public LeafExpression constant() // throws RecognitionException [1]
+    {   
+        LeafExpression result = default(LeafExpression);
+
+        IToken t_fl = null;
+        IToken t_in = null;
+        IToken t_l = null;
+
+
+        		result = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "constant");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(703, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:708:2: ( T_TRUE | T_FALSE | T_NIL | T_SELF | t_fl= T_FLOATNUMBER | t_in= T_INTNUMBER | t_l= T_STRINGLITERAL )
+            int alt79 = 7;
+            try { dbg.EnterDecision(79);
+
+            switch ( input.LA(1) ) 
+            {
+            case T_TRUE:
+            	{
+                alt79 = 1;
+                }
+                break;
+            case T_FALSE:
+            	{
+                alt79 = 2;
+                }
+                break;
+            case T_NIL:
+            	{
+                alt79 = 3;
+                }
+                break;
+            case T_SELF:
+            	{
+                alt79 = 4;
+                }
+                break;
+            case T_FLOATNUMBER:
+            	{
+                alt79 = 5;
+                }
+                break;
+            case T_INTNUMBER:
+            	{
+                alt79 = 6;
+                }
+                break;
+            case T_STRINGLITERAL:
+            	{
+                alt79 = 7;
+                }
+                break;
+            	default:
+            	    NoViableAltException nvae_d79s0 =
+            	        new NoViableAltException("", 79, 0, input);
+
+            	    dbg.RecognitionException(nvae_d79s0);
+            	    throw nvae_d79s0;
+            }
+
+            } finally { dbg.ExitDecision(79); }
+
+            switch (alt79) 
+            {
+                case 1 :
+                    dbg.EnterAlt(1);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:708:5: T_TRUE
+                    {
+                    	dbg.Location(708,5);
+                    	Match(input,T_TRUE,FOLLOW_T_TRUE_in_constant3349); 
+                    	dbg.Location(708,13);
+                    	result = createBoolConstant(true);
+
+                    }
+                    break;
+                case 2 :
+                    dbg.EnterAlt(2);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:709:4: T_FALSE
+                    {
+                    	dbg.Location(709,4);
+                    	Match(input,T_FALSE,FOLLOW_T_FALSE_in_constant3357); 
+                    	dbg.Location(709,12);
+                    	result = createBoolConstant(false);
+
+                    }
+                    break;
+                case 3 :
+                    dbg.EnterAlt(3);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:710:4: T_NIL
+                    {
+                    	dbg.Location(710,4);
+                    	Match(input,T_NIL,FOLLOW_T_NIL_in_constant3364); 
+                    	dbg.Location(710,11);
+                    	result = createNullPointerConstant();
+
+                    }
+                    break;
+                case 4 :
+                    dbg.EnterAlt(4);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:711:4: T_SELF
+                    {
+                    	dbg.Location(711,4);
+                    	Match(input,T_SELF,FOLLOW_T_SELF_in_constant3372); 
+                    	dbg.Location(711,12);
+                    	result = createSelfPointer();
+
+                    }
+                    break;
+                case 5 :
+                    dbg.EnterAlt(5);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:712:5: t_fl= T_FLOATNUMBER
+                    {
+                    	dbg.Location(712,9);
+                    	t_fl=(IToken)Match(input,T_FLOATNUMBER,FOLLOW_T_FLOATNUMBER_in_constant3383); 
+                    	dbg.Location(712,24);
+                    	result = createFloatConstant(t_fl);
+
+                    }
+                    break;
+                case 6 :
+                    dbg.EnterAlt(6);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:713:4: t_in= T_INTNUMBER
+                    {
+                    	dbg.Location(713,8);
+                    	t_in=(IToken)Match(input,T_INTNUMBER,FOLLOW_T_INTNUMBER_in_constant3392); 
+                    	dbg.Location(713,21);
+                    	result = createIntConstant(t_in);
+
+                    }
+                    break;
+                case 7 :
+                    dbg.EnterAlt(7);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:714:4: t_l= T_STRINGLITERAL
+                    {
+                    	dbg.Location(714,7);
+                    	t_l=(IToken)Match(input,T_STRINGLITERAL,FOLLOW_T_STRINGLITERAL_in_constant3401); 
+                    	dbg.Location(714,24);
+                    	result = createStringConstant(t_l);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(715, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "constant");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "constant"
+
+
+    // $ANTLR start "initializedComplexType"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:717:1: initializedComplexType returns [Expression result] : (res= initializedListType | res= initializedSetType | T_NEW T_LPAREN anid= T_IDENTIFIER ( T_COMMA aname= T_STRINGLITERAL T_RPAREN | T_RPAREN ) );
+    public Expression initializedComplexType() // throws RecognitionException [1]
+    {   
+        Expression result = default(Expression);
+
+        IToken anid = null;
+        IToken aname = null;
+        Expression res = default(Expression);
+
+
+
+        		result = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "initializedComplexType");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(717, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:722:2: (res= initializedListType | res= initializedSetType | T_NEW T_LPAREN anid= T_IDENTIFIER ( T_COMMA aname= T_STRINGLITERAL T_RPAREN | T_RPAREN ) )
+            int alt81 = 3;
+            try { dbg.EnterDecision(81);
+
+            switch ( input.LA(1) ) 
+            {
+            case T_LSQPAREN:
+            	{
+                alt81 = 1;
+                }
+                break;
+            case T_CBRL:
+            	{
+                alt81 = 2;
+                }
+                break;
+            case T_NEW:
+            	{
+                alt81 = 3;
+                }
+                break;
+            	default:
+            	    NoViableAltException nvae_d81s0 =
+            	        new NoViableAltException("", 81, 0, input);
+
+            	    dbg.RecognitionException(nvae_d81s0);
+            	    throw nvae_d81s0;
+            }
+
+            } finally { dbg.ExitDecision(81); }
+
+            switch (alt81) 
+            {
+                case 1 :
+                    dbg.EnterAlt(1);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:722:4: res= initializedListType
+                    {
+                    	dbg.Location(722,7);
+                    	PushFollow(FOLLOW_initializedListType_in_initializedComplexType3428);
+                    	res = initializedListType();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(722,28);
+                    	result = res;
+
+                    }
+                    break;
+                case 2 :
+                    dbg.EnterAlt(2);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:723:4: res= initializedSetType
+                    {
+                    	dbg.Location(723,7);
+                    	PushFollow(FOLLOW_initializedSetType_in_initializedComplexType3437);
+                    	res = initializedSetType();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(723,27);
+                    	result = res;
+
+                    }
+                    break;
+                case 3 :
+                    dbg.EnterAlt(3);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:724:5: T_NEW T_LPAREN anid= T_IDENTIFIER ( T_COMMA aname= T_STRINGLITERAL T_RPAREN | T_RPAREN )
+                    {
+                    	dbg.Location(724,5);
+                    	Match(input,T_NEW,FOLLOW_T_NEW_in_initializedComplexType3445); 
+                    	dbg.Location(724,11);
+                    	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_initializedComplexType3447); 
+                    	dbg.Location(724,24);
+                    	anid=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_initializedComplexType3451); 
+                    	dbg.Location(725,4);
+                    	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:725:4: ( T_COMMA aname= T_STRINGLITERAL T_RPAREN | T_RPAREN )
+                    	int alt80 = 2;
+                    	try { dbg.EnterSubRule(80);
+                    	try { dbg.EnterDecision(80);
+
+                    	int LA80_0 = input.LA(1);
+
+                    	if ( (LA80_0 == T_COMMA) )
+                    	{
+                    	    alt80 = 1;
+                    	}
+                    	else if ( (LA80_0 == T_RPAREN) )
+                    	{
+                    	    alt80 = 2;
+                    	}
+                    	else 
+                    	{
+                    	    NoViableAltException nvae_d80s0 =
+                    	        new NoViableAltException("", 80, 0, input);
+
+                    	    dbg.RecognitionException(nvae_d80s0);
+                    	    throw nvae_d80s0;
+                    	}
+                    	} finally { dbg.ExitDecision(80); }
+
+                    	switch (alt80) 
+                    	{
+                    	    case 1 :
+                    	        dbg.EnterAlt(1);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:726:5: T_COMMA aname= T_STRINGLITERAL T_RPAREN
+                    	        {
+                    	        	dbg.Location(726,5);
+                    	        	Match(input,T_COMMA,FOLLOW_T_COMMA_in_initializedComplexType3463); 
+                    	        	dbg.Location(726,19);
+                    	        	aname=(IToken)Match(input,T_STRINGLITERAL,FOLLOW_T_STRINGLITERAL_in_initializedComplexType3468); 
+                    	        	dbg.Location(726,36);
+                    	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_initializedComplexType3470); 
+                    	        	dbg.Location(726,45);
+                    	        	result = createNamedObject(anid, aname);
+
+                    	        }
+                    	        break;
+                    	    case 2 :
+                    	        dbg.EnterAlt(2);
+
+                    	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:727:6: T_RPAREN
+                    	        {
+                    	        	dbg.Location(727,6);
+                    	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_initializedComplexType3479); 
+                    	        	dbg.Location(727,15);
+                    	        	result = createObject(anid);
+
+                    	        }
+                    	        break;
+
+                    	}
+                    	} finally { dbg.ExitSubRule(80); }
+
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(729, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "initializedComplexType");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "initializedComplexType"
+
+
+    // $ANTLR start "initializedListType"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:731:1: initializedListType returns [ListConstructor result] : T_LSQPAREN e= expression ( ( T_COMMA e2= expression )+ | listComprehension[result] )? T_RSQPAREN ;
+    public ListConstructor initializedListType() // throws RecognitionException [1]
+    {   
+        ListConstructor result = default(ListConstructor);
+
+        Expression e = default(Expression);
+
+        Expression e2 = default(Expression);
+
+
+
+        		result = createInitializedList();
+        		pushListVarsOnResolveStack(result); // need this here for list comprehension
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "initializedListType");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(731, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:737:2: ( T_LSQPAREN e= expression ( ( T_COMMA e2= expression )+ | listComprehension[result] )? T_RSQPAREN )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:737:4: T_LSQPAREN e= expression ( ( T_COMMA e2= expression )+ | listComprehension[result] )? T_RSQPAREN
+            {
+            	dbg.Location(737,4);
+            	Match(input,T_LSQPAREN,FOLLOW_T_LSQPAREN_in_initializedListType3510); 
+            	dbg.Location(737,16);
+            	PushFollow(FOLLOW_expression_in_initializedListType3514);
+            	e = expression();
+            	state.followingStackPointer--;
+
+            	dbg.Location(737,28);
+            	addListElement(result,e);
+            	dbg.Location(737,56);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:737:56: ( ( T_COMMA e2= expression )+ | listComprehension[result] )?
+            	int alt83 = 3;
+            	try { dbg.EnterSubRule(83);
+            	try { dbg.EnterDecision(83);
+
+            	int LA83_0 = input.LA(1);
+
+            	if ( (LA83_0 == T_COMMA) )
+            	{
+            	    alt83 = 1;
+            	}
+            	else if ( (LA83_0 == T_BAR) )
+            	{
+            	    alt83 = 2;
+            	}
+            	} finally { dbg.ExitDecision(83); }
+
+            	switch (alt83) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:738:4: ( T_COMMA e2= expression )+
+            	        {
+            	        	dbg.Location(738,4);
+            	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:738:4: ( T_COMMA e2= expression )+
+            	        	int cnt82 = 0;
+            	        	try { dbg.EnterSubRule(82);
+
+            	        	do 
+            	        	{
+            	        	    int alt82 = 2;
+            	        	    try { dbg.EnterDecision(82);
+
+            	        	    int LA82_0 = input.LA(1);
+
+            	        	    if ( (LA82_0 == T_COMMA) )
+            	        	    {
+            	        	        alt82 = 1;
+            	        	    }
+
+
+            	        	    } finally { dbg.ExitDecision(82); }
+
+            	        	    switch (alt82) 
+            	        		{
+            	        			case 1 :
+            	        			    dbg.EnterAlt(1);
+
+            	        			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:738:5: T_COMMA e2= expression
+            	        			    {
+            	        			    	dbg.Location(738,5);
+            	        			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_initializedListType3525); 
+            	        			    	dbg.Location(738,15);
+            	        			    	PushFollow(FOLLOW_expression_in_initializedListType3529);
+            	        			    	e2 = expression();
+            	        			    	state.followingStackPointer--;
+
+            	        			    	dbg.Location(738,27);
+            	        			    	addListElement(result,e2);
+
+            	        			    }
+            	        			    break;
+
+            	        			default:
+            	        			    if ( cnt82 >= 1 ) goto loop82;
+            	        		            EarlyExitException eee82 =
+            	        		                new EarlyExitException(82, input);
+            	        		            dbg.RecognitionException(eee82);
+
+            	        		            throw eee82;
+            	        	    }
+            	        	    cnt82++;
+            	        	} while (true);
+
+            	        	loop82:
+            	        		;	// Stops C# compiler whining that label 'loop82' has no statements
+            	        	} finally { dbg.ExitSubRule(82); }
+
+
+            	        }
+            	        break;
+            	    case 2 :
+            	        dbg.EnterAlt(2);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:739:6: listComprehension[result]
+            	        {
+            	        	dbg.Location(739,6);
+            	        	PushFollow(FOLLOW_listComprehension_in_initializedListType3541);
+            	        	listComprehension(result);
+            	        	state.followingStackPointer--;
+
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(83); }
+
+            	dbg.Location(740,6);
+            	Match(input,T_RSQPAREN,FOLLOW_T_RSQPAREN_in_initializedListType3549); 
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            popListVarsFromResolveStack(result);
+        }
+        dbg.Location(741, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "initializedListType");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "initializedListType"
+
+
+    // $ANTLR start "listComprehension"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:745:1: listComprehension[ListConstructor result] : T_BAR T_VAR id= T_IDENTIFIER T_COLON t1= complexType ( T_SEMICOLON id2= T_IDENTIFIER t2= complexType )* ( '&' e= expression )? ;
+    public void listComprehension(ListConstructor result) // throws RecognitionException [1]
+    {   
+        IToken id = null;
+        IToken id2 = null;
+        UlyssesType t1 = default(UlyssesType);
+
+        UlyssesType t2 = default(UlyssesType);
+
+        Expression e = default(Expression);
+
+
+        	
+        		result.SetHasComprehension(true);
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "listComprehension");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(745, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:749:2: ( T_BAR T_VAR id= T_IDENTIFIER T_COLON t1= complexType ( T_SEMICOLON id2= T_IDENTIFIER t2= complexType )* ( '&' e= expression )? )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:750:3: T_BAR T_VAR id= T_IDENTIFIER T_COLON t1= complexType ( T_SEMICOLON id2= T_IDENTIFIER t2= complexType )* ( '&' e= expression )?
+            {
+            	dbg.Location(750,3);
+            	Match(input,T_BAR,FOLLOW_T_BAR_in_listComprehension3580); 
+            	dbg.Location(750,9);
+            	Match(input,T_VAR,FOLLOW_T_VAR_in_listComprehension3582); 
+            	dbg.Location(751,5);
+            	id=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_listComprehension3588); 
+            	dbg.Location(751,20);
+            	Match(input,T_COLON,FOLLOW_T_COLON_in_listComprehension3591); 
+            	dbg.Location(751,30);
+            	PushFollow(FOLLOW_complexType_in_listComprehension3595);
+            	t1 = complexType();
+            	state.followingStackPointer--;
+
+            	dbg.Location(751,43);
+            	addListComprVar(result,id,t1);
+            	dbg.Location(752,4);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:752:4: ( T_SEMICOLON id2= T_IDENTIFIER t2= complexType )*
+            	try { dbg.EnterSubRule(84);
+
+            	do 
+            	{
+            	    int alt84 = 2;
+            	    try { dbg.EnterDecision(84);
+
+            	    int LA84_0 = input.LA(1);
+
+            	    if ( (LA84_0 == T_SEMICOLON) )
+            	    {
+            	        alt84 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(84); }
+
+            	    switch (alt84) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:752:5: T_SEMICOLON id2= T_IDENTIFIER t2= complexType
+            			    {
+            			    	dbg.Location(752,5);
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_listComprehension3604); 
+            			    	dbg.Location(752,20);
+            			    	id2=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_listComprehension3608); 
+            			    	dbg.Location(752,37);
+            			    	PushFollow(FOLLOW_complexType_in_listComprehension3613);
+            			    	t2 = complexType();
+            			    	state.followingStackPointer--;
+
+            			    	dbg.Location(752,50);
+            			    	addListComprVar(result,id2,t2);
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop84;
+            	    }
+            	} while (true);
+
+            	loop84:
+            		;	// Stops C# compiler whining that label 'loop84' has no statements
+            	} finally { dbg.ExitSubRule(84); }
+
+            	dbg.Location(753,3);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:753:3: ( '&' e= expression )?
+            	int alt85 = 2;
+            	try { dbg.EnterSubRule(85);
+            	try { dbg.EnterDecision(85);
+
+            	int LA85_0 = input.LA(1);
+
+            	if ( (LA85_0 == 120) )
+            	{
+            	    alt85 = 1;
+            	}
+            	} finally { dbg.ExitDecision(85); }
+
+            	switch (alt85) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:753:4: '&' e= expression
+            	        {
+            	        	dbg.Location(753,4);
+            	        	Match(input,120,FOLLOW_120_in_listComprehension3623); 
+            	        	dbg.Location(754,4);
+            	        	PushFollow(FOLLOW_expression_in_listComprehension3629);
+            	        	e = expression();
+            	        	state.followingStackPointer--;
+
+            	        	dbg.Location(754,16);
+            	        	addListComprExpr(result,e);
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(85); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(755, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "listComprehension");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "listComprehension"
+
+
+    // $ANTLR start "initializedSetType"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:757:1: initializedSetType returns [Expression result] : ( T_CBRL T_MAPS T_CBRR | res= initializedSet );
+    public Expression initializedSetType() // throws RecognitionException [1]
+    {   
+        Expression result = default(Expression);
+
+        Expression res = default(Expression);
+
+
+
+        		result = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "initializedSetType");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(757, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:762:2: ( T_CBRL T_MAPS T_CBRR | res= initializedSet )
+            int alt86 = 2;
+            try { dbg.EnterDecision(86);
+
+            try 
+            {
+                isCyclicDecision = true;
+                alt86 = dfa86.Predict(input);
+            }
+            catch (NoViableAltException nvae) 
+            {
+                dbg.RecognitionException(nvae);
+                throw nvae;
+            }
+            } finally { dbg.ExitDecision(86); }
+
+            switch (alt86) 
+            {
+                case 1 :
+                    dbg.EnterAlt(1);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:762:4: T_CBRL T_MAPS T_CBRR
+                    {
+                    	dbg.Location(762,4);
+                    	Match(input,T_CBRL,FOLLOW_T_CBRL_in_initializedSetType3655); 
+                    	dbg.Location(762,11);
+                    	Match(input,T_MAPS,FOLLOW_T_MAPS_in_initializedSetType3657); 
+                    	dbg.Location(762,18);
+                    	Match(input,T_CBRR,FOLLOW_T_CBRR_in_initializedSetType3659); 
+                    	dbg.Location(762,25);
+                    	result = createEmptyMap();
+
+                    }
+                    break;
+                case 2 :
+                    dbg.EnterAlt(2);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:763:4: res= initializedSet
+                    {
+                    	dbg.Location(763,7);
+                    	PushFollow(FOLLOW_initializedSet_in_initializedSetType3670);
+                    	res = initializedSet();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(763,23);
+                    	result = res;
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(764, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "initializedSetType");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "initializedSetType"
+
+
+    // $ANTLR start "initializedSet"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:766:1: initializedSet returns [Expression result] : T_CBRL e1= expression ( ( T_COMMA e2= expression )+ | m= map[result, e1] | setComprehension[(SetConstructor)result] )? T_CBRR ;
+    public Expression initializedSet() // throws RecognitionException [1]
+    {   
+        Expression result = default(Expression);
+
+        Expression e1 = default(Expression);
+
+        Expression e2 = default(Expression);
+
+        Expression m = default(Expression);
+
+
+
+        		SetConstructor theset = createSet(); 
+        		pushSetVarsOnResolveStack(theset); // need this here for set comprehension
+        		result = theset;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "initializedSet");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(766, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:773:2: ( T_CBRL e1= expression ( ( T_COMMA e2= expression )+ | m= map[result, e1] | setComprehension[(SetConstructor)result] )? T_CBRR )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:773:4: T_CBRL e1= expression ( ( T_COMMA e2= expression )+ | m= map[result, e1] | setComprehension[(SetConstructor)result] )? T_CBRR
+            {
+            	dbg.Location(773,4);
+            	Match(input,T_CBRL,FOLLOW_T_CBRL_in_initializedSet3696); 
+            	dbg.Location(773,13);
+            	PushFollow(FOLLOW_expression_in_initializedSet3700);
+            	e1 = expression();
+            	state.followingStackPointer--;
+
+            	dbg.Location(774,10);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:774:10: ( ( T_COMMA e2= expression )+ | m= map[result, e1] | setComprehension[(SetConstructor)result] )?
+            	int alt88 = 4;
+            	try { dbg.EnterSubRule(88);
+            	try { dbg.EnterDecision(88);
+
+            	switch ( input.LA(1) ) 
+            	{
+            	    case T_COMMA:
+            	    	{
+            	        alt88 = 1;
+            	        }
+            	        break;
+            	    case T_MAPS:
+            	    	{
+            	        alt88 = 2;
+            	        }
+            	        break;
+            	    case T_BAR:
+            	    	{
+            	        alt88 = 3;
+            	        }
+            	        break;
+            	}
+
+            	} finally { dbg.ExitDecision(88); }
+
+            	switch (alt88) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:775:4: ( T_COMMA e2= expression )+
+            	        {
+            	        	dbg.Location(775,4);
+            	        	addToSet(result,e1);
+            	        	dbg.Location(776,4);
+            	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:776:4: ( T_COMMA e2= expression )+
+            	        	int cnt87 = 0;
+            	        	try { dbg.EnterSubRule(87);
+
+            	        	do 
+            	        	{
+            	        	    int alt87 = 2;
+            	        	    try { dbg.EnterDecision(87);
+
+            	        	    int LA87_0 = input.LA(1);
+
+            	        	    if ( (LA87_0 == T_COMMA) )
+            	        	    {
+            	        	        alt87 = 1;
+            	        	    }
+
+
+            	        	    } finally { dbg.ExitDecision(87); }
+
+            	        	    switch (alt87) 
+            	        		{
+            	        			case 1 :
+            	        			    dbg.EnterAlt(1);
+
+            	        			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:776:5: T_COMMA e2= expression
+            	        			    {
+            	        			    	dbg.Location(776,5);
+            	        			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_initializedSet3730); 
+            	        			    	dbg.Location(776,15);
+            	        			    	PushFollow(FOLLOW_expression_in_initializedSet3734);
+            	        			    	e2 = expression();
+            	        			    	state.followingStackPointer--;
+
+            	        			    	dbg.Location(776,27);
+            	        			    	addToSet(result,e2);
+
+            	        			    }
+            	        			    break;
+
+            	        			default:
+            	        			    if ( cnt87 >= 1 ) goto loop87;
+            	        		            EarlyExitException eee87 =
+            	        		                new EarlyExitException(87, input);
+            	        		            dbg.RecognitionException(eee87);
+
+            	        		            throw eee87;
+            	        	    }
+            	        	    cnt87++;
+            	        	} while (true);
+
+            	        	loop87:
+            	        		;	// Stops C# compiler whining that label 'loop87' has no statements
+            	        	} finally { dbg.ExitSubRule(87); }
+
+
+            	        }
+            	        break;
+            	    case 2 :
+            	        dbg.EnterAlt(2);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:777:6: m= map[result, e1]
+            	        {
+            	        	dbg.Location(777,7);
+            	        	PushFollow(FOLLOW_map_in_initializedSet3752);
+            	        	m = map(result, e1);
+            	        	state.followingStackPointer--;
+
+            	        	dbg.Location(777,24);
+            	        	result = m;
+
+            	        }
+            	        break;
+            	    case 3 :
+            	        dbg.EnterAlt(3);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:778:5: setComprehension[(SetConstructor)result]
+            	        {
+            	        	dbg.Location(778,5);
+            	        	addToSet(result,e1);
+            	        	dbg.Location(778,28);
+            	        	PushFollow(FOLLOW_setComprehension_in_initializedSet3765);
+            	        	setComprehension((SetConstructor)result);
+            	        	state.followingStackPointer--;
+
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(88); }
+
+            	dbg.Location(779,6);
+            	Match(input,T_CBRR,FOLLOW_T_CBRR_in_initializedSet3776); 
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            popSetVarsFromResolveStack(theset);
+        }
+        dbg.Location(780, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "initializedSet");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "initializedSet"
+
+
+    // $ANTLR start "map"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:784:1: map[Expression _map, Expression e1] returns [Expression result] : am= T_MAPS e2= expression ( T_COMMA e3= expression T_MAPS e4= expression )* ;
+    public Expression map(Expression _map, Expression e1) // throws RecognitionException [1]
+    {   
+        Expression result = default(Expression);
+
+        IToken am = null;
+        Expression e2 = default(Expression);
+
+        Expression e3 = default(Expression);
+
+        Expression e4 = default(Expression);
+
+
+
+        		result = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "map");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(784, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:789:2: (am= T_MAPS e2= expression ( T_COMMA e3= expression T_MAPS e4= expression )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:789:4: am= T_MAPS e2= expression ( T_COMMA e3= expression T_MAPS e4= expression )*
+            {
+            	dbg.Location(789,6);
+            	am=(IToken)Match(input,T_MAPS,FOLLOW_T_MAPS_in_map3812); 
+            	dbg.Location(789,16);
+            	PushFollow(FOLLOW_expression_in_map3816);
+            	e2 = expression();
+            	state.followingStackPointer--;
+
+            	dbg.Location(789,29);
+            	result = createMap(e1,e2,am);
+            	dbg.Location(789,63);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:789:63: ( T_COMMA e3= expression T_MAPS e4= expression )*
+            	try { dbg.EnterSubRule(89);
+
+            	do 
+            	{
+            	    int alt89 = 2;
+            	    try { dbg.EnterDecision(89);
+
+            	    int LA89_0 = input.LA(1);
+
+            	    if ( (LA89_0 == T_COMMA) )
+            	    {
+            	        alt89 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(89); }
+
+            	    switch (alt89) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:789:64: T_COMMA e3= expression T_MAPS e4= expression
+            			    {
+            			    	dbg.Location(789,64);
+            			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_map3824); 
+            			    	dbg.Location(789,74);
+            			    	PushFollow(FOLLOW_expression_in_map3828);
+            			    	e3 = expression();
+            			    	state.followingStackPointer--;
+
+            			    	dbg.Location(789,86);
+            			    	Match(input,T_MAPS,FOLLOW_T_MAPS_in_map3830); 
+            			    	dbg.Location(789,95);
+            			    	PushFollow(FOLLOW_expression_in_map3834);
+            			    	e4 = expression();
+            			    	state.followingStackPointer--;
+
+            			    	dbg.Location(789,107);
+            			    	addToMap(result,e3,e4);
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop89;
+            	    }
+            	} while (true);
+
+            	loop89:
+            		;	// Stops C# compiler whining that label 'loop89' has no statements
+            	} finally { dbg.ExitSubRule(89); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(790, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "map");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "map"
+
+
+    // $ANTLR start "setComprehension"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:792:1: setComprehension[SetConstructor _set] : T_BAR T_VAR (id1= T_IDENTIFIER T_COLON t1= complexType T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType )* ( '&' epx= expression )? ;
+    public void setComprehension(SetConstructor _set) // throws RecognitionException [1]
+    {   
+        IToken id1 = null;
+        IToken id2 = null;
+        UlyssesType t1 = default(UlyssesType);
+
+        UlyssesType t2 = default(UlyssesType);
+
+        Expression epx = default(Expression);
+
+
+
+        		_set.SetHasComprehension(true);
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "setComprehension");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(792, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:796:2: ( T_BAR T_VAR (id1= T_IDENTIFIER T_COLON t1= complexType T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType )* ( '&' epx= expression )? )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:796:4: T_BAR T_VAR (id1= T_IDENTIFIER T_COLON t1= complexType T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType )* ( '&' epx= expression )?
+            {
+            	dbg.Location(796,4);
+            	Match(input,T_BAR,FOLLOW_T_BAR_in_setComprehension3856); 
+            	dbg.Location(796,10);
+            	Match(input,T_VAR,FOLLOW_T_VAR_in_setComprehension3858); 
+            	dbg.Location(796,16);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:796:16: (id1= T_IDENTIFIER T_COLON t1= complexType T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType )*
+            	try { dbg.EnterSubRule(90);
+
+            	do 
+            	{
+            	    int alt90 = 2;
+            	    try { dbg.EnterDecision(90);
+
+            	    int LA90_0 = input.LA(1);
+
+            	    if ( (LA90_0 == T_IDENTIFIER) )
+            	    {
+            	        alt90 = 1;
+            	    }
+
+
+            	    } finally { dbg.ExitDecision(90); }
+
+            	    switch (alt90) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:796:17: id1= T_IDENTIFIER T_COLON t1= complexType T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType
+            			    {
+            			    	dbg.Location(796,20);
+            			    	id1=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_setComprehension3863); 
+            			    	dbg.Location(796,35);
+            			    	Match(input,T_COLON,FOLLOW_T_COLON_in_setComprehension3866); 
+            			    	dbg.Location(796,45);
+            			    	PushFollow(FOLLOW_complexType_in_setComprehension3870);
+            			    	t1 = complexType();
+            			    	state.followingStackPointer--;
+
+            			    	dbg.Location(797,3);
+            			    	 addSetComprVar(_set, id1, t1); 
+            			    	dbg.Location(798,3);
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_setComprehension3879); 
+            			    	dbg.Location(798,18);
+            			    	id2=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_setComprehension3883); 
+            			    	dbg.Location(798,32);
+            			    	Match(input,T_COLON,FOLLOW_T_COLON_in_setComprehension3885); 
+            			    	dbg.Location(798,42);
+            			    	PushFollow(FOLLOW_complexType_in_setComprehension3889);
+            			    	t2 = complexType();
+            			    	state.followingStackPointer--;
+
+            			    	dbg.Location(799,4);
+            			    	 addSetComprVar(_set, id2, t2); 
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop90;
+            	    }
+            	} while (true);
+
+            	loop90:
+            		;	// Stops C# compiler whining that label 'loop90' has no statements
+            	} finally { dbg.ExitSubRule(90); }
+
+            	dbg.Location(800,3);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:800:3: ( '&' epx= expression )?
+            	int alt91 = 2;
+            	try { dbg.EnterSubRule(91);
+            	try { dbg.EnterDecision(91);
+
+            	int LA91_0 = input.LA(1);
+
+            	if ( (LA91_0 == 120) )
+            	{
+            	    alt91 = 1;
+            	}
+            	} finally { dbg.ExitDecision(91); }
+
+            	switch (alt91) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:800:4: '&' epx= expression
+            	        {
+            	        	dbg.Location(800,4);
+            	        	Match(input,120,FOLLOW_120_in_setComprehension3903); 
+            	        	dbg.Location(801,6);
+            	        	PushFollow(FOLLOW_expression_in_setComprehension3909);
+            	        	epx = expression();
+            	        	state.followingStackPointer--;
+
+            	        	dbg.Location(802,3);
+            	        	 addSetComprExpr(_set,epx); 
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(91); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(803, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "setComprehension");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return ;
+    }
+    // $ANTLR end "setComprehension"
+
+
+    // $ANTLR start "qvalExpression"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:806:1: qvalExpression returns [QValConstructor result] : aval= 'qval' T_LPAREN ( T_NIL | (expr= qualifiedIdentifier | ( '-' )? T_INFTY ) ( T_RANGETO (expr2= qualifiedIdentifier | T_INFTY ) )? ) T_COMMA ( T_NIL | ( 'steady' | 'inc' | 'dec' ) ) T_RPAREN ;
+    public QValConstructor qvalExpression() // throws RecognitionException [1]
+    {   
+        QValConstructor result = default(QValConstructor);
+
+        IToken aval = null;
+        Expression expr = default(Expression);
+
+        Expression expr2 = default(Expression);
+
+
+
+        		bool minus = false;
+        		result = null;		
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "qvalExpression");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(806, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:812:2: (aval= 'qval' T_LPAREN ( T_NIL | (expr= qualifiedIdentifier | ( '-' )? T_INFTY ) ( T_RANGETO (expr2= qualifiedIdentifier | T_INFTY ) )? ) T_COMMA ( T_NIL | ( 'steady' | 'inc' | 'dec' ) ) T_RPAREN )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:813:3: aval= 'qval' T_LPAREN ( T_NIL | (expr= qualifiedIdentifier | ( '-' )? T_INFTY ) ( T_RANGETO (expr2= qualifiedIdentifier | T_INFTY ) )? ) T_COMMA ( T_NIL | ( 'steady' | 'inc' | 'dec' ) ) T_RPAREN
+            {
+            	dbg.Location(813,7);
+            	aval=(IToken)Match(input,122,FOLLOW_122_in_qvalExpression3944); 
+            	dbg.Location(813,15);
+            	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_qvalExpression3946); 
+            	dbg.Location(814,3);
+            	result = createQualitativeValue(aval);
+            	dbg.Location(815,3);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:815:3: ( T_NIL | (expr= qualifiedIdentifier | ( '-' )? T_INFTY ) ( T_RANGETO (expr2= qualifiedIdentifier | T_INFTY ) )? )
+            	int alt96 = 2;
+            	try { dbg.EnterSubRule(96);
+            	try { dbg.EnterDecision(96);
+
+            	int LA96_0 = input.LA(1);
+
+            	if ( (LA96_0 == T_NIL) )
+            	{
+            	    alt96 = 1;
+            	}
+            	else if ( (LA96_0 == T_IDENTIFIER || (LA96_0 >= T_MINUS && LA96_0 <= T_INFTY) || LA96_0 == T_SELF) )
+            	{
+            	    alt96 = 2;
+            	}
+            	else 
+            	{
+            	    NoViableAltException nvae_d96s0 =
+            	        new NoViableAltException("", 96, 0, input);
+
+            	    dbg.RecognitionException(nvae_d96s0);
+            	    throw nvae_d96s0;
+            	}
+            	} finally { dbg.ExitDecision(96); }
+
+            	switch (alt96) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:816:4: T_NIL
+            	        {
+            	        	dbg.Location(816,4);
+            	        	Match(input,T_NIL,FOLLOW_T_NIL_in_qvalExpression3960); 
+            	        	dbg.Location(817,4);
+            	        	setQualitativeValueDontCare(result);
+
+            	        }
+            	        break;
+            	    case 2 :
+            	        dbg.EnterAlt(2);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:819:4: (expr= qualifiedIdentifier | ( '-' )? T_INFTY ) ( T_RANGETO (expr2= qualifiedIdentifier | T_INFTY ) )?
+            	        {
+            	        	dbg.Location(819,4);
+            	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:819:4: (expr= qualifiedIdentifier | ( '-' )? T_INFTY )
+            	        	int alt93 = 2;
+            	        	try { dbg.EnterSubRule(93);
+            	        	try { dbg.EnterDecision(93);
+
+            	        	int LA93_0 = input.LA(1);
+
+            	        	if ( (LA93_0 == T_IDENTIFIER || LA93_0 == T_SELF) )
+            	        	{
+            	        	    alt93 = 1;
+            	        	}
+            	        	else if ( ((LA93_0 >= T_MINUS && LA93_0 <= T_INFTY)) )
+            	        	{
+            	        	    alt93 = 2;
+            	        	}
+            	        	else 
+            	        	{
+            	        	    NoViableAltException nvae_d93s0 =
+            	        	        new NoViableAltException("", 93, 0, input);
+
+            	        	    dbg.RecognitionException(nvae_d93s0);
+            	        	    throw nvae_d93s0;
+            	        	}
+            	        	} finally { dbg.ExitDecision(93); }
+
+            	        	switch (alt93) 
+            	        	{
+            	        	    case 1 :
+            	        	        dbg.EnterAlt(1);
+
+            	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:819:6: expr= qualifiedIdentifier
+            	        	        {
+            	        	        	dbg.Location(819,10);
+            	        	        	PushFollow(FOLLOW_qualifiedIdentifier_in_qvalExpression3981);
+            	        	        	expr = qualifiedIdentifier();
+            	        	        	state.followingStackPointer--;
+
+            	        	        	dbg.Location(820,6);
+            	        	        	setQualitativeValueLandmark(result,expr);
+
+            	        	        }
+            	        	        break;
+            	        	    case 2 :
+            	        	        dbg.EnterAlt(2);
+
+            	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:822:5: ( '-' )? T_INFTY
+            	        	        {
+            	        	        	dbg.Location(822,5);
+            	        	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:822:5: ( '-' )?
+            	        	        	int alt92 = 2;
+            	        	        	try { dbg.EnterSubRule(92);
+            	        	        	try { dbg.EnterDecision(92);
+
+            	        	        	int LA92_0 = input.LA(1);
+
+            	        	        	if ( (LA92_0 == T_MINUS) )
+            	        	        	{
+            	        	        	    alt92 = 1;
+            	        	        	}
+            	        	        	} finally { dbg.ExitDecision(92); }
+
+            	        	        	switch (alt92) 
+            	        	        	{
+            	        	        	    case 1 :
+            	        	        	        dbg.EnterAlt(1);
+
+            	        	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:822:6: '-'
+            	        	        	        {
+            	        	        	        	dbg.Location(822,6);
+            	        	        	        	Match(input,T_MINUS,FOLLOW_T_MINUS_in_qvalExpression4000); 
+            	        	        	        	dbg.Location(822,10);
+            	        	        	        	minus = true;
+
+            	        	        	        }
+            	        	        	        break;
+
+            	        	        	}
+            	        	        	} finally { dbg.ExitSubRule(92); }
+
+            	        	        	dbg.Location(822,28);
+            	        	        	Match(input,T_INFTY,FOLLOW_T_INFTY_in_qvalExpression4006); 
+            	        	        	dbg.Location(823,5);
+            	        	        	setQualitativeValueInfinity(result,minus);
+
+            	        	        }
+            	        	        break;
+
+            	        	}
+            	        	} finally { dbg.ExitSubRule(93); }
+
+            	        	dbg.Location(825,4);
+            	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:825:4: ( T_RANGETO (expr2= qualifiedIdentifier | T_INFTY ) )?
+            	        	int alt95 = 2;
+            	        	try { dbg.EnterSubRule(95);
+            	        	try { dbg.EnterDecision(95);
+
+            	        	int LA95_0 = input.LA(1);
+
+            	        	if ( (LA95_0 == T_RANGETO) )
+            	        	{
+            	        	    alt95 = 1;
+            	        	}
+            	        	} finally { dbg.ExitDecision(95); }
+
+            	        	switch (alt95) 
+            	        	{
+            	        	    case 1 :
+            	        	        dbg.EnterAlt(1);
+
+            	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:825:5: T_RANGETO (expr2= qualifiedIdentifier | T_INFTY )
+            	        	        {
+            	        	        	dbg.Location(825,5);
+            	        	        	Match(input,T_RANGETO,FOLLOW_T_RANGETO_in_qvalExpression4024); 
+            	        	        	dbg.Location(826,4);
+            	        	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:826:4: (expr2= qualifiedIdentifier | T_INFTY )
+            	        	        	int alt94 = 2;
+            	        	        	try { dbg.EnterSubRule(94);
+            	        	        	try { dbg.EnterDecision(94);
+
+            	        	        	int LA94_0 = input.LA(1);
+
+            	        	        	if ( (LA94_0 == T_IDENTIFIER || LA94_0 == T_SELF) )
+            	        	        	{
+            	        	        	    alt94 = 1;
+            	        	        	}
+            	        	        	else if ( (LA94_0 == T_INFTY) )
+            	        	        	{
+            	        	        	    alt94 = 2;
+            	        	        	}
+            	        	        	else 
+            	        	        	{
+            	        	        	    NoViableAltException nvae_d94s0 =
+            	        	        	        new NoViableAltException("", 94, 0, input);
+
+            	        	        	    dbg.RecognitionException(nvae_d94s0);
+            	        	        	    throw nvae_d94s0;
+            	        	        	}
+            	        	        	} finally { dbg.ExitDecision(94); }
+
+            	        	        	switch (alt94) 
+            	        	        	{
+            	        	        	    case 1 :
+            	        	        	        dbg.EnterAlt(1);
+
+            	        	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:826:6: expr2= qualifiedIdentifier
+            	        	        	        {
+            	        	        	        	dbg.Location(826,11);
+            	        	        	        	PushFollow(FOLLOW_qualifiedIdentifier_in_qvalExpression4034);
+            	        	        	        	expr2 = qualifiedIdentifier();
+            	        	        	        	state.followingStackPointer--;
+
+            	        	        	        	dbg.Location(827,5);
+            	        	        	        	setQualitativeValueRange(result,expr2);
+
+            	        	        	        }
+            	        	        	        break;
+            	        	        	    case 2 :
+            	        	        	        dbg.EnterAlt(2);
+
+            	        	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:829:5: T_INFTY
+            	        	        	        {
+            	        	        	        	dbg.Location(829,5);
+            	        	        	        	Match(input,T_INFTY,FOLLOW_T_INFTY_in_qvalExpression4052); 
+            	        	        	        	dbg.Location(830,5);
+            	        	        	        	setQualitativeValueRangeInfinity(result,false);
+
+            	        	        	        }
+            	        	        	        break;
+
+            	        	        	}
+            	        	        	} finally { dbg.ExitSubRule(94); }
+
+
+            	        	        }
+            	        	        break;
+
+            	        	}
+            	        	} finally { dbg.ExitSubRule(95); }
+
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(96); }
+
+            	dbg.Location(833,3);
+            	Match(input,T_COMMA,FOLLOW_T_COMMA_in_qvalExpression4076); 
+            	dbg.Location(834,3);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:834:3: ( T_NIL | ( 'steady' | 'inc' | 'dec' ) )
+            	int alt98 = 2;
+            	try { dbg.EnterSubRule(98);
+            	try { dbg.EnterDecision(98);
+
+            	int LA98_0 = input.LA(1);
+
+            	if ( (LA98_0 == T_NIL) )
+            	{
+            	    alt98 = 1;
+            	}
+            	else if ( ((LA98_0 >= 123 && LA98_0 <= 125)) )
+            	{
+            	    alt98 = 2;
+            	}
+            	else 
+            	{
+            	    NoViableAltException nvae_d98s0 =
+            	        new NoViableAltException("", 98, 0, input);
+
+            	    dbg.RecognitionException(nvae_d98s0);
+            	    throw nvae_d98s0;
+            	}
+            	} finally { dbg.ExitDecision(98); }
+
+            	switch (alt98) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:835:4: T_NIL
+            	        {
+            	        	dbg.Location(835,4);
+            	        	Match(input,T_NIL,FOLLOW_T_NIL_in_qvalExpression4086); 
+            	        	dbg.Location(836,4);
+            	        	setQualitativeDerivDontCare(result);
+
+            	        }
+            	        break;
+            	    case 2 :
+            	        dbg.EnterAlt(2);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:838:4: ( 'steady' | 'inc' | 'dec' )
+            	        {
+            	        	dbg.Location(838,4);
+            	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:838:4: ( 'steady' | 'inc' | 'dec' )
+            	        	int alt97 = 3;
+            	        	try { dbg.EnterSubRule(97);
+            	        	try { dbg.EnterDecision(97);
+
+            	        	switch ( input.LA(1) ) 
+            	        	{
+            	        	case 123:
+            	        		{
+            	        	    alt97 = 1;
+            	        	    }
+            	        	    break;
+            	        	case 124:
+            	        		{
+            	        	    alt97 = 2;
+            	        	    }
+            	        	    break;
+            	        	case 125:
+            	        		{
+            	        	    alt97 = 3;
+            	        	    }
+            	        	    break;
+            	        		default:
+            	        		    NoViableAltException nvae_d97s0 =
+            	        		        new NoViableAltException("", 97, 0, input);
+
+            	        		    dbg.RecognitionException(nvae_d97s0);
+            	        		    throw nvae_d97s0;
+            	        	}
+
+            	        	} finally { dbg.ExitDecision(97); }
+
+            	        	switch (alt97) 
+            	        	{
+            	        	    case 1 :
+            	        	        dbg.EnterAlt(1);
+
+            	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:838:6: 'steady'
+            	        	        {
+            	        	        	dbg.Location(838,6);
+            	        	        	Match(input,123,FOLLOW_123_in_qvalExpression4102); 
+            	        	        	dbg.Location(839,5);
+            	        	        	setQualitativeDerivSteady(result);
+
+            	        	        }
+            	        	        break;
+            	        	    case 2 :
+            	        	        dbg.EnterAlt(2);
+
+            	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:840:6: 'inc'
+            	        	        {
+            	        	        	dbg.Location(840,6);
+            	        	        	Match(input,124,FOLLOW_124_in_qvalExpression4115); 
+            	        	        	dbg.Location(841,5);
+            	        	        	setQualitativeDerivInc(result);
+
+            	        	        }
+            	        	        break;
+            	        	    case 3 :
+            	        	        dbg.EnterAlt(3);
+
+            	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:842:6: 'dec'
+            	        	        {
+            	        	        	dbg.Location(842,6);
+            	        	        	Match(input,125,FOLLOW_125_in_qvalExpression4128); 
+            	        	        	dbg.Location(843,5);
+            	        	        	setQualitativeDerivDec(result);
+
+            	        	        }
+            	        	        break;
+
+            	        	}
+            	        	} finally { dbg.ExitSubRule(97); }
+
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(98); }
+
+            	dbg.Location(846,3);
+            	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_qvalExpression4150); 
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(847, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "qvalExpression");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "qvalExpression"
+
+
+    // $ANTLR start "identifierExpression"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:850:1: identifierExpression returns [Expression result] : ({...}?aName= T_IDENTIFIER T_LPAREN m_params= methodCallParams T_RPAREN | res= reference );
+    public Expression identifierExpression() // throws RecognitionException [1]
+    {   
+        Expression result = default(Expression);
+
+        IToken aName = null;
+        System.Collections.Generic.List<Expression> m_params = default(System.Collections.Generic.List<Expression>);
+
+        Expression res = default(Expression);
+
+
+        try {
+        	dbg.EnterRule(GrammarFileName, "identifierExpression");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(850, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:852:2: ({...}?aName= T_IDENTIFIER T_LPAREN m_params= methodCallParams T_RPAREN | res= reference )
+            int alt99 = 2;
+            try { dbg.EnterDecision(99);
+
+            try 
+            {
+                isCyclicDecision = true;
+                alt99 = dfa99.Predict(input);
+            }
+            catch (NoViableAltException nvae) 
+            {
+                dbg.RecognitionException(nvae);
+                throw nvae;
+            }
+            } finally { dbg.ExitDecision(99); }
+
+            switch (alt99) 
+            {
+                case 1 :
+                    dbg.EnterAlt(1);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:853:3: {...}?aName= T_IDENTIFIER T_LPAREN m_params= methodCallParams T_RPAREN
+                    {
+                    	dbg.Location(853,3);
+                    	if ( !(EvalPredicate(isTuple(input.LT(1).Text),"isTuple(input.LT(1).Text)")) ) 
+                    	{
+                    	    throw new FailedPredicateException(input, "identifierExpression", "isTuple(input.LT(1).Text)");
+                    	}
+                    	dbg.Location(854,8);
+                    	aName=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_identifierExpression4183); 
+                    	dbg.Location(854,22);
+                    	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_identifierExpression4185); 
+                    	dbg.Location(854,39);
+                    	PushFollow(FOLLOW_methodCallParams_in_identifierExpression4189);
+                    	m_params = methodCallParams();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(854,57);
+                    	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_identifierExpression4191); 
+                    	dbg.Location(855,3);
+                    	result = createInitializedTuple(aName,m_params);
+
+                    }
+                    break;
+                case 2 :
+                    dbg.EnterAlt(2);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:857:3: res= reference
+                    {
+                    	dbg.Location(857,6);
+                    	PushFollow(FOLLOW_reference_in_identifierExpression4206);
+                    	res = reference();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(858,5);
+                    	result = res;
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(859, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "identifierExpression");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "identifierExpression"
+
+
+    // $ANTLR start "reference"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:862:1: reference returns [Expression result] : {...}?aName= qualifiedIdentifier (output= accessExpression[result] | ) (pr= T_PRIMED | ( '::' T_LPAREN init= expression T_RPAREN )? afold= ( T_FOLDLR | T_FOLDRL ) T_LPAREN anexpr= expression T_RPAREN )? ;
+    public Expression reference() // throws RecognitionException [1]
+    {   
+        Expression result = default(Expression);
+
+        IToken pr = null;
+        IToken afold = null;
+        Expression aName = default(Expression);
+
+        Expression output = default(Expression);
+
+        Expression init = default(Expression);
+
+        Expression anexpr = default(Expression);
+
+
+
+        		result = null;
+        		init = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "reference");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(862, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:868:2: ({...}?aName= qualifiedIdentifier (output= accessExpression[result] | ) (pr= T_PRIMED | ( '::' T_LPAREN init= expression T_RPAREN )? afold= ( T_FOLDLR | T_FOLDRL ) T_LPAREN anexpr= expression T_RPAREN )? )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:868:4: {...}?aName= qualifiedIdentifier (output= accessExpression[result] | ) (pr= T_PRIMED | ( '::' T_LPAREN init= expression T_RPAREN )? afold= ( T_FOLDLR | T_FOLDRL ) T_LPAREN anexpr= expression T_RPAREN )?
+            {
+            	dbg.Location(868,4);
+            	if ( !(EvalPredicate(!isTuple(input.LT(1).Text),"!isTuple(input.LT(1).Text)")) ) 
+            	{
+            	    throw new FailedPredicateException(input, "reference", "!isTuple(input.LT(1).Text)");
+            	}
+            	dbg.Location(869,8);
+            	PushFollow(FOLLOW_qualifiedIdentifier_in_reference4244);
+            	aName = qualifiedIdentifier();
+            	state.followingStackPointer--;
+
+            	dbg.Location(869,29);
+            	result = aName;
+            	dbg.Location(870,3);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:870:3: (output= accessExpression[result] | )
+            	int alt100 = 2;
+            	try { dbg.EnterSubRule(100);
+            	try { dbg.EnterDecision(100);
+
+            	try 
+            	{
+            	    isCyclicDecision = true;
+            	    alt100 = dfa100.Predict(input);
+            	}
+            	catch (NoViableAltException nvae) 
+            	{
+            	    dbg.RecognitionException(nvae);
+            	    throw nvae;
+            	}
+            	} finally { dbg.ExitDecision(100); }
+
+            	switch (alt100) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:870:5: output= accessExpression[result]
+            	        {
+            	        	dbg.Location(870,11);
+            	        	PushFollow(FOLLOW_accessExpression_in_reference4256);
+            	        	output = accessExpression(result);
+            	        	state.followingStackPointer--;
+
+            	        	dbg.Location(870,37);
+            	        	result = output;
+
+            	        }
+            	        break;
+            	    case 2 :
+            	        dbg.EnterAlt(2);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:873:3: 
+            	        {
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(100); }
+
+            	dbg.Location(874,3);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:874:3: (pr= T_PRIMED | ( '::' T_LPAREN init= expression T_RPAREN )? afold= ( T_FOLDLR | T_FOLDRL ) T_LPAREN anexpr= expression T_RPAREN )?
+            	int alt102 = 3;
+            	try { dbg.EnterSubRule(102);
+            	try { dbg.EnterDecision(102);
+
+            	try 
+            	{
+            	    isCyclicDecision = true;
+            	    alt102 = dfa102.Predict(input);
+            	}
+            	catch (NoViableAltException nvae) 
+            	{
+            	    dbg.RecognitionException(nvae);
+            	    throw nvae;
+            	}
+            	} finally { dbg.ExitDecision(102); }
+
+            	switch (alt102) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:874:6: pr= T_PRIMED
+            	        {
+            	        	dbg.Location(874,8);
+            	        	pr=(IToken)Match(input,T_PRIMED,FOLLOW_T_PRIMED_in_reference4281); 
+            	        	dbg.Location(874,18);
+            	        	setIdentifierExpressionPrimed(ref result,pr);
+
+            	        }
+            	        break;
+            	    case 2 :
+            	        dbg.EnterAlt(2);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:876:5: ( '::' T_LPAREN init= expression T_RPAREN )? afold= ( T_FOLDLR | T_FOLDRL ) T_LPAREN anexpr= expression T_RPAREN
+            	        {
+            	        	dbg.Location(876,5);
+            	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:876:5: ( '::' T_LPAREN init= expression T_RPAREN )?
+            	        	int alt101 = 2;
+            	        	try { dbg.EnterSubRule(101);
+            	        	try { dbg.EnterDecision(101);
+
+            	        	int LA101_0 = input.LA(1);
+
+            	        	if ( (LA101_0 == 126) )
+            	        	{
+            	        	    alt101 = 1;
+            	        	}
+            	        	} finally { dbg.ExitDecision(101); }
+
+            	        	switch (alt101) 
+            	        	{
+            	        	    case 1 :
+            	        	        dbg.EnterAlt(1);
+
+            	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:876:6: '::' T_LPAREN init= expression T_RPAREN
+            	        	        {
+            	        	        	dbg.Location(876,6);
+            	        	        	Match(input,126,FOLLOW_126_in_reference4297); 
+            	        	        	dbg.Location(876,11);
+            	        	        	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_reference4299); 
+            	        	        	dbg.Location(876,24);
+            	        	        	PushFollow(FOLLOW_expression_in_reference4303);
+            	        	        	init = expression();
+            	        	        	state.followingStackPointer--;
+
+            	        	        	dbg.Location(876,36);
+            	        	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_reference4305); 
+
+            	        	        }
+            	        	        break;
+
+            	        	}
+            	        	} finally { dbg.ExitSubRule(101); }
+
+            	        	dbg.Location(876,52);
+            	        	afold = (IToken)input.LT(1);
+            	        	if ( (input.LA(1) >= T_FOLDLR && input.LA(1) <= T_FOLDRL) ) 
+            	        	{
+            	        	    input.Consume();
+            	        	    state.errorRecovery = false;
+            	        	}
+            	        	else 
+            	        	{
+            	        	    MismatchedSetException mse = new MismatchedSetException(null,input);
+            	        	    dbg.RecognitionException(mse);
+            	        	    throw mse;
+            	        	}
+
+            	        	dbg.Location(876,73);
+            	        	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_reference4317); 
+            	        	dbg.Location(876,88);
+            	        	PushFollow(FOLLOW_expression_in_reference4321);
+            	        	anexpr = expression();
+            	        	state.followingStackPointer--;
+
+            	        	dbg.Location(876,100);
+            	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_reference4323); 
+            	        	dbg.Location(877,5);
+            	        	result = createFoldExpression(result,afold,init,anexpr);
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(102); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(879, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "reference");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "reference"
+
+
+    // $ANTLR start "accessExpression"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:881:1: accessExpression[Expression subexpr] returns [Expression result] : (tcall= T_LSQPAREN ac= expression T_RSQPAREN | bcall= T_LPAREN m_params= methodCallParams T_RPAREN )+ ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[result] )? )? ;
+    public Expression accessExpression(Expression subexpr) // throws RecognitionException [1]
+    {   
+        Expression result = default(Expression);
+
+        IToken tcall = null;
+        IToken bcall = null;
+        IToken idn = null;
+        Expression ac = default(Expression);
+
+        System.Collections.Generic.List<Expression> m_params = default(System.Collections.Generic.List<Expression>);
+
+        Expression res = default(Expression);
+
+
+
+        		UnaryOperator newExpr = null;
+        		result = subexpr;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "accessExpression");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(881, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:887:2: ( (tcall= T_LSQPAREN ac= expression T_RSQPAREN | bcall= T_LPAREN m_params= methodCallParams T_RPAREN )+ ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[result] )? )? )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:888:7: (tcall= T_LSQPAREN ac= expression T_RSQPAREN | bcall= T_LPAREN m_params= methodCallParams T_RPAREN )+ ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[result] )? )?
+            {
+            	dbg.Location(888,7);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:888:7: (tcall= T_LSQPAREN ac= expression T_RSQPAREN | bcall= T_LPAREN m_params= methodCallParams T_RPAREN )+
+            	int cnt103 = 0;
+            	try { dbg.EnterSubRule(103);
+
+            	do 
+            	{
+            	    int alt103 = 3;
+            	    try { dbg.EnterDecision(103);
+
+            	    try 
+            	    {
+            	        isCyclicDecision = true;
+            	        alt103 = dfa103.Predict(input);
+            	    }
+            	    catch (NoViableAltException nvae) 
+            	    {
+            	        dbg.RecognitionException(nvae);
+            	        throw nvae;
+            	    }
+            	    } finally { dbg.ExitDecision(103); }
+
+            	    switch (alt103) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:888:9: tcall= T_LSQPAREN ac= expression T_RSQPAREN
+            			    {
+            			    	dbg.Location(888,14);
+            			    	tcall=(IToken)Match(input,T_LSQPAREN,FOLLOW_T_LSQPAREN_in_accessExpression4368); 
+            			    	dbg.Location(888,28);
+            			    	PushFollow(FOLLOW_expression_in_accessExpression4372);
+            			    	ac = expression();
+            			    	state.followingStackPointer--;
+
+            			    	dbg.Location(888,40);
+            			    	Match(input,T_RSQPAREN,FOLLOW_T_RSQPAREN_in_accessExpression4374); 
+            			    	dbg.Location(889,8);
+            			    	 result = createTupleMapAccessExpression(result,ac,tcall); 
+
+            			    }
+            			    break;
+            			case 2 :
+            			    dbg.EnterAlt(2);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:890:10: bcall= T_LPAREN m_params= methodCallParams T_RPAREN
+            			    {
+            			    	dbg.Location(890,15);
+            			    	bcall=(IToken)Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_accessExpression4401); 
+            			    	dbg.Location(890,33);
+            			    	PushFollow(FOLLOW_methodCallParams_in_accessExpression4405);
+            			    	m_params = methodCallParams();
+            			    	state.followingStackPointer--;
+
+            			    	dbg.Location(890,51);
+            			    	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_accessExpression4407); 
+            			    	dbg.Location(891,4);
+            			    	 result = createMethodAccessExpression(result,m_params,bcall); 
+
+            			    }
+            			    break;
+
+            			default:
+            			    if ( cnt103 >= 1 ) goto loop103;
+            		            EarlyExitException eee103 =
+            		                new EarlyExitException(103, input);
+            		            dbg.RecognitionException(eee103);
+
+            		            throw eee103;
+            	    }
+            	    cnt103++;
+            	} while (true);
+
+            	loop103:
+            		;	// Stops C# compiler whining that label 'loop103' has no statements
+            	} finally { dbg.ExitSubRule(103); }
+
+            	dbg.Location(893,3);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:893:3: ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[result] )? )?
+            	int alt106 = 2;
+            	try { dbg.EnterSubRule(106);
+            	try { dbg.EnterDecision(106);
+
+            	try 
+            	{
+            	    isCyclicDecision = true;
+            	    alt106 = dfa106.Predict(input);
+            	}
+            	catch (NoViableAltException nvae) 
+            	{
+            	    dbg.RecognitionException(nvae);
+            	    throw nvae;
+            	}
+            	} finally { dbg.ExitDecision(106); }
+
+            	switch (alt106) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:894:4: ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[result] )?
+            	        {
+            	        	dbg.Location(894,4);
+            	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:894:4: ( T_POINT idn= T_IDENTIFIER )+
+            	        	int cnt104 = 0;
+            	        	try { dbg.EnterSubRule(104);
+
+            	        	do 
+            	        	{
+            	        	    int alt104 = 2;
+            	        	    try { dbg.EnterDecision(104);
+
+            	        	    try 
+            	        	    {
+            	        	        isCyclicDecision = true;
+            	        	        alt104 = dfa104.Predict(input);
+            	        	    }
+            	        	    catch (NoViableAltException nvae) 
+            	        	    {
+            	        	        dbg.RecognitionException(nvae);
+            	        	        throw nvae;
+            	        	    }
+            	        	    } finally { dbg.ExitDecision(104); }
+
+            	        	    switch (alt104) 
+            	        		{
+            	        			case 1 :
+            	        			    dbg.EnterAlt(1);
+
+            	        			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:894:5: T_POINT idn= T_IDENTIFIER
+            	        			    {
+            	        			    	dbg.Location(894,5);
+            	        			    	Match(input,T_POINT,FOLLOW_T_POINT_in_accessExpression4429); 
+            	        			    	dbg.Location(895,7);
+            	        			    	idn=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_accessExpression4437); 
+            	        			    	dbg.Location(896,4);
+            	        			    	result = addIdentifierAccessExpression(result,idn);
+
+            	        			    }
+            	        			    break;
+
+            	        			default:
+            	        			    if ( cnt104 >= 1 ) goto loop104;
+            	        		            EarlyExitException eee104 =
+            	        		                new EarlyExitException(104, input);
+            	        		            dbg.RecognitionException(eee104);
+
+            	        		            throw eee104;
+            	        	    }
+            	        	    cnt104++;
+            	        	} while (true);
+
+            	        	loop104:
+            	        		;	// Stops C# compiler whining that label 'loop104' has no statements
+            	        	} finally { dbg.ExitSubRule(104); }
+
+            	        	dbg.Location(897,4);
+            	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:897:4: (res= accessExpression[result] )?
+            	        	int alt105 = 2;
+            	        	try { dbg.EnterSubRule(105);
+            	        	try { dbg.EnterDecision(105);
+
+            	        	try 
+            	        	{
+            	        	    isCyclicDecision = true;
+            	        	    alt105 = dfa105.Predict(input);
+            	        	}
+            	        	catch (NoViableAltException nvae) 
+            	        	{
+            	        	    dbg.RecognitionException(nvae);
+            	        	    throw nvae;
+            	        	}
+            	        	} finally { dbg.ExitDecision(105); }
+
+            	        	switch (alt105) 
+            	        	{
+            	        	    case 1 :
+            	        	        dbg.EnterAlt(1);
+
+            	        	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:897:5: res= accessExpression[result]
+            	        	        {
+            	        	        	dbg.Location(897,8);
+            	        	        	PushFollow(FOLLOW_accessExpression_in_accessExpression4453);
+            	        	        	res = accessExpression(result);
+            	        	        	state.followingStackPointer--;
+
+            	        	        	dbg.Location(897,34);
+            	        	        	result=res;
+
+            	        	        }
+            	        	        break;
+
+            	        	}
+            	        	} finally { dbg.ExitSubRule(105); }
+
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(106); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(899, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "accessExpression");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "accessExpression"
+
+
+    // $ANTLR start "qualifiedIdentifier"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:901:1: qualifiedIdentifier returns [Expression top] : (self= T_SELF T_POINT )? idb= T_IDENTIFIER ( T_POINT idd= T_IDENTIFIER )* ;
+    public Expression qualifiedIdentifier() // throws RecognitionException [1]
+    {   
+        Expression top = default(Expression);
+
+        IToken self = null;
+        IToken idb = null;
+        IToken idd = null;
+
+
+        		IdentifierExpression selfexpr = null;
+        		top = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "qualifiedIdentifier");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(901, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:907:2: ( (self= T_SELF T_POINT )? idb= T_IDENTIFIER ( T_POINT idd= T_IDENTIFIER )* )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:908:3: (self= T_SELF T_POINT )? idb= T_IDENTIFIER ( T_POINT idd= T_IDENTIFIER )*
+            {
+            	dbg.Location(908,3);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:908:3: (self= T_SELF T_POINT )?
+            	int alt107 = 2;
+            	try { dbg.EnterSubRule(107);
+            	try { dbg.EnterDecision(107);
+
+            	int LA107_0 = input.LA(1);
+
+            	if ( (LA107_0 == T_SELF) )
+            	{
+            	    alt107 = 1;
+            	}
+            	} finally { dbg.ExitDecision(107); }
+
+            	switch (alt107) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:908:4: self= T_SELF T_POINT
+            	        {
+            	        	dbg.Location(908,8);
+            	        	self=(IToken)Match(input,T_SELF,FOLLOW_T_SELF_in_qualifiedIdentifier4492); 
+            	        	dbg.Location(908,16);
+            	        	Match(input,T_POINT,FOLLOW_T_POINT_in_qualifiedIdentifier4494); 
+            	        	dbg.Location(908,25);
+            	        	selfexpr = createSelfIdentifierExpression(self);
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(107); }
+
+            	dbg.Location(909,6);
+            	idb=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_qualifiedIdentifier4506); 
+            	dbg.Location(909,22);
+            	top = createIdentifierAccessExpression(selfexpr,idb);
+            	dbg.Location(910,3);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:910:3: ( T_POINT idd= T_IDENTIFIER )*
+            	try { dbg.EnterSubRule(108);
+
+            	do 
+            	{
+            	    int alt108 = 2;
+            	    try { dbg.EnterDecision(108);
+
+            	    try 
+            	    {
+            	        isCyclicDecision = true;
+            	        alt108 = dfa108.Predict(input);
+            	    }
+            	    catch (NoViableAltException nvae) 
+            	    {
+            	        dbg.RecognitionException(nvae);
+            	        throw nvae;
+            	    }
+            	    } finally { dbg.ExitDecision(108); }
+
+            	    switch (alt108) 
+            		{
+            			case 1 :
+            			    dbg.EnterAlt(1);
+
+            			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:910:4: T_POINT idd= T_IDENTIFIER
+            			    {
+            			    	dbg.Location(910,4);
+            			    	Match(input,T_POINT,FOLLOW_T_POINT_in_qualifiedIdentifier4515); 
+            			    	dbg.Location(910,15);
+            			    	idd=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_qualifiedIdentifier4519); 
+            			    	dbg.Location(910,30);
+            			    	top = addIdentifierAccessExpression(top,idd);
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop108;
+            	    }
+            	} while (true);
+
+            	loop108:
+            		;	// Stops C# compiler whining that label 'loop108' has no statements
+            	} finally { dbg.ExitSubRule(108); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(911, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "qualifiedIdentifier");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return top;
+    }
+    // $ANTLR end "qualifiedIdentifier"
+
+
+    // $ANTLR start "methodCallParams"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:914:1: methodCallParams returns [System.Collections.Generic.List<Expression> result] : (expa= expression ( T_COMMA expb= expression )* )? ;
+    public System.Collections.Generic.List<Expression> methodCallParams() // throws RecognitionException [1]
+    {   
+        System.Collections.Generic.List<Expression> result = default(System.Collections.Generic.List<Expression>);
+
+        Expression expa = default(Expression);
+
+        Expression expb = default(Expression);
+
+
+
+        		result = new System.Collections.Generic.List<Expression>();
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "methodCallParams");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(914, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:919:2: ( (expa= expression ( T_COMMA expb= expression )* )? )
+            dbg.EnterAlt(1);
+
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:919:4: (expa= expression ( T_COMMA expb= expression )* )?
+            {
+            	dbg.Location(919,4);
+            	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:919:4: (expa= expression ( T_COMMA expb= expression )* )?
+            	int alt110 = 2;
+            	try { dbg.EnterSubRule(110);
+            	try { dbg.EnterDecision(110);
+
+            	try 
+            	{
+            	    isCyclicDecision = true;
+            	    alt110 = dfa110.Predict(input);
+            	}
+            	catch (NoViableAltException nvae) 
+            	{
+            	    dbg.RecognitionException(nvae);
+            	    throw nvae;
+            	}
+            	} finally { dbg.ExitDecision(110); }
+
+            	switch (alt110) 
+            	{
+            	    case 1 :
+            	        dbg.EnterAlt(1);
+
+            	        // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:919:5: expa= expression ( T_COMMA expb= expression )*
+            	        {
+            	        	dbg.Location(919,9);
+            	        	PushFollow(FOLLOW_expression_in_methodCallParams4552);
+            	        	expa = expression();
+            	        	state.followingStackPointer--;
+
+            	        	dbg.Location(919,21);
+            	        	result.Add(expa);
+            	        	dbg.Location(919,41);
+            	        	// C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:919:41: ( T_COMMA expb= expression )*
+            	        	try { dbg.EnterSubRule(109);
+
+            	        	do 
+            	        	{
+            	        	    int alt109 = 2;
+            	        	    try { dbg.EnterDecision(109);
+
+            	        	    int LA109_0 = input.LA(1);
+
+            	        	    if ( (LA109_0 == T_COMMA) )
+            	        	    {
+            	        	        alt109 = 1;
+            	        	    }
+
+
+            	        	    } finally { dbg.ExitDecision(109); }
+
+            	        	    switch (alt109) 
+            	        		{
+            	        			case 1 :
+            	        			    dbg.EnterAlt(1);
+
+            	        			    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:919:42: T_COMMA expb= expression
+            	        			    {
+            	        			    	dbg.Location(919,42);
+            	        			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_methodCallParams4557); 
+            	        			    	dbg.Location(919,54);
+            	        			    	PushFollow(FOLLOW_expression_in_methodCallParams4561);
+            	        			    	expb = expression();
+            	        			    	state.followingStackPointer--;
+
+            	        			    	dbg.Location(919,66);
+            	        			    	result.Add(expb);
+
+            	        			    }
+            	        			    break;
+
+            	        			default:
+            	        			    goto loop109;
+            	        	    }
+            	        	} while (true);
+
+            	        	loop109:
+            	        		;	// Stops C# compiler whining that label 'loop109' has no statements
+            	        	} finally { dbg.ExitSubRule(109); }
+
+
+            	        }
+            	        break;
+
+            	}
+            	} finally { dbg.ExitSubRule(110); }
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(920, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "methodCallParams");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return result;
+    }
+    // $ANTLR end "methodCallParams"
+
+
+    // $ANTLR start "op_un"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:929:1: op_un returns [UnaryOperator expr] : (r= op_un_set_list | r2= op_un_map | T_MINUS | T_NOT | T_ABS );
+    public UnaryOperator op_un() // throws RecognitionException [1]
+    {   
+        UnaryOperator expr = default(UnaryOperator);
+
+        UnaryOperator r = default(UnaryOperator);
+
+        UnaryOperator r2 = default(UnaryOperator);
+
+
+
+        		expr = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "op_un");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(929, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:934:2: (r= op_un_set_list | r2= op_un_map | T_MINUS | T_NOT | T_ABS )
+            int alt111 = 5;
+            try { dbg.EnterDecision(111);
+
+            try 
+            {
+                isCyclicDecision = true;
+                alt111 = dfa111.Predict(input);
+            }
+            catch (NoViableAltException nvae) 
+            {
+                dbg.RecognitionException(nvae);
+                throw nvae;
+            }
+            } finally { dbg.ExitDecision(111); }
+
+            switch (alt111) 
+            {
+                case 1 :
+                    dbg.EnterAlt(1);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:934:4: r= op_un_set_list
+                    {
+                    	dbg.Location(934,5);
+                    	PushFollow(FOLLOW_op_un_set_list_in_op_un4600);
+                    	r = op_un_set_list();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(934,21);
+                    	expr = r;
+
+                    }
+                    break;
+                case 2 :
+                    dbg.EnterAlt(2);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:935:4: r2= op_un_map
+                    {
+                    	dbg.Location(935,6);
+                    	PushFollow(FOLLOW_op_un_map_in_op_un4609);
+                    	r2 = op_un_map();
+                    	state.followingStackPointer--;
+
+                    	dbg.Location(935,18);
+                    	expr = r2;
+
+                    }
+                    break;
+                case 3 :
+                    dbg.EnterAlt(3);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:936:4: T_MINUS
+                    {
+                    	dbg.Location(936,4);
+                    	Match(input,T_MINUS,FOLLOW_T_MINUS_in_op_un4617); 
+                    	dbg.Location(936,13);
+                    	expr = createUnaryOperator(ExpressionKind.unminus);
+
+                    }
+                    break;
+                case 4 :
+                    dbg.EnterAlt(4);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:937:4: T_NOT
+                    {
+                    	dbg.Location(937,4);
+                    	Match(input,T_NOT,FOLLOW_T_NOT_in_op_un4625); 
+                    	dbg.Location(937,11);
+                    	expr = createUnaryOperator(ExpressionKind.not);
+
+                    }
+                    break;
+                case 5 :
+                    dbg.EnterAlt(5);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:938:4: T_ABS
+                    {
+                    	dbg.Location(938,4);
+                    	Match(input,T_ABS,FOLLOW_T_ABS_in_op_un4633); 
+                    	dbg.Location(938,11);
+                    	expr = createUnaryOperator(ExpressionKind.abs);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(939, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "op_un");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return expr;
+    }
+    // $ANTLR end "op_un"
+
+
+    // $ANTLR start "op_un_set_list"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:942:1: op_un_set_list returns [UnaryOperator expr] : ( T_CARD | T_DCONC | T_DINTER | T_DUNION | T_ELEMS | T_HEAD | T_INDS | T_LEN | T_TAIL );
+    public UnaryOperator op_un_set_list() // throws RecognitionException [1]
+    {   
+        UnaryOperator expr = default(UnaryOperator);
+
+
+        		expr = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "op_un_set_list");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(942, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:947:2: ( T_CARD | T_DCONC | T_DINTER | T_DUNION | T_ELEMS | T_HEAD | T_INDS | T_LEN | T_TAIL )
+            int alt112 = 9;
+            try { dbg.EnterDecision(112);
+
+            try 
+            {
+                isCyclicDecision = true;
+                alt112 = dfa112.Predict(input);
+            }
+            catch (NoViableAltException nvae) 
+            {
+                dbg.RecognitionException(nvae);
+                throw nvae;
+            }
+            } finally { dbg.ExitDecision(112); }
+
+            switch (alt112) 
+            {
+                case 1 :
+                    dbg.EnterAlt(1);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:947:4: T_CARD
+                    {
+                    	dbg.Location(947,4);
+                    	Match(input,T_CARD,FOLLOW_T_CARD_in_op_un_set_list4660); 
+                    	dbg.Location(948,3);
+                    	expr = createUnaryOperator(ExpressionKind.card);
+
+                    }
+                    break;
+                case 2 :
+                    dbg.EnterAlt(2);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:949:4: T_DCONC
+                    {
+                    	dbg.Location(949,4);
+                    	Match(input,T_DCONC,FOLLOW_T_DCONC_in_op_un_set_list4671); 
+                    	dbg.Location(950,3);
+                    	expr = createUnaryOperator(ExpressionKind.dconc);
+
+                    }
+                    break;
+                case 3 :
+                    dbg.EnterAlt(3);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:951:4: T_DINTER
+                    {
+                    	dbg.Location(951,4);
+                    	Match(input,T_DINTER,FOLLOW_T_DINTER_in_op_un_set_list4682); 
+                    	dbg.Location(952,3);
+                    	expr = createUnaryOperator(ExpressionKind.dinter);
+
+                    }
+                    break;
+                case 4 :
+                    dbg.EnterAlt(4);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:953:4: T_DUNION
+                    {
+                    	dbg.Location(953,4);
+                    	Match(input,T_DUNION,FOLLOW_T_DUNION_in_op_un_set_list4692); 
+                    	dbg.Location(954,3);
+                    	expr = createUnaryOperator(ExpressionKind.dunion);
+
+                    }
+                    break;
+                case 5 :
+                    dbg.EnterAlt(5);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:955:4: T_ELEMS
+                    {
+                    	dbg.Location(955,4);
+                    	Match(input,T_ELEMS,FOLLOW_T_ELEMS_in_op_un_set_list4702); 
+                    	dbg.Location(956,3);
+                    	expr = createUnaryOperator(ExpressionKind.elems);
+
+                    }
+                    break;
+                case 6 :
+                    dbg.EnterAlt(6);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:957:4: T_HEAD
+                    {
+                    	dbg.Location(957,4);
+                    	Match(input,T_HEAD,FOLLOW_T_HEAD_in_op_un_set_list4713); 
+                    	dbg.Location(958,3);
+                    	expr = createUnaryOperator(ExpressionKind.head);
+
+                    }
+                    break;
+                case 7 :
+                    dbg.EnterAlt(7);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:959:4: T_INDS
+                    {
+                    	dbg.Location(959,4);
+                    	Match(input,T_INDS,FOLLOW_T_INDS_in_op_un_set_list4724); 
+                    	dbg.Location(960,3);
+                    	expr = createUnaryOperator(ExpressionKind.inds);
+
+                    }
+                    break;
+                case 8 :
+                    dbg.EnterAlt(8);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:961:4: T_LEN
+                    {
+                    	dbg.Location(961,4);
+                    	Match(input,T_LEN,FOLLOW_T_LEN_in_op_un_set_list4735); 
+                    	dbg.Location(962,3);
+                    	expr = createUnaryOperator(ExpressionKind.len);
+
+                    }
+                    break;
+                case 9 :
+                    dbg.EnterAlt(9);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:963:4: T_TAIL
+                    {
+                    	dbg.Location(963,4);
+                    	Match(input,T_TAIL,FOLLOW_T_TAIL_in_op_un_set_list4746); 
+                    	dbg.Location(964,3);
+                    	expr = createUnaryOperator(ExpressionKind.tail);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(965, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "op_un_set_list");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return expr;
+    }
+    // $ANTLR end "op_un_set_list"
+
+
+    // $ANTLR start "op_un_map"
+    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:968:1: op_un_map returns [UnaryOperator expr] : ( T_DOM | T_RNG | T_MERGE );
+    public UnaryOperator op_un_map() // throws RecognitionException [1]
+    {   
+        UnaryOperator expr = default(UnaryOperator);
+
+
+        		expr = null;
+        	
+        try {
+        	dbg.EnterRule(GrammarFileName, "op_un_map");
+        	if ( RuleLevel==0 ) {dbg.Commence();}
+        	IncRuleLevel();
+        	dbg.Location(968, 1);
+
+        try 
+    	{
+            // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:973:2: ( T_DOM | T_RNG | T_MERGE )
+            int alt113 = 3;
+            try { dbg.EnterDecision(113);
+
+            switch ( input.LA(1) ) 
+            {
+            case T_DOM:
+            	{
+                alt113 = 1;
+                }
+                break;
+            case T_RNG:
+            	{
+                alt113 = 2;
+                }
+                break;
+            case T_MERGE:
+            	{
+                alt113 = 3;
+                }
+                break;
+            	default:
+            	    NoViableAltException nvae_d113s0 =
+            	        new NoViableAltException("", 113, 0, input);
+
+            	    dbg.RecognitionException(nvae_d113s0);
+            	    throw nvae_d113s0;
+            }
+
+            } finally { dbg.ExitDecision(113); }
+
+            switch (alt113) 
+            {
+                case 1 :
+                    dbg.EnterAlt(1);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:973:4: T_DOM
+                    {
+                    	dbg.Location(973,4);
+                    	Match(input,T_DOM,FOLLOW_T_DOM_in_op_un_map4775); 
+                    	dbg.Location(974,3);
+                    	expr = createUnaryOperator(ExpressionKind.dom);
+
+                    }
+                    break;
+                case 2 :
+                    dbg.EnterAlt(2);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:975:4: T_RNG
+                    {
+                    	dbg.Location(975,4);
+                    	Match(input,T_RNG,FOLLOW_T_RNG_in_op_un_map4786); 
+                    	dbg.Location(976,3);
+                    	expr = createUnaryOperator(ExpressionKind.range);
+
+                    }
+                    break;
+                case 3 :
+                    dbg.EnterAlt(3);
+
+                    // C:\\Users\\stiran\\homer\\argos\\trunk\\src\\ooa.g:977:4: T_MERGE
+                    {
+                    	dbg.Location(977,4);
+                    	Match(input,T_MERGE,FOLLOW_T_MERGE_in_op_un_map4797); 
+                    	dbg.Location(978,3);
+                    	expr = createUnaryOperator(ExpressionKind.merge);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        dbg.Location(979, 2);
+
+        }
+        finally {
+            dbg.ExitRule(GrammarFileName, "op_un_map");
+            DecRuleLevel();
+            if ( RuleLevel==0 ) {dbg.Terminate();}
+        }
+
+        return expr;
+    }
+    // $ANTLR end "op_un_map"
+
+    // Delegated rules
+
+
+   	protected DFA4 dfa4;
+   	protected DFA14 dfa14;
+   	protected DFA67 dfa67;
+   	protected DFA70 dfa70;
+   	protected DFA68 dfa68;
+   	protected DFA69 dfa69;
+   	protected DFA77 dfa77;
+   	protected DFA71 dfa71;
+   	protected DFA75 dfa75;
+   	protected DFA74 dfa74;
+   	protected DFA72 dfa72;
+   	protected DFA73 dfa73;
+   	protected DFA76 dfa76;
+   	protected DFA86 dfa86;
+   	protected DFA99 dfa99;
+   	protected DFA100 dfa100;
+   	protected DFA102 dfa102;
+   	protected DFA103 dfa103;
+   	protected DFA106 dfa106;
+   	protected DFA104 dfa104;
+   	protected DFA105 dfa105;
+   	protected DFA108 dfa108;
+   	protected DFA110 dfa110;
+   	protected DFA111 dfa111;
+   	protected DFA112 dfa112;
+	private void InitializeCyclicDFAs(IDebugEventListener dbg)
+	{
+    	this.dfa4 = new DFA4(this, dbg);
+    	this.dfa14 = new DFA14(this, dbg);
+    	this.dfa67 = new DFA67(this, dbg);
+    	this.dfa70 = new DFA70(this, dbg);
+    	this.dfa68 = new DFA68(this, dbg);
+    	this.dfa69 = new DFA69(this, dbg);
+    	this.dfa77 = new DFA77(this, dbg);
+    	this.dfa71 = new DFA71(this, dbg);
+    	this.dfa75 = new DFA75(this, dbg);
+    	this.dfa74 = new DFA74(this, dbg);
+    	this.dfa72 = new DFA72(this, dbg);
+    	this.dfa73 = new DFA73(this, dbg);
+    	this.dfa76 = new DFA76(this, dbg);
+    	this.dfa86 = new DFA86(this, dbg);
+    	this.dfa99 = new DFA99(this, dbg);
+    	this.dfa100 = new DFA100(this, dbg);
+    	this.dfa102 = new DFA102(this, dbg);
+    	this.dfa103 = new DFA103(this, dbg);
+    	this.dfa106 = new DFA106(this, dbg);
+    	this.dfa104 = new DFA104(this, dbg);
+    	this.dfa105 = new DFA105(this, dbg);
+    	this.dfa108 = new DFA108(this, dbg);
+    	this.dfa110 = new DFA110(this, dbg);
+    	this.dfa111 = new DFA111(this, dbg);
+    	this.dfa112 = new DFA112(this, dbg);
+	    this.dfa99.specialStateTransitionHandler = new DFA.SpecialStateTransitionHandler(DFA99_SpecialStateTransition);
+	}
+
+    const string DFA4_eotS =
+        "\x0e\uffff";
+    const string DFA4_eofS =
+        "\x0e\uffff";
+    const string DFA4_minS =
+        "\x01\x06\x0d\uffff";
+    const string DFA4_maxS =
+        "\x01\x21\x0d\uffff";
+    const string DFA4_acceptS =
+        "\x01\uffff\x01\x01\x0a\uffff\x01\x02\x01\uffff";
+    const string DFA4_specialS =
+        "\x0e\uffff}>";
+    static readonly string[] DFA4_transitionS = {
+            "\x01\x0c\x01\uffff\x01\x01\x03\uffff\x01\x01\x01\uffff\x02"+
+            "\x01\x04\uffff\x01\x01\x01\uffff\x01\x01\x02\uffff\x02\x01\x01"+
+            "\uffff\x01\x01\x01\uffff\x02\x01\x01\uffff\x01\x0c",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA4_eot = DFA.UnpackEncodedString(DFA4_eotS);
+    static readonly short[] DFA4_eof = DFA.UnpackEncodedString(DFA4_eofS);
+    static readonly char[] DFA4_min = DFA.UnpackEncodedStringToUnsignedChars(DFA4_minS);
+    static readonly char[] DFA4_max = DFA.UnpackEncodedStringToUnsignedChars(DFA4_maxS);
+    static readonly short[] DFA4_accept = DFA.UnpackEncodedString(DFA4_acceptS);
+    static readonly short[] DFA4_special = DFA.UnpackEncodedString(DFA4_specialS);
+    static readonly short[][] DFA4_transition = DFA.UnpackEncodedStringArray(DFA4_transitionS);
+
+    protected class DFA4 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA4(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 4;
+            this.eot = DFA4_eot;
+            this.eof = DFA4_eof;
+            this.min = DFA4_min;
+            this.max = DFA4_max;
+            this.accept = DFA4_accept;
+            this.special = DFA4_special;
+            this.transition = DFA4_transition;
+
+        }
+            public DFA4(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "175:3: (aType= complexType | anOoaType= ooActionSystem )"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA14_eotS =
+        "\x0c\uffff";
+    const string DFA14_eofS =
+        "\x0c\uffff";
+    const string DFA14_minS =
+        "\x01\x08\x0b\uffff";
+    const string DFA14_maxS =
+        "\x01\x1f\x0b\uffff";
+    const string DFA14_acceptS =
+        "\x01\uffff\x01\x01\x01\x02\x01\x03\x01\x04\x01\x05\x01\x06\x05"+
+        "\uffff";
+    const string DFA14_specialS =
+        "\x0c\uffff}>";
+    static readonly string[] DFA14_transitionS = {
+            "\x01\x06\x03\uffff\x01\x05\x01\uffff\x01\x01\x01\x02\x04\uffff"+
+            "\x01\x03\x01\uffff\x01\x04\x02\uffff\x02\x06\x01\uffff\x01\x06"+
+            "\x01\uffff\x02\x06",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA14_eot = DFA.UnpackEncodedString(DFA14_eotS);
+    static readonly short[] DFA14_eof = DFA.UnpackEncodedString(DFA14_eofS);
+    static readonly char[] DFA14_min = DFA.UnpackEncodedStringToUnsignedChars(DFA14_minS);
+    static readonly char[] DFA14_max = DFA.UnpackEncodedStringToUnsignedChars(DFA14_maxS);
+    static readonly short[] DFA14_accept = DFA.UnpackEncodedString(DFA14_acceptS);
+    static readonly short[] DFA14_special = DFA.UnpackEncodedString(DFA14_specialS);
+    static readonly short[][] DFA14_transition = DFA.UnpackEncodedStringArray(DFA14_transitionS);
+
+    protected class DFA14 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA14(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 14;
+            this.eot = DFA14_eot;
+            this.eof = DFA14_eof;
+            this.min = DFA14_min;
+            this.max = DFA14_max;
+            this.accept = DFA14_accept;
+            this.special = DFA14_special;
+            this.transition = DFA14_transition;
+
+        }
+            public DFA14(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "209:1: complexType returns [UlyssesType aTypeSymbol] : ( T_LIST T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN T_OF innertype= complexType | T_LSQPAREN alistelem= T_IDENTIFIER ( T_COMMA otherlistelem= T_IDENTIFIER )* T_RSQPAREN | T_MAP ( T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN )? mapfromtype= simpleType T_TO maptotype= complexType | T_QUANTITY T_OF T_LSQPAREN (alandmark= T_IDENTIFIER | alandmark= T_MINUS T_INFTY ) ( T_COMMA (otherlandmark= T_IDENTIFIER | otherlandmark= T_INFTY ) )* T_RSQPAREN | T_LPAREN aType= complexType ( T_COMMA anotherType= complexType )* T_RPAREN | r= simpleType );"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA67_eotS =
+        "\x32\uffff";
+    const string DFA67_eofS =
+        "\x32\uffff";
+    const string DFA67_minS =
+        "\x01\x05\x31\uffff";
+    const string DFA67_maxS =
+        "\x01\x76\x31\uffff";
+    const string DFA67_acceptS =
+        "\x01\uffff\x01\x02\x12\uffff\x01\x01\x1d\uffff";
+    const string DFA67_specialS =
+        "\x32\uffff}>";
+    static readonly string[] DFA67_transitionS = {
+            "\x01\x01\x01\uffff\x01\x01\x01\uffff\x01\x14\x02\x01\x01\uffff"+
+            "\x01\x01\x03\uffff\x01\x01\x01\uffff\x01\x01\x03\uffff\x01\x14"+
+            "\x08\uffff\x01\x01\x02\uffff\x03\x01\x04\uffff\x02\x01\x03\uffff"+
+            "\x03\x14\x07\uffff\x01\x01\x08\x14\x01\uffff\x11\x14\x02\uffff"+
+            "\x02\x01\x07\uffff\x02\x01\x15\uffff\x01\x01",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA67_eot = DFA.UnpackEncodedString(DFA67_eotS);
+    static readonly short[] DFA67_eof = DFA.UnpackEncodedString(DFA67_eofS);
+    static readonly char[] DFA67_min = DFA.UnpackEncodedStringToUnsignedChars(DFA67_minS);
+    static readonly char[] DFA67_max = DFA.UnpackEncodedStringToUnsignedChars(DFA67_maxS);
+    static readonly short[] DFA67_accept = DFA.UnpackEncodedString(DFA67_acceptS);
+    static readonly short[] DFA67_special = DFA.UnpackEncodedString(DFA67_specialS);
+    static readonly short[][] DFA67_transition = DFA.UnpackEncodedStringArray(DFA67_transitionS);
+
+    protected class DFA67 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA67(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 67;
+            this.eot = DFA67_eot;
+            this.eof = DFA67_eof;
+            this.min = DFA67_min;
+            this.max = DFA67_max;
+            this.accept = DFA67_accept;
+            this.special = DFA67_special;
+            this.transition = DFA67_transition;
+
+        }
+            public DFA67(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "()* loopback of 583:3: (op= binoperator right= atomExpression )*"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA70_eotS =
+        "\x1f\uffff";
+    const string DFA70_eofS =
+        "\x1f\uffff";
+    const string DFA70_minS =
+        "\x01\x09\x1e\uffff";
+    const string DFA70_maxS =
+        "\x01\x53\x1e\uffff";
+    const string DFA70_acceptS =
+        "\x01\uffff\x01\x01\x01\x02\x01\x03\x01\x04\x01\x05\x01\x06\x01"+
+        "\x07\x01\x08\x01\x09\x01\x0a\x01\x0b\x01\x0c\x01\x0d\x01\x0e\x01"+
+        "\x0f\x01\x10\x01\x11\x01\x12\x01\x13\x01\x14\x01\x15\x01\x16\x01"+
+        "\x17\x01\x18\x01\x19\x01\x1a\x01\x1b\x01\x1c\x01\x1d\x01\x1e";
+    const string DFA70_specialS =
+        "\x1f\uffff}>";
+    static readonly string[] DFA70_transitionS = {
+            "\x01\x06\x0d\uffff\x01\x09\x17\uffff\x01\x0a\x01\x14\x01\x10"+
+            "\x08\uffff\x01\x01\x01\x02\x01\x03\x01\x04\x01\x05\x01\x07\x01"+
+            "\x08\x01\x0b\x01\uffff\x01\x0c\x01\x0d\x01\x0e\x01\x0f\x01\x11"+
+            "\x01\x12\x01\x13\x01\x15\x01\x16\x01\x17\x01\x18\x01\x19\x01"+
+            "\x1a\x01\x1b\x01\x1c\x01\x1d\x01\x1e",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA70_eot = DFA.UnpackEncodedString(DFA70_eotS);
+    static readonly short[] DFA70_eof = DFA.UnpackEncodedString(DFA70_eofS);
+    static readonly char[] DFA70_min = DFA.UnpackEncodedStringToUnsignedChars(DFA70_minS);
+    static readonly char[] DFA70_max = DFA.UnpackEncodedStringToUnsignedChars(DFA70_maxS);
+    static readonly short[] DFA70_accept = DFA.UnpackEncodedString(DFA70_acceptS);
+    static readonly short[] DFA70_special = DFA.UnpackEncodedString(DFA70_specialS);
+    static readonly short[][] DFA70_transition = DFA.UnpackEncodedStringArray(DFA70_transitionS);
+
+    protected class DFA70 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA70(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 70;
+            this.eot = DFA70_eot;
+            this.eof = DFA70_eof;
+            this.min = DFA70_min;
+            this.max = DFA70_max;
+            this.accept = DFA70_accept;
+            this.special = DFA70_special;
+            this.transition = DFA70_transition;
+
+        }
+            public DFA70(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "594:1: binoperator returns [BinaryOperator binop] : ( T_BIIMPLIES | T_GREATER | T_GREATEREQUAL | T_LESS | T_LESSEQUAL | T_EQUAL | T_NOTEQUAL | T_IMPLIES | T_MINUS | T_SUM | T_IN ( T_SET )? | T_NOT T_IN ( T_SET )? | T_SUBSET | T_OR | T_DIV | T_PROD | T_IDIV | T_MOD | T_UNION | T_DIFF | T_INTER | T_AND | T_POW | T_CONC | T_DOMRESBY | T_DOMRESTO | T_RNGRESBY | T_RNGRESTO | T_MUNION | T_SEQMOD_MAPOVERRIDE );"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA68_eotS =
+        "\x20\uffff";
+    const string DFA68_eofS =
+        "\x20\uffff";
+    const string DFA68_minS =
+        "\x01\x08\x1f\uffff";
+    const string DFA68_maxS =
+        "\x01\x7a\x1f\uffff";
+    const string DFA68_acceptS =
+        "\x01\uffff\x01\x01\x01\x02\x1d\uffff";
+    const string DFA68_specialS =
+        "\x20\uffff}>";
+    static readonly string[] DFA68_transitionS = {
+            "\x01\x02\x03\uffff\x01\x02\x02\uffff\x02\x02\x06\uffff\x01"+
+            "\x02\x05\uffff\x01\x02\x01\uffff\x01\x02\x17\uffff\x01\x02\x0a"+
+            "\uffff\x01\x01\x01\x02\x11\uffff\x01\x02\x02\uffff\x07\x02\x03"+
+            "\uffff\x0d\x02\x0b\uffff\x01\x02",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA68_eot = DFA.UnpackEncodedString(DFA68_eotS);
+    static readonly short[] DFA68_eof = DFA.UnpackEncodedString(DFA68_eofS);
+    static readonly char[] DFA68_min = DFA.UnpackEncodedStringToUnsignedChars(DFA68_minS);
+    static readonly char[] DFA68_max = DFA.UnpackEncodedStringToUnsignedChars(DFA68_maxS);
+    static readonly short[] DFA68_accept = DFA.UnpackEncodedString(DFA68_acceptS);
+    static readonly short[] DFA68_special = DFA.UnpackEncodedString(DFA68_specialS);
+    static readonly short[][] DFA68_transition = DFA.UnpackEncodedStringArray(DFA68_transitionS);
+
+    protected class DFA68 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA68(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 68;
+            this.eot = DFA68_eot;
+            this.eof = DFA68_eof;
+            this.min = DFA68_min;
+            this.max = DFA68_max;
+            this.accept = DFA68_accept;
+            this.special = DFA68_special;
+            this.transition = DFA68_transition;
+
+        }
+            public DFA68(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "616:9: ( T_SET )?"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA69_eotS =
+        "\x20\uffff";
+    const string DFA69_eofS =
+        "\x20\uffff";
+    const string DFA69_minS =
+        "\x01\x08\x1f\uffff";
+    const string DFA69_maxS =
+        "\x01\x7a\x1f\uffff";
+    const string DFA69_acceptS =
+        "\x01\uffff\x01\x01\x01\x02\x1d\uffff";
+    const string DFA69_specialS =
+        "\x20\uffff}>";
+    static readonly string[] DFA69_transitionS = {
+            "\x01\x02\x03\uffff\x01\x02\x02\uffff\x02\x02\x06\uffff\x01"+
+            "\x02\x05\uffff\x01\x02\x01\uffff\x01\x02\x17\uffff\x01\x02\x0a"+
+            "\uffff\x01\x01\x01\x02\x11\uffff\x01\x02\x02\uffff\x07\x02\x03"+
+            "\uffff\x0d\x02\x0b\uffff\x01\x02",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA69_eot = DFA.UnpackEncodedString(DFA69_eotS);
+    static readonly short[] DFA69_eof = DFA.UnpackEncodedString(DFA69_eofS);
+    static readonly char[] DFA69_min = DFA.UnpackEncodedStringToUnsignedChars(DFA69_minS);
+    static readonly char[] DFA69_max = DFA.UnpackEncodedStringToUnsignedChars(DFA69_maxS);
+    static readonly short[] DFA69_accept = DFA.UnpackEncodedString(DFA69_acceptS);
+    static readonly short[] DFA69_special = DFA.UnpackEncodedString(DFA69_specialS);
+    static readonly short[][] DFA69_transition = DFA.UnpackEncodedStringArray(DFA69_transitionS);
+
+    protected class DFA69 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA69(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 69;
+            this.eot = DFA69_eot;
+            this.eof = DFA69_eof;
+            this.min = DFA69_min;
+            this.max = DFA69_max;
+            this.accept = DFA69_accept;
+            this.special = DFA69_special;
+            this.transition = DFA69_transition;
+
+        }
+            public DFA69(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "618:15: ( T_SET )?"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA77_eotS =
+        "\x1f\uffff";
+    const string DFA77_eofS =
+        "\x1f\uffff";
+    const string DFA77_minS =
+        "\x01\x08\x1e\uffff";
+    const string DFA77_maxS =
+        "\x01\x7a\x1e\uffff";
+    const string DFA77_acceptS =
+        "\x01\uffff\x01\x01\x1c\uffff\x01\x02";
+    const string DFA77_specialS =
+        "\x1f\uffff}>";
+    static readonly string[] DFA77_transitionS = {
+            "\x01\x01\x03\uffff\x01\x01\x02\uffff\x02\x01\x06\uffff\x01"+
+            "\x01\x05\uffff\x01\x01\x01\uffff\x01\x01\x17\uffff\x01\x01\x0b"+
+            "\uffff\x01\x01\x11\uffff\x01\x1e\x02\uffff\x07\x01\x03\uffff"+
+            "\x0d\x01\x0b\uffff\x01\x01",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA77_eot = DFA.UnpackEncodedString(DFA77_eotS);
+    static readonly short[] DFA77_eof = DFA.UnpackEncodedString(DFA77_eofS);
+    static readonly char[] DFA77_min = DFA.UnpackEncodedStringToUnsignedChars(DFA77_minS);
+    static readonly char[] DFA77_max = DFA.UnpackEncodedStringToUnsignedChars(DFA77_maxS);
+    static readonly short[] DFA77_accept = DFA.UnpackEncodedString(DFA77_acceptS);
+    static readonly short[] DFA77_special = DFA.UnpackEncodedString(DFA77_specialS);
+    static readonly short[][] DFA77_transition = DFA.UnpackEncodedStringArray(DFA77_transitionS);
+
+    protected class DFA77 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA77(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 77;
+            this.eot = DFA77_eot;
+            this.eof = DFA77_eof;
+            this.min = DFA77_min;
+            this.max = DFA77_max;
+            this.accept = DFA77_accept;
+            this.special = DFA77_special;
+            this.transition = DFA77_transition;
+
+        }
+            public DFA77(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "660:1: atomExpression returns [Expression expr] : ( ( (unexpr= op_un )? (e= identifierExpression | e= qvalExpression | e= constant | e= initializedComplexType | e= quantifierExpression | T_LPAREN e= expression T_RPAREN ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )? ) ( 'as' cid= T_IDENTIFIER )? ) | ie= T_IF ce= expression T_THEN te= expression T_ELSE ee= expression T_END );"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA71_eotS =
+        "\x1e\uffff";
+    const string DFA71_eofS =
+        "\x1e\uffff";
+    const string DFA71_minS =
+        "\x01\x08\x1d\uffff";
+    const string DFA71_maxS =
+        "\x01\x7a\x1d\uffff";
+    const string DFA71_acceptS =
+        "\x01\uffff\x01\x01\x0e\uffff\x01\x02\x0d\uffff";
+    const string DFA71_specialS =
+        "\x1e\uffff}>";
+    static readonly string[] DFA71_transitionS = {
+            "\x01\x10\x03\uffff\x01\x10\x02\uffff\x02\x10\x06\uffff\x01"+
+            "\x01\x05\uffff\x01\x10\x01\uffff\x01\x10\x17\uffff\x01\x10\x0b"+
+            "\uffff\x01\x01\x14\uffff\x07\x10\x03\uffff\x0d\x01\x0b\uffff"+
+            "\x01\x10",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA71_eot = DFA.UnpackEncodedString(DFA71_eotS);
+    static readonly short[] DFA71_eof = DFA.UnpackEncodedString(DFA71_eofS);
+    static readonly char[] DFA71_min = DFA.UnpackEncodedStringToUnsignedChars(DFA71_minS);
+    static readonly char[] DFA71_max = DFA.UnpackEncodedStringToUnsignedChars(DFA71_maxS);
+    static readonly short[] DFA71_accept = DFA.UnpackEncodedString(DFA71_acceptS);
+    static readonly short[] DFA71_special = DFA.UnpackEncodedString(DFA71_specialS);
+    static readonly short[][] DFA71_transition = DFA.UnpackEncodedStringArray(DFA71_transitionS);
+
+    protected class DFA71 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA71(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 71;
+            this.eot = DFA71_eot;
+            this.eof = DFA71_eof;
+            this.min = DFA71_min;
+            this.max = DFA71_max;
+            this.accept = DFA71_accept;
+            this.special = DFA71_special;
+            this.transition = DFA71_transition;
+
+        }
+            public DFA71(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "665:11: (unexpr= op_un )?"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA75_eotS =
+        "\x42\uffff";
+    const string DFA75_eofS =
+        "\x42\uffff";
+    const string DFA75_minS =
+        "\x01\x08\x01\uffff\x01\x05\x3f\uffff";
+    const string DFA75_maxS =
+        "\x01\x7a\x01\uffff\x01\x79\x3f\uffff";
+    const string DFA75_acceptS =
+        "\x01\uffff\x01\x01\x01\uffff\x01\x02\x01\x03\x05\uffff\x01\x04"+
+        "\x02\uffff\x01\x05\x01\x06\x33\uffff";
+    const string DFA75_specialS =
+        "\x42\uffff}>";
+    static readonly string[] DFA75_transitionS = {
+            "\x01\x01\x03\uffff\x01\x0e\x02\uffff\x01\x0a\x01\x04\x0c\uffff"+
+            "\x01\x04\x01\uffff\x01\x0a\x17\uffff\x01\x02\x20\uffff\x02\x0d"+
+            "\x04\x04\x01\x0a\x1b\uffff\x01\x03",
+            "",
+            "\x01\x04\x01\uffff\x01\x04\x01\uffff\x03\x04\x01\uffff\x01"+
+            "\x04\x03\uffff\x01\x04\x01\uffff\x01\x04\x03\uffff\x01\x04\x08"+
+            "\uffff\x01\x04\x02\uffff\x03\x04\x04\uffff\x02\x04\x03\uffff"+
+            "\x03\x04\x07\uffff\x09\x04\x01\uffff\x11\x04\x01\x01\x01\uffff"+
+            "\x02\x04\x07\uffff\x02\x04\x15\uffff\x01\x04\x02\uffff\x01\x04",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA75_eot = DFA.UnpackEncodedString(DFA75_eotS);
+    static readonly short[] DFA75_eof = DFA.UnpackEncodedString(DFA75_eofS);
+    static readonly char[] DFA75_min = DFA.UnpackEncodedStringToUnsignedChars(DFA75_minS);
+    static readonly char[] DFA75_max = DFA.UnpackEncodedStringToUnsignedChars(DFA75_maxS);
+    static readonly short[] DFA75_accept = DFA.UnpackEncodedString(DFA75_acceptS);
+    static readonly short[] DFA75_special = DFA.UnpackEncodedString(DFA75_specialS);
+    static readonly short[][] DFA75_transition = DFA.UnpackEncodedStringArray(DFA75_transitionS);
+
+    protected class DFA75 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA75(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 75;
+            this.eot = DFA75_eot;
+            this.eof = DFA75_eof;
+            this.min = DFA75_min;
+            this.max = DFA75_max;
+            this.accept = DFA75_accept;
+            this.special = DFA75_special;
+            this.transition = DFA75_transition;
+
+        }
+            public DFA75(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "665:19: (e= identifierExpression | e= qvalExpression | e= constant | e= initializedComplexType | e= quantifierExpression | T_LPAREN e= expression T_RPAREN ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )? )"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA74_eotS =
+        "\x36\uffff";
+    const string DFA74_eofS =
+        "\x36\uffff";
+    const string DFA74_minS =
+        "\x01\x05\x35\uffff";
+    const string DFA74_maxS =
+        "\x01\x79\x35\uffff";
+    const string DFA74_acceptS =
+        "\x01\uffff\x01\x01\x01\x02\x01\uffff\x01\x03\x31\uffff";
+    const string DFA74_specialS =
+        "\x36\uffff}>";
+    static readonly string[] DFA74_transitionS = {
+            "\x01\x04\x01\uffff\x01\x04\x01\uffff\x03\x04\x01\x02\x01\x04"+
+            "\x01\uffff\x01\x02\x01\uffff\x01\x04\x01\uffff\x01\x04\x03\uffff"+
+            "\x01\x04\x08\uffff\x01\x04\x02\uffff\x03\x04\x04\uffff\x02\x04"+
+            "\x03\uffff\x03\x04\x07\uffff\x09\x04\x01\uffff\x11\x04\x01\x01"+
+            "\x01\uffff\x02\x04\x07\uffff\x02\x04\x15\uffff\x01\x04\x02\uffff"+
+            "\x01\x04",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA74_eot = DFA.UnpackEncodedString(DFA74_eotS);
+    static readonly short[] DFA74_eof = DFA.UnpackEncodedString(DFA74_eofS);
+    static readonly char[] DFA74_min = DFA.UnpackEncodedStringToUnsignedChars(DFA74_minS);
+    static readonly char[] DFA74_max = DFA.UnpackEncodedStringToUnsignedChars(DFA74_maxS);
+    static readonly short[] DFA74_accept = DFA.UnpackEncodedString(DFA74_acceptS);
+    static readonly short[] DFA74_special = DFA.UnpackEncodedString(DFA74_specialS);
+    static readonly short[][] DFA74_transition = DFA.UnpackEncodedStringArray(DFA74_transitionS);
+
+    protected class DFA74 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA74(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 74;
+            this.eot = DFA74_eot;
+            this.eof = DFA74_eof;
+            this.min = DFA74_min;
+            this.max = DFA74_max;
+            this.accept = DFA74_accept;
+            this.special = DFA74_special;
+            this.transition = DFA74_transition;
+
+        }
+            public DFA74(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "672:8: ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )?"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA72_eotS =
+        "\x36\uffff";
+    const string DFA72_eofS =
+        "\x36\uffff";
+    const string DFA72_minS =
+        "\x01\x05\x35\uffff";
+    const string DFA72_maxS =
+        "\x01\x79\x35\uffff";
+    const string DFA72_acceptS =
+        "\x01\uffff\x01\x02\x33\uffff\x01\x01";
+    const string DFA72_specialS =
+        "\x36\uffff}>";
+    static readonly string[] DFA72_transitionS = {
+            "\x01\x01\x01\uffff\x01\x01\x01\uffff\x05\x01\x01\uffff\x01"+
+            "\x01\x01\uffff\x01\x01\x01\uffff\x01\x01\x03\uffff\x01\x01\x08"+
+            "\uffff\x01\x01\x02\uffff\x03\x01\x04\uffff\x02\x01\x03\uffff"+
+            "\x03\x01\x07\uffff\x09\x01\x01\uffff\x11\x01\x01\x35\x01\uffff"+
+            "\x02\x01\x07\uffff\x02\x01\x15\uffff\x01\x01\x02\uffff\x01\x01",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA72_eot = DFA.UnpackEncodedString(DFA72_eotS);
+    static readonly short[] DFA72_eof = DFA.UnpackEncodedString(DFA72_eofS);
+    static readonly char[] DFA72_min = DFA.UnpackEncodedStringToUnsignedChars(DFA72_minS);
+    static readonly char[] DFA72_max = DFA.UnpackEncodedStringToUnsignedChars(DFA72_maxS);
+    static readonly short[] DFA72_accept = DFA.UnpackEncodedString(DFA72_acceptS);
+    static readonly short[] DFA72_special = DFA.UnpackEncodedString(DFA72_specialS);
+    static readonly short[][] DFA72_transition = DFA.UnpackEncodedStringArray(DFA72_transitionS);
+
+    protected class DFA72 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA72(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 72;
+            this.eot = DFA72_eot;
+            this.eof = DFA72_eof;
+            this.min = DFA72_min;
+            this.max = DFA72_max;
+            this.accept = DFA72_accept;
+            this.special = DFA72_special;
+            this.transition = DFA72_transition;
+
+        }
+            public DFA72(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "()+ loopback of 673:6: ( T_POINT idn= T_IDENTIFIER )+"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA73_eotS =
+        "\x35\uffff";
+    const string DFA73_eofS =
+        "\x35\uffff";
+    const string DFA73_minS =
+        "\x01\x05\x34\uffff";
+    const string DFA73_maxS =
+        "\x01\x79\x34\uffff";
+    const string DFA73_acceptS =
+        "\x01\uffff\x01\x01\x01\uffff\x01\x02\x31\uffff";
+    const string DFA73_specialS =
+        "\x35\uffff}>";
+    static readonly string[] DFA73_transitionS = {
+            "\x01\x03\x01\uffff\x01\x03\x01\uffff\x03\x03\x01\x01\x01\x03"+
+            "\x01\uffff\x01\x01\x01\uffff\x01\x03\x01\uffff\x01\x03\x03\uffff"+
+            "\x01\x03\x08\uffff\x01\x03\x02\uffff\x03\x03\x04\uffff\x02\x03"+
+            "\x03\uffff\x03\x03\x07\uffff\x09\x03\x01\uffff\x11\x03\x02\uffff"+
+            "\x02\x03\x07\uffff\x02\x03\x15\uffff\x01\x03\x02\uffff\x01\x03",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA73_eot = DFA.UnpackEncodedString(DFA73_eotS);
+    static readonly short[] DFA73_eof = DFA.UnpackEncodedString(DFA73_eofS);
+    static readonly char[] DFA73_min = DFA.UnpackEncodedStringToUnsignedChars(DFA73_minS);
+    static readonly char[] DFA73_max = DFA.UnpackEncodedStringToUnsignedChars(DFA73_maxS);
+    static readonly short[] DFA73_accept = DFA.UnpackEncodedString(DFA73_acceptS);
+    static readonly short[] DFA73_special = DFA.UnpackEncodedString(DFA73_specialS);
+    static readonly short[][] DFA73_transition = DFA.UnpackEncodedStringArray(DFA73_transitionS);
+
+    protected class DFA73 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA73(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 73;
+            this.eot = DFA73_eot;
+            this.eof = DFA73_eof;
+            this.min = DFA73_min;
+            this.max = DFA73_max;
+            this.accept = DFA73_accept;
+            this.special = DFA73_special;
+            this.transition = DFA73_transition;
+
+        }
+            public DFA73(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "676:8: (res= accessExpression[e] )?"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA76_eotS =
+        "\x33\uffff";
+    const string DFA76_eofS =
+        "\x33\uffff";
+    const string DFA76_minS =
+        "\x01\x05\x32\uffff";
+    const string DFA76_maxS =
+        "\x01\x79\x32\uffff";
+    const string DFA76_acceptS =
+        "\x01\uffff\x01\x01\x01\x02\x30\uffff";
+    const string DFA76_specialS =
+        "\x33\uffff}>";
+    static readonly string[] DFA76_transitionS = {
+            "\x01\x02\x01\uffff\x01\x02\x01\uffff\x03\x02\x01\uffff\x01"+
+            "\x02\x03\uffff\x01\x02\x01\uffff\x01\x02\x03\uffff\x01\x02\x08"+
+            "\uffff\x01\x02\x02\uffff\x03\x02\x04\uffff\x02\x02\x03\uffff"+
+            "\x03\x02\x07\uffff\x09\x02\x01\uffff\x11\x02\x02\uffff\x02\x02"+
+            "\x07\uffff\x02\x02\x15\uffff\x01\x02\x02\uffff\x01\x01",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA76_eot = DFA.UnpackEncodedString(DFA76_eotS);
+    static readonly short[] DFA76_eof = DFA.UnpackEncodedString(DFA76_eofS);
+    static readonly char[] DFA76_min = DFA.UnpackEncodedStringToUnsignedChars(DFA76_minS);
+    static readonly char[] DFA76_max = DFA.UnpackEncodedStringToUnsignedChars(DFA76_maxS);
+    static readonly short[] DFA76_accept = DFA.UnpackEncodedString(DFA76_acceptS);
+    static readonly short[] DFA76_special = DFA.UnpackEncodedString(DFA76_specialS);
+    static readonly short[][] DFA76_transition = DFA.UnpackEncodedStringArray(DFA76_transitionS);
+
+    protected class DFA76 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA76(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 76;
+            this.eot = DFA76_eot;
+            this.eof = DFA76_eof;
+            this.min = DFA76_min;
+            this.max = DFA76_max;
+            this.accept = DFA76_accept;
+            this.special = DFA76_special;
+            this.transition = DFA76_transition;
+
+        }
+            public DFA76(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "680:5: ( 'as' cid= T_IDENTIFIER )?"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA86_eotS =
+        "\x21\uffff";
+    const string DFA86_eofS =
+        "\x21\uffff";
+    const string DFA86_minS =
+        "\x01\x1f\x01\x08\x1f\uffff";
+    const string DFA86_maxS =
+        "\x01\x1f\x01\x7a\x1f\uffff";
+    const string DFA86_acceptS =
+        "\x02\uffff\x01\x01\x01\x02\x1d\uffff";
+    const string DFA86_specialS =
+        "\x21\uffff}>";
+    static readonly string[] DFA86_transitionS = {
+            "\x01\x01",
+            "\x01\x03\x03\uffff\x01\x03\x02\uffff\x02\x03\x06\uffff\x01"+
+            "\x03\x05\uffff\x01\x03\x01\uffff\x01\x03\x17\uffff\x01\x03\x0b"+
+            "\uffff\x01\x03\x11\uffff\x01\x03\x02\uffff\x07\x03\x01\uffff"+
+            "\x01\x02\x01\uffff\x0d\x03\x0b\uffff\x01\x03",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA86_eot = DFA.UnpackEncodedString(DFA86_eotS);
+    static readonly short[] DFA86_eof = DFA.UnpackEncodedString(DFA86_eofS);
+    static readonly char[] DFA86_min = DFA.UnpackEncodedStringToUnsignedChars(DFA86_minS);
+    static readonly char[] DFA86_max = DFA.UnpackEncodedStringToUnsignedChars(DFA86_maxS);
+    static readonly short[] DFA86_accept = DFA.UnpackEncodedString(DFA86_acceptS);
+    static readonly short[] DFA86_special = DFA.UnpackEncodedString(DFA86_specialS);
+    static readonly short[][] DFA86_transition = DFA.UnpackEncodedStringArray(DFA86_transitionS);
+
+    protected class DFA86 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA86(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 86;
+            this.eot = DFA86_eot;
+            this.eof = DFA86_eof;
+            this.min = DFA86_min;
+            this.max = DFA86_max;
+            this.accept = DFA86_accept;
+            this.special = DFA86_special;
+            this.transition = DFA86_transition;
+
+        }
+            public DFA86(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "757:1: initializedSetType returns [Expression result] : ( T_CBRL T_MAPS T_CBRR | res= initializedSet );"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA99_eotS =
+        "\x3c\uffff";
+    const string DFA99_eofS =
+        "\x3c\uffff";
+    const string DFA99_minS =
+        "\x01\x08\x01\x05\x01\uffff\x01\x00\x38\uffff";
+    const string DFA99_maxS =
+        "\x01\x37\x01\x7e\x01\uffff\x01\x00\x38\uffff";
+    const string DFA99_acceptS =
+        "\x02\uffff\x01\x02\x38\uffff\x01\x01";
+    const string DFA99_specialS =
+        "\x03\uffff\x01\x00\x38\uffff}>";
+    static readonly string[] DFA99_transitionS = {
+            "\x01\x01\x2e\uffff\x01\x02",
+            "\x01\x02\x01\uffff\x01\x02\x01\uffff\x03\x02\x01\x03\x01\x02"+
+            "\x01\uffff\x01\x02\x01\uffff\x01\x02\x01\uffff\x01\x02\x03\uffff"+
+            "\x01\x02\x08\uffff\x01\x02\x02\uffff\x03\x02\x04\uffff\x02\x02"+
+            "\x03\uffff\x05\x02\x05\uffff\x09\x02\x01\uffff\x12\x02\x01\uffff"+
+            "\x02\x02\x07\uffff\x03\x02\x14\uffff\x01\x02\x02\uffff\x01\x02"+
+            "\x04\uffff\x01\x02",
+            "",
+            "\x01\uffff",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA99_eot = DFA.UnpackEncodedString(DFA99_eotS);
+    static readonly short[] DFA99_eof = DFA.UnpackEncodedString(DFA99_eofS);
+    static readonly char[] DFA99_min = DFA.UnpackEncodedStringToUnsignedChars(DFA99_minS);
+    static readonly char[] DFA99_max = DFA.UnpackEncodedStringToUnsignedChars(DFA99_maxS);
+    static readonly short[] DFA99_accept = DFA.UnpackEncodedString(DFA99_acceptS);
+    static readonly short[] DFA99_special = DFA.UnpackEncodedString(DFA99_specialS);
+    static readonly short[][] DFA99_transition = DFA.UnpackEncodedStringArray(DFA99_transitionS);
+
+    protected class DFA99 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA99(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 99;
+            this.eot = DFA99_eot;
+            this.eof = DFA99_eof;
+            this.min = DFA99_min;
+            this.max = DFA99_max;
+            this.accept = DFA99_accept;
+            this.special = DFA99_special;
+            this.transition = DFA99_transition;
+
+        }
+            public DFA99(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "850:1: identifierExpression returns [Expression result] : ({...}?aName= T_IDENTIFIER T_LPAREN m_params= methodCallParams T_RPAREN | res= reference );"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+
+    protected internal int DFA99_SpecialStateTransition(DFA dfa, int s, IIntStream _input) //throws NoViableAltException
+    {
+            ITokenStream input = (ITokenStream)_input;
+    	int _s = s;
+        switch ( s )
+        {
+               	case 0 : 
+                   	int LA99_3 = input.LA(1);
+
+                   	 
+                   	int index99_3 = input.Index();
+                   	input.Rewind();
+                   	s = -1;
+                   	if ( (EvalPredicate(isTuple(input.LT(1).Text),"isTuple(input.LT(1).Text)")) ) { s = 59; }
+
+                   	else if ( (EvalPredicate(!isTuple(input.LT(1).Text),"!isTuple(input.LT(1).Text)")) ) { s = 2; }
+
+                   	 
+                   	input.Seek(index99_3);
+                   	if ( s >= 0 ) return s;
+                   	break;
+        }
+        NoViableAltException nvae99 =
+            new NoViableAltException(dfa.Description, 99, _s, input);
+        dfa.Error(nvae99);
+        throw nvae99;
+    }
+    const string DFA100_eotS =
+        "\x39\uffff";
+    const string DFA100_eofS =
+        "\x39\uffff";
+    const string DFA100_minS =
+        "\x01\x05\x38\uffff";
+    const string DFA100_maxS =
+        "\x01\x7e\x38\uffff";
+    const string DFA100_acceptS =
+        "\x01\uffff\x01\x01\x01\uffff\x01\x02\x35\uffff";
+    const string DFA100_specialS =
+        "\x39\uffff}>";
+    static readonly string[] DFA100_transitionS = {
+            "\x01\x03\x01\uffff\x01\x03\x01\uffff\x03\x03\x01\x01\x01\x03"+
+            "\x01\uffff\x01\x01\x01\uffff\x01\x03\x01\uffff\x01\x03\x03\uffff"+
+            "\x01\x03\x08\uffff\x01\x03\x02\uffff\x03\x03\x04\uffff\x02\x03"+
+            "\x03\uffff\x05\x03\x04\uffff\x0a\x03\x01\uffff\x11\x03\x02\uffff"+
+            "\x02\x03\x07\uffff\x03\x03\x14\uffff\x01\x03\x02\uffff\x01\x03"+
+            "\x04\uffff\x01\x03",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA100_eot = DFA.UnpackEncodedString(DFA100_eotS);
+    static readonly short[] DFA100_eof = DFA.UnpackEncodedString(DFA100_eofS);
+    static readonly char[] DFA100_min = DFA.UnpackEncodedStringToUnsignedChars(DFA100_minS);
+    static readonly char[] DFA100_max = DFA.UnpackEncodedStringToUnsignedChars(DFA100_maxS);
+    static readonly short[] DFA100_accept = DFA.UnpackEncodedString(DFA100_acceptS);
+    static readonly short[] DFA100_special = DFA.UnpackEncodedString(DFA100_specialS);
+    static readonly short[][] DFA100_transition = DFA.UnpackEncodedStringArray(DFA100_transitionS);
+
+    protected class DFA100 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA100(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 100;
+            this.eot = DFA100_eot;
+            this.eof = DFA100_eof;
+            this.min = DFA100_min;
+            this.max = DFA100_max;
+            this.accept = DFA100_accept;
+            this.special = DFA100_special;
+            this.transition = DFA100_transition;
+
+        }
+            public DFA100(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "870:3: (output= accessExpression[result] | )"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA102_eotS =
+        "\x37\uffff";
+    const string DFA102_eofS =
+        "\x37\uffff";
+    const string DFA102_minS =
+        "\x01\x05\x36\uffff";
+    const string DFA102_maxS =
+        "\x01\x7e\x36\uffff";
+    const string DFA102_acceptS =
+        "\x01\uffff\x01\x01\x01\x02\x01\uffff\x01\x03\x32\uffff";
+    const string DFA102_specialS =
+        "\x37\uffff}>";
+    static readonly string[] DFA102_transitionS = {
+            "\x01\x04\x01\uffff\x01\x04\x01\uffff\x03\x04\x01\uffff\x01"+
+            "\x04\x03\uffff\x01\x04\x01\uffff\x01\x04\x03\uffff\x01\x04\x08"+
+            "\uffff\x01\x04\x02\uffff\x03\x04\x04\uffff\x02\x04\x03\uffff"+
+            "\x03\x04\x02\x02\x04\uffff\x0a\x04\x01\uffff\x11\x04\x02\uffff"+
+            "\x02\x04\x07\uffff\x02\x04\x01\x01\x14\uffff\x01\x04\x02\uffff"+
+            "\x01\x04\x04\uffff\x01\x02",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA102_eot = DFA.UnpackEncodedString(DFA102_eotS);
+    static readonly short[] DFA102_eof = DFA.UnpackEncodedString(DFA102_eofS);
+    static readonly char[] DFA102_min = DFA.UnpackEncodedStringToUnsignedChars(DFA102_minS);
+    static readonly char[] DFA102_max = DFA.UnpackEncodedStringToUnsignedChars(DFA102_maxS);
+    static readonly short[] DFA102_accept = DFA.UnpackEncodedString(DFA102_acceptS);
+    static readonly short[] DFA102_special = DFA.UnpackEncodedString(DFA102_specialS);
+    static readonly short[][] DFA102_transition = DFA.UnpackEncodedStringArray(DFA102_transitionS);
+
+    protected class DFA102 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA102(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 102;
+            this.eot = DFA102_eot;
+            this.eof = DFA102_eof;
+            this.min = DFA102_min;
+            this.max = DFA102_max;
+            this.accept = DFA102_accept;
+            this.special = DFA102_special;
+            this.transition = DFA102_transition;
+
+        }
+            public DFA102(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "874:3: (pr= T_PRIMED | ( '::' T_LPAREN init= expression T_RPAREN )? afold= ( T_FOLDLR | T_FOLDRL ) T_LPAREN anexpr= expression T_RPAREN )?"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA103_eotS =
+        "\x3a\uffff";
+    const string DFA103_eofS =
+        "\x3a\uffff";
+    const string DFA103_minS =
+        "\x01\x05\x39\uffff";
+    const string DFA103_maxS =
+        "\x01\x7e\x39\uffff";
+    const string DFA103_acceptS =
+        "\x01\uffff\x01\x03\x36\uffff\x01\x01\x01\x02";
+    const string DFA103_specialS =
+        "\x3a\uffff}>";
+    static readonly string[] DFA103_transitionS = {
+            "\x01\x01\x01\uffff\x01\x01\x01\uffff\x03\x01\x01\x39\x01\x01"+
+            "\x01\uffff\x01\x38\x01\uffff\x01\x01\x01\uffff\x01\x01\x03\uffff"+
+            "\x01\x01\x08\uffff\x01\x01\x02\uffff\x03\x01\x04\uffff\x02\x01"+
+            "\x03\uffff\x05\x01\x04\uffff\x0a\x01\x01\uffff\x12\x01\x01\uffff"+
+            "\x02\x01\x07\uffff\x03\x01\x14\uffff\x01\x01\x02\uffff\x01\x01"+
+            "\x04\uffff\x01\x01",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA103_eot = DFA.UnpackEncodedString(DFA103_eotS);
+    static readonly short[] DFA103_eof = DFA.UnpackEncodedString(DFA103_eofS);
+    static readonly char[] DFA103_min = DFA.UnpackEncodedStringToUnsignedChars(DFA103_minS);
+    static readonly char[] DFA103_max = DFA.UnpackEncodedStringToUnsignedChars(DFA103_maxS);
+    static readonly short[] DFA103_accept = DFA.UnpackEncodedString(DFA103_acceptS);
+    static readonly short[] DFA103_special = DFA.UnpackEncodedString(DFA103_specialS);
+    static readonly short[][] DFA103_transition = DFA.UnpackEncodedStringArray(DFA103_transitionS);
+
+    protected class DFA103 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA103(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 103;
+            this.eot = DFA103_eot;
+            this.eof = DFA103_eof;
+            this.min = DFA103_min;
+            this.max = DFA103_max;
+            this.accept = DFA103_accept;
+            this.special = DFA103_special;
+            this.transition = DFA103_transition;
+
+        }
+            public DFA103(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "()+ loopback of 888:7: (tcall= T_LSQPAREN ac= expression T_RSQPAREN | bcall= T_LPAREN m_params= methodCallParams T_RPAREN )+"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA106_eotS =
+        "\x38\uffff";
+    const string DFA106_eofS =
+        "\x38\uffff";
+    const string DFA106_minS =
+        "\x01\x05\x37\uffff";
+    const string DFA106_maxS =
+        "\x01\x7e\x37\uffff";
+    const string DFA106_acceptS =
+        "\x01\uffff\x01\x01\x01\x02\x35\uffff";
+    const string DFA106_specialS =
+        "\x38\uffff}>";
+    static readonly string[] DFA106_transitionS = {
+            "\x01\x02\x01\uffff\x01\x02\x01\uffff\x03\x02\x01\uffff\x01"+
+            "\x02\x03\uffff\x01\x02\x01\uffff\x01\x02\x03\uffff\x01\x02\x08"+
+            "\uffff\x01\x02\x02\uffff\x03\x02\x04\uffff\x02\x02\x03\uffff"+
+            "\x05\x02\x04\uffff\x0a\x02\x01\uffff\x11\x02\x01\x01\x01\uffff"+
+            "\x02\x02\x07\uffff\x03\x02\x14\uffff\x01\x02\x02\uffff\x01\x02"+
+            "\x04\uffff\x01\x02",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA106_eot = DFA.UnpackEncodedString(DFA106_eotS);
+    static readonly short[] DFA106_eof = DFA.UnpackEncodedString(DFA106_eofS);
+    static readonly char[] DFA106_min = DFA.UnpackEncodedStringToUnsignedChars(DFA106_minS);
+    static readonly char[] DFA106_max = DFA.UnpackEncodedStringToUnsignedChars(DFA106_maxS);
+    static readonly short[] DFA106_accept = DFA.UnpackEncodedString(DFA106_acceptS);
+    static readonly short[] DFA106_special = DFA.UnpackEncodedString(DFA106_specialS);
+    static readonly short[][] DFA106_transition = DFA.UnpackEncodedStringArray(DFA106_transitionS);
+
+    protected class DFA106 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA106(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 106;
+            this.eot = DFA106_eot;
+            this.eof = DFA106_eof;
+            this.min = DFA106_min;
+            this.max = DFA106_max;
+            this.accept = DFA106_accept;
+            this.special = DFA106_special;
+            this.transition = DFA106_transition;
+
+        }
+            public DFA106(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "893:3: ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[result] )? )?"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA104_eotS =
+        "\x3a\uffff";
+    const string DFA104_eofS =
+        "\x3a\uffff";
+    const string DFA104_minS =
+        "\x01\x05\x39\uffff";
+    const string DFA104_maxS =
+        "\x01\x7e\x39\uffff";
+    const string DFA104_acceptS =
+        "\x01\uffff\x01\x02\x37\uffff\x01\x01";
+    const string DFA104_specialS =
+        "\x3a\uffff}>";
+    static readonly string[] DFA104_transitionS = {
+            "\x01\x01\x01\uffff\x01\x01\x01\uffff\x05\x01\x01\uffff\x01"+
+            "\x01\x01\uffff\x01\x01\x01\uffff\x01\x01\x03\uffff\x01\x01\x08"+
+            "\uffff\x01\x01\x02\uffff\x03\x01\x04\uffff\x02\x01\x03\uffff"+
+            "\x05\x01\x04\uffff\x0a\x01\x01\uffff\x11\x01\x01\x39\x01\uffff"+
+            "\x02\x01\x07\uffff\x03\x01\x14\uffff\x01\x01\x02\uffff\x01\x01"+
+            "\x04\uffff\x01\x01",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA104_eot = DFA.UnpackEncodedString(DFA104_eotS);
+    static readonly short[] DFA104_eof = DFA.UnpackEncodedString(DFA104_eofS);
+    static readonly char[] DFA104_min = DFA.UnpackEncodedStringToUnsignedChars(DFA104_minS);
+    static readonly char[] DFA104_max = DFA.UnpackEncodedStringToUnsignedChars(DFA104_maxS);
+    static readonly short[] DFA104_accept = DFA.UnpackEncodedString(DFA104_acceptS);
+    static readonly short[] DFA104_special = DFA.UnpackEncodedString(DFA104_specialS);
+    static readonly short[][] DFA104_transition = DFA.UnpackEncodedStringArray(DFA104_transitionS);
+
+    protected class DFA104 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA104(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 104;
+            this.eot = DFA104_eot;
+            this.eof = DFA104_eof;
+            this.min = DFA104_min;
+            this.max = DFA104_max;
+            this.accept = DFA104_accept;
+            this.special = DFA104_special;
+            this.transition = DFA104_transition;
+
+        }
+            public DFA104(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "()+ loopback of 894:4: ( T_POINT idn= T_IDENTIFIER )+"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA105_eotS =
+        "\x39\uffff";
+    const string DFA105_eofS =
+        "\x39\uffff";
+    const string DFA105_minS =
+        "\x01\x05\x38\uffff";
+    const string DFA105_maxS =
+        "\x01\x7e\x38\uffff";
+    const string DFA105_acceptS =
+        "\x01\uffff\x01\x01\x01\uffff\x01\x02\x35\uffff";
+    const string DFA105_specialS =
+        "\x39\uffff}>";
+    static readonly string[] DFA105_transitionS = {
+            "\x01\x03\x01\uffff\x01\x03\x01\uffff\x03\x03\x01\x01\x01\x03"+
+            "\x01\uffff\x01\x01\x01\uffff\x01\x03\x01\uffff\x01\x03\x03\uffff"+
+            "\x01\x03\x08\uffff\x01\x03\x02\uffff\x03\x03\x04\uffff\x02\x03"+
+            "\x03\uffff\x05\x03\x04\uffff\x0a\x03\x01\uffff\x11\x03\x02\uffff"+
+            "\x02\x03\x07\uffff\x03\x03\x14\uffff\x01\x03\x02\uffff\x01\x03"+
+            "\x04\uffff\x01\x03",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA105_eot = DFA.UnpackEncodedString(DFA105_eotS);
+    static readonly short[] DFA105_eof = DFA.UnpackEncodedString(DFA105_eofS);
+    static readonly char[] DFA105_min = DFA.UnpackEncodedStringToUnsignedChars(DFA105_minS);
+    static readonly char[] DFA105_max = DFA.UnpackEncodedStringToUnsignedChars(DFA105_maxS);
+    static readonly short[] DFA105_accept = DFA.UnpackEncodedString(DFA105_acceptS);
+    static readonly short[] DFA105_special = DFA.UnpackEncodedString(DFA105_specialS);
+    static readonly short[][] DFA105_transition = DFA.UnpackEncodedStringArray(DFA105_transitionS);
+
+    protected class DFA105 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA105(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 105;
+            this.eot = DFA105_eot;
+            this.eof = DFA105_eof;
+            this.min = DFA105_min;
+            this.max = DFA105_max;
+            this.accept = DFA105_accept;
+            this.special = DFA105_special;
+            this.transition = DFA105_transition;
+
+        }
+            public DFA105(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "897:4: (res= accessExpression[result] )?"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA108_eotS =
+        "\x3b\uffff";
+    const string DFA108_eofS =
+        "\x3b\uffff";
+    const string DFA108_minS =
+        "\x01\x05\x3a\uffff";
+    const string DFA108_maxS =
+        "\x01\x7e\x3a\uffff";
+    const string DFA108_acceptS =
+        "\x01\uffff\x01\x02\x38\uffff\x01\x01";
+    const string DFA108_specialS =
+        "\x3b\uffff}>";
+    static readonly string[] DFA108_transitionS = {
+            "\x01\x01\x01\uffff\x01\x01\x01\uffff\x05\x01\x01\uffff\x01"+
+            "\x01\x01\uffff\x01\x01\x01\uffff\x01\x01\x03\uffff\x01\x01\x03"+
+            "\uffff\x01\x01\x04\uffff\x01\x01\x02\uffff\x03\x01\x04\uffff"+
+            "\x02\x01\x03\uffff\x05\x01\x04\uffff\x0a\x01\x01\uffff\x11\x01"+
+            "\x01\x3a\x01\uffff\x02\x01\x07\uffff\x03\x01\x14\uffff\x01\x01"+
+            "\x02\uffff\x01\x01\x04\uffff\x01\x01",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA108_eot = DFA.UnpackEncodedString(DFA108_eotS);
+    static readonly short[] DFA108_eof = DFA.UnpackEncodedString(DFA108_eofS);
+    static readonly char[] DFA108_min = DFA.UnpackEncodedStringToUnsignedChars(DFA108_minS);
+    static readonly char[] DFA108_max = DFA.UnpackEncodedStringToUnsignedChars(DFA108_maxS);
+    static readonly short[] DFA108_accept = DFA.UnpackEncodedString(DFA108_acceptS);
+    static readonly short[] DFA108_special = DFA.UnpackEncodedString(DFA108_specialS);
+    static readonly short[][] DFA108_transition = DFA.UnpackEncodedStringArray(DFA108_transitionS);
+
+    protected class DFA108 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA108(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 108;
+            this.eot = DFA108_eot;
+            this.eof = DFA108_eof;
+            this.min = DFA108_min;
+            this.max = DFA108_max;
+            this.accept = DFA108_accept;
+            this.special = DFA108_special;
+            this.transition = DFA108_transition;
+
+        }
+            public DFA108(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "()* loopback of 910:3: ( T_POINT idd= T_IDENTIFIER )*"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA110_eotS =
+        "\x20\uffff";
+    const string DFA110_eofS =
+        "\x20\uffff";
+    const string DFA110_minS =
+        "\x01\x08\x1f\uffff";
+    const string DFA110_maxS =
+        "\x01\x7a\x1f\uffff";
+    const string DFA110_acceptS =
+        "\x01\uffff\x01\x01\x1d\uffff\x01\x02";
+    const string DFA110_specialS =
+        "\x20\uffff}>";
+    static readonly string[] DFA110_transitionS = {
+            "\x01\x01\x03\uffff\x01\x01\x01\x1f\x01\uffff\x02\x01\x06\uffff"+
+            "\x01\x01\x05\uffff\x01\x01\x01\uffff\x01\x01\x17\uffff\x01\x01"+
+            "\x0b\uffff\x01\x01\x11\uffff\x01\x01\x02\uffff\x07\x01\x03\uffff"+
+            "\x0d\x01\x0b\uffff\x01\x01",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA110_eot = DFA.UnpackEncodedString(DFA110_eotS);
+    static readonly short[] DFA110_eof = DFA.UnpackEncodedString(DFA110_eofS);
+    static readonly char[] DFA110_min = DFA.UnpackEncodedStringToUnsignedChars(DFA110_minS);
+    static readonly char[] DFA110_max = DFA.UnpackEncodedStringToUnsignedChars(DFA110_maxS);
+    static readonly short[] DFA110_accept = DFA.UnpackEncodedString(DFA110_acceptS);
+    static readonly short[] DFA110_special = DFA.UnpackEncodedString(DFA110_specialS);
+    static readonly short[][] DFA110_transition = DFA.UnpackEncodedStringArray(DFA110_transitionS);
+
+    protected class DFA110 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA110(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 110;
+            this.eot = DFA110_eot;
+            this.eof = DFA110_eof;
+            this.min = DFA110_min;
+            this.max = DFA110_max;
+            this.accept = DFA110_accept;
+            this.special = DFA110_special;
+            this.transition = DFA110_transition;
+
+        }
+            public DFA110(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "919:4: (expa= expression ( T_COMMA expb= expression )* )?"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA111_eotS =
+        "\x10\uffff";
+    const string DFA111_eofS =
+        "\x10\uffff";
+    const string DFA111_minS =
+        "\x01\x17\x0f\uffff";
+    const string DFA111_maxS =
+        "\x01\x6e\x0f\uffff";
+    const string DFA111_acceptS =
+        "\x01\uffff\x01\x01\x08\uffff\x01\x02\x02\uffff\x01\x03\x01\x04"+
+        "\x01\x05";
+    const string DFA111_specialS =
+        "\x10\uffff}>";
+    static readonly string[] DFA111_transitionS = {
+            "\x01\x0d\x2b\uffff\x01\x0e\x1e\uffff\x01\x0f\x09\x01\x03\x0a",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA111_eot = DFA.UnpackEncodedString(DFA111_eotS);
+    static readonly short[] DFA111_eof = DFA.UnpackEncodedString(DFA111_eofS);
+    static readonly char[] DFA111_min = DFA.UnpackEncodedStringToUnsignedChars(DFA111_minS);
+    static readonly char[] DFA111_max = DFA.UnpackEncodedStringToUnsignedChars(DFA111_maxS);
+    static readonly short[] DFA111_accept = DFA.UnpackEncodedString(DFA111_acceptS);
+    static readonly short[] DFA111_special = DFA.UnpackEncodedString(DFA111_specialS);
+    static readonly short[][] DFA111_transition = DFA.UnpackEncodedStringArray(DFA111_transitionS);
+
+    protected class DFA111 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA111(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 111;
+            this.eot = DFA111_eot;
+            this.eof = DFA111_eof;
+            this.min = DFA111_min;
+            this.max = DFA111_max;
+            this.accept = DFA111_accept;
+            this.special = DFA111_special;
+            this.transition = DFA111_transition;
+
+        }
+            public DFA111(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "929:1: op_un returns [UnaryOperator expr] : (r= op_un_set_list | r2= op_un_map | T_MINUS | T_NOT | T_ABS );"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+    const string DFA112_eotS =
+        "\x0a\uffff";
+    const string DFA112_eofS =
+        "\x0a\uffff";
+    const string DFA112_minS =
+        "\x01\x63\x09\uffff";
+    const string DFA112_maxS =
+        "\x01\x6b\x09\uffff";
+    const string DFA112_acceptS =
+        "\x01\uffff\x01\x01\x01\x02\x01\x03\x01\x04\x01\x05\x01\x06\x01"+
+        "\x07\x01\x08\x01\x09";
+    const string DFA112_specialS =
+        "\x0a\uffff}>";
+    static readonly string[] DFA112_transitionS = {
+            "\x01\x01\x01\x02\x01\x03\x01\x04\x01\x05\x01\x06\x01\x07\x01"+
+            "\x08\x01\x09",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA112_eot = DFA.UnpackEncodedString(DFA112_eotS);
+    static readonly short[] DFA112_eof = DFA.UnpackEncodedString(DFA112_eofS);
+    static readonly char[] DFA112_min = DFA.UnpackEncodedStringToUnsignedChars(DFA112_minS);
+    static readonly char[] DFA112_max = DFA.UnpackEncodedStringToUnsignedChars(DFA112_maxS);
+    static readonly short[] DFA112_accept = DFA.UnpackEncodedString(DFA112_acceptS);
+    static readonly short[] DFA112_special = DFA.UnpackEncodedString(DFA112_specialS);
+    static readonly short[][] DFA112_transition = DFA.UnpackEncodedStringArray(DFA112_transitionS);
+
+    protected class DFA112 : DFA
+    {
+        IDebugEventListener dbg;
+
+        public DFA112(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 112;
+            this.eot = DFA112_eot;
+            this.eof = DFA112_eof;
+            this.min = DFA112_min;
+            this.max = DFA112_max;
+            this.accept = DFA112_accept;
+            this.special = DFA112_special;
+            this.transition = DFA112_transition;
+
+        }
+            public DFA112(BaseRecognizer recognizer, IDebugEventListener dbg) : this(recognizer)
+            {
+        		this.dbg = dbg;
+            }
+
+        override public string Description
+        {
+            get { return "942:1: op_un_set_list returns [UnaryOperator expr] : ( T_CARD | T_DCONC | T_DINTER | T_DUNION | T_ELEMS | T_HEAD | T_INDS | T_LEN | T_TAIL );"; }
+        }
+
+        public override void Error(NoViableAltException nvae) 
+        {
+            dbg.RecognitionException(nvae);
+        }
+    }
+
+ 
+
+    public static readonly BitSet FOLLOW_T_CONSTS_in_ooActionSystems93 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_namedConstList_in_ooActionSystems95 = new BitSet(new ulong[]{0x0000000000000020UL});
+    public static readonly BitSet FOLLOW_T_TYPES_in_ooActionSystems105 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_namedTypeList_in_ooActionSystems113 = new BitSet(new ulong[]{0x0000000000000040UL});
+    public static readonly BitSet FOLLOW_T_SYSTEM_in_ooActionSystems118 = new BitSet(new ulong[]{0x0000000000001100UL});
+    public static readonly BitSet FOLLOW_asTypeComposition_in_ooActionSystems125 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_namedConst_in_namedConstList148 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_namedConstList151 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_namedConst_in_namedConstList153 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_namedConst169 = new BitSet(new ulong[]{0x0000000000000200UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_namedConst173 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_namedConst179 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_namedType_in_namedTypeList199 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_namedTypeList202 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_namedType_in_namedTypeList204 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_namedType220 = new BitSet(new ulong[]{0x0000000000000200UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_namedType225 = new BitSet(new ulong[]{0x00000002D650D140UL});
+    public static readonly BitSet FOLLOW_complexType_in_namedType237 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_ooActionSystem_in_namedType249 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_asTypeCompositionParallel_in_asTypeComposition285 = new BitSet(new ulong[]{0x0000000000000402UL});
+    public static readonly BitSet FOLLOW_T_PRIO_in_asTypeComposition290 = new BitSet(new ulong[]{0x0000000000001100UL});
+    public static readonly BitSet FOLLOW_asTypeCompositionParallel_in_asTypeComposition292 = new BitSet(new ulong[]{0x0000000000000402UL});
+    public static readonly BitSet FOLLOW_asTypeCompositionSequential_in_asTypeCompositionParallel315 = new BitSet(new ulong[]{0x0000000000000802UL});
+    public static readonly BitSet FOLLOW_T_NONDET_in_asTypeCompositionParallel319 = new BitSet(new ulong[]{0x0000000000001100UL});
+    public static readonly BitSet FOLLOW_asTypeCompositionSequential_in_asTypeCompositionParallel321 = new BitSet(new ulong[]{0x0000000000000802UL});
+    public static readonly BitSet FOLLOW_asTypeCompositionBlockParen_in_asTypeCompositionSequential343 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_asTypeCompositionBlockParen358 = new BitSet(new ulong[]{0x0000000000001100UL});
+    public static readonly BitSet FOLLOW_asTypeComposition_in_asTypeCompositionBlockParen360 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_asTypeCompositionBlockParen363 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_asTypeCompositionBlockParen370 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_LIST_in_complexType401 = new BitSet(new ulong[]{0x0000000000008000UL});
+    public static readonly BitSet FOLLOW_T_LSQPAREN_in_complexType404 = new BitSet(new ulong[]{0x0000000000010100UL});
+    public static readonly BitSet FOLLOW_set_in_complexType408 = new BitSet(new ulong[]{0x0000000000020000UL});
+    public static readonly BitSet FOLLOW_T_RSQPAREN_in_complexType414 = new BitSet(new ulong[]{0x0000000000040000UL});
+    public static readonly BitSet FOLLOW_T_OF_in_complexType416 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_complexType421 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_LSQPAREN_in_complexType436 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_complexType440 = new BitSet(new ulong[]{0x00000000000A0000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_complexType449 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_complexType453 = new BitSet(new ulong[]{0x00000000000A0000UL});
+    public static readonly BitSet FOLLOW_T_RSQPAREN_in_complexType459 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_MAP_in_complexType469 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_T_LSQPAREN_in_complexType474 = new BitSet(new ulong[]{0x0000000000010100UL});
+    public static readonly BitSet FOLLOW_set_in_complexType478 = new BitSet(new ulong[]{0x0000000000020000UL});
+    public static readonly BitSet FOLLOW_T_RSQPAREN_in_complexType484 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_simpleType_in_complexType490 = new BitSet(new ulong[]{0x0000000000200000UL});
+    public static readonly BitSet FOLLOW_T_TO_in_complexType492 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_complexType496 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_QUANTITY_in_complexType510 = new BitSet(new ulong[]{0x0000000000040000UL});
+    public static readonly BitSet FOLLOW_T_OF_in_complexType512 = new BitSet(new ulong[]{0x0000000000008000UL});
+    public static readonly BitSet FOLLOW_T_LSQPAREN_in_complexType514 = new BitSet(new ulong[]{0x0000000000800100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_complexType519 = new BitSet(new ulong[]{0x00000000000A0000UL});
+    public static readonly BitSet FOLLOW_T_MINUS_in_complexType524 = new BitSet(new ulong[]{0x0000000001000000UL});
+    public static readonly BitSet FOLLOW_T_INFTY_in_complexType526 = new BitSet(new ulong[]{0x00000000000A0000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_complexType536 = new BitSet(new ulong[]{0x0000000001000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_complexType541 = new BitSet(new ulong[]{0x00000000000A0000UL});
+    public static readonly BitSet FOLLOW_T_INFTY_in_complexType545 = new BitSet(new ulong[]{0x00000000000A0000UL});
+    public static readonly BitSet FOLLOW_T_RSQPAREN_in_complexType552 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_complexType562 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_complexType566 = new BitSet(new ulong[]{0x0000000000082000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_complexType575 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_complexType579 = new BitSet(new ulong[]{0x0000000000082000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_complexType586 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_simpleType_in_complexType599 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_BOOL_in_simpleType632 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_INT_in_simpleType645 = new BitSet(new ulong[]{0x0000000000008000UL});
+    public static readonly BitSet FOLLOW_T_LSQPAREN_in_simpleType647 = new BitSet(new ulong[]{0x0000000001010100UL});
+    public static readonly BitSet FOLLOW_set_in_simpleType651 = new BitSet(new ulong[]{0x0000000008000000UL});
+    public static readonly BitSet FOLLOW_T_RANGETO_in_simpleType659 = new BitSet(new ulong[]{0x0000000001010100UL});
+    public static readonly BitSet FOLLOW_set_in_simpleType663 = new BitSet(new ulong[]{0x0000000000020000UL});
+    public static readonly BitSet FOLLOW_T_RSQPAREN_in_simpleType671 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_FLOAT_in_simpleType690 = new BitSet(new ulong[]{0x0000000000008000UL});
+    public static readonly BitSet FOLLOW_T_LSQPAREN_in_simpleType693 = new BitSet(new ulong[]{0x0000000021000100UL});
+    public static readonly BitSet FOLLOW_set_in_simpleType697 = new BitSet(new ulong[]{0x0000000008000000UL});
+    public static readonly BitSet FOLLOW_T_RANGETO_in_simpleType705 = new BitSet(new ulong[]{0x0000000021000100UL});
+    public static readonly BitSet FOLLOW_set_in_simpleType709 = new BitSet(new ulong[]{0x0000000000020000UL});
+    public static readonly BitSet FOLLOW_T_RSQPAREN_in_simpleType717 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_CHAR_in_simpleType735 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_CBRL_in_simpleType751 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_simpleType755 = new BitSet(new ulong[]{0x0000000100080200UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_simpleType758 = new BitSet(new ulong[]{0x0000000000010000UL});
+    public static readonly BitSet FOLLOW_T_INTNUMBER_in_simpleType762 = new BitSet(new ulong[]{0x0000000100080000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_simpleType773 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_simpleType777 = new BitSet(new ulong[]{0x0000000100080200UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_simpleType780 = new BitSet(new ulong[]{0x0000000000010000UL});
+    public static readonly BitSet FOLLOW_T_INTNUMBER_in_simpleType784 = new BitSet(new ulong[]{0x0000000100080000UL});
+    public static readonly BitSet FOLLOW_T_CBRR_in_simpleType792 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_simpleType803 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_AUTOCONS_in_ooActionSystem846 = new BitSet(new ulong[]{0x0000000000000040UL});
+    public static readonly BitSet FOLLOW_T_SYSTEM_in_ooActionSystem855 = new BitSet(new ulong[]{0x0000000000001000UL,0x0020000000000000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_ooActionSystem858 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_ooActionSystem862 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_ooActionSystem864 = new BitSet(new ulong[]{0x0000000000000000UL,0x0020000000000000UL});
+    public static readonly BitSet FOLLOW_117_in_ooActionSystem877 = new BitSet(new ulong[]{0x0000003C00000000UL,0x0040000000000000UL});
+    public static readonly BitSet FOLLOW_T_VAR_in_ooActionSystem883 = new BitSet(new ulong[]{0x0000038000000100UL});
+    public static readonly BitSet FOLLOW_attrList_in_ooActionSystem885 = new BitSet(new ulong[]{0x0000003800000000UL,0x0040000000000000UL});
+    public static readonly BitSet FOLLOW_T_METHODS_in_ooActionSystem893 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_methodList_in_ooActionSystem895 = new BitSet(new ulong[]{0x0000003000000000UL,0x0040000000000000UL});
+    public static readonly BitSet FOLLOW_T_ACTIONS_in_ooActionSystem903 = new BitSet(new ulong[]{0x0000130000000100UL});
+    public static readonly BitSet FOLLOW_namedActionList_in_ooActionSystem905 = new BitSet(new ulong[]{0x0000002000000000UL,0x0040000000000000UL});
+    public static readonly BitSet FOLLOW_T_DO_in_ooActionSystem913 = new BitSet(new ulong[]{0x0010304400001100UL});
+    public static readonly BitSet FOLLOW_actionBlock_in_ooActionSystem918 = new BitSet(new ulong[]{0x0000004000000000UL});
+    public static readonly BitSet FOLLOW_T_OD_in_ooActionSystem925 = new BitSet(new ulong[]{0x0000000000000000UL,0x0040000000000000UL});
+    public static readonly BitSet FOLLOW_118_in_ooActionSystem931 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_attr_in_attrList962 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_attrList965 = new BitSet(new ulong[]{0x0000038000000100UL});
+    public static readonly BitSet FOLLOW_attr_in_attrList967 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_STATIC_in_attr992 = new BitSet(new ulong[]{0x0000030000000100UL});
+    public static readonly BitSet FOLLOW_T_OBS_in_attr999 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_CTRL_in_attr1005 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_attr1016 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_attr1019 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_attr1023 = new BitSet(new ulong[]{0x0000000000000202UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_attr1026 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_attr1030 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_method_in_methodList1052 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_methodList1055 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_method_in_methodList1057 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_method1079 = new BitSet(new ulong[]{0x0000040000001200UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_method1087 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_methodParameterList_in_method1089 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_method1093 = new BitSet(new ulong[]{0x0000040000000200UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_method1101 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_method1105 = new BitSet(new ulong[]{0x0000000000000200UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_method1115 = new BitSet(new ulong[]{0x00F0300400001100UL});
+    public static readonly BitSet FOLLOW_T_VAR_in_method1122 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_localActionVars_in_method1124 = new BitSet(new ulong[]{0x0000000000000000UL,0x0080000000000000UL});
+    public static readonly BitSet FOLLOW_119_in_method1127 = new BitSet(new ulong[]{0x00F0300400001100UL});
+    public static readonly BitSet FOLLOW_actionBody_in_method1136 = new BitSet(new ulong[]{0x0000080000000000UL});
+    public static readonly BitSet FOLLOW_T_END_in_method1144 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_methodParameterList1168 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_methodParameterList1170 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_methodParameterList1174 = new BitSet(new ulong[]{0x0000000000080002UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_methodParameterList1182 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_methodParameterList1186 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_methodParameterList1188 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_methodParameterList1192 = new BitSet(new ulong[]{0x0000000000080002UL});
+    public static readonly BitSet FOLLOW_namedAction_in_namedActionList1219 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_namedActionList1222 = new BitSet(new ulong[]{0x0000130000000100UL});
+    public static readonly BitSet FOLLOW_namedAction_in_namedActionList1224 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_CONT_in_namedAction1244 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_namedAction1248 = new BitSet(new ulong[]{0x0000000000001200UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_namedAction1256 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_methodParameterList_in_namedAction1258 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_namedAction1262 = new BitSet(new ulong[]{0x0000000000000200UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_namedAction1269 = new BitSet(new ulong[]{0x0000100000000000UL});
+    public static readonly BitSet FOLLOW_continuousActionBody_in_namedAction1273 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_CTRL_in_namedAction1288 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_OBS_in_namedAction1293 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_namedAction1305 = new BitSet(new ulong[]{0x0000000000001200UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_namedAction1313 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_methodParameterList_in_namedAction1315 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_namedAction1319 = new BitSet(new ulong[]{0x0000000000000200UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_namedAction1326 = new BitSet(new ulong[]{0x0000300400000000UL});
+    public static readonly BitSet FOLLOW_T_VAR_in_namedAction1332 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_localActionVars_in_namedAction1334 = new BitSet(new ulong[]{0x0000300000000000UL});
+    public static readonly BitSet FOLLOW_discreteActionBody_in_namedAction1345 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_localActionVars1377 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_localActionVars1379 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_localActionVars1383 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_localActionVars1392 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_localActionVars1396 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_localActionVars1398 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_localActionVars1402 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_continuousActionBody_in_anonymousAction1432 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_discreteActionBody_in_anonymousAction1441 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_CONT_in_continuousActionBody1466 = new BitSet(new ulong[]{0x0000200000000000UL});
+    public static readonly BitSet FOLLOW_T_REQUIRES_in_continuousActionBody1468 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_continuousActionBody1472 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_continuousActionBody1474 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_qualConstraintList_in_continuousActionBody1481 = new BitSet(new ulong[]{0x0000080000000000UL});
+    public static readonly BitSet FOLLOW_T_END_in_continuousActionBody1486 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_qualConstraint_in_qualConstraintList1514 = new BitSet(new ulong[]{0x0000000000080002UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_qualConstraintList1521 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_qualConstraint_in_qualConstraintList1525 = new BitSet(new ulong[]{0x0000000000080002UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_qualConstraint1556 = new BitSet(new ulong[]{0x0000000000000200UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_qualConstraint1558 = new BitSet(new ulong[]{0x0000400000000100UL});
+    public static readonly BitSet FOLLOW_T_DERIV_in_qualConstraint1565 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_qualConstraint1569 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_qualConstraint1604 = new BitSet(new ulong[]{0x0003800000000002UL});
+    public static readonly BitSet FOLLOW_T_SUM_in_qualConstraint1635 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_DIFF_in_qualConstraint1652 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_PROD_in_qualConstraint1669 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_qualConstraint1698 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_REQUIRES_in_discreteActionBody1788 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_discreteActionBody1792 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_discreteActionBody1794 = new BitSet(new ulong[]{0x00F0300400001100UL});
+    public static readonly BitSet FOLLOW_actionBody_in_discreteActionBody1801 = new BitSet(new ulong[]{0x0000080000000000UL});
+    public static readonly BitSet FOLLOW_T_END_in_discreteActionBody1806 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_actionBlockParallel_in_actionBlock1842 = new BitSet(new ulong[]{0x0000000000000402UL});
+    public static readonly BitSet FOLLOW_T_PRIO_in_actionBlock1846 = new BitSet(new ulong[]{0x0010300400001100UL});
+    public static readonly BitSet FOLLOW_actionBlockParallel_in_actionBlock1848 = new BitSet(new ulong[]{0x0000000000000402UL});
+    public static readonly BitSet FOLLOW_actionBlockSequential_in_actionBlockParallel1873 = new BitSet(new ulong[]{0x0000000000000802UL});
+    public static readonly BitSet FOLLOW_T_NONDET_in_actionBlockParallel1877 = new BitSet(new ulong[]{0x0010300400001100UL});
+    public static readonly BitSet FOLLOW_actionBlockSequential_in_actionBlockParallel1879 = new BitSet(new ulong[]{0x0000000000000802UL});
+    public static readonly BitSet FOLLOW_T_VAR_in_actionBlockSequential1908 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_blockvarlist_in_actionBlockSequential1912 = new BitSet(new ulong[]{0x0000040000000000UL,0x0100000000000000UL});
+    public static readonly BitSet FOLLOW_120_in_actionBlockSequential1916 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_actionBlockSequential1920 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_actionBlockSequential1927 = new BitSet(new ulong[]{0x0010300400001100UL});
+    public static readonly BitSet FOLLOW_actionBlockParen_in_actionBlockSequential1936 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_actionBlockSequential1940 = new BitSet(new ulong[]{0x0010300400001100UL});
+    public static readonly BitSet FOLLOW_actionBlockParen_in_actionBlockSequential1942 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_actionBlockParen1966 = new BitSet(new ulong[]{0x0010300400001100UL});
+    public static readonly BitSet FOLLOW_actionBlock_in_actionBlockParen1968 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_actionBlockParen1971 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_anonymousOrNamedAction_in_actionBlockParen1976 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_anonymousAction_in_anonymousOrNamedAction1993 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_anonymousOrNamedAction2002 = new BitSet(new ulong[]{0x000C000000001002UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_anonymousOrNamedAction2016 = new BitSet(new ulong[]{0x00800000A081B100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_methodCallParams_in_anonymousOrNamedAction2021 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_anonymousOrNamedAction2023 = new BitSet(new ulong[]{0x000C000000000002UL});
+    public static readonly BitSet FOLLOW_set_in_anonymousOrNamedAction2041 = new BitSet(new ulong[]{0x0000000000001000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_anonymousOrNamedAction2047 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_anonymousOrNamedAction2051 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_anonymousOrNamedAction2053 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_SKIP_in_anonymousOrNamedAction2064 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_blockvar_in_blockvarlist2080 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_blockvarlist2085 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_blockvar_in_blockvarlist2087 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_blockvar2107 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_blockvar2110 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_blockvar2114 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_actionBodyParallel_in_actionBody2149 = new BitSet(new ulong[]{0x0000000000000402UL});
+    public static readonly BitSet FOLLOW_T_PRIO_in_actionBody2153 = new BitSet(new ulong[]{0x00F0300400001100UL});
+    public static readonly BitSet FOLLOW_actionBodyParallel_in_actionBody2155 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_actionBodySequential_in_actionBodyParallel2183 = new BitSet(new ulong[]{0x0000000000000802UL});
+    public static readonly BitSet FOLLOW_T_NONDET_in_actionBodyParallel2189 = new BitSet(new ulong[]{0x00F0300400001100UL});
+    public static readonly BitSet FOLLOW_actionBodySequential_in_actionBodyParallel2193 = new BitSet(new ulong[]{0x0000000000000802UL});
+    public static readonly BitSet FOLLOW_actionBodyParen_in_actionBodySequential2220 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_actionBodySequential2224 = new BitSet(new ulong[]{0x00F0300400001100UL});
+    public static readonly BitSet FOLLOW_actionBodyParen_in_actionBodySequential2226 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_actionBodyParen2244 = new BitSet(new ulong[]{0x00F0300400001100UL});
+    public static readonly BitSet FOLLOW_actionBody_in_actionBodyParen2246 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_actionBodyParen2249 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_statement_in_actionBodyParen2256 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_ABORT_in_statement2284 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_SKIP_in_statement2291 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_KILL_in_statement2298 = new BitSet(new ulong[]{0x0000000000001000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_statement2300 = new BitSet(new ulong[]{0x0080000000000100UL});
+    public static readonly BitSet FOLLOW_set_in_statement2304 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_statement2312 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_discreteActionBody_in_statement2322 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_reference_in_statement2331 = new BitSet(new ulong[]{0x0100000000080002UL});
+    public static readonly BitSet FOLLOW_T_ASSIGNMENT_in_statement2359 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_statement2364 = new BitSet(new ulong[]{0x0200000000000002UL});
+    public static readonly BitSet FOLLOW_T_WITH_in_statement2384 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_statement2388 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_statement2441 = new BitSet(new ulong[]{0x0080000000000100UL});
+    public static readonly BitSet FOLLOW_reference_in_statement2445 = new BitSet(new ulong[]{0x0100000000080000UL});
+    public static readonly BitSet FOLLOW_T_ASSIGNMENT_in_statement2460 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_statement2482 = new BitSet(new ulong[]{0x0000000000080000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_statement2501 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_statement2505 = new BitSet(new ulong[]{0x0200000000080002UL});
+    public static readonly BitSet FOLLOW_T_WITH_in_statement2519 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_statement2523 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_atomExpression_in_expression2598 = new BitSet(new ulong[]{0xFC03800000800202UL,0x00000000000FFFFBUL});
+    public static readonly BitSet FOLLOW_binoperator_in_expression2611 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_atomExpression_in_expression2619 = new BitSet(new ulong[]{0xFC03800000800202UL,0x00000000000FFFFBUL});
+    public static readonly BitSet FOLLOW_T_BIIMPLIES_in_binoperator2652 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_GREATER_in_binoperator2661 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_GREATEREQUAL_in_binoperator2671 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_LESS_in_binoperator2680 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_LESSEQUAL_in_binoperator2690 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_binoperator2699 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_NOTEQUAL_in_binoperator2711 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IMPLIES_in_binoperator2722 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_MINUS_in_binoperator2731 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_SUM_in_binoperator2741 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IN_in_binoperator2751 = new BitSet(new ulong[]{0x0000000000000002UL,0x0000000000000004UL});
+    public static readonly BitSet FOLLOW_T_SET_in_binoperator2753 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_NOT_in_binoperator2764 = new BitSet(new ulong[]{0x0000000000000000UL,0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IN_in_binoperator2766 = new BitSet(new ulong[]{0x0000000000000002UL,0x0000000000000004UL});
+    public static readonly BitSet FOLLOW_T_SET_in_binoperator2768 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_SUBSET_in_binoperator2779 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_OR_in_binoperator2789 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_DIV_in_binoperator2798 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_PROD_in_binoperator2807 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IDIV_in_binoperator2817 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_MOD_in_binoperator2827 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_UNION_in_binoperator2837 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_DIFF_in_binoperator2848 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_INTER_in_binoperator2859 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_AND_in_binoperator2870 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_POW_in_binoperator2885 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_CONC_in_binoperator2900 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_DOMRESBY_in_binoperator2913 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_DOMRESTO_in_binoperator2923 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_RNGRESBY_in_binoperator2933 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_RNGRESTO_in_binoperator2943 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_MUNION_in_binoperator2953 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_SEQMOD_MAPOVERRIDE_in_binoperator2963 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_op_un_in_atomExpression3001 = new BitSet(new ulong[]{0x00800000A0019100UL,0x040000007F000000UL});
+    public static readonly BitSet FOLLOW_identifierExpression_in_atomExpression3018 = new BitSet(new ulong[]{0x0000000000000002UL,0x0200000000000000UL});
+    public static readonly BitSet FOLLOW_qvalExpression_in_atomExpression3029 = new BitSet(new ulong[]{0x0000000000000002UL,0x0200000000000000UL});
+    public static readonly BitSet FOLLOW_constant_in_atomExpression3040 = new BitSet(new ulong[]{0x0000000000000002UL,0x0200000000000000UL});
+    public static readonly BitSet FOLLOW_initializedComplexType_in_atomExpression3051 = new BitSet(new ulong[]{0x0000000000000002UL,0x0200000000000000UL});
+    public static readonly BitSet FOLLOW_quantifierExpression_in_atomExpression3063 = new BitSet(new ulong[]{0x0000000000000002UL,0x0200000000000000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_atomExpression3072 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_atomExpression3076 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_atomExpression3078 = new BitSet(new ulong[]{0x0000000000009002UL,0x0200000000100000UL});
+    public static readonly BitSet FOLLOW_T_POINT_in_atomExpression3101 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_atomExpression3113 = new BitSet(new ulong[]{0x0000000000009002UL,0x0200000000100000UL});
+    public static readonly BitSet FOLLOW_accessExpression_in_atomExpression3137 = new BitSet(new ulong[]{0x0000000000000002UL,0x0200000000000000UL});
+    public static readonly BitSet FOLLOW_accessExpression_in_atomExpression3157 = new BitSet(new ulong[]{0x0000000000000002UL,0x0200000000000000UL});
+    public static readonly BitSet FOLLOW_121_in_atomExpression3176 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_atomExpression3180 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IF_in_atomExpression3201 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_atomExpression3205 = new BitSet(new ulong[]{0x0000000000000000UL,0x0000000000400000UL});
+    public static readonly BitSet FOLLOW_T_THEN_in_atomExpression3207 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_atomExpression3211 = new BitSet(new ulong[]{0x0000000000000000UL,0x0000000000800000UL});
+    public static readonly BitSet FOLLOW_T_ELSE_in_atomExpression3213 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_atomExpression3217 = new BitSet(new ulong[]{0x0000080000000000UL});
+    public static readonly BitSet FOLLOW_T_END_in_atomExpression3219 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_set_in_quantifierExpression3251 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_quantifierExpression3268 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_quantifierExpression3271 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_simpleType_in_quantifierExpression3275 = new BitSet(new ulong[]{0x0000040000080000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_quantifierExpression3286 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_quantifierExpression3290 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_quantifierExpression3293 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_simpleType_in_quantifierExpression3297 = new BitSet(new ulong[]{0x0000040000080000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_quantifierExpression3307 = new BitSet(new ulong[]{0x0000000000001000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_quantifierExpression3309 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_quantifierExpression3313 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_quantifierExpression3315 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_TRUE_in_constant3349 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_FALSE_in_constant3357 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_NIL_in_constant3364 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_SELF_in_constant3372 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_FLOATNUMBER_in_constant3383 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_INTNUMBER_in_constant3392 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_STRINGLITERAL_in_constant3401 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_initializedListType_in_initializedComplexType3428 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_initializedSetType_in_initializedComplexType3437 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_NEW_in_initializedComplexType3445 = new BitSet(new ulong[]{0x0000000000001000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_initializedComplexType3447 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_initializedComplexType3451 = new BitSet(new ulong[]{0x0000000000082000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_initializedComplexType3463 = new BitSet(new ulong[]{0x0000000000000000UL,0x0000000020000000UL});
+    public static readonly BitSet FOLLOW_T_STRINGLITERAL_in_initializedComplexType3468 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_initializedComplexType3470 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_initializedComplexType3479 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_LSQPAREN_in_initializedListType3510 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_initializedListType3514 = new BitSet(new ulong[]{0x00000000000A0000UL,0x0000000080000000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_initializedListType3525 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_initializedListType3529 = new BitSet(new ulong[]{0x00000000000A0000UL});
+    public static readonly BitSet FOLLOW_listComprehension_in_initializedListType3541 = new BitSet(new ulong[]{0x0000000000020000UL});
+    public static readonly BitSet FOLLOW_T_RSQPAREN_in_initializedListType3549 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_BAR_in_listComprehension3580 = new BitSet(new ulong[]{0x0000000400000000UL});
+    public static readonly BitSet FOLLOW_T_VAR_in_listComprehension3582 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_listComprehension3588 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_listComprehension3591 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_listComprehension3595 = new BitSet(new ulong[]{0x0000000000000082UL,0x0100000000000000UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_listComprehension3604 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_listComprehension3608 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_listComprehension3613 = new BitSet(new ulong[]{0x0000000000000082UL,0x0100000000000000UL});
+    public static readonly BitSet FOLLOW_120_in_listComprehension3623 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_listComprehension3629 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_CBRL_in_initializedSetType3655 = new BitSet(new ulong[]{0x0000000000000000UL,0x0000000100000000UL});
+    public static readonly BitSet FOLLOW_T_MAPS_in_initializedSetType3657 = new BitSet(new ulong[]{0x0000000100000000UL});
+    public static readonly BitSet FOLLOW_T_CBRR_in_initializedSetType3659 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_initializedSet_in_initializedSetType3670 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_CBRL_in_initializedSet3696 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_initializedSet3700 = new BitSet(new ulong[]{0x0000000100080000UL,0x0000000180000000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_initializedSet3730 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_initializedSet3734 = new BitSet(new ulong[]{0x0000000100080000UL});
+    public static readonly BitSet FOLLOW_map_in_initializedSet3752 = new BitSet(new ulong[]{0x0000000100000000UL});
+    public static readonly BitSet FOLLOW_setComprehension_in_initializedSet3765 = new BitSet(new ulong[]{0x0000000100000000UL});
+    public static readonly BitSet FOLLOW_T_CBRR_in_initializedSet3776 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_MAPS_in_map3812 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_map3816 = new BitSet(new ulong[]{0x0000000000080002UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_map3824 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_map3828 = new BitSet(new ulong[]{0x0000000000000000UL,0x0000000100000000UL});
+    public static readonly BitSet FOLLOW_T_MAPS_in_map3830 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_map3834 = new BitSet(new ulong[]{0x0000000000080002UL});
+    public static readonly BitSet FOLLOW_T_BAR_in_setComprehension3856 = new BitSet(new ulong[]{0x0000000400000000UL});
+    public static readonly BitSet FOLLOW_T_VAR_in_setComprehension3858 = new BitSet(new ulong[]{0x0000000000000102UL,0x0100000000000000UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_setComprehension3863 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_setComprehension3866 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_setComprehension3870 = new BitSet(new ulong[]{0x0000000000000080UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_setComprehension3879 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_setComprehension3883 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_setComprehension3885 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_setComprehension3889 = new BitSet(new ulong[]{0x0000000000000102UL,0x0100000000000000UL});
+    public static readonly BitSet FOLLOW_120_in_setComprehension3903 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_setComprehension3909 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_122_in_qvalExpression3944 = new BitSet(new ulong[]{0x0000000000001000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_qvalExpression3946 = new BitSet(new ulong[]{0x0080000001800100UL,0x0000000010000000UL});
+    public static readonly BitSet FOLLOW_T_NIL_in_qvalExpression3960 = new BitSet(new ulong[]{0x0000000000080000UL});
+    public static readonly BitSet FOLLOW_qualifiedIdentifier_in_qvalExpression3981 = new BitSet(new ulong[]{0x0000000008080000UL});
+    public static readonly BitSet FOLLOW_T_MINUS_in_qvalExpression4000 = new BitSet(new ulong[]{0x0000000001000000UL});
+    public static readonly BitSet FOLLOW_T_INFTY_in_qvalExpression4006 = new BitSet(new ulong[]{0x0000000008080000UL});
+    public static readonly BitSet FOLLOW_T_RANGETO_in_qvalExpression4024 = new BitSet(new ulong[]{0x0080000001000100UL});
+    public static readonly BitSet FOLLOW_qualifiedIdentifier_in_qvalExpression4034 = new BitSet(new ulong[]{0x0000000000080000UL});
+    public static readonly BitSet FOLLOW_T_INFTY_in_qvalExpression4052 = new BitSet(new ulong[]{0x0000000000080000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_qvalExpression4076 = new BitSet(new ulong[]{0x0000000000000000UL,0x3800000010000000UL});
+    public static readonly BitSet FOLLOW_T_NIL_in_qvalExpression4086 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_123_in_qvalExpression4102 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_124_in_qvalExpression4115 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_125_in_qvalExpression4128 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_qvalExpression4150 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_identifierExpression4183 = new BitSet(new ulong[]{0x0000000000001000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_identifierExpression4185 = new BitSet(new ulong[]{0x00800000A081B100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_methodCallParams_in_identifierExpression4189 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_identifierExpression4191 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_reference_in_identifierExpression4206 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_qualifiedIdentifier_in_reference4244 = new BitSet(new ulong[]{0x000C000000009002UL,0x4000000200000000UL});
+    public static readonly BitSet FOLLOW_accessExpression_in_reference4256 = new BitSet(new ulong[]{0x000C000000000002UL,0x4000000200000000UL});
+    public static readonly BitSet FOLLOW_T_PRIMED_in_reference4281 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_126_in_reference4297 = new BitSet(new ulong[]{0x0000000000001000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_reference4299 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_reference4303 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_reference4305 = new BitSet(new ulong[]{0x000C000000000000UL});
+    public static readonly BitSet FOLLOW_set_in_reference4311 = new BitSet(new ulong[]{0x0000000000001000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_reference4317 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_reference4321 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_reference4323 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_LSQPAREN_in_accessExpression4368 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_accessExpression4372 = new BitSet(new ulong[]{0x0000000000020000UL});
+    public static readonly BitSet FOLLOW_T_RSQPAREN_in_accessExpression4374 = new BitSet(new ulong[]{0x0000000000009002UL,0x0000000000100000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_accessExpression4401 = new BitSet(new ulong[]{0x00800000A081B100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_methodCallParams_in_accessExpression4405 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_accessExpression4407 = new BitSet(new ulong[]{0x0000000000009002UL,0x0000000000100000UL});
+    public static readonly BitSet FOLLOW_T_POINT_in_accessExpression4429 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_accessExpression4437 = new BitSet(new ulong[]{0x0000000000009002UL,0x0000000000100000UL});
+    public static readonly BitSet FOLLOW_accessExpression_in_accessExpression4453 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_SELF_in_qualifiedIdentifier4492 = new BitSet(new ulong[]{0x0000000000000000UL,0x0000000000100000UL});
+    public static readonly BitSet FOLLOW_T_POINT_in_qualifiedIdentifier4494 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_qualifiedIdentifier4506 = new BitSet(new ulong[]{0x0000000000000002UL,0x0000000000100000UL});
+    public static readonly BitSet FOLLOW_T_POINT_in_qualifiedIdentifier4515 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_qualifiedIdentifier4519 = new BitSet(new ulong[]{0x0000000000000002UL,0x0000000000100000UL});
+    public static readonly BitSet FOLLOW_expression_in_methodCallParams4552 = new BitSet(new ulong[]{0x0000000000080002UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_methodCallParams4557 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_methodCallParams4561 = new BitSet(new ulong[]{0x0000000000080002UL});
+    public static readonly BitSet FOLLOW_op_un_set_list_in_op_un4600 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_op_un_map_in_op_un4609 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_MINUS_in_op_un4617 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_NOT_in_op_un4625 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_ABS_in_op_un4633 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_CARD_in_op_un_set_list4660 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_DCONC_in_op_un_set_list4671 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_DINTER_in_op_un_set_list4682 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_DUNION_in_op_un_set_list4692 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_ELEMS_in_op_un_set_list4702 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_HEAD_in_op_un_set_list4713 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_INDS_in_op_un_set_list4724 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_LEN_in_op_un_set_list4735 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_TAIL_in_op_un_set_list4746 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_DOM_in_op_un_map4775 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_RNG_in_op_un_map4786 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_MERGE_in_op_un_map4797 = new BitSet(new ulong[]{0x0000000000000002UL});
+
+}
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaActionClassifierVisitor.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaActionClassifierVisitor.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaActionClassifierVisitor.cs	(revision 3)
@@ -0,0 +1,249 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TUG.Mogentes
+{
+    /// <summary>
+    /// This visitor scans all methods and named actions in order to check
+    /// whether they are safe, in the sense that they are only using 
+    /// basic commands that obey the excluded miracle rule automatically.
+    /// 
+    /// The idea is that the weakest precondition of "safe named actions"
+    /// automatically is the guard of the obligatorty guarded command.
+    /// 
+    /// Allowed commands for "safe" code:
+    ///    -> Assignment (deterministic!)
+    ///    -> Sequential Composition
+    /// Currently not supported within the analysis:
+    ///    -> Conditional Statement (emulated by requires A: end [] requires not A: end)
+    ///    -> Iteration (not available)
+    /// </summary>
+    public sealed class OoaActionClassifierVisitor : OoaCompleteAstTraversalVisitor
+    {
+
+
+        private void CalcBodySafe(FunctionIdentifier methodIdentifier, FunctionType mType, ref bool m_hasUnsafeElement, ref Block ablock)
+        {
+            string methodAction;
+            if (mType.functionType == FunctionTypeEnum.Method)
+                methodAction = "Method";
+            else
+                methodAction = "Action";
+
+
+            while ((ablock != null) && (ablock.kind != StatementKind.SeqBlock) && (ablock.statements.Count > 0))
+            {
+                if (ablock.statements.Count > 1)
+                {
+                    m_ParserState.AddMessage(
+                        new ParserMessage(m_ParserState.filename, ablock.line,
+                            ablock.pos, String.Format("{0} {1} extended: More than one element in Nondet/Prio Block.",
+                            methodAction, methodIdentifier.tokenText)));
+                    mType.SetMiracleSafe(false);
+                }
+                ablock = (Block)ablock.statements.First.Value;
+            }
+
+            foreach (var s in ablock.statements)
+            {
+                switch (s.kind)
+                {
+                    case StatementKind.Abort:
+                        // abort maps any postcondition to false, iow. wp(abort,X) = false
+                        m_hasUnsafeElement = true; // excluded miracle holds, but I'm not sure about continuity.. *g*
+                        m_ParserState.AddMessage(
+                            new ParserMessage(m_ParserState.filename, ablock.line,
+                                ablock.pos, String.Format("{0} {1} extended: Abort detected.",
+                                methodAction, methodIdentifier.tokenText)));
+                        break;
+                    case StatementKind.Assignment:
+                        Assignment ass = (Assignment)s;
+                        m_hasUnsafeElement |= ass.nondetExpression != null;
+                        if (m_hasUnsafeElement)
+                            m_ParserState.AddMessage(
+                                new ParserMessage(m_ParserState.filename, ablock.line,
+                                    ablock.pos, String.Format("{0} {1} extended: possibly nondeterministic assignment.",
+                                    methodAction, methodIdentifier.tokenText)));
+                        // check value expressions
+                        foreach (var x in ass.values)
+                        {
+                            if (x.GetUninitializedFreeVariables().Count > 0)
+                            {
+                                m_hasUnsafeElement = true;
+                                m_ParserState.AddMessage(
+                                    new ParserMessage(m_ParserState.filename, ablock.line,
+                                        ablock.pos, String.Format("{0} {1} extended: uninitialized free variables in expression.",
+                                        methodAction, methodIdentifier.tokenText)));
+                                continue;
+                            }
+                            foreach (var ct in x.callTargets)
+                            {
+                                if ( ((FunctionType)ct.type).isMiracleSafe == null)
+                                    ct.Accept(this);
+                                m_hasUnsafeElement |= ((FunctionType)ct.type).isMiracleSafe ?? true;
+                                if (m_hasUnsafeElement)
+                                    m_ParserState.AddMessage(
+                                        new ParserMessage(m_ParserState.filename, ablock.line,
+                                            ablock.pos, String.Format("{0} {1} extended: call of extended method in value expression.",
+                                            methodAction, methodIdentifier.tokenText)));
+                            }
+                        }
+                        break;
+                    case StatementKind.GuardedCommand:
+                        m_hasUnsafeElement = true; // we do not allow guarded commands in methods as they would be included in actions!
+                        // we do not allow a second guarded command in named actions.
+                        m_ParserState.AddMessage(
+                            new ParserMessage(m_ParserState.filename, ablock.line,
+                                ablock.pos, String.Format("{0} {1} extended: guarded command detected.",
+                                methodAction, methodIdentifier.tokenText)));
+                        break;
+                    case StatementKind.Kill:
+                        m_hasUnsafeElement = true;
+                        m_ParserState.AddMessage(
+                            new ParserMessage(m_ParserState.filename, ablock.line,
+                                ablock.pos, String.Format("{0} {1} extended: Kill detected.",
+                                methodAction, methodIdentifier.tokenText)));
+                        break;
+                    case StatementKind.MethodCall:
+                        Call acall = (Call)s;
+
+                        foreach (FunctionIdentifier anid in acall.callExpression.callTargets)
+                        {
+                            FunctionType atype = (FunctionType)anid.type;
+                            if (atype.isMiracleSafe == null)
+                                atype.identifier.Accept(this);
+                            m_hasUnsafeElement |= atype.isMiracleSafe ?? true;
+                            if (m_hasUnsafeElement)
+                                m_ParserState.AddMessage(
+                                    new ParserMessage(m_ParserState.filename, ablock.line,
+                                        ablock.pos, String.Format("{0} {1} extended: calls extended method '{2}'.",
+                                        methodAction, methodIdentifier.tokenText,anid.tokenText)));
+                        }
+                        break;
+                    case StatementKind.NondetBlock:
+                        m_hasUnsafeElement = true;
+                        m_ParserState.AddMessage(
+                            new ParserMessage(m_ParserState.filename, ablock.line,
+                                ablock.pos, String.Format("{0} {1} extended: more than one nondet-block.",
+                                methodAction, methodIdentifier.tokenText)));
+                        break;
+                    case StatementKind.PrioBlock:
+                        m_hasUnsafeElement = true;
+                        m_ParserState.AddMessage(
+                            new ParserMessage(m_ParserState.filename, ablock.line,
+                                ablock.pos, String.Format("{0} {1} extended: more than one prio block.",
+                                methodAction, methodIdentifier.tokenText)));
+                        break;
+                    case StatementKind.Skip:
+                        break;
+                    case StatementKind.QualConstraint:
+                        m_hasUnsafeElement = true;
+                        break;
+                    case StatementKind.SeqBlock:
+                    // seq block in seq block should not occur..
+                    default:
+                        throw new NotImplementedException();
+                }
+                if (m_hasUnsafeElement)
+                    break;
+            }
+        }
+
+
+        public override void visit(MethodIdentifier methodIdentifier)
+        {
+            FunctionType mType = (FunctionType)methodIdentifier.type;
+            if (mType.isMiracleSafe != null)
+                return;
+
+            // AST of method may have one prioritized block before the nondet block
+            // both blocks must not have more than one element. (we do not implement conditional)
+            bool m_hasUnsafeElement = false;
+            Block ablock = methodIdentifier.body;
+
+            CalcBodySafe(methodIdentifier, mType, ref m_hasUnsafeElement, ref ablock);
+
+            /*
+            if (!m_hasUnsafeElement)
+                m_ParserState.AddMessage(
+                    new ParserMessage(m_ParserState.filename, ablock.line,
+                        ablock.pos, String.Format("Found basic method: '{0}'",
+                        methodIdentifier.tokenText)));
+            */
+
+            mType.SetMiracleSafe(!m_hasUnsafeElement);
+        }
+
+
+        public override void visit(NamedActionIdentifier namedActionIdentifier)
+        {
+            FunctionType mType = (FunctionType)namedActionIdentifier.type;
+            if (mType.isMiracleSafe != null)
+                return;
+
+            // AST of namedaction starts with a seq block with only one guarded command..
+            Block seqb = namedActionIdentifier.body;
+            System.Diagnostics.Debug.Assert(seqb.statements.Count == 1);
+            System.Diagnostics.Debug.Assert(seqb.statements.First.Value.kind == StatementKind.GuardedCommand);
+
+            GuardedCommand gc = (GuardedCommand)seqb.statements.First.Value;
+            Block ablock = gc.body;
+            bool hasUnsafeElement = false;
+
+            CalcBodySafe(namedActionIdentifier, mType, ref hasUnsafeElement, ref ablock);
+            /*
+            if (!hasUnsafeElement)
+                m_ParserState.AddMessage(
+                    new ParserMessage(m_ParserState.filename, ablock.line,
+                        ablock.pos, String.Format("Found basic action: '{0}'",
+                        namedActionIdentifier.tokenText)));
+            */
+            mType.SetMiracleSafe(!hasUnsafeElement);
+        }
+
+        public override void visit(OoActionSystemType ooActionSystemType)
+        {
+            base.visit(ooActionSystemType);
+            bool allsafe = true;
+            foreach (var x in ooActionSystemType.symbols.symbolList)
+            {
+                if (x.kind == IdentifierKind.MethodIdentifier 
+                    || x.kind == IdentifierKind.NamedActionIdentifier)
+                {
+                    allsafe &= ((FunctionType)x.type).isMiracleSafe ?? false;
+                }
+            }
+            if (allsafe)
+                m_ParserState.AddMessage(
+                    new ParserMessage(m_ParserState.filename, ooActionSystemType.identifier.line,
+                        ooActionSystemType.identifier.column, String.Format("Found action system with basic actions/methods only: '{0}'",
+                         ooActionSystemType.identifier.tokenText)));
+
+        }
+
+
+        public OoaActionClassifierVisitor(ParserState aState)
+            : base(aState)
+        { }
+    }
+}
+
Index: branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaCloneVisitor.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaCloneVisitor.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaCloneVisitor.cs	(revision 3)
@@ -0,0 +1,463 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TUG.Mogentes
+{
+
+    
+
+    public sealed class OoaDeepCloneVisitor : OoaCompleteAstTraversalVisitor
+    {
+        Dictionary<object, object> mapping;
+        Identifier selfreplacement;
+        //List<SymbolTable> symboltables = new List<SymbolTable>();
+
+
+        public bool quantifierState = false;
+
+        /* we do not clone types */
+        public override void visit(AnyType anyType)
+        { throw new NotImplementedException(); }
+        public override void visit(BoolType boolType)
+        { throw new NotImplementedException(); }
+        public override void visit(CharType charType)
+        { throw new NotImplementedException(); }
+        public override void visit(EnumType enumType)
+        { throw new NotImplementedException(); }
+        public override void visit(FloatType floatType)
+        { throw new NotImplementedException(); }
+        public override void visit(FunctionType functionType)
+        { throw new NotImplementedException(); }
+        public override void visit(IntType intType)
+        { throw new NotImplementedException(); }
+        public override void visit(ListType listType)
+        { throw new NotImplementedException(); }
+        public override void visit(MapType mapType)
+        { throw new NotImplementedException(); }
+        public override void visit(NullType nullType)
+        { throw new NotImplementedException(); }
+        public override void visit(OoActionSystemType ooActionSystemType)
+        { throw new NotImplementedException(); }
+        public override void visit(TupleType tupleType)
+        { throw new NotImplementedException(); }
+        public override void visit(EnumIdentifier enumIdentifier)
+        { throw new NotImplementedException(); }
+        public override void visit(LandmarkIdentifier landmarkIdentifier)
+        { throw new NotImplementedException(); }
+        public override void visit(ExpressionVariableIdentifier expressionVariableIdentifier)
+        { throw new NotImplementedException(); }
+
+
+        public override void visit(LocalVariableIdentifier localVariableIdentifier)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void visit(MainModule mainModule)
+        {
+            throw new NotImplementedException();
+        }
+
+
+        public override void visit(MapConstructor mapConstructor)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void visit(MethodIdentifier methodIdentifier)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void visit(NamedActionIdentifier namedActionIdentifier)
+        {
+            Block newBlock = (Block)SClone(namedActionIdentifier.body);
+            namedActionIdentifier.SetBody(newBlock);
+            // we do not clone the parameters..
+        }
+
+        public override void visit(Module module)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void visit(NondetIdentifierList nondetIdentifierList)
+        {
+            throw new NotImplementedException();
+        }
+
+
+        public override void visit(OpaqueType opaqueType)
+        {
+            throw new NotImplementedException(); // must not happen
+        }
+
+        public override void visit(ParameterIdentifier parameterIdentifier)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void visit(PrioIdentifierList prioIdentifierList)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void visit(QrType qrType)
+        {
+            throw new NotImplementedException();
+        }
+
+
+
+        public override void visit(ObjectConstructor objectConstructor)
+        {
+            //base.visit(objectConstructor);
+        }
+
+        private void UpdateScope(IScope aScope)
+        {
+            if (aScope.GetParentScope() != null && !mapping.ContainsKey(aScope.GetParentScope()))
+                throw new ArgumentException();
+            else if (aScope.GetParentScope() != null)
+            {
+                aScope.SetParentScope((IScope)mapping[aScope.GetParentScope()]);
+            }
+        }
+
+
+        private Expression EClone(Expression anExpr)
+        {
+            Expression result = null;
+            if (anExpr != null)
+            {
+                result = anExpr.Clone();
+
+                if (anExpr is IScope)
+                {
+                    mapping.Add(anExpr, result);
+                    UpdateScope((IScope)result);
+                }
+
+                result.Accept(this);
+            }
+            return result;
+        }
+
+        private Statement SClone(Statement aStatement)
+        {
+            Statement result = null;
+            if (aStatement != null)
+            {
+                result = aStatement.Clone();
+
+                if (aStatement is IScope)
+                {
+                    mapping.Add(aStatement, result);
+                    UpdateScope((IScope)result);
+                }
+
+                result.Accept(this);
+            }
+            return result;
+        }
+
+        // clones symbols found in symbol table
+        private void SymTabClone(SymbolTable aTable)
+        {
+            if (aTable != null && aTable.symbolList.Count > 0)
+            {
+                List<Identifier> newList = new List<Identifier>();
+                foreach (var x in aTable.symbolList)
+                {
+                    if (!mapping.ContainsKey(x))
+                    {
+                        Identifier newid = x.Clone();
+                        newList.Add(newid);
+                        mapping.Add(x, newid);
+                    }
+                    else
+                        newList.Add((Identifier)mapping[x]);
+                }
+                aTable.SetSymbolList(newList);
+            }
+        }
+
+
+        private void cloneExpressionList(LinkedListNode<Expression> anElem)
+        {
+            while (anElem != null)
+            {
+                anElem.Value = EClone(anElem.Value);
+                anElem = anElem.Next;
+            }
+        }
+
+
+        /*no need to clone leafs (they are already cloned and a shallow copy is sufficient*/
+        public override void visit(AbortStatement abortStatement)
+        { }
+        public override void visit<T>(ValueExpression<T> valueExpression)
+        { }
+
+
+        /*clone a block*/
+        public void cloneBlock(Block aBlock)
+        {
+            SymTabClone(aBlock.symbols);
+            LinkedListNode<Statement> stmnt = aBlock.statements.First;
+            while (stmnt != null)
+            {
+                stmnt.Value = SClone(stmnt.Value);
+                stmnt = stmnt.Next;
+            }
+        }
+        public override void visit(NondetBlock nondetBlock)
+        {
+            cloneBlock(nondetBlock);
+        }
+        public override void visit(SeqBlock seqBlock)
+        {
+            seqBlock.SetFilter(EClone(seqBlock.filter));
+            cloneBlock(seqBlock);
+        }
+        public override void visit(PrioBlock prioBlock)
+        {
+            cloneBlock(prioBlock);
+        }
+
+        public override void visit(AccessExpression accessExpression)
+        {
+            visit((BinaryOperator)accessExpression);
+        }
+        public override void visit(BinaryOperator binaryOperator)
+        {
+            Expression left = EClone(binaryOperator.left);
+            Expression right = EClone(binaryOperator.right);
+            binaryOperator.SetLeftChild(left);
+            binaryOperator.SetRightChild(right);
+        }
+
+        public override void visit(Assignment assignment)
+        {
+            SymTabClone(assignment.symbols);
+            cloneExpressionList(assignment.places.First);
+            cloneExpressionList(assignment.values.First);
+            assignment.SetNondetExpression(EClone(assignment.nondetExpression));
+            UpdateScope(assignment);
+        }
+        public override void visit(AttributeIdentifier attributeIdentifier)
+        {
+            Expression initializer = EClone(attributeIdentifier.initializer);
+            attributeIdentifier.SetInitializer(initializer);
+        }
+        public override void visit(Call call)
+        {
+            Expression cExpr = EClone(call.callExpression);
+            call.SetCallExpression(cExpr);
+        }
+
+        public override void visit(CallExpression callExpression)
+        {
+            List<Expression> newargs = new List<Expression>();
+            foreach (var x in callExpression.arguments)
+            {
+                newargs.Add(EClone(x));
+            }
+            callExpression.SetArguments(newargs);
+
+            visit((UnaryOperator)callExpression);
+        }
+
+        public void CloneQuantifier(Quantifier qf)
+        {
+            SymTabClone(qf.symbols);
+            bool oldQunatifierState = quantifierState;
+            quantifierState = true;
+            visit((UnaryOperator)qf);
+            quantifierState = oldQunatifierState;
+        }
+        public override void visit(ExistsQuantifier quantifier)
+        {
+            CloneQuantifier(quantifier);
+        }
+        public override void visit(ForallQuantifier quantifier)
+        {
+            CloneQuantifier(quantifier);
+        }
+
+
+
+
+        public override void visit(GuardedCommand guardedCommand)
+        {
+            Block newblock = (Block)SClone(guardedCommand.body);
+            Expression newguard = EClone(guardedCommand.guard);
+            guardedCommand.SetBody(newblock);
+            guardedCommand.SetGuard(newguard);
+        }
+
+        public override void visit(IdentifierExpression identifierExpression)
+        {
+            
+            if (identifierExpression.isSelf)
+            {
+                /*if (quantifierState) //FIXXME
+                {
+                    if (!selfreplacement.tokenText.StartsWith("attr"))
+                    {
+                        String oldTokenText = selfreplacement.tokenText;
+                        selfreplacement.SetTokenText("attr____model_root_" + selfreplacement.tokenText);
+                        identifierExpression.SetIdentifier(selfreplacement);
+                        selfreplacement.SetTokenText(oldTokenText);
+                    }
+                }
+                else
+                */
+                identifierExpression.SetIdentifier(selfreplacement);
+                
+               
+            }
+            else if (mapping.ContainsKey(identifierExpression.identifier) 
+                && identifierExpression.identifier.kind != IdentifierKind.MethodIdentifier)
+
+            /* we do NOT replace method calls here, since they are prefixed by self if it's a
+             * method in the current object or by some field/method access if it's another 
+             * object.
+             */ 
+                identifierExpression.SetIdentifier((Identifier)mapping[identifierExpression.identifier]);
+            
+        }
+
+        public override void visit(KillStatement killStatement)
+        {
+            if (mapping.ContainsKey(killStatement.someOne))
+                killStatement.SetIdentifier((Identifier)mapping[killStatement.someOne]);
+        }
+
+
+        public override void visit(ListConstructor listConstructor)
+        {
+            SymTabClone(listConstructor.comprehensionVariables);
+
+            List<Expression> newelems = new List<Expression>();
+            foreach (var x in listConstructor.elements)
+                newelems.Add(EClone(x));
+
+            listConstructor.SetElements(newelems);
+            listConstructor.SetComprehension(EClone(listConstructor.comprehension));
+        }
+
+        public override void visit(QualitativeConstraintStatement qalitativeConstraintStatement)
+        {
+            if (qalitativeConstraintStatement.variable0 != null && mapping.ContainsKey(qalitativeConstraintStatement.variable0))
+                qalitativeConstraintStatement.SetVariable0((Identifier)mapping[qalitativeConstraintStatement.variable0]);
+            if (qalitativeConstraintStatement.variable1 != null && mapping.ContainsKey(qalitativeConstraintStatement.variable1))
+                qalitativeConstraintStatement.SetVariable1((Identifier)mapping[qalitativeConstraintStatement.variable1]);
+            if (qalitativeConstraintStatement.variable2 != null && mapping.ContainsKey(qalitativeConstraintStatement.variable2))
+                qalitativeConstraintStatement.SetVariable2((Identifier)mapping[qalitativeConstraintStatement.variable2]);
+        }
+
+
+        public override void visit(QValConstructor qValConstructor)
+        {
+            List<Expression> values = new List<Expression>(qValConstructor.value);
+            for (int i = 0; i < values.Count; i++)
+                qValConstructor.value[i] = EClone(values[i]);
+        }
+
+        public override void visit(SeqIdentifierList seqIdentifierList)
+        {
+            throw new NotImplementedException();
+        }
+
+
+        public override void visit(SetConstructor setConstructor)
+        {
+            SymTabClone(setConstructor.comprehensionVariables);
+            List<Expression> newelems = new List<Expression>();
+            foreach (var x in setConstructor.items)
+                newelems.Add(EClone(x));
+
+            setConstructor.SetItems(newelems);
+            setConstructor.SetComprehension(EClone(setConstructor.comprehension));
+        }
+
+
+        public override void visit(SkipStatement skipStatement)
+        { }
+
+        public override void visit(TernaryOperator ternaryOperator)
+        {
+            ternaryOperator.SetLeftChild(EClone(ternaryOperator.left));
+            ternaryOperator.SetMidChild(EClone(ternaryOperator.mid));
+            ternaryOperator.SetRightChild(EClone(ternaryOperator.right));
+        }
+
+        public override void visit(TupleConstructor tupleConstructor)
+        {
+            List<Expression> values = new List<Expression>();
+            foreach (var x in tupleConstructor.values)
+                values.Add(EClone(x));
+            tupleConstructor.SetTupleValues(values);
+        }
+
+        public override void visit(TupleMapAccessExpression tupleMapAccessExpression)
+        {
+            tupleMapAccessExpression.SetArgument(EClone(tupleMapAccessExpression.argument));
+            visit((UnaryOperator)tupleMapAccessExpression);
+        }
+
+        public override void visit(TypeExpression typeExpression)
+        { /*we do not clone types*/ }
+
+
+        public override void visit(TypeIdentifier typeIdentifier)
+        {
+            throw new NotImplementedException();
+        }
+
+        public override void visit(UnaryOperator unaryOperator)
+        {
+            Expression child = EClone(unaryOperator.child);
+            unaryOperator.SetChild(child);
+        }
+
+
+        public override void visit(UnresolvedIdentifierExpression unresolvedIdentifierExpression)
+        {
+            throw new NotImplementedException(); // must not occur
+        }
+
+        public override void visit(UnspecIdentifierList unspecIdentifierList)
+        {
+            throw new NotImplementedException();
+        }
+
+        public OoaDeepCloneVisitor(Dictionary<object, object> initMapping, Identifier selfreplace)
+            : base(null)
+        {
+            mapping = new Dictionary<object, object>(initMapping);
+            selfreplacement = selfreplace;
+        }
+    }
+    
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaMethodCallVisitor.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaMethodCallVisitor.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaMethodCallVisitor.cs	(revision 3)
@@ -0,0 +1,54 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TUG.Mogentes.parser.visitors
+{
+
+    /// <summary>
+    /// Visitor that inlines method calls (this works easily because we do not allow for recursion!)
+    /// </summary>
+
+    class OoaMethodCallVisitor : OoaCompleteAstTraversalVisitor
+    {
+
+        protected override void VisitAstElement(IAst element, IAst parent)
+        {
+            if (element.nodeType == AstNodeTypeEnum.statement)
+            {
+                if (((Statement)element).kind == StatementKind.MethodCall)
+                {
+                    Call aCallStatement = (Call)element;
+                    
+                    // parent should be seq block.
+                    System.Diagnostics.Debug.Assert(parent is SeqBlock);
+
+                    return;
+                }
+            }
+            base.VisitAstElement(element, parent);
+        }
+
+        public OoaMethodCallVisitor(ParserState aState)
+            : base(aState)
+        { }
+    }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaMethodPureClassifier.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaMethodPureClassifier.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaMethodPureClassifier.cs	(revision 3)
@@ -0,0 +1,99 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TUG.Mogentes
+{
+    /// <summary>
+    /// This visitor scans all methods and decides whether they are pure, i.e. there is no state-update.
+    /// </summary>
+    public sealed class OoaMethodPureClassifierVisitor : OoaCompleteAstTraversalVisitor
+    {
+
+        Stack<MethodIdentifier> currentMethod = new Stack<MethodIdentifier>();
+
+        public override void visit(MethodIdentifier methodIdentifier)
+        {
+            
+            currentMethod.Push( methodIdentifier);
+            ((FunctionType)currentMethod.Peek().type).SetIsPureFunction(true); // assume is true..
+
+            base.visit(currentMethod.Peek());
+          
+            if (((FunctionType)currentMethod.Peek().type).isPureFunction)
+            {
+                m_ParserState.AddMessage(
+                    new ParserMessage(m_ParserState.filename, methodIdentifier.line,
+                        methodIdentifier.column, String.Format("Found pure method: {0}",
+                         methodIdentifier.tokenText)));
+            } else
+                m_ParserState.AddMessage(                    new ParserMessage(m_ParserState.filename, methodIdentifier.line,
+                        methodIdentifier.column, String.Format("Found extended method: {0}",
+                         methodIdentifier.tokenText)));
+
+            currentMethod.Pop();
+        }
+
+        public override void visit(OoActionSystemType systemType)
+        {
+            bool functionPure = false; //introduce variable with save value 
+            if (currentMethod.Count > 0 && currentMethod.Peek() != null) //if we are determining the pureness...
+            {
+                functionPure = ((FunctionType)currentMethod.Peek().type).isPureFunction; //...save the current value
+            }
+            base.visit(systemType); // go down in recursion 
+            if ( currentMethod.Count > 0 && currentMethod.Peek() != null) //but restore old pureness!
+            {
+                         
+                ((FunctionType)currentMethod.Peek().type).SetIsPureFunction(functionPure);
+                
+            }
+                    
+        }
+
+
+        public override void visit(Assignment assignment)
+        {
+            
+            bool assignmentPure = true;
+            if (currentMethod.Count > 0 && currentMethod.Peek() != null)
+            {
+                foreach (var x in assignment.places)
+                {
+                    if (x.kind != ExpressionKind.Identifier)
+                        assignmentPure = false;
+                    else if (((IdentifierExpression)x).identifier.kind == IdentifierKind.AttributeIdentifier)
+                        assignmentPure = false;
+                }
+                bool functionPure = assignmentPure && ((FunctionType)currentMethod.Peek().type).isPureFunction;
+                ((FunctionType)currentMethod.Peek().type).SetIsPureFunction(functionPure);
+            }
+            base.visit(assignment);
+        }
+
+
+
+        public OoaMethodPureClassifierVisitor(ParserState aState)
+            : base(aState)
+        { }
+    }
+}
+
Index: branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaObjectsInstantiateVisitor.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaObjectsInstantiateVisitor.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaObjectsInstantiateVisitor.cs	(revision 3)
@@ -0,0 +1,344 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+/*
+ * Visitor that "compiles down" objects to normal action systems
+ * Implementing the algorithm layed out in 
+ * Bonsangue, Kok, Sere: An Approach to Object-Orientation in Action Systems, In
+ * MPC'98, LNCS 1422, pp. 68{95, 1998
+ *
+ * Notes:
+ * 
+ *    WE DO OBJECT INSTANTIATION HERE: This means (more or less) that we will duplicate all the 
+ *    classes found. In particular we will create one copy per object. In order to do that, we
+ *    need to know exactly how many objects of a certain type there will be. We also need to assign each of these
+ *    new action systems a particular name. Hence within this compilation step, we need to do 
+ *    the following.
+ * 
+ *  -) need to count number of constructed objects per class (in order to be able to assign names)
+ *       => This is implemented by compiling the action system initialization to CSharp Code and 
+ *          subsequently running the initialization step.
+ *  -) each action system (resembling an object now) gets a name that encodes the class name, and 
+ *       information about which object created the new object.
+ *       => Per class: find root element, and do instantiation. Then iterate through all objects and
+ *          do instantiation for objects created in these.... (It makes sense to forbid creation of
+ *          objects of class A in class A...)
+ *  -) after the names are known, start instantiation (=copy) process and add necessary runtime 
+ *       code (see the paper)
+ * 
+ * 
+*/
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TUG.Mogentes.Codegen;
+using TUG.Mogentes.Codegen.CSharp;
+
+
+namespace TUG.Mogentes
+{
+    internal sealed class OoaDummyCheckVisitor : OoaExpressionVisitor
+    {
+        public override void visit(AccessExpression accessExpression)
+        {
+            if (accessExpression.left.type == null)
+                System.Console.WriteLine("outch");
+            base.visit(accessExpression);
+        }
+
+        public OoaDummyCheckVisitor()
+        {
+        }
+
+    }
+
+
+    public sealed class OoaObjectInstantiationVisitor : OoaCompleteAstTraversalVisitor
+    {
+        private OoaCSharpInitVisitor m_simulator;
+        private ActionSystem m_actionSystem;
+        private Identifier self;
+        private Dictionary<object, object> m_toReplace = new Dictionary<object, object>();
+
+        /// <summary>
+        /// for a given object and type, the method duplicates the attributes and adds them to the resulting
+        /// instantiated action system.
+        /// </summary>
+        private void DuplicateAttribute(AttributeIdentifier attributeIdentifier,
+            OoActionSystemInstance obj, OoActionSystemType aType, ActionSystem m_actionSystem)
+        {
+            AttributeIdentifier newAttribute = new AttributeIdentifier(attributeIdentifier);
+            newAttribute.SetTokenText(String.Format("{0}_{1}", obj.Name, attributeIdentifier.tokenText));
+            m_toReplace.Add(attributeIdentifier, newAttribute);
+
+            newAttribute.SetInitializer(newAttribute.initializer.Clone());
+            OoaDeepCloneVisitor cloner = new OoaDeepCloneVisitor(m_toReplace, self);
+            newAttribute.initializer.Accept(cloner);
+
+            m_actionSystem.symbols.AddIdentifier(newAttribute);
+        }
+
+        private void DuplicateNamedAction(NamedActionIdentifier namedActionIdentifier,
+            OoActionSystemInstance obj, OoActionSystemType aType, ActionSystem m_actionSystem)
+        {
+            NamedActionIdentifier newAction = new NamedActionIdentifier(namedActionIdentifier);
+            newAction.SetTokenText(String.Format("{0}_{1}", obj.Name, namedActionIdentifier.tokenText));
+            m_toReplace.Add(namedActionIdentifier, newAction);
+            OoaDeepCloneVisitor cloner = new OoaDeepCloneVisitor(m_toReplace, self);
+            newAction.Accept(cloner);
+
+            m_actionSystem.symbols.AddIdentifier(newAction);
+        }
+
+        public static string GetInstanceFunctionName(OoActionSystemInstance obj, FunctionIdentifier afunction)
+        {
+            return String.Format("{0}_{1}", obj.Name, afunction.tokenText);
+        }
+
+        private void DuplicateMethod(MethodIdentifier methodIdentifier, OoActionSystemInstance obj,
+            OoActionSystemType aType, ActionSystem m_actionSystem)
+        {
+            MethodIdentifier newMethod = new MethodIdentifier(methodIdentifier);
+            newMethod.SetTokenText(GetInstanceFunctionName(obj, methodIdentifier));
+            m_toReplace.Add(methodIdentifier, newMethod);
+
+            newMethod.SetBody((Block)newMethod.body.Clone());
+            OoaDeepCloneVisitor cloner = new OoaDeepCloneVisitor(m_toReplace, self);
+            newMethod.body.Accept(cloner);
+
+            m_actionSystem.symbols.AddIdentifier(newMethod);
+        }
+
+
+        /*Duplicates the do-od block (incl. any do-od blocks of parent classes)*/
+        private void DuplicateDoOdBlock(OoActionSystemInstance obj, OoActionSystemType aType, ActionSystem m_actionSystem, Block result)
+        {
+            OoActionSystemType rootType = aType;
+            Block block;
+            while (aType != null)
+            {
+                block = aType.doOdBlock;
+                if (block != null)
+                {
+                    Block clone = (Block)block.Clone();
+                    OoaDeepCloneVisitor cloner = new OoaDeepCloneVisitor(m_toReplace, self);
+                    clone.Accept(cloner);
+                    result.AddStatement(clone);
+                }
+                aType = aType.baseType;
+            }
+        }
+
+        Dictionary<object, object> objectsdone = new Dictionary<object, object>();
+
+        /// <summary>
+        /// Generates an OoActionSystemType that is the instantiation of all the objects found in the System Assembling Block
+        /// </summary>
+        private void InstantiateObjects(ActionSystem m_actionSystem, MainModule mainModule, IdentifierList sysdescr, Block parent)
+        {
+
+            //C5.HashSet<OoActionSystemInstance> done = new C5.HashSet<OoActionSystemInstance>();
+            //
+
+            Block newBlock;
+            switch (sysdescr.listType)
+            {
+                case IdentifierListType.nondeterministic:
+                    newBlock = new NondetBlock(0, 0);
+                    break;
+                case IdentifierListType.prioritized:
+                    newBlock = new PrioBlock(0, 0);
+                    break;
+                case IdentifierListType.seqential:
+                    newBlock = new SeqBlock(0, 0);
+                    break;
+
+                case IdentifierListType.normal:
+                default:
+                    throw new NotImplementedException();
+            }
+
+            if (parent == null)
+                m_actionSystem.SetDoOdBlock(newBlock);
+            else
+                parent.AddStatement(newBlock);
+
+            foreach (var id in sysdescr.identifiers)
+            {
+                Identifier ident = id;
+                while (ident.kind == IdentifierKind.List && ((IdentifierList)ident).identifiers.Count == 1)
+                {
+                    ident = ((IdentifierList)ident).identifiers.First.Value;
+                }
+
+                if (ident.kind == IdentifierKind.List)
+                    InstantiateObjects(m_actionSystem, mainModule, (IdentifierList)ident, newBlock);
+                else
+                {
+                    if (ident.kind == IdentifierKind.TypeIdentifier &&
+                        ((TypeIdentifier)ident).type.kind == TypeKind.OoActionSystemType)
+                    {
+
+                        OoActionSystemType aType = (OoActionSystemType)((TypeIdentifier)ident).type;
+                        objectsdone.Add(aType, m_actionSystem);
+
+
+                        Block NondetBlock = null; // holds parallel comp of all objects
+                        if (aType.doOdBlock != null)
+                        {
+                            NondetBlock = new NondetBlock(0, 0);
+                            newBlock.AddStatement(NondetBlock);
+                        }
+
+
+                        foreach (var obj in aType.objects)
+                        {
+                            m_toReplace = new Dictionary<object, object>(objectsdone);
+                            addParentClassMappings(m_toReplace, aType, m_actionSystem);
+                            self = new SelfTypeIdentifier(obj.Name, aType, null);
+                            SymbolTable table = aType.getAllSymbols();
+                            foreach (var x in table.symbolList)
+                            {
+                                // resolve attributes first
+                                if (x.kind == IdentifierKind.AttributeIdentifier)
+                                    DuplicateAttribute((AttributeIdentifier)x, obj, aType, m_actionSystem);
+                            }
+                            foreach (var x in table.symbolList)
+                            {
+                                // now do methods and other stuff
+                                if (x.kind == IdentifierKind.MethodIdentifier)
+                                    DuplicateMethod((MethodIdentifier)x, obj, aType, m_actionSystem);
+                                else if (x.kind == IdentifierKind.NamedActionIdentifier)
+                                    DuplicateNamedAction((NamedActionIdentifier)x, obj, aType, m_actionSystem);
+                            }
+                            // construct parallel composition of all the objects of one class.
+                            if (aType.doOdBlock != null)
+                            {
+                                DuplicateDoOdBlock(obj, aType, m_actionSystem, NondetBlock);
+                            }
+                        }
+
+                        // add an error, if a type does not get instantiated and the do-od block is filled..
+                        // !!!!!!!!!!!!!!! note, if new is also allowed in normal actions, this needs to be disabled (or become a warning) !!!!!!!!!!!!!!!!!!!!!!!!!!
+                        if (aType.objects.Count == 0 && aType.doOdBlock != null)
+                        {
+                            m_ParserState.AddErrorMessage(new ParserError(m_ParserState.filename, aType.identifier.line, aType.identifier.column,
+                                String.Format("Type '{0}' is never instantiated but has a non-empty do-od block", aType.ToString())));
+                        }
+
+
+                    }
+                    else
+                        throw new NotImplementedException();
+                }
+            }
+        }
+
+        private void addParentClassMappings(Dictionary<object, object> m_toReplace, OoActionSystemType aType, ActionSystem m_actionSystem)
+        {
+            while (aType != null)
+            {
+                if (!m_toReplace.ContainsKey(aType))
+                    m_toReplace.Add(aType, m_actionSystem); // add base classes to mapping...
+                aType = aType.baseType;
+            }
+        }
+
+        /// <summary>
+        /// Adds those objects of types that are not found in the SAB.
+        /// </summary>
+        private void InstantiatePassiveObjects(ActionSystem m_actionSystem, MainModule mainModule)
+        {
+            foreach (var x in mainModule.symbolTable.symbolList)
+            {
+                if (x.type.kind == TypeKind.OoActionSystemType && !objectsdone.ContainsKey(x.type))
+                    if (((OoActionSystemType)x.type).autoConstruction)
+                    {
+                        OoActionSystemType aType = (OoActionSystemType)x.type;
+                        m_ParserState.AddErrorMessage(new ParserError(m_ParserState.filename, aType.identifier.line, aType.identifier.column,
+                            String.Format("Type '{0}' marked autocons but omitted in system description!", aType.ToString())));
+                    }
+                    else
+                    {
+                        OoActionSystemType aType = (OoActionSystemType)x.type;
+                        foreach (var obj in aType.objects)
+                        {
+                            m_toReplace = new Dictionary<object, object>(objectsdone);
+                            addParentClassMappings(m_toReplace, aType, m_actionSystem);
+                            self = new SelfTypeIdentifier(obj.Name, aType, null);
+                            SymbolTable table = aType.getAllSymbols();
+                            foreach (var y in table.symbolList)
+                            {
+                                // resolve attributes first
+                                if (y.kind == IdentifierKind.AttributeIdentifier)
+                                    DuplicateAttribute((AttributeIdentifier)y, obj, aType, m_actionSystem);
+                            }
+                            foreach (var y in table.symbolList)
+                            {
+                                // now do methods
+                                if (y.kind == IdentifierKind.MethodIdentifier)
+                                    DuplicateMethod((MethodIdentifier)y, obj, aType, m_actionSystem);
+                                //else if (y.kind == IdentifierKind.NamedActionIdentifier)
+                                //    m_ParserState.AddErrorMessage(new ParserError(m_ParserState.filename, aType.identifier.line, aType.identifier.column,
+                                //        String.Format("Type '{0}' has named actions but was omitted in system description!", aType.ToString())));
+                            }
+                            if (aType.doOdBlock != null)
+                                m_ParserState.AddErrorMessage(new ParserError(m_ParserState.filename, aType.identifier.line, aType.identifier.column,
+                                    String.Format("Type '{0}' has do-od block but was omitted in system description!", aType.ToString())));
+                        }
+
+                    }
+            }
+        }
+
+
+
+
+
+        public override void visit(MainModule mainModule)
+        {
+            if (mainModule.systemDescription == null)
+                return;
+
+            /* determine names of objects */
+            mainModule.Accept(m_simulator);
+
+            /* add information about all the objects to the AST */
+            //mainModule.SetObjects(m_simulator.initialObjectWorkingSet);
+            m_actionSystem = new ActionSystem();
+            m_actionSystem.SetParentScope(mainModule);
+            InstantiateObjects(m_actionSystem, mainModule, mainModule.systemDescription, m_actionSystem.doOdBlock);
+            InstantiatePassiveObjects(m_actionSystem, mainModule);
+
+            mainModule.SetInstance(m_actionSystem);
+
+        }
+
+        public override string ToString()
+        {
+            return m_simulator.ToString();
+        }
+
+
+        public OoaObjectInstantiationVisitor(ParserState aState)
+            : base(aState)
+        {
+            m_simulator = new OoaCSharpInitVisitor(aState);
+        }
+    }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaOpaqueVisitor.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaOpaqueVisitor.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaOpaqueVisitor.cs	(revision 3)
@@ -0,0 +1,163 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TUG.Mogentes
+{
+    /// <summary>
+    /// Replaces all Opaque types (types we could not resolve in the first run of the parser)
+    /// with the resolved ones. Note: The actual resolving has already been done, i.e., the 
+    /// resolvedType member is already set to the correct value. Now we just want to get an
+    /// AST that does not contain any OpaqueTypeNodes at all.
+    /// </summary>
+    public sealed class OoaReplaceOpaqueVisitor : OoaCompleteAstTraversalVisitor
+    {
+
+        private void ReplaceOpaque(IAst parent)
+        {
+            switch (parent.nodeType)
+            {
+                case AstNodeTypeEnum.type:
+                    ReplaceOpaqueInType((UlyssesType)parent);
+                    break;
+                case AstNodeTypeEnum.identifier:
+                    ReplaceOpaqueInIdentifier((Identifier)parent);
+                    break;
+                case AstNodeTypeEnum.expression:
+                    ReplaceOpaqueInExpression((Expression)parent);
+                    break;
+                default:
+                    throw new NotImplementedException();
+            }
+        }
+
+
+        private void ReplaceOpaqueInExpression(Expression expression)
+        {
+            switch (expression.kind)
+            {
+                case ExpressionKind.ObjectConstr:
+                    ObjectConstructor c = (ObjectConstructor)expression;
+                    c.SetType(((OpaqueType)c.type).resolvedType);
+                    break;
+                case ExpressionKind.Cast:
+                    UnaryOperator unop = (UnaryOperator)expression;
+                    unop.SetType(((OpaqueType)unop.type).resolvedType);
+                    break;
+                default:
+                    throw new NotImplementedException();
+            }
+        }
+
+
+        private void ReplaceOpaqueInIdentifier(Identifier identifier)
+        {
+            switch (identifier.kind)
+            {
+                case IdentifierKind.AttributeIdentifier:
+                    AttributeIdentifier id = (AttributeIdentifier)identifier;
+                    System.Diagnostics.Debug.Assert(id.type is OpaqueType); // that's why we are here
+                    id.SetType(((OpaqueType)id.type).resolvedType);
+                    break;
+                case IdentifierKind.ExpressionVariableIdentifier:
+                    ExpressionVariableIdentifier exprvar = (ExpressionVariableIdentifier)identifier;
+                    System.Diagnostics.Debug.Assert(exprvar.type is OpaqueType);
+                    exprvar.SetType(((OpaqueType)exprvar.type).resolvedType);
+                    break;
+                case IdentifierKind.LocalVariableIdentifier:
+                    LocalVariableIdentifier var = (LocalVariableIdentifier)identifier;
+                    System.Diagnostics.Debug.Assert(var.type is OpaqueType);
+                    var.SetType(((OpaqueType)var.type).resolvedType);
+                    break;
+                case IdentifierKind.ParameterIdentifier:
+                    ParameterIdentifier param = (ParameterIdentifier)identifier;
+                    System.Diagnostics.Debug.Assert(param.type is OpaqueType);
+                    param.SetType(((OpaqueType)identifier.type).resolvedType);
+                    break;
+                default:
+                    throw new NotImplementedException();
+            }
+        }
+
+        private void ReplaceOpaqueInType(UlyssesType ulyssesType)
+        {
+            switch (ulyssesType.kind)
+            {
+                case TypeKind.FunctionType:
+                    FunctionType func = (FunctionType)ulyssesType;
+                    if (func.returnType is OpaqueType)
+                        func.SetReturnType(((OpaqueType)func.returnType).resolvedType);
+
+                    LinkedListNode<UlyssesType> item = func.parameter.First;
+                    while (item != null)
+                    {
+                        if (item.Value.kind == TypeKind.OpaqueType)
+                            item.Value = ((OpaqueType)item.Value).resolvedType;
+                        item = item.Next;
+                    }
+                    break;
+                case TypeKind.ListType:
+                    ListType alist = (ListType)ulyssesType;
+                    if (alist.innerType.kind == TypeKind.OpaqueType)
+                        alist.SetInnerType(((OpaqueType)alist.innerType).resolvedType);
+                    break;
+                case TypeKind.MapType:
+                    MapType aMap = (MapType)ulyssesType;
+                    if (aMap.fromType.kind == TypeKind.OpaqueType)
+                        aMap.SetFromType(((OpaqueType)aMap.fromType).resolvedType);
+                    if (aMap.toType.kind == TypeKind.OpaqueType)
+                        aMap.SetToType(((OpaqueType)aMap.toType).resolvedType);
+                    break;
+                /*case TypeKind.OoActionSystemType:
+                   // handeled by the other cases...
+                    break;*/
+                case TypeKind.TupleType:
+                    TupleType aTuple = (TupleType)ulyssesType;
+                    LinkedListNode<UlyssesType> titem = aTuple.innerTypes.First;
+                    while (titem != null)
+                    {
+                        if (titem.Value.kind == TypeKind.OpaqueType)
+                            titem.Value = ((OpaqueType)titem.Value).resolvedType;
+                        titem = titem.Next;
+                    }
+                    break;
+                default:
+                    throw new NotImplementedException();
+            }
+        }
+
+        protected override void VisitAstElement(IAst subElement, IAst parent)
+        {
+            base.VisitAstElement(subElement, parent);
+
+            /*see whether the subElement is an OpaqueType, we need
+              to replace.*/
+            if ((subElement != null)
+              && (subElement.nodeType == AstNodeTypeEnum.type)
+              && (((UlyssesType)subElement).kind == TypeKind.OpaqueType))
+                ReplaceOpaque(parent);
+        }
+
+        public OoaReplaceOpaqueVisitor(ParserState aState)
+            : base(aState)
+        { }
+    }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaPrintVisitor.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaPrintVisitor.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaPrintVisitor.cs	(revision 3)
@@ -0,0 +1,1049 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+
+/* 
+ * ooaPrintVisitor
+ * 
+ * Prints AST in some sort of OOA - Syntax.
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using TUG.Mogentes.Codegen;
+
+namespace TUG.Mogentes
+{
+    public delegate void Action();
+
+    public sealed class OoaPrintVisitor : OoaCompleteAstTraversalVisitor
+    {
+        private bool writeTypes;
+        private Identifier currentTypeDef;
+        private OoaCodeEmitter output;
+
+
+
+        private void PrintSubElementOrNull(IAst anElem)
+        {
+            if (anElem == null)
+                output.Append("<null>");
+            else
+                anElem.Accept(this);
+        }
+
+        private void PrintEnumeration(System.Collections.IEnumerable arg)
+        {
+            int i = 0;
+            foreach (IAst sym in arg)
+            {
+                if (i != 0)
+                    output.Append(", ");
+                i++;
+                PrintSubElementOrNull(sym);
+            }
+        }
+
+        /*print the type identifier, or the type definition by calling the anAction delegate.*/
+        private void PrintType(UlyssesType atype, Action anAction)
+        {
+            if (   (atype.identifier != null)
+                && (!atype.isAnonymousType)
+                && (!ReferenceEquals(currentTypeDef, atype.identifier) || !writeTypes))
+            {
+                bool write = writeTypes;
+                writeTypes = false;
+                atype.identifier.Accept(this);
+                writeTypes = write;
+            }
+            else
+                anAction();
+
+        }
+
+
+
+        public override void visit(MainModule mainModule)
+        {
+            int i = 0;
+            bool haveInstance = mainModule.instance != null;
+            /*print all types*/
+            writeTypes = true;
+            output.IncIndent();
+            output.AppendLine("types");
+            foreach (var type in mainModule.symbolTable.symbolList)
+            {
+                if (type.kind != IdentifierKind.TypeIdentifier)
+                    continue;
+
+                if (i != 0)
+                    output.AppendLine(";");
+                i++;
+                if (!haveInstance || ((TypeIdentifier)type).type.kind != TypeKind.OoActionSystemType)
+                    type.Accept(this);
+            }
+
+            if (haveInstance)
+                mainModule.instance.Accept(this);
+
+            output.DecIndent();
+            output.AppendLine("");
+            output.IncIndent();
+            output.IncIndent();
+            output.AppendLine("system");
+            writeTypes = false;
+            if (!haveInstance)
+                mainModule.systemDescription.Accept(this);
+            else
+                output.Append(mainModule.instance.identifier.tokenText);
+        }
+
+        public override void visit(TypeIdentifier typeIdentifier)
+        {
+            output.Append(typeIdentifier.tokenText);
+            if (writeTypes)
+            {
+                currentTypeDef = typeIdentifier;
+                output.Append(" = ");
+                PrintSubElementOrNull(typeIdentifier.type);
+            }
+        }
+
+        /*write out type definitions*/
+        public override void visit(BoolType boolType)
+        {
+            output.Append("bool");
+        }
+
+        public override void visit(CharType charType)
+        {
+            output.Append("char");
+        }
+
+        public override void visit(IntType intType)
+        {
+            PrintType(intType, () =>
+            {
+                output.Append("int [");
+                output.Append(intType.rangeLow.ToString());
+                output.Append(" .. ");
+                output.Append(intType.rangeHigh.ToString());
+                output.Append("]");
+            });
+        }
+
+        public override void visit(FloatType floatType)
+        {
+            PrintType(floatType, () =>
+            {
+                output.Append("float [");
+                output.Append(floatType.low.ToString());
+                output.Append(" .. ");
+                output.Append(floatType.high.ToString());
+                output.Append("] /*");
+                output.Append(floatType.precision.ToString());
+                output.Append("*/");
+            });
+        }
+
+
+        public override void visit(EnumIdentifier enumIdentifier)
+        {
+            output.Append(enumIdentifier.tokenText);
+            if (enumIdentifier.HaveValue)
+                output.Append(String.Format(" = {0}", enumIdentifier.Value));
+        }
+
+        public override void visit(EnumType enumType)
+        {
+            PrintType(enumType, () =>
+            {
+                output.Append("{");
+                PrintEnumeration(enumType.listOfEnumSymbols);
+                output.Append("}");
+            });
+        }
+
+
+        public override void visit(ListType listType)
+        {
+            PrintType(listType, () =>
+            {
+                output.Append("list [");
+                output.Append(listType.maxNumberOfElements.ToString());
+                output.Append("] of ");
+                PrintSubElementOrNull(listType.innerType);
+            });
+        }
+
+        public override void visit(MapType mapType)
+        {
+            PrintType(mapType, () =>
+            {
+                output.Append("map [");
+                output.Append(mapType.maxNumberOfElements.ToString());
+                output.Append("] ");
+                PrintSubElementOrNull(mapType.fromType);
+                output.Append(" to ");
+                PrintSubElementOrNull(mapType.toType);
+            });
+        }
+
+        public override void visit(TupleType tupleType)
+        {
+            PrintType(tupleType, () =>
+            {
+                output.Append("(");
+                PrintEnumeration(tupleType.innerTypes);
+                output.Append(")");
+            });
+        }
+
+        public override void visit(OpaqueType opaqueType)
+        {
+            PrintSubElementOrNull(opaqueType.resolvedType);
+
+            output.Append(" /*opagque*/");
+        }
+
+        public override void visit(QrType qrType)
+        {
+            PrintType(qrType, () =>
+                {
+                    output.Append("qspace of [");
+                    PrintEnumeration(qrType.landmarks);
+                    output.Append("]");
+                });
+        }
+
+        public override void visit(LandmarkIdentifier landmarkIdentifier)
+        {
+            output.Append(landmarkIdentifier.tokenText);
+        }
+
+        public override void visit(OoActionSystemType ooActionSystemType)
+        {
+            PrintType(ooActionSystemType, () =>
+            {
+                if (ooActionSystemType.autoConstruction)
+                    output.Append("autocons ");
+
+
+                output.Append("system ");
+                if (ooActionSystemType.baseType != null)
+                    output.Append(String.Format("({0})", ooActionSystemType.baseType.identifier.tokenText));
+                output.AppendLine("");
+
+
+                output.IncIndent();
+                output.AppendLine("|[");
+
+
+                // get a list of interesting symbols
+                List<AttributeIdentifier> attrs = new List<AttributeIdentifier>();
+                List<MethodIdentifier> methods = new List<MethodIdentifier>();
+                List<NamedActionIdentifier> namedActions = new List<NamedActionIdentifier>();
+
+                foreach (var sym in ooActionSystemType.symbols.symbolList)
+                {
+                    if (sym.kind == IdentifierKind.AttributeIdentifier)
+                        attrs.Add((AttributeIdentifier)sym);
+                    else if (sym.kind == IdentifierKind.MethodIdentifier)
+                        methods.Add((MethodIdentifier)sym);
+                    else if (sym.kind == IdentifierKind.NamedActionIdentifier)
+                        namedActions.Add((NamedActionIdentifier)sym);
+                }
+
+                int i = 0;
+                if (attrs.Count > 0)
+                {
+                    // variables
+                    output.IncIndent();
+                    output.AppendLine("var");
+
+                    foreach (var attr in attrs)
+                    {
+                        if (i != 0)
+                            output.AppendLine(";");
+                        i++;
+                        PrintSubElementOrNull(attr);
+                    }
+
+                    output.DecIndent();
+                    output.AppendLine("");
+                }
+                bool writeTypesSave = writeTypes;
+                writeTypes = false;
+
+                i = 0;
+                if (methods.Count > 0)
+                {
+                    output.IncIndent();
+                    output.AppendLine("methods");
+
+                    foreach (var method in methods)
+                    {
+                        if (i != 0)
+                            output.AppendLine(";");
+                        i++;
+                        PrintSubElementOrNull(method);
+                    }
+
+                    output.DecIndent();
+                    output.AppendLine("");
+                }
+
+                i = 0;
+                if (namedActions.Count > 0)
+                {
+                    output.IncIndent();
+                    output.AppendLine("actions");
+
+                    foreach (var action in namedActions)
+                    {
+                        if (i != 0)
+                            output.AppendLine(";");
+                        i++;
+                        PrintSubElementOrNull(action);
+                    }
+
+                    output.DecIndent();
+                    output.AppendLine("");
+                }
+
+                if ((ooActionSystemType.doOdBlock != null) && (ooActionSystemType.doOdBlock.statements.Count > 0))
+                {
+                    output.IncIndent();
+                    output.AppendLine("do");
+
+                    PrintSubElementOrNull(ooActionSystemType.doOdBlock);
+
+                    output.DecIndent();
+                    output.AppendLine("");
+                    output.AppendLine("od");
+                }
+                output.DecIndent();
+                output.AppendLine("");
+                output.Append("]|");
+                writeTypes = writeTypesSave;
+            });
+        }
+
+        public override void visit(NullType nullType)
+        {
+            output.Append("nil");
+        }
+
+
+        public override void visit(AttributeIdentifier attributeIdentifier)
+        {
+            if (attributeIdentifier.isStatic)
+                output.Append("static ");
+            if (attributeIdentifier.isObservable)
+                output.Append("obs ");
+            if (attributeIdentifier.isControllable)
+                output.Append("ctr ");
+
+            output.Append(attributeIdentifier.tokenText);
+            if (writeTypes)
+            {
+                output.Append(": ");
+                PrintSubElementOrNull(attributeIdentifier.type);
+                output.Append(" = ");
+                PrintSubElementOrNull(attributeIdentifier.initializer);
+            }
+        }
+
+
+        public override void visit<T>(ValueExpression<T> valueExpression)
+        {
+            if (valueExpression.value != null)
+                output.Append(valueExpression.value.ToString());
+            else
+                output.Append("nil");
+        }
+
+        public override void visit(AbortStatement abortStatement)
+        {
+            output.Append("abort");
+        }
+
+        public override void visit(Assignment assignment)
+        {
+            PrintEnumeration(assignment.places);
+            output.Append(" := ");
+            PrintEnumeration(assignment.values);
+            if (assignment.nondetExpression != null)
+            {
+                output.IncIndent();
+                output.AppendLine("");
+                output.Append("with ");
+                assignment.nondetExpression.Accept(this);
+
+                if (assignment.symbols.symbolList.Count > 0)
+                {
+                    output.Append(" /* vars: ");
+                    foreach (var localVar in assignment.symbols.symbolList)
+                    {
+                        localVar.Accept(this);
+                        output.Append(" ");
+                    }
+                    output.Append("*/");
+                }
+                output.DecIndent();
+                output.AppendLine("");
+            }
+        }
+
+        public override void visit(KillStatement killStatement)
+        {
+            output.Append("kill (");
+            PrintSubElementOrNull(killStatement.someOne);
+            output.Append(")");
+        }
+
+        public override void visit(AccessExpression accessExpression)
+        {
+            if (accessExpression.right != null)
+            {
+                output.Append("(");
+                PrintSubElementOrNull(accessExpression.left);
+                output.Append(").");
+                PrintSubElementOrNull(accessExpression.right);
+            }
+            else
+            {
+                output.Append("(");
+                PrintSubElementOrNull(accessExpression.left);
+                output.Append(")");
+            }
+        }
+
+        private void PrintOperator(Expression expression)
+        {
+            switch (expression.kind)
+            {
+                case ExpressionKind.abs:    // T_ABS:
+                    output.Append("abs");
+                    break;
+                case ExpressionKind.card:   // T_CARD:
+                    output.Append("card");
+                    break;
+                case ExpressionKind.dom:    // T_DOM:
+                    output.Append("dom");
+                    break;
+                case ExpressionKind.range:  // T_RNG:
+                    output.Append("range");
+                    break;
+                case ExpressionKind.merge:  // T_MERGE:
+                    output.Append("merge");
+                    break;
+                case ExpressionKind.len:    // T_LEN:
+                    output.Append("len");
+                    break;
+                case ExpressionKind.elems:  // T_ELEMS:
+                    output.Append("elems");
+                    break;
+                case ExpressionKind.head:   // T_HEAD:
+                    output.Append("head");
+                    break;
+                case ExpressionKind.tail:   // T_TAIL:
+                    output.Append("tail");
+                    break;
+                case ExpressionKind.conc:   // T_CONC:
+                    output.Append("conc");
+                    break;
+                case ExpressionKind.inds:   // T_INDS:
+                    output.Append("inds");
+                    break;
+                case ExpressionKind.dinter: // T_DINTER:
+                    output.Append("dinter");
+                    break;
+                case ExpressionKind.dunion: // T_DUNION:
+                    output.Append("dunion");
+                    break;
+                case ExpressionKind.domresby:   // T_DOMRESBY:
+                    output.Append("domresby");
+                    break;
+                case ExpressionKind.domresto:   // T_DOMRESTO:
+                    output.Append("domresto");
+                    break;
+                case ExpressionKind.rngresby:   // T_RNGRESBY:
+                    output.Append("rngresby");
+                    break;
+                case ExpressionKind.rngresto:   // T_RNGRESTO:
+                    output.Append("rngresto");
+                    break;
+                case ExpressionKind.div:    // T_DIV:
+                    output.Append("div");
+                    break;
+                case ExpressionKind.idiv:   // T_IDIV:
+                    output.Append("idiv");
+                    break;
+                case ExpressionKind.mod:    // T_MOD:
+                    output.Append("mod");
+                    break;
+                case ExpressionKind.prod:   // T_PROD:
+                    output.Append("*");
+                    break;
+                case ExpressionKind.inter:  // T_INTER:
+                    output.Append("inter");
+                    break;
+                case ExpressionKind.sum:    // T_SUM:
+                    output.Append("+");
+                    break;
+                case ExpressionKind.minus:  // T_MINUS:
+                    output.Append("-");
+                    break;
+                case ExpressionKind.union:  // T_UNION:
+                    output.Append("union");
+                    break;
+                case ExpressionKind.diff:   // T_DIFF:
+                    output.Append("diff");
+                    break;
+                case ExpressionKind.munion: // T_MUNION:
+                    output.Append("munion");
+                    break;
+                case ExpressionKind.seqmod_mapoverride: // T_SEQMOD_MAPOVERRIDE:
+                    output.Append("seqmod_mapoverride");
+                    break;
+                case ExpressionKind.less:
+                    output.Append("<");
+                    break;
+                case ExpressionKind.lessequal:
+                    output.Append("<=");
+                    break;
+                case ExpressionKind.greater:
+                    output.Append(">");
+                    break;
+                case ExpressionKind.greaterequal:
+                    output.Append(">=");
+                    break;
+                case ExpressionKind.equal:
+                    output.Append("=");
+                    break;
+                case ExpressionKind.notequal:
+                    output.Append("<>");
+                    break;
+                case ExpressionKind.subset:
+                    output.Append("subset");
+                    break;
+                case ExpressionKind.elemin:
+                    output.Append("in");
+                    break;
+                case ExpressionKind.notelemin:
+                    output.Append("not in");
+                    break;
+                case ExpressionKind.and:    // T_AND:
+                    output.Append("and");
+                    break;
+
+                case ExpressionKind.or:     // T_OR:
+                    output.Append("or");
+                    break;
+                case ExpressionKind.implies:    // T_IMPLIES:
+                    output.Append("=>");
+                    break;
+                case ExpressionKind.biimplies:  // T_BIIMPLIES:
+                    output.Append("<=>");
+                    break;
+
+                case ExpressionKind.Primed:
+                    output.Append("'");
+                    break;
+
+
+                case ExpressionKind.Cast:
+                    output.Append("(");
+                    if (expression.type != null)
+                        output.Append(expression.type.ToString());
+                    else
+                        output.Append("Cast??");
+                    output.Append(")");
+                    break;
+
+                default:
+                    output.Append(Enum.GetName(typeof(ExpressionKind), expression.kind));
+                    break;
+            }
+        }
+
+        public override void visit(TypeExpression typeExpression)
+        {
+            PrintSubElementOrNull(typeExpression.type);
+        }
+
+        public override void visit(BinaryOperator binaryOperator)
+        {
+            output.IncIndent();
+            output.AppendLine("(");
+            PrintSubElementOrNull(binaryOperator.left);
+            output.DecIndent();
+            output.AppendLine("");
+            output.AppendLine(")");
+
+            PrintOperator(binaryOperator); output.AppendLine("");
+
+            output.IncIndent();
+            output.AppendLine("(");
+            PrintSubElementOrNull(binaryOperator.right);
+            output.DecIndent();
+            output.AppendLine("");
+            output.AppendLine(")");
+        }
+
+        public override void visit(UnaryOperator unaryOperator)
+        {
+            PrintOperator(unaryOperator);
+            output.Append("(");
+            PrintSubElementOrNull(unaryOperator.child);
+            output.Append(")");
+        }
+
+        public override void visit(UnresolvedIdentifierExpression unresolvedIdentifierExpression)
+        {
+            output.Append(unresolvedIdentifierExpression.tokenText);
+        }
+
+        public override void visit(CallExpression callExpression)
+        {
+            if (callExpression.child != null)
+                callExpression.child.Accept(this);
+            if ((callExpression.arguments != null) && (callExpression.arguments.Count > 0))
+            {
+                output.Append("(");
+                PrintEnumeration(callExpression.arguments);
+                output.Append(")");
+            }
+            else
+            {
+                output.Append("()");
+            }
+        }
+
+        public override void visit(TupleMapAccessExpression tupleMapAccessExpression)
+        {
+            if (tupleMapAccessExpression.child != null)
+                tupleMapAccessExpression.child.Accept(this);
+            output.Append("[");
+            PrintSubElementOrNull(tupleMapAccessExpression.argument);
+            output.Append("]");
+        }
+
+        public override void visit(TupleConstructor tupleConstructor)
+        {
+            output.Append(tupleConstructor.tupleType.tokenText);
+            output.Append("(");
+            PrintEnumeration(tupleConstructor.values);
+            output.Append(")");
+        }
+
+        public override void visit(ListConstructor listConstructor)
+        {
+            output.Append("[");
+            PrintEnumeration(listConstructor.elements);
+            if (listConstructor.hasComprehension)
+            {
+                output.Append("| var ");
+                int i = 0;
+                foreach (var element in listConstructor.comprehensionVariables.symbolList)
+                {
+                    if (i != 0)
+                        output.Append("; ");
+                    i++;
+                    PrintSubElementOrNull(element);
+                }
+                output.AppendLine(" &");
+                PrintSubElementOrNull(listConstructor.comprehension);
+            }
+            output.Append("]");
+        }
+
+        public override void visit(QValConstructor qValConstructor)
+        {
+            output.Append("qval(");
+            PrintSubElementOrNull(qValConstructor.value[0]);
+            if (qValConstructor.value.Length == 2)
+            {
+                output.Append(" .. ");
+                PrintSubElementOrNull(qValConstructor.value[1]);
+            }
+            output.Append(",");
+            output.Append(qValConstructor.valueDeriv.ToString());
+            output.Append(")");
+        }
+
+
+        private bool make_parens = false;
+
+        public override void visit(NondetBlock nondetBlock)
+        {
+            int i = 0;
+            if (make_parens)
+            {
+                output.IncIndent();
+                output.AppendLine("(");
+            }
+            foreach (var smt in nondetBlock.statements)
+            {
+                if (i != 0)
+                {
+                    output.DecIndent();
+                    output.AppendLine("");
+                    output.IncIndent();
+                    output.AppendLine("[] ");
+                }
+                i++;
+                smt.Accept(this);
+            }
+            if (make_parens)
+            {
+                output.DecIndent();
+                output.AppendLine("");
+                output.AppendLine(")");
+            }
+        }
+
+        public override void visit(PrioBlock prioBlock)
+        {
+            int i = 0;
+            if (make_parens)
+            {
+                output.IncIndent();
+                output.AppendLine("(");
+            }
+            foreach (var smt in prioBlock.statements)
+            {
+                if (i != 0)
+                {
+                    output.DecIndent();
+                    output.AppendLine("");
+                    output.IncIndent();
+                    output.AppendLine("// ");
+                }
+                i++;
+                smt.Accept(this);
+            }
+            if (make_parens)
+            {
+                output.DecIndent();
+                output.AppendLine("");
+                output.AppendLine(")");
+            }
+        }
+
+        public override void visit(SeqBlock seqBlock)
+        {
+            int i = 0;
+            bool old_makeparens = make_parens;
+            output.IncIndent();
+            output.AppendLine("(");
+            if (seqBlock.symbols.symbolList.Count > 0)
+            {
+                output.Append("var ");
+                foreach (var id in seqBlock.symbols.symbolList)
+                {
+                    output.Append(id.tokenText);
+                    output.Append(": ");
+                    PrintSubElementOrNull(id);
+                }
+                output.Append(": ");
+            }
+            foreach (var smt in seqBlock.statements)
+            {
+                if (smt == null)
+                    continue;
+                if (i != 0)
+                {
+                    output.DecIndent();
+                    output.AppendLine("");
+                    output.IncIndent();
+                    output.AppendLine("; ");
+                }
+                i++;
+                make_parens = true;
+                smt.Accept(this);
+                make_parens = old_makeparens;
+            }
+            output.DecIndent();
+            output.AppendLine("");
+            output.AppendLine(")");
+        }
+
+        public override void visit(Call call)
+        {
+            call.callExpression.Accept(this);
+        }
+
+        public override void visit(GuardedCommand guardedCommand)
+        {
+            output.Append("requires ");
+            PrintSubElementOrNull(guardedCommand.guard);
+            output.IncIndent();
+            output.AppendLine(" :");
+
+            guardedCommand.body.Accept(this);
+
+            output.DecIndent();
+            output.AppendLine("");
+            output.AppendLine("end");
+        }
+
+        public override void visit(IdentifierExpression identifierExpression)
+        {
+            output.Append(identifierExpression.identifier.tokenText);
+        }
+
+        public override void visit(NondetIdentifierList nondetIdentifierList)
+        {
+            int i = 0;
+            foreach (var smt in nondetIdentifierList.identifiers)
+            {
+                if (i != 0)
+                {
+                    output.DecIndent();
+                    output.AppendLine("");
+                    output.IncIndent();
+                    output.AppendLine("[] ");
+                }
+                i++;
+                smt.Accept(this);
+            }
+        }
+
+        public override void visit(PrioIdentifierList prioIdentifierList)
+        {
+            int i = 0;
+            foreach (var smt in prioIdentifierList.identifiers)
+            {
+                if (i != 0)
+                {
+                    output.DecIndent();
+                    output.AppendLine("");
+                    output.IncIndent();
+                    output.AppendLine("//");
+                }
+                i++;
+                smt.Accept(this);
+            }
+        }
+
+
+        public override void visit(SeqIdentifierList seqIdentifierList)
+        {
+            int i = 0;
+            output.IncIndent();
+            output.AppendLine("(");
+            foreach (var smt in seqIdentifierList.identifiers)
+            {
+                if (i != 0)
+                {
+                    output.AppendLine("; ");
+                }
+                i++;
+                smt.Accept(this);
+            }
+            output.DecIndent();
+            output.AppendLine("");
+            output.AppendLine(")");
+        }
+
+        public override void visit(SkipStatement skipStatement)
+        {
+            output.Append("skip");
+        }
+
+        public override void visit(TernaryOperator ternaryOperator)
+        {
+            if (ternaryOperator.kind == ExpressionKind.conditional)
+            {
+                output.Append("if");
+                PrintSubElementOrNull(ternaryOperator.left);
+                output.IncIndent();
+                output.AppendLine("then");
+                PrintSubElementOrNull(ternaryOperator.mid);
+                output.DecIndent();
+                output.AppendLine("");
+                output.IncIndent();
+                output.AppendLine("else");
+                PrintSubElementOrNull(ternaryOperator.right);
+                output.DecIndent();
+                output.AppendLine("");
+                output.Append("end");
+            }
+            else if (ternaryOperator.kind == ExpressionKind.foldLR ||
+                ternaryOperator.kind == ExpressionKind.foldRL)
+            {
+                PrintSubElementOrNull(ternaryOperator.left);
+                if (ternaryOperator.mid != null)
+                {
+                    output.Append(" :: (");
+                    PrintSubElementOrNull(ternaryOperator.mid);
+                    output.Append(")");
+                }
+                if (ternaryOperator.kind == ExpressionKind.foldLR)
+                    output.Append(" :>: (");
+                else
+                    output.Append(" :<: (");
+                PrintSubElementOrNull(ternaryOperator.right);
+                output.Append(")");
+            }
+            else
+                throw new NotImplementedException();
+        }
+
+        public override void visit(MethodIdentifier methodIdentifier)
+        {
+            if (((FunctionType)methodIdentifier.type).isMiracleSafe ?? false)
+                output.Append("/*BASIC*/ ");
+
+
+            FunctionType atype = (FunctionType)methodIdentifier.type;
+
+            output.Append(methodIdentifier.tokenText);
+            output.Append("(");
+            int j = 0;
+            foreach (var x in methodIdentifier.parameter)
+            {
+                if (j != 0)
+                    output.Append(", ");
+                else
+                    j++;
+                output.Append(x.tokenText);
+                output.Append(": ");
+                PrintSubElementOrNull(x.type);
+            }
+            output.Append(")");
+            if (atype.returnType != null)
+            {
+                output.Append(": ");
+                PrintSubElementOrNull(atype.returnType);
+            }
+            output.AppendLine("");
+
+            output.IncIndent();
+            output.AppendLine("var");
+            int i = 0;
+            foreach (var sym in methodIdentifier.symbolTable.symbolList)
+            {
+                if (i != 0)
+                    output.AppendLine(";");
+                i++;
+                output.Append(sym.tokenText); output.Append(": "); PrintSubElementOrNull(sym.type);
+            }
+            output.DecIndent();
+            output.AppendLine("");
+
+            PrintSubElementOrNull(methodIdentifier.body);
+            output.Append("end");
+        }
+
+        public override void visit(NamedActionIdentifier namedActionIdentifier)
+        {
+            if (((FunctionType)namedActionIdentifier.type).isMiracleSafe ?? false)
+                output.Append("/*BASIC*/ ");
+
+            output.Append(namedActionIdentifier.tokenText);
+            output.Append("(");
+            FunctionType atype = (FunctionType)namedActionIdentifier.type;
+            PrintEnumeration(atype.parameter);
+            output.Append(")");
+            output.AppendLine("");
+
+            output.IncIndent();
+            output.AppendLine("var");
+            int i = 0;
+            foreach (var sym in namedActionIdentifier.symbolTable.symbolList)
+            {
+                if (i != 0)
+                    output.AppendLine(";");
+                i++;
+                output.Append(sym.tokenText); output.Append(": "); PrintSubElementOrNull(sym.type);
+            }
+            output.DecIndent();
+            output.AppendLine("");
+
+            PrintSubElementOrNull(namedActionIdentifier.body);
+            output.Append("end");
+        }
+
+        public override void visit(MapConstructor mapConstructor)
+        {
+            output.Append("{");
+            int i = 0;
+            foreach (var x in mapConstructor.items)
+            {
+                if (i != 0)
+                    output.Append(", ");
+                i++;
+                PrintSubElementOrNull(x.key);
+                output.Append(" -> ");
+                PrintSubElementOrNull(x.value);
+            }
+            output.Append("}");
+        }
+
+        public override void visit(SetConstructor setConstructor)
+        {
+            output.Append("[");
+            PrintEnumeration(setConstructor.items);
+            if (setConstructor.hasComprehension)
+            {
+                output.Append("| var ");
+                int i = 0;
+                foreach (var elem in setConstructor.comprehensionVariables.symbolList)
+                {
+                    if (i != 0)
+                        output.Append("; ");
+                    i++;
+                    PrintSubElementOrNull(elem);
+                }
+                output.AppendLine(" &");
+                PrintSubElementOrNull(setConstructor.comprehension);
+            }
+            output.Append("]");
+        }
+
+        public override void visit(ExpressionVariableIdentifier expressionVariableIdentifier)
+        {
+            output.Append(expressionVariableIdentifier.tokenText); output.Append(": ");
+            PrintSubElementOrNull(expressionVariableIdentifier.type);
+        }
+
+
+        public override void visit(ObjectConstructor objectConstructor)
+        {
+            output.Append("new (");
+            PrintSubElementOrNull(objectConstructor.type);
+            output.Append(")");
+        }
+
+        public override string ToString()
+        {
+            return output.ToString();
+        }
+
+        public OoaPrintVisitor(ParserState aState)
+            : base(aState)
+        {
+            writeTypes = true;
+            output = new OoaCodeEmitter();
+        }
+    }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaPrioritizedCompositionVisitor.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaPrioritizedCompositionVisitor.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaPrioritizedCompositionVisitor.cs	(revision 3)
@@ -0,0 +1,126 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TUG.Mogentes
+{
+    /// <summary>
+    /// removes trivial prioritized compositions.
+    /// </summary>
+    public sealed class OoaRemoveTrivialPrioritizedCompositionVisitor : OoaCompleteAstTraversalVisitor
+    {
+        /// <summary>
+        /// replaces the prioBlock by its child (most likely a parBlock)
+        /// </summary>
+        private IAst ConvertPrioBlock(PrioBlock prioBlock, IAst parent)
+        {
+            if (prioBlock.statements.Count <= 1)
+            {
+                LinkedListNode<Statement> child = prioBlock.statements.First;
+                Block newBlock = (Block)child.Value;
+
+                switch (parent.nodeType)
+                {
+                    case AstNodeTypeEnum.type:
+                        switch (((UlyssesType)parent).kind)
+                        {
+                            case TypeKind.OoActionSystemType:
+                                OoActionSystemType atype = (OoActionSystemType)parent;
+                                Block ablock = atype.doOdBlock;
+                                System.Diagnostics.Debug.Assert(ReferenceEquals(ablock, prioBlock));
+                                atype.SetDoOdBlock(newBlock);
+                                break;
+                            default:
+                                throw new NotImplementedException();
+                        }
+                        break;
+                    case AstNodeTypeEnum.statement:
+                        switch (((Statement)parent).kind)
+                        {
+                            case StatementKind.SeqBlock:
+                                SeqBlock aseqblock = (SeqBlock)parent;
+                                LinkedListNode<Statement> toChange = aseqblock.statements.Find(prioBlock);
+                                toChange.Value = newBlock;
+                                break;
+                            case StatementKind.GuardedCommand:
+                                GuardedCommand gc = (GuardedCommand)parent;
+                                System.Diagnostics.Debug.Assert(ReferenceEquals(gc.body, prioBlock));
+                                gc.SetBody(newBlock);
+                                break;
+                            default:
+                                throw new NotImplementedException();
+                        }
+                        break;
+                    case AstNodeTypeEnum.identifier:
+                        switch (((Identifier)parent).kind)
+                        {
+                            case IdentifierKind.MethodIdentifier:
+                                MethodIdentifier method = (MethodIdentifier)parent;
+                                System.Diagnostics.Debug.Assert(ReferenceEquals(method.body, prioBlock));
+                                method.SetBody(newBlock);
+                                break;
+                            default:
+                                throw new NotImplementedException();
+                        }
+                        break;
+                    default:
+                        throw new NotImplementedException();
+                }
+                return newBlock;
+            }
+            else
+                return prioBlock;
+        }
+
+
+        protected override void VisitAstElement(IAst element, IAst parent)
+        {
+            if ((element.nodeType == AstNodeTypeEnum.statement) &&
+                (((Statement)element).kind == StatementKind.PrioBlock) &&
+                // we're only interested in actionblock and actionbody composition, not in type composition
+                !(parent.nodeType == AstNodeTypeEnum.identifier && ((Identifier)parent).kind == IdentifierKind.List))
+            {
+                IAst newchild = ConvertPrioBlock((PrioBlock)element, parent);
+                base.VisitAstElement(newchild, parent);
+            }
+            else
+                base.VisitAstElement(element, parent);
+        }
+
+
+        public override void visit(MainModule mainModule)
+        {
+            // get rid of any top-level spurious block
+            if (mainModule.systemDescription != null)
+                while (mainModule.systemDescription.identifiers.Count == 1
+                    && mainModule.systemDescription.identifiers.First.Value.kind == IdentifierKind.List)
+                {
+                    mainModule.SetSystemDescription((IdentifierList)mainModule.systemDescription.identifiers.First.Value);
+                }
+            base.visit(mainModule);
+        }
+
+
+        public OoaRemoveTrivialPrioritizedCompositionVisitor(ParserState aState)
+            : base(aState)
+        { }
+    }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaResolveVisitor.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaResolveVisitor.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaResolveVisitor.cs	(revision 3)
@@ -0,0 +1,1927 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TUG.Mogentes
+{
+
+    /// <summary>
+    /// Requires: ReplaceOpaqueVisitor
+    /// 
+    /// After we have an AST without any Opaquetypes, we still need to replace all the
+    /// UnresolvedIdentifierExpressions. We also need to compute the expression types,
+    /// which is also necessary to resolve all the identifiers. So, this visitor
+    /// goes over all expressions and 
+    ///   - resolves all identifiers
+    ///   - calculates resulting types (incl. coercion)
+    /// </summary>
+    public sealed class OoaResolveExpressionsVisitor : OoaCompleteAstTraversalVisitor
+    {
+        // we allow for free variable in expressions. collect them here.
+        private Stack<SymbolTable> m_freeVariables = new Stack<SymbolTable>();
+        private Expression m_entryExpression = null;
+
+        // helpers that replace the old expression in the AST by the new one.
+        private void ReplaceExpression(IAst parent, Expression subElement, Expression newExpression)
+        {
+            switch (parent.nodeType)
+            {
+                case AstNodeTypeEnum.identifier:
+                    ReplaceExpressionInIdentifier((Identifier)parent, subElement, newExpression);
+                    break;
+                case AstNodeTypeEnum.statement:
+                    ReplaceExpressionInStatement((Statement)parent, subElement, newExpression);
+                    break;
+                default:
+                    throw new NotImplementedException();
+            }
+        }
+        private void ReplaceExpressionInIdentifier(Identifier identifier, Expression subElement, Expression newExpression)
+        {
+            switch (identifier.kind)
+            {
+                case IdentifierKind.AttributeIdentifier:
+                    AttributeIdentifier ident = (AttributeIdentifier)identifier;
+                    System.Diagnostics.Debug.Assert(ReferenceEquals(ident.initializer, subElement));
+                    ident.SetInitializer(newExpression);
+                    break;
+                case IdentifierKind.Constant:
+                    ConstantIdentifier aconst = (ConstantIdentifier)identifier;
+                    System.Diagnostics.Debug.Assert(ReferenceEquals(aconst.Value, subElement));
+                    aconst.SetValue(newExpression);
+                    if (newExpression.kind != ExpressionKind.Value)
+                    {
+                        Error(aconst.Value, String.Format("{0} not a constant!", aconst.tokenText));
+                    }
+
+                    break;
+                default:
+                    throw new NotImplementedException();
+            }
+        }
+        private void ReplaceExpressionInStatement(Statement statement, Expression subElement, Expression newExpression)
+        {
+            switch (statement.kind)
+            {
+                case StatementKind.GuardedCommand:
+                    GuardedCommand gc = (GuardedCommand)statement;
+                    System.Diagnostics.Debug.Assert(ReferenceEquals(gc.guard, subElement));
+                    gc.SetGuard(newExpression);
+                    break;
+                case StatementKind.SeqBlock:
+                    SeqBlock sqblock = (SeqBlock)statement;
+                    System.Diagnostics.Debug.Assert(ReferenceEquals(sqblock.filter, subElement));
+                    sqblock.SetFilter(null);
+                    // we convert the filter to a guarded command...
+                    SeqBlock implseq = new SeqBlock(sqblock.line, sqblock.pos);
+                    implseq.SetStatements(sqblock.statements);
+                    GuardedCommand implguard = new GuardedCommand(newExpression, implseq, sqblock.line, sqblock.pos);
+                    sqblock.SetStatements(new LinkedList<Statement>());
+                    sqblock.AddStatement(implguard);
+                    break;
+                case StatementKind.Assignment:
+                    Assignment zw = (Assignment)statement;
+                    bool found = false;
+                    if (ReferenceEquals(zw.nondetExpression, subElement))
+                    {
+                        zw.SetNondetExpression(newExpression);
+                        found = true;
+                    }
+                    else
+                    {
+                        LinkedListNode<Expression> anode = zw.places.First;
+                        while (anode != null)
+                        {
+                            if (ReferenceEquals(anode.Value, subElement))
+                            {
+                                anode.Value = newExpression;
+                                found = true;
+                                break;
+                            }
+                            anode = anode.Next;
+                        }
+
+                        anode = zw.values.First;
+                        while (anode != null)
+                        {
+                            if (ReferenceEquals(anode.Value, subElement))
+                            {
+                                anode.Value = newExpression;
+                                found = true;
+                                break;
+                            }
+                            anode = anode.Next;
+                        }
+                    }
+                    System.Diagnostics.Debug.Assert(found);
+                    break;
+                case StatementKind.MethodCall:
+                    Call call = (Call)statement;
+                    System.Diagnostics.Debug.Assert(ReferenceEquals(call.callExpression, subElement));
+                    call.SetCallExpression(newExpression);
+                    break;
+                default:
+                    throw new NotImplementedException();
+            }
+        }
+
+        // helper that returns null and adds an error message in the parserstate errorlist.
+        private Expression Error(Expression expression, string p)
+        {
+            ParserError error = new ParserError(m_ParserState.filename,
+                expression.line, expression.pos, p);
+            m_ParserState.AddErrorMessage(error);
+            return null;
+        }
+        private Expression Error(int line, int pos, string p)
+        {
+            ParserError error = new ParserError(m_ParserState.filename, line, pos, p);
+            m_ParserState.AddErrorMessage(error);
+            return null;
+        }
+        // helper that adds a warning message to the output
+        private void Warning(Identifier expression, string p)
+        {
+            ParserWarning warning = new ParserWarning(m_ParserState.filename,
+                expression.line, expression.column, p);
+            m_ParserState.AddWarningMessage(warning);
+        }
+        private void Warning(Expression expression, string p)
+        {
+            ParserWarning warning = new ParserWarning(m_ParserState.filename,
+                expression.line, expression.pos, p);
+            m_ParserState.AddWarningMessage(warning);
+        }
+        private void Info(Expression expression, String p)
+        {
+            ParserMessage msg = new ParserMessage(m_ParserState.filename,
+            expression.line, expression.pos, p);
+            m_ParserState.AddMessage(msg);
+        }
+
+        private List<TupleConstructor> m_matcherList = new List<TupleConstructor>();
+
+        /// 
+        ///   Resolve Expressions
+        /// 
+
+        private Expression ResolveExpression(TernaryOperator expression)
+        {
+            if (expression.kind == ExpressionKind.conditional)
+            {
+
+                Expression left = ResolveExpression(expression.left);
+                Expression mid = ResolveExpression(expression.mid);
+                Expression right = ResolveExpression(expression.right);
+
+                if (left == null
+                    || mid == null
+                    || right == null)
+                    return null;
+
+                if (left.type == null ||
+                    left.type.kind != TypeKind.BoolType)
+                    return Error(expression, "Conditional: Condition not a bool");
+
+                if (mid.type == null
+                    || right.type == null)
+                    return Error(expression, "Conditional: Then or Else branch has void-type");
+
+                UlyssesType acover = UlyssesType.CoverType(mid.type, right.type);
+
+                if (acover == null)
+                    return Error(expression, String.Format("Conditional: Then and Else branch must be of same type. ({0} <> {1})", mid.type.ToString(), right.type.ToString()));
+
+                if (!UlyssesType.TypeEqual(acover, mid.type))
+                {
+                    mid = new UnaryOperator(ExpressionKind.Cast, mid, mid.line, mid.pos);
+                    mid.SetType(acover);
+                }
+                if (!UlyssesType.TypeEqual(acover, right.type))
+                {
+                    right = new UnaryOperator(ExpressionKind.Cast, right, right.line, right.pos);
+                    right.SetType(acover);
+                }
+
+
+                expression.SetLeftChild(left);
+                expression.SetMidChild(mid);
+                expression.SetRightChild(right);
+                expression.SetType(mid.type);
+                return expression;
+            }
+            else if (expression.kind == ExpressionKind.foldLR || expression.kind == ExpressionKind.foldRL)
+            {
+                CallExpression leftcall =
+                    expression.left.kind != ExpressionKind.Call ?
+                    new CallExpression(expression.left, new List<Expression>(), expression.line,
+                        expression.pos, expression.definingScope)
+                    : (CallExpression)expression.left;
+
+                leftcall = (CallExpression)ResolveExpression(leftcall, true);
+                if (leftcall == null)
+                    return null;
+
+                Expression afun = ResolveExpression(leftcall.child);
+                leftcall.SetChild(afun);
+                if (afun == null || afun.type == null || afun.type.kind != TypeKind.FunctionType)
+                    return Error(expression, "Fold/Map operation needs a method or named action as LHS");
+
+                FunctionType funType = (FunctionType)afun.type;
+                if (funType.returnType == null && expression.mid != null)
+                    return Error(expression, "Fold operation needs a method with matching return type");
+                if (funType.returnType != null && expression.mid == null)
+                    Warning(expression, "Map operation will discard result of function");
+
+                bool isMap = expression.mid == null;
+                Expression mid = expression.mid;
+                if (!isMap)
+                {
+                    mid = ResolveExpression(mid);
+                    if ((funType.parameter.Count - leftcall.arguments.Count) != 2)
+                        return Error(expression, "Function used in fold operation needs 2 not-instantiated parameters");
+                }
+                else if ((funType.parameter.Count - leftcall.arguments.Count) != 1)
+                    return Error(expression, "Function used in map operation needs one not-instantiated parameter");
+
+                Expression right = ResolveExpression(expression.right);
+                if (right == null || right.type == null || right.type.kind != TypeKind.ListType)
+                    return Error(expression, "Fold/Map operation needs list as RHS");
+
+                if (!isMap)
+                {
+                    UlyssesType initCover = UlyssesType.CoverType(funType.parameter.Last.Previous.Value, mid.type);
+                    if (initCover == null)
+                        return Error(expression, "Next to last parameter does not match initializer type in map operation.");
+                    if (!UlyssesType.TypeEqual(mid.type, initCover))
+                        mid = new UnaryOperator(ExpressionKind.Cast, mid, mid.line, mid.pos);
+                    mid.SetType(initCover);
+
+
+                    //List<Expression> args = new List<Expression> ();
+                    leftcall.arguments.Add(new IdentifierExpression(new ParameterIdentifier("_result", initCover, null), 0, 0));
+                    leftcall.arguments.Add(new IdentifierExpression(new ParameterIdentifier("_elem", funType.parameter.Last.Value, null), 0, 0));
+
+                    //leftcall.SetArguments(args);
+
+                }
+                // UlyssesType listCover = UlyssesType.CoverType(funType.parameter.Last.Value, ((ListType)right.type).innerType);
+                // if (listCover == null)
+                if (!UlyssesType.TypeEqual(funType.parameter.Last.Value, ((ListType)right.type).innerType))
+                    return Error(expression, "Last paramter does not match inner-type of list in fold/map operation");
+
+
+                expression.SetLeftChild(leftcall);
+                expression.SetMidChild(mid);
+                expression.SetRightChild(right);
+                if (!isMap)
+                    expression.SetType(funType.returnType);
+                else
+                    expression.SetType(new NullType());
+                return expression;
+            }
+            else
+                throw new ArgumentException();
+        }
+        private Expression ResolveExpression(ForallQuantifier expression)
+        {
+            Expression child = ResolveExpression(expression.child);
+            if (child == null)
+                return null;
+
+            expression.SetType(new BoolType(null));
+            expression.SetChild(child);
+            return expression;
+        }
+        private Expression ResolveExpression(ExistsQuantifier expression)
+        {
+            Expression child = ResolveExpression(expression.child);
+            if (child == null)
+                return null;
+
+            expression.SetType(new BoolType(null));
+            expression.SetChild(child);
+            return expression;
+        }
+        private Expression ResolveExpression(ListConstructor expression)
+        {
+            UlyssesType type = null;
+            ListType restype = null;
+            Expression comprehension = null;
+            if (expression.comprehension != null)
+            {
+                comprehension = ResolveExpressionNewScope(expression.comprehension);
+
+                if (comprehension == null)
+                    return null;
+
+                if (comprehension.type == null)
+                    return Error(expression, "List comprehension has void expression");
+
+                if (comprehension.type.kind != TypeKind.BoolType)
+                    return Error(expression, "List comprehension has to be bool-expression");
+
+                expression.SetComprehension(comprehension);
+
+                if (expression.elements.Count != 1)
+                    return Error(expression, "List comprehension expects one initializer expression");
+            }
+
+            List<Expression> newitems = new List<Expression>();
+
+            if (expression.elements.Count == 0 || expression.elements[0] == null || (
+                expression.elements[0].kind == ExpressionKind.Value &&
+                expression.elements[0] is ValueExpression<object> &&
+                ((ValueExpression<object>)expression.elements[0]).value == null))
+            {
+                // empty list
+                type = new NullType();
+            }
+            else
+            {
+                List<Expression> tmpitems = new List<Expression>();
+                foreach (var item in expression.elements)
+                {
+                    Expression element = ResolveExpression(item);
+                    if (element == null)
+                        return null;
+                    if (element.type == null)
+                        return Error(expression, "Void expression in list initializer");
+
+                    if (element.kind == ExpressionKind.Value &&
+                        element is ValueExpression<object> &&
+                        ((ValueExpression<object>)element).value == null)
+                        return Error(expression, "Not-In-List (nil) values not allowed in a list");
+
+                    // calculate the type we're constructing
+                    if (type == null)
+                        type = element.type;
+
+                    type = UlyssesType.CoverType(type, element.type);
+                    if (type == null)
+                        return Error(expression, "List constructor needs matching types");
+
+                    tmpitems.Add(element);
+                }
+
+                // now we have the resulting type - we still need to insert casts that might be necessary
+                foreach (var item in tmpitems)
+                {
+                    if (!UlyssesType.TypeEqual(item.type, type))
+                    {
+                        Expression cast = new UnaryOperator(ExpressionKind.Cast, item, item.line, item.pos);
+                        cast.SetType(type);
+                        newitems.Add(cast);
+                    }
+                    else
+                        newitems.Add(item);
+                }
+
+            }
+
+            expression.SetElements(newitems);
+            if (comprehension == null)
+                restype = new ListType(type, newitems.Count, null);
+            else
+                restype = new ListType(type, -1, null); // we do not know anything about the bound
+
+            expression.SetType(restype);
+            return expression;
+        }
+        private Expression ResolveExpression(SetConstructor expression)
+        {
+            UlyssesType type = null;
+            ListType restype = null;
+            Expression comprehension = null;
+            if (expression.comprehension != null)
+            {
+                comprehension = ResolveExpressionNewScope(expression.comprehension);
+
+                if (comprehension == null)
+                    return null;
+
+                if (comprehension.type == null)
+                    return Error(expression, "Set comprehension has void expression");
+
+                if (comprehension.type.kind != TypeKind.BoolType)
+                    return Error(expression, "Set comprehension has to be bool-expression");
+
+                expression.SetComprehension(comprehension);
+
+                if (expression.items.Count != 1)
+                    return Error(expression, "Set comprehension expects one initializer expression");
+            }
+
+            List<Expression> newitems = new List<Expression>();
+            foreach (var item in expression.items)
+            {
+                Expression element = ResolveExpression(item);
+                if (element == null)
+                    return null;
+
+                if (element.type == null)
+                    return Error(expression, "Void expression in set initializer");
+
+                if (type == null)
+                    type = element.type;
+                type = UlyssesType.CoverType(type, element.type);
+                if (type == null)
+                    return Error(expression, "Set initializer needs matching types");
+
+                newitems.Add(element);
+            }
+            expression.SetItems(newitems);
+            restype = new ListType(type, newitems.Count, null);
+
+            expression.SetType(restype);
+            return expression;
+        }
+        private Expression ResolveExpression(MapConstructor expression)
+        {
+            UlyssesType domain = null;
+            UlyssesType range = null;
+            List<MapConstructor.MapItem> newitems = new List<MapConstructor.MapItem>();
+
+            foreach (MapConstructor.MapItem item in expression.items)
+            {
+                Expression domexpr = ResolveExpression(item.key);
+                if (domexpr == null)
+                    return null;
+
+                if (domexpr.type == null)
+                    return Error(expression, "Domain initializing expression void");
+
+                if (domain == null)
+                    domain = domexpr.type;
+
+                Expression rangeexpr = ResolveExpression(item.value);
+                if (rangeexpr == null)
+                    return null;
+
+                if (rangeexpr.type == null)
+                    return Error(expression, "Range initializing expression void");
+
+                if (range == null)
+                    range = rangeexpr.type;
+
+                domain = UlyssesType.CoverType(domain, domexpr.type);
+                range = UlyssesType.CoverType(range, rangeexpr.type);
+                if (domain == null)
+                    return Error(expression, "Types of domain expressions do not match");
+
+                if (range == null)
+                    return Error(expression, "Types of range expressions do not match");
+
+                newitems.Add(new MapConstructor.MapItem(domexpr, rangeexpr));
+            }
+
+            expression.SetItems(newitems);
+            MapType resulttype = new MapType(domain, range, newitems.Count, null);
+            expression.SetType(resulttype);
+            return expression;
+        }
+        private Expression ResolveExpression(TupleConstructor expression)
+        {
+            TupleType typeToConstruct = (TupleType)expression.tupleType.type;
+
+            if (expression.values.Count != typeToConstruct.innerTypes.Count)
+                return Error(expression, String.Format("Tuple constructor has wrong arity. ({0} <> {1})", typeToConstruct.innerTypes.Count, expression.values.Count));
+
+            //TupleType resulttype = new TupleType(null);
+            List<Expression> newvalexprs = new List<Expression>();
+
+            LinkedListNode<UlyssesType> innerTargetType = typeToConstruct.innerTypes.First;
+            int freeVarCount = 0;
+            foreach (var initexpr in expression.values)
+            {
+                Expression newval = ResolveExpression(initexpr);
+                if (newval == null)
+                    return null;
+                if (newval.type == null)
+                    return Error(expression, "Element has void type");
+
+                if (newval.type.kind == TypeKind.Any)
+                {
+                    // free var - so set type.
+                    AnyType freevar = (AnyType)newval.type;
+                    freevar.VariableIdentifier.SetType(innerTargetType.Value);
+                    freevar.VariableIdentifier.SetInitialized(true);
+                    freeVarCount++;
+                }
+                else
+                {
+                    UlyssesType acover = UlyssesType.CoverType(innerTargetType.Value, newval.type);
+                    if (acover == null || !UlyssesType.TypeEqualByKind(innerTargetType.Value, acover))
+                        return Error(expression, String.Format("Element in tuple constructor has non-matching type ({0} <> {1})", innerTargetType.Value.ToString(), newval.type.ToString()));
+
+                    if (!UlyssesType.TypeEqual(acover, newval.type))
+                    {
+                        newval = new UnaryOperator(ExpressionKind.Cast, newval, newval.line, newval.pos);
+                        newval.SetType(acover);
+                    }
+                    if (UlyssesType.FirstTypeLessRange(innerTargetType.Value, acover))
+                        Warning(expression, String.Format("Tuple constructor may over/underflow: {0} := {1}", innerTargetType.Value.ToString(), acover.ToString()));
+                }
+
+
+                newvalexprs.Add(newval);
+                //resulttype.AddType(newval.type);
+                innerTargetType = innerTargetType.Next;
+            }
+
+            if (freeVarCount > 0)
+            {
+                if (freeVarCount != expression.values.Count)
+                    return Error(expression, String.Format("Tuple constructor must have 0 or #elems ({0}) free variables", expression.values.Count));
+                else
+                {
+                    expression.SetIsMatcher(true); // mark this tuple constructor as matcher, since this is the only thing it does..
+                    m_matcherList.Add(expression); // matcher has to be bound by one equality
+                }
+            }
+
+            expression.SetTupleValues(newvalexprs);
+            //expression.SetType(resulttype);
+            expression.SetType(typeToConstruct); // the constructor always will create the correct type!
+            return expression;
+        }
+
+        private Expression ResolveExpression(QValConstructor expression)
+        {
+            Expression basevalue = null;
+            Expression rangevalue = null;
+
+            basevalue = ResolveExpression(expression.value[0]);
+            if (basevalue == null || basevalue.kind != ExpressionKind.Access
+                || basevalue.type == null || basevalue.type.kind != TypeKind.QrType)
+                return Error(expression, "Landmark expected.");
+            expression.SetType(basevalue.type);
+            expression.SetValue(basevalue);
+
+            if (expression.value.Length == 2)
+            {
+                rangevalue = ResolveExpression(expression.value[1]);
+                if (rangevalue == null || rangevalue.kind != ExpressionKind.Access
+                    || rangevalue.type == null || rangevalue.type.kind != TypeKind.QrType)
+                    return Error(expression, "Landmark expected.");
+                if (!UlyssesType.TypeEqual(basevalue.type, rangevalue.type))
+                    return Error(expression, String.Format("Quantity spaces do not match: {0} <> {1}",
+                        basevalue.type.ToString(),
+                        rangevalue.type.ToString()));
+                expression.AddRange(rangevalue);
+            }
+            return expression;
+        }
+
+        private Expression ResolveExpression(IdentifierExpression expression)
+        {
+            // nothing to do here, since we do not have any consts that may be
+            // folded
+            if (expression.identifier.kind == IdentifierKind.MethodIdentifier
+                || expression.identifier.kind == IdentifierKind.NamedActionIdentifier)
+                m_entryExpression.callTargets.Add((FunctionIdentifier)expression.identifier);
+
+            return expression;
+        }
+        private Expression ResolveExpression(UnresolvedIdentifierExpression expression)
+        {
+            Identifier anid;
+            //Identifier self = m_ParserState.Lookup("self");
+
+            if (m_freeVariables.Peek().Defined(expression.tokenText))
+                anid = m_freeVariables.Peek().Get(expression.tokenText);
+            else
+                anid = m_ParserState.Lookup(expression.tokenText, expression.scope);
+
+            if (anid != null)
+            {
+                switch (anid.kind)
+                {
+                    case IdentifierKind.TypeIdentifier:
+                        return new TypeExpression(anid.type, expression.line, expression.pos);
+
+                    case IdentifierKind.MethodIdentifier:
+
+                        m_entryExpression.callTargets.Add((FunctionIdentifier)anid);
+                        SelfTypeIdentifier selfid = (SelfTypeIdentifier)m_ParserState.Lookup("self", expression.scope);
+                        if ((selfid != null) && ((OoActionSystemType)(selfid).type).symbols.Defined(anid))
+                        {
+                            // if it's a self access, add a self identifier (needed by cadp backend, e.g.)
+                            // self.<method> is handled in a separate method and does not call us here!! (hence this code is working)
+                            IdentifierExpression aself = new IdentifierExpression(selfid, expression.line, expression.pos);
+                            aself.setIsSelf(true);
+                            AccessExpression localaccess = new AccessExpression(aself, new IdentifierExpression(anid, expression.line, expression.pos),
+                                expression.line, expression.pos);
+                            ResolveExpression(localaccess);
+                            return localaccess;
+                        }
+                        else
+                        {
+                            return new IdentifierExpression(anid, expression.line, expression.pos);
+                        }
+
+                    case IdentifierKind.NamedActionIdentifier:
+                        m_entryExpression.callTargets.Add((FunctionIdentifier)anid);
+                        return new IdentifierExpression(anid, expression.line, expression.pos);
+
+                    case IdentifierKind.Constant:
+                        if (((ConstantIdentifier)anid).Value != null)
+                            return ((ConstantIdentifier)anid).Value.Clone();
+                        else
+                            return null;
+
+                    default:
+                        return new IdentifierExpression(anid, expression.line, expression.pos);
+                }
+            }
+            else
+            {
+                ExpressionVariableIdentifier freeVar =
+                    new ExpressionVariableIdentifier(expression.tokenText, expression.line, expression.pos);
+                freeVar.SetType(new AnyType(freeVar));
+                m_freeVariables.Peek().AddIdentifier(freeVar);
+
+                // add a warning about free variables - do not change text without changing the text in ooaTypeCheckVisitor..
+                Warning(freeVar, String.Format("Free variable in expression: '{0}'.", freeVar.tokenText));
+
+                return new IdentifierExpression(freeVar, expression.line, expression.pos);
+            }
+        }
+        private Expression ResolveExpression(TupleMapAccessExpression expression)
+        {
+            Expression child = ResolveExpression(expression.child);
+            if (child == null)
+                return null;
+
+            Expression arg = ResolveExpression(expression.argument);
+            if (arg == null)
+                return null;
+
+
+            System.Diagnostics.Debug.Assert(child.type != null);
+
+            if ((child.kind != ExpressionKind.Type) && (child.type.kind == TypeKind.TupleType))
+            {
+                if ((arg.kind != ExpressionKind.Value)
+                    || (((LeafExpression)arg).valueType != LeafTypeEnum.integer))
+                {
+                    return Error(expression, "Argument to tuple access must be constant integer value!");
+                }
+                TupleType aTuple = (TupleType)child.type;
+                ValueExpression<int> aval = (ValueExpression<int>)arg;
+                if ((aval.value < 0) || (aval.value >= aTuple.innerTypes.Count))
+                {
+                    return Error(expression, "Argument to tuple access has to be in range 0..#elems-1");
+                }
+                LinkedListNode<UlyssesType> anode = aTuple.innerTypes.First;
+                int target = aval.value;
+                while (target > 0)
+                {
+                    target--;
+                    anode = anode.Next;
+                }
+                expression.SetType(anode.Value);
+            }
+            else if ((child.kind != ExpressionKind.Type) && (child.type.kind == TypeKind.MapType))
+            {
+                MapType amap = (MapType)child.type;
+                expression.SetType(amap.toType);
+            }
+            else if ((child.kind != ExpressionKind.Type) && (child.type.kind == TypeKind.ListType))
+            {
+                // we allow element access of lists via list[i]
+                ListType alist = (ListType)child.type;
+                expression.SetType(alist.innerType);
+            }
+            else
+            {
+                return Error(expression, "Not a list, tuple, or map instance");
+            }
+            expression.SetArgument(arg);
+            expression.SetChild(child);
+            return expression;
+        }
+        private Expression ResolveExpression(CallExpression expression)
+        {
+            return ResolveExpression(expression, false);
+        }
+        private Expression ResolveExpression(CallExpression expression, bool allowFewerParameters)
+        {
+            // calc type of child
+            Expression child = ResolveExpression(expression.child);
+            if (child == null)
+                return null;
+
+            System.Diagnostics.Debug.Assert(child.type != null);
+
+            expression.SetChild(child);
+
+            if (child.type.kind != TypeKind.FunctionType)
+            {
+                return Error(expression, "No function to call!");
+            }
+
+
+            FunctionType funtype = (FunctionType)child.type;
+
+            // check whether call of named action is allowed
+            if (funtype.functionType != FunctionTypeEnum.Method)
+            {
+                // see if call is allowed: must not be called from within a named action
+                IScope callingScope = expression.scope;
+                while (callingScope != null)
+                {
+                    if (callingScope is NamedActionIdentifier || callingScope is MethodIdentifier)
+                        return Error(expression, "Call of named Action only allowed in do-od block!");
+                    callingScope = callingScope.GetParentScope();
+                }
+            }
+
+            // check arguments
+            int argsSpec = funtype.parameter.Count;
+            int argsHave = expression.arguments.Count;
+            if (argsHave < argsSpec && !allowFewerParameters)
+            {
+                return Error(expression, "Too few parameters in function call");
+            }
+            if (argsHave > argsSpec)
+            {
+                return Error(expression, "Too much parameters in function call");
+            }
+
+            List<Expression> newargs = new List<Expression>();
+            LinkedListNode<UlyssesType> demandedArgType = funtype.parameter.First;
+            foreach (var arg in expression.arguments)
+            {
+                Expression newarg = ResolveExpression(arg);
+                if (newarg == null)
+                    return null;
+
+                if (newarg.GetUninitializedFreeVariables().Count > 0)
+                    Error(arg, String.Format("Undefined variable '{0}'", newarg.GetUninitializedFreeVariables()[0].tokenText));
+
+                Expression constantvalue = newarg.kind == ExpressionKind.Value ? newarg : null;
+
+                UlyssesType acover = UlyssesType.CoverType(newarg.type, demandedArgType.Value);
+                if (acover == null || !UlyssesType.TypeEqualByKind(demandedArgType.Value, acover))
+                    return Error(arg, String.Format("Argument type does not match; expected: {0} delivered: {1}",
+                        demandedArgType.Value.ToString(), newarg.type.ToString()));
+
+                newarg = UnaryOperator.TryCoerceUp(newarg, acover);
+
+                if (UlyssesType.FirstTypeLessRange(demandedArgType.Value, acover))
+                {
+                    if (constantvalue == null)
+                    {
+                        Warning(arg, String.Format("Call parameter may over/underflow: {0} := {1}", demandedArgType.Value.ToString(), acover.ToString()));
+                        UnaryOperator cast = new UnaryOperator(ExpressionKind.Cast, newarg, newarg.line, newarg.pos);
+                        cast.SetType(demandedArgType.Value);
+                        newarg = cast;
+                    }
+                    else
+                    {
+                        Error(arg, String.Format("Call parameter out of range ({0}  := {1})", demandedArgType.Value.ToString(), constantvalue.ToString()));
+                    }
+                }
+
+                demandedArgType = demandedArgType.Next;
+                newargs.Add(newarg);
+            }
+            expression.SetArguments(newargs);
+
+            if (funtype.returnType != null)
+                expression.SetType(funtype.returnType);
+            return expression;
+        }
+        private Expression ResolveExpression(AccessExpression expression)
+        {
+            Expression lhs = ResolveExpression(expression.left);
+            if (lhs == null)
+                return null;
+            if (!(expression.right is UnresolvedIdentifierExpression))
+            {
+                expression.SetRightChild(ResolveExpression(expression.right));
+                expression.SetType(expression.right.type);
+                return expression;
+            }
+
+            bool selfAccess = (lhs.kind == ExpressionKind.Identifier) && ((IdentifierExpression)lhs).isSelf;
+            bool staticAccess = lhs.kind == ExpressionKind.Type;
+            UnresolvedIdentifierExpression access = (UnresolvedIdentifierExpression)expression.right;
+            // atype could be null...
+            UlyssesType atype = lhs.type;
+            if ((lhs.kind == ExpressionKind.Call) && (atype == null))
+            {
+                return Error(access, "Can not access return type of void-function");
+            }
+            else if (atype == null)
+            {
+                return Error(access, "Can not access member of a void type");
+            }
+
+            // if we did not apply a call expression to a function
+            if (atype.kind == TypeKind.FunctionType)
+            {
+                // we can access the return val...
+                FunctionType fun = (FunctionType)atype;
+
+                // check arity
+                if (fun.parameter.Count > 0)
+                    return Error(access, "Implicit function call not possible: Too few parameters.");
+
+                // check return type
+                if (fun.returnType == null)
+                    return Error(access, "Can not access return type of void-function!");
+
+                // call ok
+                atype = fun.returnType;
+                // but add callExpression
+                lhs = new CallExpression(lhs, null, lhs.line, lhs.pos, null); // we do not know the scope
+                lhs.SetType(atype);
+            }
+
+            // update left child
+            expression.SetLeftChild(lhs);
+
+
+            switch (atype.kind)
+            {
+                case TypeKind.OoActionSystemType:
+                    Identifier anid = ((OoActionSystemType)atype).ResolveIdentifier(access.tokenText);
+                    if (anid != null)
+                    {
+                        if (anid.kind == IdentifierKind.MethodIdentifier && !m_entryExpression.callTargets.Contains((FunctionIdentifier)anid))
+                            m_entryExpression.callTargets.Add((FunctionIdentifier)anid);
+
+                        if (staticAccess)
+                        {
+                            if ((anid.kind == IdentifierKind.AttributeIdentifier) &&
+                                (((AttributeIdentifier)anid).isStatic))
+                            {
+                                IdentifierExpression newrhs = new IdentifierExpression(anid, access.line, access.pos);
+                                expression.SetRightChild(newrhs);
+                            }
+                            else
+                                return Error(access, "Can not access non-static member of an action system");
+                        }
+                        else
+                        {
+                            if (anid.kind != IdentifierKind.MethodIdentifier && !selfAccess)
+                                return Error(access, "Can only access methods of action system objects");
+                            else
+                            {
+                                IdentifierExpression newrhs = new IdentifierExpression(anid, access.line, access.pos);
+                                expression.SetRightChild(newrhs);
+                            }
+                        }
+                    }
+                    else
+                        return Error(access, String.Format("{0} no member of {1}",
+                                access.tokenText, ((OoActionSystemType)atype).identifier.tokenText));
+                    break;
+                case TypeKind.EnumeratedType:
+                    EnumType anEnum = (EnumType)atype;
+                    if (!staticAccess)
+                    {
+                        return Error(access, "Enum values can only be accessed statically.");
+                    }
+                    if (anEnum.symbolTable.Defined(access.tokenText))
+                    {
+                        Identifier enumid = anEnum.symbolTable.Get(access.tokenText);
+                        IdentifierExpression newrhs = new IdentifierExpression(enumid, access.line, access.pos);
+                        expression.SetRightChild(newrhs);
+                    }
+                    else
+                        return Error(access, String.Format("{0} not contained in enum {1}",
+                                access.tokenText, anEnum.identifier.tokenText));
+                    break;
+                case TypeKind.QrType:
+                    QrType aQualitativeType = (QrType)atype;
+                    if (!staticAccess)
+                    {
+                        return Error(access, String.Format("QSpace values can only be accessed statically."));
+                    }
+                    if (aQualitativeType.symbolTable.Defined(access.tokenText))
+                    {
+                        Identifier landmark = aQualitativeType.symbolTable.Get(access.tokenText);
+                        IdentifierExpression newrhs = new IdentifierExpression(landmark, access.line, access.pos);
+                        expression.SetRightChild(newrhs);
+                    }
+                    else
+                        return Error(access, String.Format("{0} not contained in qspace {1}",
+                                 access.tokenText, aQualitativeType.identifier.tokenText));
+                    break;
+                default:
+                    /*error, we can not access an element with '.' in any other type*/
+                    return Error(expression, "Expected: System, Enum, Func, or QR type");
+            }
+
+            expression.SetType(expression.right.type);
+            return expression;
+        }
+        private Expression ResolveExpression(UnaryOperator expression)
+        {
+            Expression child = ResolveExpression(expression.child);
+            // if there was some error, then exit
+            if (child == null)
+                return null;
+
+            if (child.type == null)
+                return Error(expression, "Can not apply unary operator to void-expression");
+
+
+            switch (expression.kind)
+            {
+                case ExpressionKind.Primed:
+                    expression.SetType(child.type);
+                    break;
+
+                /*map unary*/
+                case ExpressionKind.dom:           // map A to B -> list of A
+                    if (child.type.kind != TypeKind.MapType)
+                        return Error(expression, "Domain operator only applicable to map types.");
+                    MapType amap = (MapType)child.type;
+                    ListType list = new ListType(amap.fromType, amap.maxNumberOfElements, null);
+                    expression.SetType(list);
+                    break;
+                case ExpressionKind.range:         // map A to B -> list of B
+                    if (child.type.kind != TypeKind.MapType)
+                        return Error(expression, "Range operator only applicable to map types.");
+                    amap = (MapType)child.type;
+                    list = new ListType(amap.toType, amap.maxNumberOfElements, null);
+                    expression.SetType(list);
+                    break;
+                case ExpressionKind.merge:         // list of map A to B -> map A to B
+                    if ((child.type.kind == TypeKind.ListType) &&
+                        (((ListType)child.type).innerType.kind == TypeKind.MapType))
+                    {
+                        expression.SetType(((ListType)child.type).innerType);
+                        break;
+                    }
+                    else
+                        return Error(expression, "Merge operator only applicable to a list of maps");
+                /*set/list unary*/
+                case ExpressionKind.card:       // list of A -> int (does not respect dupes, i.e. dupes do not count)
+                    if (child.type.kind != TypeKind.ListType)
+                        return Error(expression, "Cardinality operator only applicable to list types.");
+                    expression.SetType(new IntType(0, ((ListType)child.type).maxNumberOfElements, null));
+                    break;
+                case ExpressionKind.dconc:      // list of list of A -> list of A
+                    if ((child.type.kind == TypeKind.ListType)
+                        && (((ListType)child.type).innerType.kind == TypeKind.ListType))
+                    {
+                        list = (ListType)child.type;
+                        ListType innerlist = (ListType)list.innerType;
+                        int maxnumber = innerlist.maxNumberOfElements * list.maxNumberOfElements;
+                        expression.SetType(new ListType(innerlist.innerType, maxnumber, null));
+                        break;
+                    }
+                    else
+                        return Error(expression, "Distributed Concatenation operator only applicable to list of lists");
+                case ExpressionKind.dinter:     // list of list of A -> list of A (intersection, does not respect dupes)
+                    if ((child.type.kind == TypeKind.ListType)
+                        && (((ListType)child.type).innerType.kind == TypeKind.ListType))
+                    {
+                        list = (ListType)child.type;
+                        ListType innerlist = (ListType)list.innerType;
+                        int maxnumber = innerlist.maxNumberOfElements;
+                        expression.SetType(new ListType(innerlist.innerType, maxnumber, null));
+                        break;
+                    }
+                    else
+                        return Error(expression, "Distributed Intersection operator only applicable to list of lists");
+                case ExpressionKind.dunion:     // list of list of A -> list of A (union, does not respect dupes)
+                    if ((child.type.kind == TypeKind.ListType)
+                        && (((ListType)child.type).innerType.kind == TypeKind.ListType))
+                    {
+                        list = (ListType)child.type;
+                        ListType innerlist = (ListType)list.innerType;
+                        // better upper limit?!
+                        int maxnumber = innerlist.maxNumberOfElements * list.maxNumberOfElements;
+                        expression.SetType(new ListType(innerlist.innerType, maxnumber, null));
+                        break;
+                    }
+                    else
+                        return Error(expression, "Distributed Union operator only applicable to list of lists");
+                case ExpressionKind.elems:      // list of A -> list of A (does not respect dupes)
+                    if (child.type.kind != TypeKind.ListType)
+                        return Error(expression, "Element operator only applicable to list");
+                    expression.SetType(child.type);
+                    break;
+                case ExpressionKind.head:       // list of A -> A
+                    if (child.type.kind != TypeKind.ListType)
+                        return Error(expression, "Head operator only applicable to list");
+                    expression.SetType(((ListType)child.type).innerType);
+                    break;
+                case ExpressionKind.inds:       // list of A -> list of int
+                    if (child.type.kind != TypeKind.ListType)
+                        return Error(expression, "Indices operator only applicable to list");
+                    list = (ListType)child.type;
+                    IntType inner = new IntType(0, list.maxNumberOfElements, null);
+                    expression.SetType(new ListType(inner, list.maxNumberOfElements, null));
+                    break;
+                case ExpressionKind.len:        // list of A -> int (dupes count)
+                    if (child.type.kind != TypeKind.ListType)
+                        return Error(expression, "Length operator only applicable to list");
+                    list = (ListType)child.type;
+                    expression.SetType(new IntType(0, list.maxNumberOfElements, null));
+                    break;
+                case ExpressionKind.tail:       // list of A -> list of A
+                    if (child.type.kind != TypeKind.ListType)
+                        return Error(expression, "Tail operator only applicable to list");
+                    list = (ListType)child.type;
+                    if (list.maxNumberOfElements == 0)
+                        return Error(expression, "Tail operator only applicable to list of length > 0");
+                    int newmaxelems = list.maxNumberOfElements - 1;
+                    if (newmaxelems == 0)
+                        Warning(expression, "Tail operator returns empty list.");
+                    // set the return type null when list is empty?
+                    expression.SetType(new ListType(list.innerType, newmaxelems, null));
+                    break;
+                /*unary numberic*/
+                case ExpressionKind.unminus:
+                    if (!child.type.IsNumeric())
+                        return Error(expression, "Unary minus only applicable to numeric types");
+                    expression.SetType(Expression.ArithmeticCover(child.type, null, expression.kind));
+                    break;
+                case ExpressionKind.unplus:
+                    if (!child.type.IsNumeric())
+                        return Error(expression, "Unary plus only applicable to numeric types");
+                    expression.SetType(child.type);
+                    break;
+                case ExpressionKind.abs:
+                    if (!child.type.IsNumeric())
+                        return Error(expression, "Abs only applicable to numeric types");
+                    expression.SetType(child.type);
+                    break;
+                case ExpressionKind.not:
+                    if (/*!IsNumeric(child.type) && */
+                        (child.type.kind != TypeKind.BoolType))
+                        return Error(expression, "Not only applicable to bool types");
+                    expression.SetType(child.type);
+                    break;
+                /*unary quantors*/
+                case ExpressionKind.forall:
+                    expression.SetType(new BoolType(null));
+                    break;
+                case ExpressionKind.exists:
+                    expression.SetType(new BoolType(null));
+                    break;
+                default:
+                    throw new NotImplementedException();
+            }
+
+            expression.SetChild(child);
+            return expression;
+        }
+        private Expression ResolveExpression(BinaryOperator expression)
+        {
+            Expression lhs = ResolveExpression(expression.left);
+            Expression rhs = ResolveExpression(expression.right);
+
+
+            // if there was some error, then exit
+            if ((lhs == null) || (rhs == null))
+                return null;
+
+            UlyssesType lt = lhs.type;
+            UlyssesType rt = rhs.type;
+
+            if ((lt == null) || (rt == null))
+                return Error(expression, "Binary operator not applicable to void-type subexpression.");
+
+
+            switch (expression.kind)
+            {
+                /*map operators*/
+                case ExpressionKind.domresby:   // list of A * map A to B -> map A to B
+                case ExpressionKind.domresto:   // list of A * map A to B -> map A to B
+                    if (lt.kind != TypeKind.ListType)
+                        return Error(expression, "Domain restriction operator expects list on LHS");
+                    if (rt.kind != TypeKind.MapType)
+                        return Error(expression, "Domain restriction operator expects map on RHS");
+                    ListType domlist = (ListType)lt;
+                    MapType domMap = (MapType)rt;
+                    if (!UlyssesType.TypeEqual(domlist.innerType, domMap.fromType))
+                        return Error(expression, "Inner type of list and domain-type of map do not match");
+                    // since this is a restriction, maxnumofelems is ok
+                    expression.SetType(domMap);
+                    break;
+                case ExpressionKind.rngresby:   // map A to B * list of B -> map A to B
+                case ExpressionKind.rngresto:   // map A to B * list of B -> map A to B
+                    if (lt.kind != TypeKind.MapType)
+                        return Error(expression, "Range restriction operator expects map on LHS");
+                    if (rt.kind != TypeKind.ListType)
+                        return Error(expression, "Rangle restriction operator expects list on RHS");
+                    ListType rangelist = (ListType)rt;
+                    domMap = (MapType)lt;
+                    if (!UlyssesType.TypeEqual(rangelist.innerType, domMap.fromType))
+                        return Error(expression, "Inner type of list and rangle-type of map do not match");
+                    // since this is a restriction, maxnumofelems is ok
+                    expression.SetType(domMap);
+                    break;
+                case ExpressionKind.munion:     // map A to B * map A to B -> map A to B
+                    if (lt.kind != TypeKind.MapType ||
+                        rt.kind != TypeKind.MapType)
+                        return Error(expression, "Map union expects maps on LHS and RHS");
+                    domMap = (MapType)lt;
+                    MapType rngMap = (MapType)rt;
+                    if (!UlyssesType.TypeEqual(domMap.fromType, rngMap.fromType) ||
+                        !UlyssesType.TypeEqual(domMap.toType, rngMap.toType))
+                        return Error(expression, "Domain and Range types of maps must be equal");
+                    // union may change maximum number of elements..
+                    MapType resMap = new MapType(domMap.fromType, domMap.toType,
+                        domMap.maxNumberOfElements + rngMap.maxNumberOfElements, null);
+                    expression.SetType(resMap);
+                    break;
+                /*set/list binary*/
+                case ExpressionKind.conc:       // list of A * list of A -> list of A
+                    if (lt.kind != TypeKind.ListType ||
+                        rt.kind != TypeKind.ListType)
+                        return Error(expression, "List concatenation expects two lists.");
+                    ListType la = (ListType)lt;
+                    ListType lb = (ListType)rt;
+
+                    if (lb.innerType.kind == TypeKind.Null || lb.maxNumberOfElements == 0)
+                        return lhs;
+                    if (la.innerType.kind == TypeKind.Null || la.maxNumberOfElements == 0)
+                        return rhs;
+                    if (!UlyssesType.TypeEqual(la.innerType, lb.innerType))
+                        return Error(expression, String.Format("Set/List concatenation expects two lists of same type. ({0} <> {1})", la.ToString(), lb.ToString()));
+                    ListType resultList = new ListType(la.innerType,
+                        la.maxNumberOfElements + lb.maxNumberOfElements, null);
+                    expression.SetType(resultList);
+                    break;
+                case ExpressionKind.diff:       // list of A * list of A -> list of A (does not respect dupes)
+                    if (lt.kind != TypeKind.ListType ||
+                        rt.kind != TypeKind.ListType)
+                        return Error(expression, "Set difference expects two lists.");
+                    la = (ListType)lt;
+                    lb = (ListType)rt;
+                    if (!UlyssesType.TypeEqual(la.innerType, lb.innerType))
+                        return Error(expression, "Set difference expects two lists of same type.");
+                    expression.SetType(la);
+                    break;
+                case ExpressionKind.inter:      // list of A * list of A -> list of A (does not respect dupes)
+                    if (lt.kind != TypeKind.ListType ||
+                        rt.kind != TypeKind.ListType)
+                        return Error(expression, "Set intersection expects two lists.");
+                    la = (ListType)lt;
+                    lb = (ListType)rt;
+                    if (!UlyssesType.TypeEqual(la.innerType, lb.innerType))
+                        return Error(expression, "Set intersection expects two lists of same type.");
+                    expression.SetType(la.maxNumberOfElements > lb.maxNumberOfElements ? la : lb);
+                    break;
+                case ExpressionKind.elemin:     // A * list of A -> bool
+                case ExpressionKind.notelemin:  // A * list of A -> bool
+                    if (rt.kind != TypeKind.ListType)
+                        return Error(expression, "Element (not) in operator expects list-type as RHS.");
+                    lb = (ListType)rt;
+                    if (!UlyssesType.TypeEqual(lt, lb.innerType))
+                        return Error(expression, "List and element must be of same type.");
+                    expression.SetType(new BoolType(null));
+                    break;
+                case ExpressionKind.subset:     // list of A * list of A -> bool (does not respect dupes)
+                    if (lt.kind != TypeKind.ListType ||
+                        rt.kind != TypeKind.ListType)
+                        return Error(expression, "Subset operation expects two lists.");
+                    la = (ListType)lt;
+                    lb = (ListType)rt;
+                    if (!UlyssesType.TypeEqual(la.innerType, lb.innerType))
+                        return Error(expression, "Subset operation expects two lists of same type.");
+                    expression.SetType(new BoolType(null));
+                    break;
+                case ExpressionKind.union:      // list of A * list of A -> list of A (does not respect dupes)
+                    if (lt.kind != TypeKind.ListType ||
+                        rt.kind != TypeKind.ListType)
+                        return Error(expression, "Set union expects two lists.");
+                    la = (ListType)lt;
+                    lb = (ListType)rt;
+
+                    if (la.innerType.kind == TypeKind.Null || la.maxNumberOfElements == 0)
+                        return rhs;
+                    if (lb.innerType.kind == TypeKind.Null || lb.maxNumberOfElements == 0)
+                        return lhs;
+
+                    if (!UlyssesType.TypeEqual(la.innerType, lb.innerType))
+                        return Error(expression, "Set union expects two lists of same type.");
+                    resultList = new ListType(la.innerType,
+                        la.maxNumberOfElements + lb.maxNumberOfElements, null);
+                    expression.SetType(resultList);
+                    break;
+
+                /*numeric binary*/
+                case ExpressionKind.pow:
+                    if (!lt.IsNumeric() ||
+                        !rt.IsNumeric())
+                        return Error(expression, "Operator expects LHS and RHS to be numeric");
+                    if (lt.kind == TypeKind.IntType
+                        && rt.kind == TypeKind.IntType)
+                        expression.SetType(lt);
+                    else
+                        if (lt.kind == TypeKind.FloatType)
+                            expression.SetType(lt);
+                        else
+                        {
+                            IntType anint = (IntType)lt;
+                            expression.SetType(new FloatType(anint.rangeLow, anint.rangeHigh,
+                                FloatType.defaultPrecision, null));
+                        }
+                    break;
+
+                case ExpressionKind.idiv:
+                case ExpressionKind.mod:
+                    if (rt.kind != TypeKind.IntType ||
+                        lt.kind != TypeKind.IntType)
+                        return Error(expression, "Operator expects LHS and RHS to be integer");
+                    expression.SetType(Expression.ArithmeticCover(lt, rt, expression.kind));
+                    break;
+                case ExpressionKind.div:
+                    if (!rt.IsNumeric() || !lt.IsNumeric())
+                        return Error(expression, "Operator expects LHS and RHS to be numeric");
+                    if (lhs.type is ValuedEnumType)
+                        lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type).getIntType());
+                    if (rhs.type is ValuedEnumType)
+                        rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type).getIntType());
+                    UlyssesType cover = Expression.ArithmeticCover(lt, rt, expression.kind);
+                    expression.SetType(cover);
+                    break;
+                case ExpressionKind.minus:
+                    if (!rt.IsNumeric() || !lt.IsNumeric())
+                        return Error(expression, "Operator expects LHS and RHS to be numeric");
+                    if (lhs.type is ValuedEnumType)
+                        lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type).getIntType());
+                    if (rhs.type is ValuedEnumType)
+                        rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type).getIntType());
+                    cover = Expression.ArithmeticCover(lt, rt, expression.kind);
+                    expression.SetType(cover);
+                    break;
+                case ExpressionKind.prod:
+                    if (!rt.IsNumeric() || !lt.IsNumeric())
+                        return Error(expression, "Operator expects LHS and RHS to be numeric");
+                    if (lhs.type is ValuedEnumType)
+                        lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type).getIntType());
+                    if (rhs.type is ValuedEnumType)
+                        rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type).getIntType());
+                    cover = Expression.ArithmeticCover(lt, rt, expression.kind);
+                    expression.SetType(cover);
+                    break;
+                case ExpressionKind.sum:
+                    if (!rt.IsNumeric() || !lt.IsNumeric())
+                        return Error(expression, "Operator expects LHS and RHS to be numeric");
+                    if (lhs.type is ValuedEnumType)
+                        lhs = UnaryOperator.TryCoerceUp(lhs, ((ValuedEnumType)lhs.type).getIntType());
+                    if (rhs.type is ValuedEnumType)
+                        rhs = UnaryOperator.TryCoerceUp(rhs, ((ValuedEnumType)rhs.type).getIntType());
+                    cover = Expression.ArithmeticCover(lt, rt, expression.kind);
+                    expression.SetType(cover);
+                    break;
+                case ExpressionKind.greater:
+                case ExpressionKind.greaterequal:
+                case ExpressionKind.less:
+                case ExpressionKind.lessequal:
+                    if (!((rt.IsNumeric() && lt.IsNumeric()) || (rt.IsQualitative() && lt.IsQualitative())))
+                        return Error(expression, "Operator expects LHS and RHS to be numeric or qualitative");
+                    cover = UlyssesType.CoverType(lt, rt);
+                    if (cover != null)
+                    {
+                        lhs = UnaryOperator.TryCoerceUp(lhs, cover);
+                        rhs = UnaryOperator.TryCoerceUp(rhs, cover);
+                        expression.SetType(new BoolType(null));
+                    }
+                    else
+                        return Error(expression, String.Format("Operator expects LHS and RHS to be of same type ({0} <> {1})", lhs.type.ToString(), rhs.type.ToString()));
+                    break;
+                /*bool binary*/
+                case ExpressionKind.and:
+                    if (rt.kind != TypeKind.BoolType ||
+                        lt.kind != TypeKind.BoolType)
+                        return Error(expression, "Operator expects LHS and RHS of bool.");
+
+                    expression.SetType(rt);
+                    // little bit of optimization..
+                    if (rhs.kind == ExpressionKind.Value
+                        && ((ValueExpression<bool>)rhs).value == false)
+                        return rhs;
+                    else if (lhs.kind == ExpressionKind.Value
+                        && ((ValueExpression<bool>)lhs).value == false)
+                        return lhs;
+
+                    // if both are true, then this will be taken care of in constant folding.
+                    break;
+                case ExpressionKind.biimplies:
+                    if (rt.kind != TypeKind.BoolType ||
+                        lt.kind != TypeKind.BoolType)
+                        return Error(expression, "Operator expects LHS and RHS of bool.");
+                    expression.SetType(rt);
+                    break;
+                case ExpressionKind.implies:
+                    if (rt.kind != TypeKind.BoolType ||
+                        lt.kind != TypeKind.BoolType)
+                        return Error(expression, "Operator expects LHS and RHS of bool.");
+                    expression.SetType(rt);
+
+                    // ex falso...
+                    if (lhs.kind == ExpressionKind.Value
+                        && ((ValueExpression<bool>)lhs).value == false)
+                    {
+                        Expression shortcut = new ValueExpression<bool>(true, expression.line, expression.pos);
+                        shortcut.SetType(lt);
+                        return shortcut;
+                    }
+
+                    break;
+                case ExpressionKind.or:
+                    if (rt.kind != TypeKind.BoolType ||
+                        lt.kind != TypeKind.BoolType)
+                        return Error(expression, "Operator expects LHS and RHS of bool.");
+                    expression.SetType(rt);
+
+                    if (rhs.kind == ExpressionKind.Value
+                        && ((ValueExpression<bool>)rhs).value == true)
+                        return rhs;
+                    else if (lhs.kind == ExpressionKind.Value
+                        && ((ValueExpression<bool>)lhs).value == true)
+                        return lhs;
+                    break;
+                /*other binary*/
+                case ExpressionKind.equal:
+                case ExpressionKind.notequal:
+                    cover = UlyssesType.CoverType(lt, rt);
+                    if (cover != null)
+                    {
+                        /* see whether we have a tuple-matcher on one side.. */
+                        if (expression.kind == ExpressionKind.equal)
+                        {
+                            if (lhs.kind == ExpressionKind.TupleConstr &&
+                                ((TupleConstructor)lhs).isMatcher)
+                            {
+                                if (rhs.kind == ExpressionKind.TupleConstr &&
+                                    ((TupleConstructor)rhs).isMatcher)
+                                    return Error(expression, "Free variables on both sides of the equality sign in tuple constructors.");
+                                m_matcherList.Remove((TupleConstructor)lhs);
+                            }
+                            else if (rhs.kind == ExpressionKind.TupleConstr &&
+                                    ((TupleConstructor)rhs).isMatcher)
+                            {
+                                if (lhs.kind == ExpressionKind.TupleConstr &&
+                                    ((TupleConstructor)lhs).isMatcher)
+                                    return Error(expression, "Free variables on both sides of the equality sign in tuple constructors.");
+                                m_matcherList.Remove((TupleConstructor)rhs);
+                            }
+                        }
+
+                        lhs = UnaryOperator.TryCoerceUp(lhs, cover);
+                        rhs = UnaryOperator.TryCoerceUp(rhs, cover);
+                        expression.SetType(new BoolType(null));
+                    }
+                    else
+                        return Error(expression, String.Format("Operator expects LHS and RHS to be of same type ({0} <> {1})", lhs.type.ToString(), rhs.type.ToString()));
+                    break;
+                case ExpressionKind.seqmod_mapoverride:
+                    if (rt.kind != TypeKind.MapType)
+                        return Error(expression, "Map expected as RHS on sequence modification or map override.");
+                    // list of A * map int to A -> list of A or
+                    if (lt.kind == TypeKind.ListType)
+                    {
+                        // we're in sequence modification.
+                        domlist = (ListType)lt;
+                        rngMap = (MapType)rt;
+                        if (rngMap.fromType.kind != TypeKind.IntType)
+                            return Error(expression, "Domain of map has to be integer");
+                        if (!UlyssesType.TypeEqual(domlist.innerType, rngMap.toType))
+                            return Error(expression, "Type of list expected to match range of map");
+                        // since we only replace elements in the list (by matching ones from the map),
+                        // we're save to return the original list..
+                        expression.SetType(lt);
+                    }
+                    // map A to B * map A to B -> map A to B
+                    else if (lt.kind == TypeKind.MapType)
+                    {
+                        domMap = (MapType)lt;
+                        rngMap = (MapType)rt;
+                        if (!UlyssesType.TypeEqual(domMap.fromType, rngMap.fromType) ||
+                             !UlyssesType.TypeEqual(domMap.toType, rngMap.toType))
+                            return Error(expression, "Maps need same domain and range types");
+                        // since we override entries in the first map:
+                        expression.SetType(domMap);
+                    }
+                    else
+                        return Error(expression, "Sequence Modification or Map override expects list or map as LHS");
+                    break;
+                default:
+                    throw new NotImplementedException();
+            }
+
+            // set subtrees.
+            expression.SetLeftChild(lhs);
+            expression.SetRightChild(rhs);
+
+            // we only allow:  a = MyTuple(c,d) style matchers
+            if (m_matcherList.Count > 0)
+            {
+                m_matcherList.Clear();
+                return Error(expression, "Free variables in tuple constructor only allowed in expressions of the form 'atuple = ATupleConstructor(free1,free2...)'");
+            }
+
+            // try simple constant folding
+            return ApplyConstantFolding(expression);
+        }
+
+
+        /// 
+        ///  We're also doing a bit of constant folding here.
+        /// 
+
+        private Expression ApplyConstantFolding(UnaryOperator expression)
+        {
+            Expression child = expression.child;
+            if (child.type.IsNumeric() && expression.kind == ExpressionKind.Cast)
+            {
+                switch (expression.type.kind)
+                {
+                    case TypeKind.FloatType:
+                        if (child.type.kind == TypeKind.IntType && child.kind == ExpressionKind.Value)
+                        {
+                            Expression result = new ValueExpression<double>(((ValueExpression<int>)child).value, child.line, child.pos);
+                            result.SetType(expression.type);
+                            return result;
+                        }
+                        break;
+                }
+            }
+            return expression;
+        }
+
+        private Expression ApplyConstantFolding(BinaryOperator expression)
+        {
+            Expression lhs = expression.left;
+            Expression rhs = expression.right;
+
+            if (lhs.kind == ExpressionKind.Cast)
+            {
+                lhs = ApplyConstantFolding((UnaryOperator)lhs);
+                expression.SetLeftChild(lhs);
+            }
+            if (rhs.kind == ExpressionKind.Cast)
+            {
+                rhs = ApplyConstantFolding((UnaryOperator)rhs);
+                expression.SetRightChild(rhs);
+            }
+
+
+            if (lhs.kind == ExpressionKind.Value && rhs.kind == ExpressionKind.Value)
+                if (expression.type.kind == TypeKind.FloatType)
+                {
+                    double fval1 = ((ValueExpression<double>)lhs).value;
+                    double fval2 = ((ValueExpression<double>)rhs).value;
+                    double result = 0;
+                    switch (expression.kind)
+                    {
+
+                        case ExpressionKind.sum:
+                            result = fval1 + fval2;
+                            break;
+                        case ExpressionKind.minus:
+                            result = fval1 - fval2;
+                            break;
+                        case ExpressionKind.prod:
+                            result = fval1 * fval2;
+                            break;
+                        case ExpressionKind.div:
+                            if (fval2 == 0)
+                                return Error(expression, "Division not defined");
+                            result = fval1 / fval2;
+                            break;
+                        default:
+                            // bail out, if we can not handle it
+                            return expression;
+                    }
+                    if (result < ((FloatType)expression.type).low
+                        || result > ((FloatType)expression.type).high)
+                        return Error(expression, "Internal Error: value after constant folding not in float-range!");
+
+                    ValueExpression<double> resexp = new ValueExpression<double>(result, expression.line, expression.pos);
+                    resexp.SetType(expression.type);
+                    return resexp;
+                }
+                else if (expression.type.kind == TypeKind.IntType)
+                {
+                    int val1 = ((ValueExpression<int>)lhs).value;
+                    int val2 = ((ValueExpression<int>)rhs).value;
+                    int result = 0;
+                    switch (expression.kind)
+                    {
+                        case ExpressionKind.sum:
+                            result = val1 + val2;
+                            break;
+                        case ExpressionKind.minus:
+                            result = val1 - val2;
+                            break;
+                        case ExpressionKind.prod:
+                            result = val1 * val2;
+                            break;
+                        case ExpressionKind.idiv:
+                            if (val2 == 0)
+                                return Error(expression, "Division not defined.");
+                            result = val1 / val2;
+                            break;
+                        case ExpressionKind.mod:
+                            result = val1 % val2;
+                            break;
+                        default:
+                            // bail out, if we can not handle it
+                            return expression;
+                    }
+
+                    if (result < ((IntType)expression.type).rangeLow
+                        || result > ((IntType)expression.type).rangeHigh)
+                        return Error(expression, "Internal Error: value after constant folding not in int-range!");
+
+                    ValueExpression<int> intres = new ValueExpression<int>(result, expression.line, expression.pos);
+                    intres.SetType(expression.type);
+                    return intres;
+                }
+                else if (expression.type.kind == TypeKind.BoolType)
+                {
+                    bool result = false;
+                    switch (expression.kind)
+                    {
+                        case ExpressionKind.greater:
+                            System.Diagnostics.Debug.Assert(lhs.type.kind == rhs.type.kind);
+                            switch (lhs.type.kind)
+                            {
+                                case TypeKind.IntType:
+                                    result = ((ValueExpression<int>)lhs).value >
+                                                ((ValueExpression<int>)rhs).value;
+                                    break;
+                                case TypeKind.FloatType:
+                                    result = ((ValueExpression<double>)lhs).value >
+                                                ((ValueExpression<double>)rhs).value;
+                                    break;
+                                default:
+                                    return expression;
+                            }
+                            break;
+                        case ExpressionKind.greaterequal:
+                            System.Diagnostics.Debug.Assert(lhs.type.kind == rhs.type.kind);
+                            switch (lhs.type.kind)
+                            {
+                                case TypeKind.IntType:
+                                    result = ((ValueExpression<int>)lhs).value >=
+                                                ((ValueExpression<int>)rhs).value;
+                                    break;
+                                case TypeKind.FloatType:
+                                    result = ((ValueExpression<double>)lhs).value >=
+                                                ((ValueExpression<double>)rhs).value;
+                                    break;
+                                default:
+                                    return expression;
+                            }
+                            break;
+                        case ExpressionKind.less:
+                            System.Diagnostics.Debug.Assert(lhs.type.kind == rhs.type.kind);
+                            switch (lhs.type.kind)
+                            {
+                                case TypeKind.IntType:
+                                    result = ((ValueExpression<int>)lhs).value <
+                                                ((ValueExpression<int>)rhs).value;
+                                    break;
+                                case TypeKind.FloatType:
+                                    result = ((ValueExpression<double>)lhs).value <
+                                                ((ValueExpression<double>)rhs).value;
+                                    break;
+                                default:
+                                    return expression;
+                            }
+                            break;
+                        case ExpressionKind.lessequal:
+                            System.Diagnostics.Debug.Assert(lhs.type.kind == rhs.type.kind);
+                            switch (lhs.type.kind)
+                            {
+                                case TypeKind.IntType:
+                                    result = ((ValueExpression<int>)lhs).value <=
+                                                ((ValueExpression<int>)rhs).value;
+                                    break;
+                                case TypeKind.FloatType:
+                                    result = ((ValueExpression<double>)lhs).value <=
+                                                ((ValueExpression<double>)rhs).value;
+                                    break;
+                                default:
+                                    return expression;
+                            }
+                            break;
+                        case ExpressionKind.and:
+                            result = ((ValueExpression<bool>)lhs).value && ((ValueExpression<bool>)rhs).value;
+                            break;
+                        case ExpressionKind.equal:
+                            // we have to be careful here, since equal takes all sorts of types..
+                            System.Diagnostics.Debug.Assert(lhs.type.kind == rhs.type.kind);
+                            switch (lhs.type.kind)
+                            {
+                                case TypeKind.BoolType:
+                                    result = ((ValueExpression<bool>)lhs).value ==
+                                        ((ValueExpression<bool>)rhs).value;
+                                    break;
+                                case TypeKind.IntType:
+                                    result = ((ValueExpression<int>)lhs).value ==
+                                        ((ValueExpression<int>)rhs).value;
+                                    break;
+                                case TypeKind.FloatType:
+                                    result = ((ValueExpression<double>)lhs).value ==
+                                        ((ValueExpression<double>)rhs).value;
+                                    break;
+                                default:
+                                    return expression;
+                            }
+                            break;
+                        case ExpressionKind.biimplies:
+                            result = ((ValueExpression<bool>)lhs).value == ((ValueExpression<bool>)rhs).value;
+                            break;
+                        case ExpressionKind.implies:
+                            result = !((ValueExpression<bool>)lhs).value || ((ValueExpression<bool>)rhs).value;
+                            break;
+                        case ExpressionKind.or:
+                            result = ((ValueExpression<bool>)lhs).value || ((ValueExpression<bool>)rhs).value;
+                            break;
+                        default:
+                            return expression;
+                    }
+                    ValueExpression<bool> boolres = new ValueExpression<bool>(result, expression.line, expression.pos);
+                    boolres.SetType(expression.type);
+                    return boolres;
+                }
+
+            return expression;
+        }
+
+
+        /// 
+        ///  "jump table" (could by avoided by 'dynamic' type as found in c#4)
+        /// 
+
+        private Expression ResolveExpression(Expression expression)
+        {
+            if (expression == null) return null;
+
+            Expression result = expression;
+
+            switch (expression.kind)
+            {
+                case ExpressionKind.Value:
+                    LeafExpression aValue = (LeafExpression)expression;
+                    switch (aValue.valueType)
+                    {
+                        case LeafTypeEnum.boolean:
+                            expression.SetType(new BoolType(null));
+                            break;
+                        case LeafTypeEnum.chr:
+                            expression.SetType(new CharType(null));// IntType(0, 255, null));
+                            break;
+                        case LeafTypeEnum.complex:
+                        case LeafTypeEnum.identifier:
+                            System.Diagnostics.Debug.Assert(false);
+                            break;
+                        case LeafTypeEnum.integer:
+                            int val = ((ValueExpression<int>)expression).value;
+                            expression.SetType(new IntType(val, val, null));
+                            break;
+                        case LeafTypeEnum.qval:
+                            throw new NotImplementedException();
+                        case LeafTypeEnum.real:
+                            double fval = ((ValueExpression<double>)expression).value;
+                            expression.SetType(new FloatType(fval, fval, fval, null));
+                            break;
+                        case LeafTypeEnum.reference:
+                            object aref = ((ValueExpression<object>)expression).value;
+                            if (aref == null)
+                                expression.SetType(new NullType());
+                            else
+                            {
+                                System.Diagnostics.Debug.Assert(false);
+                                return null;
+                            }
+                            break;
+                        case LeafTypeEnum.unset:
+                            throw new NotImplementedException();
+                    }
+                    result = expression;
+                    break;
+
+                /* ternary operators */
+                case ExpressionKind.conditional:
+                case ExpressionKind.foldLR:
+                case ExpressionKind.foldRL:
+                    result = ResolveExpression((TernaryOperator)expression);
+                    break;
+
+                /* forall */
+                case ExpressionKind.forall:
+                    result = ResolveExpression((ForallQuantifier)expression);
+                    break;
+
+                /* exists */
+                case ExpressionKind.exists:
+                    result = ResolveExpression((ExistsQuantifier)expression);
+                    break;
+
+                /* constructors */
+                case ExpressionKind.ListConstr:
+                    result = ResolveExpression((ListConstructor)expression);
+                    break;
+                case ExpressionKind.SetConstr:
+                    result = ResolveExpression((SetConstructor)expression);
+                    break;
+                case ExpressionKind.MapConstr:
+                    result = ResolveExpression((MapConstructor)expression);
+                    break;
+                case ExpressionKind.TupleConstr:
+                    result = ResolveExpression((TupleConstructor)expression);
+                    break;
+                case ExpressionKind.ObjectConstr:
+                    result = expression;
+                    break;
+                case ExpressionKind.QValConstr:
+                    result = ResolveExpression((QValConstructor)expression);
+                    break;
+
+                /* identifiers */
+                case ExpressionKind.Identifier:
+                    result = ResolveExpression((IdentifierExpression)expression);
+                    break;
+                case ExpressionKind.UnresolvedIdentifier:
+                    result = ResolveExpression((UnresolvedIdentifierExpression)expression);
+                    break;
+
+                /* evaluate */
+                case ExpressionKind.TupleMapAccess:
+                    result = ResolveExpression((TupleMapAccessExpression)expression);
+                    break;
+                case ExpressionKind.Call:
+                    result = ResolveExpression((CallExpression)expression);
+                    break;
+
+                /* access some element within a class.. */
+                case ExpressionKind.Access:
+                    result = ResolveExpression((AccessExpression)expression);
+                    break;
+
+
+                case ExpressionKind.Cast:
+                    UnaryOperator cast = (UnaryOperator)expression;
+
+                    /*prevent casts of complex datatypes, e.g. lists etc..*/
+                    if (cast.type.kind != TypeKind.OoActionSystemType)
+                        return Error(cast, String.Format("Cast operator needs class type as argument"));
+
+                    cast.SetChild(ResolveExpression(cast.child));
+                    UlyssesType acover = UlyssesType.CoverType(cast.type, cast.child.type);
+                    bool upcast = UlyssesType.TypeEqual(acover, cast.type);           // the cast is safe; Mostly used in list constructors..
+                    bool downcast = UlyssesType.TypeEqual(acover, cast.child.type); // downcast, unsafe.
+                    if (downcast)
+                        Info(cast, String.Format("Potentially unsafe downcast: {0} as {1} (cover: {2})",
+                            cast.child.type.ToString(), cast.type.ToString(), acover.ToString()));
+                    if (acover == null || !(upcast || downcast))
+                    if (acover == null || !UlyssesType.TypeEqual(acover, cast.type))
+                        return Error(cast, String.Format("Invalid cast: {0} as {1} (cover: {2})", cast.child.type.ToString(), cast.type.ToString(), acover != null ? acover.ToString() : "<none>"));
+                    result = cast;
+                    break;
+
+                /* general unary operators */
+                case ExpressionKind.Primed:
+                case ExpressionKind.unminus:
+                case ExpressionKind.unplus:
+                case ExpressionKind.not:
+                case ExpressionKind.abs:
+                case ExpressionKind.dom:
+                case ExpressionKind.range:
+                case ExpressionKind.merge:
+                case ExpressionKind.card:
+                case ExpressionKind.dconc:
+                case ExpressionKind.dinter:
+                case ExpressionKind.dunion:
+                case ExpressionKind.elems:
+                case ExpressionKind.head:
+                case ExpressionKind.inds:
+                case ExpressionKind.len:
+                case ExpressionKind.tail:
+                    result = ResolveExpression((UnaryOperator)expression);
+                    break;
+
+                /* general binary operators */
+                case ExpressionKind.domresby:
+                case ExpressionKind.domresto:
+                case ExpressionKind.rngresby:
+                case ExpressionKind.rngresto:
+                case ExpressionKind.munion:
+                case ExpressionKind.conc:
+                case ExpressionKind.diff:
+                case ExpressionKind.inter:
+                case ExpressionKind.elemin:
+                case ExpressionKind.notelemin:
+                case ExpressionKind.subset:
+                case ExpressionKind.union:
+                case ExpressionKind.div:
+                case ExpressionKind.greater:
+                case ExpressionKind.greaterequal:
+                case ExpressionKind.idiv:
+                case ExpressionKind.less:
+                case ExpressionKind.lessequal:
+                case ExpressionKind.minus:
+                case ExpressionKind.mod:
+                case ExpressionKind.pow:
+                case ExpressionKind.prod:
+                case ExpressionKind.sum:
+                case ExpressionKind.and:
+                case ExpressionKind.biimplies:
+                case ExpressionKind.implies:
+                case ExpressionKind.or:
+                case ExpressionKind.equal:
+                case ExpressionKind.notequal:
+                case ExpressionKind.seqmod_mapoverride:
+                    result = ResolveExpression((BinaryOperator)expression);
+                    break;
+                default:
+                    throw new NotImplementedException();
+            }
+
+            return result;
+        }
+
+
+        public Expression ResolveExpressionNewScope(Expression toResolve)
+        {
+            Expression result = null;
+
+            m_freeVariables.Push(new SymbolTable());
+            try
+            {
+                result = ResolveExpression(toResolve);
+            }
+            finally
+            {
+                if (result != null)
+                    result.SetFreeVariables(m_freeVariables.Pop());
+            }
+            return result;
+        }
+
+
+        /// 
+        ///  called for every element in the ast        
+        /// 
+
+        protected override void VisitAstElement(IAst subElement, IAst parent)
+        {
+            if (subElement.nodeType == AstNodeTypeEnum.expression)
+            {
+                // calculate a new (resolved) expression
+                m_freeVariables.Push(new SymbolTable());
+                // save toplevel -- used to keep track of method calls.
+                m_entryExpression = (Expression)subElement;
+
+                Expression newExpression = ResolveExpression(m_entryExpression);
+                // replace the expression in the parent
+                if (newExpression != null)
+                {
+                    newExpression.SetFreeVariables(m_freeVariables.Pop());
+                    ReplaceExpression(parent, (Expression)subElement, newExpression);
+                }
+
+            }
+            else
+                subElement.Accept(this); // saves us the call to base.VisitAstElement
+        }
+
+
+        /// 
+        ///  PUBLIC METHODS
+        /// 
+
+        public OoaResolveExpressionsVisitor(ParserState aState)
+            : base(aState)
+        {
+            if (aState == null)
+                throw new ArgumentException();
+        }
+    }
+
+}
Index: branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaTypeCheckVisitor.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaTypeCheckVisitor.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaTypeCheckVisitor.cs	(revision 3)
@@ -0,0 +1,432 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TUG.Mogentes
+{
+
+    /// <summary>
+    /// internal; used to count occurrences of attribute access in an expression
+    /// </summary>
+    internal sealed class OoaInitializerCheck : OoaExpressionVisitor
+    {
+        internal List<Identifier> attributeAccess = new List<Identifier>();
+
+        public override void visit(IdentifierExpression identifierExpression)
+        {
+            Identifier id = identifierExpression.identifier;
+            if (id.kind == IdentifierKind.AttributeIdentifier)
+                attributeAccess.Add(id);
+            base.visit(identifierExpression);
+        }
+
+        internal OoaInitializerCheck()
+            : base()
+        { }
+    }
+
+
+    /// <summary>
+    /// Requires: ResolveExpressionVisitor and MethodPureClassifierVisitor
+    /// 
+    /// Does the typechecking of statements and initializers.
+    /// Needs resolved expressions, hence a run of ResolveVisitor first.
+    /// </summary>
+    public sealed class OoaTypeCheckVisitor : OoaCompleteAstTraversalVisitor
+    {
+        private void Error(Statement statement, string p)
+        {
+            ParserError error = new ParserError(m_ParserState.filename,
+                statement.line, statement.pos, p);
+            m_ParserState.AddErrorMessage(error);
+        }
+        private void Error(Identifier id, string p)
+        {
+            ParserError error = new ParserError(m_ParserState.filename,
+                id.line, id.column, p);
+            m_ParserState.AddErrorMessage(error);
+        }
+
+
+
+        private void Warning(Statement aStatement, string p)
+        {
+            ParserWarning warn = new ParserWarning(m_ParserState.filename,
+                aStatement.line, aStatement.pos, p);
+            m_ParserState.AddWarningMessage(warn);
+        }
+        private void Warning(Identifier aStatement, string p)
+        {
+            ParserWarning warn = new ParserWarning(m_ParserState.filename,
+                aStatement.line, aStatement.column, p);
+            m_ParserState.AddWarningMessage(warn);
+        }
+
+
+
+        private void RemoveWarning(Identifier expression, string p)
+        {
+            List<ParserWarning> toRemove = new List<ParserWarning>();
+            foreach (var x in m_ParserState.listOfParserWarnings)
+            {
+                if (p.Equals(x.message) && x.line == expression.line && x.column == expression.column)
+                    toRemove.Add(x);
+            }
+            foreach (var x in toRemove)
+                m_ParserState.listOfParserWarnings.Remove(x);
+        }
+
+        private void TypeCheckGuardedCommand(GuardedCommand gc)
+        {
+            if (gc.guard.type == null ||
+                gc.guard.type.kind != TypeKind.BoolType)
+                Error(gc, "Guard needs to be boolean expression");
+
+            List<ExpressionVariableIdentifier> uninitfree = gc.guard.GetUninitializedFreeVariables();
+            if (uninitfree.Count > 0)
+                Error(gc, String.Format("Undefined variable: '{0}'", uninitfree[0].tokenText));
+
+            CheckMethodCallsArePure(gc.guard);
+
+            gc.body.Accept(this);
+        }
+
+        private void CheckMethodCallsArePure(Expression expression)
+        {
+            foreach (var method in expression.callTargets)
+            {
+                if (!((FunctionType)method.type).isPureFunction)
+                    Error(method, String.Format("Method '{0}' needs to be pure: No change of state allowed.", method.tokenText));
+            }
+        }
+
+
+        private void TypeCheckAssignment(Assignment assignment)
+        {
+            SymbolTable freevars = new SymbolTable();
+            if (assignment.nondetExpression != null)
+            {
+                CheckMethodCallsArePure(assignment.nondetExpression);
+
+                if (assignment.nondetExpression.freeVariables != null
+                    && assignment.nondetExpression.freeVariables.symbolList.Count > 0)
+                {
+                    // expression has free variables we need to match with right-hand-side of assignment.
+                    freevars = assignment.nondetExpression.freeVariables;
+
+                    foreach (var aRhsExpr in assignment.values)
+                    {
+                        if (aRhsExpr.freeVariables != null)
+                            foreach (var freeRhsVar in aRhsExpr.freeVariables.symbolList)
+                            {
+                                if (freevars.Defined(freeRhsVar.tokenText))
+                                {
+                                    Identifier exprvar = freevars.Get(freeRhsVar.tokenText);
+                                    if (freeRhsVar.type.kind == TypeKind.Any)
+                                    {
+                                        freeRhsVar.SetType(exprvar.type);
+                                        assignment.AddIdentifier(exprvar, null);
+                                        // remove free variable warnings
+                                        RemoveWarning(exprvar, String.Format("Free variable in expression: '{0}'.", exprvar.tokenText));
+                                        RemoveWarning(freeRhsVar, String.Format("Free variable in expression: '{0}'.", exprvar.tokenText));
+                                    }
+                                    else if (UlyssesType.TypeEqual(freeRhsVar.type, exprvar.type))
+                                    {
+                                        assignment.AddIdentifier(exprvar, null);
+                                        // remove free variable warnings
+                                        RemoveWarning(exprvar, String.Format("Free variable in expression: '{0}'.", exprvar.tokenText));
+                                        RemoveWarning(freeRhsVar, String.Format("Free variable in expression: '{0}'.", exprvar.tokenText));
+                                    }
+                                    else
+                                        Error(assignment, String.Format("Type mismatch on variable {0}: {1} <> {2}", freeRhsVar.tokenText, freeRhsVar.type.ToString(), exprvar.type.ToString()));
+                                }
+                                else
+                                    Error(assignment, String.Format("Undefined variable '{0}'", freeRhsVar.tokenText));
+                            }
+                    }
+                }
+            }
+
+            foreach (var avar in freevars.symbolList)
+                if (!assignment.symbols.Defined(avar.tokenText))
+                    Error(assignment, String.Format("Undefined variable '{0}'", avar.tokenText));
+
+            if (assignment.places.Count != assignment.values.Count)
+            {
+                Error(assignment, "Number of places does not match number of values in assignment.");
+                //return;
+            }
+
+            LinkedListNode<Expression> aplace = assignment.places.First;
+            LinkedListNode<Expression> avalue = assignment.values.First;
+
+            while (aplace != null && avalue != null)
+            {
+                CheckPlace(aplace.Value, assignment);
+
+                // we allow non-pure methods only for assignments of the form 'variable := function(x,y)'
+                if (avalue.Value.kind != ExpressionKind.Call)
+                    CheckMethodCallsArePure(avalue.Value);
+
+                UlyssesType acover = UlyssesType.CoverType(aplace.Value.type, avalue.Value.type);
+                if (acover == null)
+                    Error(assignment, String.Format("Type mismatch in assignment: {0} ( {1} := {2} )", aplace.Value.ToString(), aplace.Value.type.ToString(), avalue.Value.type.ToString()));
+                else if (!UlyssesType.TypeEqualByKind(aplace.Value.type, acover)) /*ignore range things.. (see warning below)*/
+                    Error(assignment, String.Format("Type mismatch in assignment: {0} ( {1} := {2} )", aplace.Value.ToString(), aplace.Value.type.ToString(), acover.ToString()));
+                else
+                {
+                    List<ExpressionVariableIdentifier> uninitvars = avalue.Value.GetUninitializedFreeVariables();
+                    Expression constantvalue = avalue.Value.kind == ExpressionKind.Value ? avalue.Value : null;
+
+                    if (uninitvars.Count > 0)
+                        Error(assignment, String.Format("Undefined variable '{0}'", uninitvars[0].tokenText));
+
+                    if (!UlyssesType.TypeEqual(avalue.Value.type, acover))
+                    {
+                        UnaryOperator cast = new UnaryOperator(ExpressionKind.Cast, avalue.Value, avalue.Value.line, avalue.Value.pos);
+                        cast.SetType(acover);
+                        avalue.Value = cast;
+                    }
+
+                    if (UlyssesType.FirstTypeLessRange(aplace.Value.type, acover))
+                    {
+                        if (constantvalue == null)
+                        {
+                            Warning(assignment, String.Format("Assignment may over/underflow: {0} := {1}", aplace.Value.type.ToString(), acover.ToString()));
+                            UnaryOperator cast = new UnaryOperator(ExpressionKind.Cast, avalue.Value, avalue.Value.line, avalue.Value.pos);
+                            cast.SetType(aplace.Value.type);
+                            avalue.Value = cast;
+                        }
+                        else
+                        {
+                            Error(assignment, String.Format("Assignment out of range ({0}  := {1})", aplace.Value.ToString(), constantvalue.ToString()));
+                        }
+                    }
+                }
+
+
+                aplace = aplace.Next;
+                avalue = avalue.Next;
+            }
+
+        }
+
+        /// <summary>
+        /// Checks whether the LHS-expression of an assignment is a valid place.
+        /// IMPORTANT: If more complicated LHS expressions are allowed, then
+        ///            ooaPrologExpression.cs needs to be adapted too!
+        /// </summary>
+        private void CheckPlace(Expression expression, Assignment assignment)
+        {
+            // check that we have some LHS of following forms
+            // self.<var/attr> 
+            // attr[..]
+            bool result = true;
+
+            // one array/map access allowed
+            if (expression.kind == ExpressionKind.TupleMapAccess)
+            {
+                TupleMapAccessExpression tAccessExpression = (TupleMapAccessExpression)expression;
+                expression = tAccessExpression.child;
+            }
+
+            // attributes feature a self ref
+            if (expression.kind == ExpressionKind.Access)
+            {
+                AccessExpression accessExpression = (AccessExpression)expression;
+                if (accessExpression.left.kind == ExpressionKind.Identifier && ((IdentifierExpression)accessExpression.left).isSelf)
+                    expression = accessExpression.right;
+                else
+                    result = false;
+            }
+
+            // now we need to have an identifier
+            if (expression.kind != ExpressionKind.Identifier)
+                result = false;
+
+            if (!result)
+                Error(assignment, String.Format("LHS of assignment must be variable or attribute."));
+        }
+
+
+        private void TypeCheckQualConstraint(QualitativeConstraintStatement qualConstr)
+        {
+            if (qualConstr.variable0.type.kind != TypeKind.QrType && qualConstr.variable0.type.kind != TypeKind.Any)
+                Error(qualConstr, String.Format("Qualitative type expected: '{0}'", qualConstr.variable0.tokenText));
+            if (qualConstr.variable1.type.kind != TypeKind.QrType && qualConstr.variable1.type.kind != TypeKind.Any)
+                Error(qualConstr, String.Format("Qualitative type expected: '{0}'", qualConstr.variable0.tokenText));
+            if (qualConstr.variable2 != null && qualConstr.variable2.type.kind != TypeKind.QrType
+                 && qualConstr.variable2.type.kind != TypeKind.Any)
+                Error(qualConstr, String.Format("Qualitative type expected: '{0}'", qualConstr.variable0.tokenText));
+        }
+        private void TypeCheck(Statement statement)
+        {
+            switch (statement.kind)
+            {
+                case StatementKind.Abort:
+                case StatementKind.Skip:
+                    break;
+
+                case StatementKind.NondetBlock:
+                case StatementKind.PrioBlock:
+                case StatementKind.SeqBlock:
+                    statement.Accept(this);
+                    break;
+
+                case StatementKind.Assignment:
+                    Assignment assignment = (Assignment)statement;
+                    TypeCheckAssignment(assignment);
+                    break;
+                case StatementKind.GuardedCommand:
+                    GuardedCommand gc = (GuardedCommand)statement;
+                    TypeCheckGuardedCommand(gc);
+                    break;
+                case StatementKind.Kill:
+                    KillStatement kill = (KillStatement)statement;
+                    if (kill.someOne.type.kind != TypeKind.OoActionSystemType)
+                        Error(kill, String.Format(" {0} not an object", kill.someOne.tokenText));
+                    break;
+                case StatementKind.MethodCall:
+                    Call callstatement = (Call)statement;
+                    if (callstatement.callExpression.GetUninitializedFreeVariables().Count > 0)
+                        Error(callstatement, "Uninitialized free variables in call expression.");
+                    if (callstatement.callExpression.kind != ExpressionKind.Call
+                        && callstatement.callExpression.kind != ExpressionKind.foldRL
+                        && callstatement.callExpression.kind != ExpressionKind.foldLR)
+                        Error(callstatement, "Not a valid method call");
+                    break;
+                case StatementKind.QualConstraint:
+                    QualitativeConstraintStatement qualConstr = (QualitativeConstraintStatement)statement;
+                    TypeCheckQualConstraint(qualConstr);
+                    break;
+                default:
+                    throw new NotImplementedException();
+            }
+        }
+
+        //private void TypeCheck()
+
+        private void TypeCheck(AttributeIdentifier attributeIdentifier)
+        {
+            if (attributeIdentifier.initializer == null)
+                throw new ArgumentException();
+
+            UlyssesType atype = attributeIdentifier.initializer.type;
+            if (atype == null)
+                Error(attributeIdentifier, "Initializer lacks type.");
+            else
+            {
+                /* we use the typecheck to validate a few more properties of the initializer that
+                 * need a completely resolved expression
+                 */
+                OoaInitializerCheck initCheck = new OoaInitializerCheck();
+                attributeIdentifier.initializer.Accept(initCheck);
+                if (initCheck.attributeAccess.Count > 0)
+                    // disallow use of other attributes in initializer
+                    Error(attributeIdentifier, "Access of other attributes not allowed in attribute initializer.");
+                else if (attributeIdentifier.initializer.callTargets.Count > 0)
+                    // disallow method calls in initializer
+                    Error(attributeIdentifier, "Method calls not allowed in attribute initializer.");
+                else if (attributeIdentifier.initializer.freeVariables.symbolList.Count > 0)
+                    // disallow use of free variables in initializer
+                    Error(attributeIdentifier,
+                        String.Format("Unknown identifier in initializer: '{0}'",
+                            attributeIdentifier.initializer.freeVariables.symbolList[0].tokenText));
+                else
+                {
+                    UlyssesType idtype = attributeIdentifier.type;
+                    UlyssesType acover = UlyssesType.CoverType(idtype, atype);
+
+                    if (acover == null)
+                        Error(attributeIdentifier, String.Format("Type mismatch in attribute initializer: {0} ( {1} := {2} )", attributeIdentifier.ToString(), idtype.ToString(), atype.ToString()));
+                    else if (!UlyssesType.TypeEqualByKind(idtype, acover)) /*ignore range things.. (see warning below)*/
+                        Error(attributeIdentifier, String.Format("Type mismatch in attribute initializer: {0} ( {1} := {2} )", attributeIdentifier.ToString(), idtype.ToString(), acover.ToString()));
+                    else
+                    {
+                        Expression constantvalue = attributeIdentifier.initializer.kind == ExpressionKind.Value ? attributeIdentifier.initializer : null;
+
+                        if (!UlyssesType.TypeEqual(atype, acover))
+                        {
+                            UnaryOperator cast = new UnaryOperator(ExpressionKind.Cast, attributeIdentifier.initializer,
+                                attributeIdentifier.initializer.line, attributeIdentifier.initializer.pos);
+                            cast.SetType(acover);
+                            attributeIdentifier.SetInitializer(cast);
+                        }
+
+                        if (UlyssesType.FirstTypeLessRange(idtype, acover))
+                        {
+                            if (constantvalue == null)
+                            {
+                                Warning(attributeIdentifier, String.Format("Assignment may over/underflow: {0} := {1}", idtype.ToString(), acover.ToString()));
+                                UnaryOperator cast = new UnaryOperator(ExpressionKind.Cast, attributeIdentifier.initializer,
+                                    attributeIdentifier.initializer.line, attributeIdentifier.initializer.pos);
+                                cast.SetType(idtype);
+                                attributeIdentifier.SetInitializer(cast);
+                            }
+                            else
+                            {
+                                Error(attributeIdentifier, String.Format("Initialization out of range ({0}  := {1})", attributeIdentifier.ToString(), constantvalue.ToString()));
+                            }
+                        }
+                    }
+
+                    /*
+
+
+                    if (cover == null || !UlyssesType.TypeEqual(cover, idtype))
+                        Error(attributeIdentifier,
+                            String.Format("Type mismatch in attribute initializer: expected '{0}', found '{1}'",
+                                idtype.ToString(), atype.ToString()));
+                    else
+                        attributeIdentifier.SetInitializer(UnaryOperator.CoerceUp(attributeIdentifier.initializer, idtype));
+                     * */
+                }
+            }
+        }
+
+
+        protected override void VisitAstElement(IAst element, IAst parent)
+        {
+            if (element.nodeType == AstNodeTypeEnum.statement)
+            {
+                TypeCheck((Statement)element);
+            }
+            else if (element.nodeType == AstNodeTypeEnum.identifier
+                && ((Identifier)element).kind == IdentifierKind.AttributeIdentifier)
+            {
+                TypeCheck((AttributeIdentifier)element);
+            }
+            else base.VisitAstElement(element, parent);
+        }
+
+
+
+        public OoaTypeCheckVisitor(ParserState aState)
+            : base(aState)
+        {
+            if (aState == null)
+                throw new ArgumentException();
+        }
+    }
+
+
+
+}
Index: branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaTypeRenameVisitor.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaTypeRenameVisitor.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaTypeRenameVisitor.cs	(revision 3)
@@ -0,0 +1,81 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TUG.Mogentes
+{
+    public sealed class OoaTypeRenameVisitor : OoaCompleteAstTraversalVisitor
+    {
+        public override void visit(TypeIdentifier typeIdentifier)
+        {
+            if (!typeIdentifier.type.isAnonymousType)
+                typeIdentifier.prefix = m_ParserState.namesTypePrefix;
+
+            base.visit(typeIdentifier);
+        }
+
+        public OoaTypeRenameVisitor(ParserState aState)
+            : base(aState, false)
+        {
+            if (aState == null)
+                throw new ArgumentException();
+            if (aState.namesTypePrefix == String.Empty)
+                throw new ArgumentException();
+        }
+    }
+
+    public sealed class OoaSymbolSortVisitor : OoaCompleteAstTraversalVisitor
+    {
+        /* Sorting of enums is not necessarily a good idea in terms of the user wanting to know what's going on
+         * however, we need to do this for the ulysses prolog target - otherwise mutations won't be correct..
+         * (regardeless in what order the enum symbols were declared, the order must be the same - then we can
+         * map them to ints)
+         */
+        public override void visit(EnumType enumType)
+        {
+            enumType.listOfEnumSymbols.Sort();
+
+            base.visit(enumType);
+        }
+
+        public override void visit(MainModule mainModule)
+        {
+            foreach (var s in mainModule.symbolTable.symbolList)
+            {
+                if (s.kind == IdentifierKind.TypeIdentifier &&
+                    ((TypeIdentifier)s).type.kind == TypeKind.OoActionSystemType)
+                {
+                    OoActionSystemType ooa = (OoActionSystemType)((TypeIdentifier)s).type;
+                    ooa.symbols.Sort();
+                }
+            }
+            mainModule.symbolTable.Sort();
+            base.visit(mainModule);
+        }
+
+        public OoaSymbolSortVisitor(ParserState aState)
+            : base(aState, false)
+        {
+            if (aState == null)
+                throw new ArgumentException();
+        }
+    }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaTypesVisitor.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaTypesVisitor.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaTypesVisitor.cs	(revision 3)
@@ -0,0 +1,132 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TUG.Mogentes
+{
+
+    /// <summary>
+    /// Requires: ResolveOpaque
+    /// 
+    /// Checks whether types have been defined in a sane way (no self refs etc.)
+    /// </summary>
+    public sealed class OoaTypesVisitor : OoaCompleteAstTraversalVisitor
+    {
+        private void Error(UlyssesType aType, string p)
+        {
+            ParserError error = new ParserError(m_ParserState.filename,
+                aType.identifier.line, aType.identifier.column, p);
+            m_ParserState.AddErrorMessage(error);
+        }
+
+        C5.HashSet<UlyssesType> typesSeen = new C5.HashSet<UlyssesType>();
+
+
+        public override void visit(MainModule mainModule)
+        {
+            foreach (var x in mainModule.symbolTable.symbolList)
+            {
+                if (x.kind == IdentifierKind.TypeIdentifier)
+                    x.Accept(this);
+            }
+        }
+
+        protected override void VisitAstElement(IAst element, IAst parent)
+        {
+            if (element.nodeType != AstNodeTypeEnum.type)
+                m_visited.Add(element);
+
+            base.VisitAstElement(element, parent);
+        }
+
+
+        public override void visit(TypeIdentifier typeIdentifier)
+        {
+            typesSeen.Clear();
+            base.visit(typeIdentifier);
+        }
+
+
+        private delegate void Action<T>(T param) where T : UlyssesType;
+
+        /* Does the check for recursion */
+        private void CheckForRecursion<T>(T aType, string Message, Action<T> toCall) where T : UlyssesType
+        {
+            if (typesSeen.Contains(aType))
+            {
+                Error(aType, Message);
+                return;
+            }
+            typesSeen.Add(aType);
+            try
+            {
+                toCall(aType);
+            }
+            finally
+            {
+                typesSeen.Remove(aType);
+            }
+        }
+
+        /* see whether a tuple-type includes itself */
+        public void HackUntilCSharp4(TupleType t)
+        { base.visit(t); }
+        public override void visit(TupleType tupleType)
+        {
+            CheckForRecursion<TupleType>(tupleType,
+                String.Format("Tuple contains itself: '{0}' (Recursive definitions not allowed.)",
+                        tupleType.ToString()), (x) => HackUntilCSharp4(x));
+        }
+
+        /* see whether a list-type includes itself */
+        public void HackUntilCSharp4(ListType t)
+        { base.visit(t); }
+        public override void visit(ListType listType)
+        {
+            CheckForRecursion<ListType>(listType,
+                String.Format("List contains itself: '{0}' (Recursive definitions not allowed.)",
+                        listType.ToString()), (x) => HackUntilCSharp4(x));
+        }
+
+        /* see whether a map-type includes itself */
+        public void HackUntilCSharp4(MapType t)
+        { base.visit(t); }
+        public override void visit(MapType mapType)
+        {
+            CheckForRecursion<MapType>(mapType,
+                String.Format("Map contains itself: '{0}' (Recursive definitions not allowed.)",
+                        mapType.ToString()), (x) => HackUntilCSharp4(x));
+        }
+
+        public override void visit(OoActionSystemType ooActionSystemType)
+        {
+            // do not go into classes..
+        }
+
+        public OoaTypesVisitor(ParserState aState)
+            : base(aState, true)
+        {
+            if (aState == null)
+                throw new ArgumentException();
+        }
+
+    }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaVisitor.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaVisitor.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/visitors/ooaVisitor.cs	(revision 3)
@@ -0,0 +1,618 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TUG.Mogentes
+{
+    /*Notice: The visitor must implement the traversal!*/
+    public interface IAstVisitor
+    {
+        string returnVisitorName();
+
+        /*Identifiers*/
+        void visit(EnumIdentifier enumIdentifier);
+        void visit(LandmarkIdentifier landmarkIdentifier);
+        void visit(AttributeIdentifier attributeIdentifier);
+        void visit(ExpressionVariableIdentifier expressionVariableIdentifier);
+        void visit(ParameterIdentifier parameterIdentifier);
+        void visit(LocalVariableIdentifier localVariableIdentifier);
+        void visit(TypeIdentifier typeIdentifier);
+        void visit(SelfTypeIdentifier typeIdentifier);
+        void visit(MethodIdentifier methodIdentifier);
+        void visit(NamedActionIdentifier namedActionIdentifier);
+        void visit(MainModule mainModule);
+        void visit(Module module);
+        void visit(NondetIdentifierList nondetIdentifierList);
+        void visit(SeqIdentifierList seqIdentifierList);
+        void visit(PrioIdentifierList prioIdentifierList);
+        void visit(UnspecIdentifierList unspecIdentifierList);
+
+
+        /*Statements*/
+        void visit(NondetBlock nondetBlock);
+        void visit(SeqBlock seqBlock);
+        void visit(PrioBlock prioBlock);
+        void visit(GuardedCommand guardedCommand);
+        void visit(Assignment assignment);
+        void visit(Call call);
+        void visit(SkipStatement skipStatement);
+        void visit(AbortStatement abortStatement);
+        void visit(KillStatement killStatement);
+
+
+        /*Expressions*/
+        void visit<T>(ValueExpression<T> valueExpression);
+        void visit(UnresolvedIdentifierExpression unresolvedIdentifierExpression);
+        void visit(IdentifierExpression identifierExpression);
+        void visit(ListConstructor listConstructor);
+        void visit(SetConstructor setConstructor);
+        void visit(MapConstructor mapConstructor);
+        void visit(TupleConstructor tupleConstructor);
+        void visit(AccessExpression accessExpression);
+        void visit(BinaryOperator binaryOperator);
+        void visit(TernaryOperator ternaryOperator);
+        void visit(TupleMapAccessExpression tupleMapAccessExpression);
+        void visit(CallExpression callExpression);
+        void visit(ForallQuantifier quantifier);
+        void visit(ExistsQuantifier quantifier);
+        void visit(UnaryOperator unaryOperator);
+        void visit(TypeExpression typeExpression);
+        void visit(NullType nullType);
+
+        /*Types*/
+        void visit(CharType charType);
+        void visit(IntType intType);
+        void visit(BoolType boolType);
+        void visit(FloatType floatType);
+        void visit(EnumType enumType);
+        void visit(ListType listType);
+        void visit(MapType mapType);
+        void visit(QrType qrType);
+        void visit(TupleType tupleType);
+        void visit(FunctionType functionType);
+        void visit(OoActionSystemType ooActionSystemType);
+        void visit(OpaqueType opaqueType);
+
+        void visit(AnyType anyType);
+
+        void visit(ObjectConstructor objectConstructor);
+
+        void visit(QValConstructor qValConstructor);
+
+        void visit(QualitativeConstraintStatement qalitativeConstraintStatement);
+
+        void visit(ConstantIdentifier constantIdentifier);
+    }
+
+    public delegate IAstVisitor CreateVisitor(ParserState aState);
+
+    public abstract class OoaCompleteAstTraversalVisitor : IAstVisitor
+    {
+        protected C5.HashSet<object> m_visited = new C5.HashSet<object>();
+        protected ParserState m_ParserState;
+        protected bool m_DuplicateVisit;
+
+        protected void VisitSub(IAst subElement, IAst parent)
+        {
+            if (subElement == null)
+                return;
+            if (m_visited.Contains(subElement))
+                return;
+            if (!(subElement is OpaqueType) && !m_DuplicateVisit)
+                m_visited.Add(subElement);
+            VisitAstElement(subElement, parent);
+        }
+
+        /// <summary>
+        ///  Is called once per Ast element. Makes sense to override it in a 
+        ///  subclass..
+        /// </summary>
+        /// <param name="element">to be visited</param>
+        /// <param name="parent">parent of the element in the ast</param>
+        protected virtual void VisitAstElement(IAst element, IAst parent)
+        {
+            element.Accept(this);
+        }
+
+        public OoaCompleteAstTraversalVisitor(ParserState aState)
+        {
+            m_ParserState = aState;
+        }
+
+        public OoaCompleteAstTraversalVisitor(ParserState aState, bool completeTraversal)
+            : this(aState)
+        {
+            m_DuplicateVisit = completeTraversal;
+        }
+
+        public string returnVisitorName()
+        {
+            return this.GetType().ToString();
+        }
+
+        public override string ToString()
+        {
+            return returnVisitorName();
+        }
+
+        public virtual void visit(EnumIdentifier enumIdentifier)
+        {
+            VisitSub(enumIdentifier.type, enumIdentifier);
+        }
+
+        public virtual void visit(ConstantIdentifier constantIdentifier)
+        {
+            if (constantIdentifier.type != null)
+                VisitSub(constantIdentifier.type, constantIdentifier);
+            VisitSub(constantIdentifier.Value, constantIdentifier);
+        }
+
+
+        public virtual void visit(LandmarkIdentifier landmarkIdentifier)
+        {
+            VisitSub(landmarkIdentifier.type, landmarkIdentifier);
+        }
+
+        public virtual void visit(AttributeIdentifier attributeIdentifier)
+        {
+            VisitSub(attributeIdentifier.type, attributeIdentifier);
+            VisitSub(attributeIdentifier.initializer, attributeIdentifier);
+        }
+
+        public virtual void visit(ExpressionVariableIdentifier expressionVariableIdentifier)
+        {
+            VisitSub(expressionVariableIdentifier.type, expressionVariableIdentifier);
+        }
+
+        public virtual void visit(ParameterIdentifier parameterIdentifier)
+        {
+            VisitSub(parameterIdentifier.type, parameterIdentifier);
+        }
+
+        public virtual void visit(LocalVariableIdentifier localVariableIdentifier)
+        {
+            VisitSub(localVariableIdentifier.type, localVariableIdentifier);
+        }
+
+        public virtual void visit(TypeIdentifier typeIdentifier)
+        {
+            VisitSub(typeIdentifier.type, typeIdentifier);
+        }
+
+        public virtual void visit(SelfTypeIdentifier aself)
+        {
+            visit((TypeIdentifier)aself);
+        }
+
+        public virtual void visit(MethodIdentifier methodIdentifier)
+        {
+            VisitSub(methodIdentifier.type, methodIdentifier);
+            foreach (var sym in methodIdentifier.symbolTable.symbolList)
+                VisitSub(sym, methodIdentifier);
+            foreach (var par in methodIdentifier.parameter)
+                VisitSub(par, methodIdentifier);
+            VisitSub(methodIdentifier.body, methodIdentifier);
+        }
+
+        public virtual void visit(NamedActionIdentifier namedActionIdentifier)
+        {
+            VisitSub(namedActionIdentifier.type, namedActionIdentifier);
+            foreach (var sym in namedActionIdentifier.symbolTable.symbolList)
+                VisitSub(sym, namedActionIdentifier);
+            foreach (var par in namedActionIdentifier.parameter)
+                VisitSub(par, namedActionIdentifier);
+            VisitSub(namedActionIdentifier.body, namedActionIdentifier);
+        }
+
+        public virtual void visit(MainModule mainModule)
+        {
+            foreach (var sym in mainModule.symbolTable.symbolList)
+                VisitSub(sym, mainModule);
+            bool haveInstance = mainModule.instance != null;
+            if (haveInstance)
+                VisitSub(mainModule.instance, mainModule);
+            else
+                VisitSub(mainModule.systemDescription, mainModule);
+        }
+
+        public virtual void visit(Module module)
+        {
+            foreach (var sym in module.symbolTable.symbolList)
+                VisitSub(sym, module);
+        }
+
+        public virtual void visit(NondetIdentifierList nondetIdentifierList)
+        {
+            foreach (var id in nondetIdentifierList.identifiers)
+                VisitSub(id, nondetIdentifierList);
+        }
+
+        public virtual void visit(SeqIdentifierList seqIdentifierList)
+        {
+            foreach (var id in seqIdentifierList.identifiers)
+                VisitSub(id, seqIdentifierList);
+        }
+
+        public virtual void visit(PrioIdentifierList prioIdentifierList)
+        {
+            foreach (var id in prioIdentifierList.identifiers)
+                VisitSub(id, prioIdentifierList);
+        }
+
+        public virtual void visit(UnspecIdentifierList unspecIdentifierList)
+        {
+            foreach (var id in unspecIdentifierList.identifiers)
+                VisitSub(id, unspecIdentifierList);
+        }
+
+        public virtual void visit(NondetBlock nondetBlock)
+        {
+            foreach (var id in nondetBlock.symbols.symbolList)
+                VisitSub(id, nondetBlock);
+
+            foreach (var stmnt in nondetBlock.statements)
+                VisitSub(stmnt, nondetBlock);
+        }
+
+        public virtual void visit(SeqBlock seqBlock)
+        {
+            foreach (var id in seqBlock.symbols.symbolList)
+                VisitSub(id, seqBlock);
+
+            if (seqBlock.filter != null)
+                VisitSub(seqBlock.filter, seqBlock);
+
+            foreach (var stmnt in seqBlock.statements)
+                VisitSub(stmnt, seqBlock);
+        }
+
+        public virtual void visit(PrioBlock prioBlock)
+        {
+            foreach (var id in prioBlock.symbols.symbolList)
+                VisitSub(id, prioBlock);
+
+            foreach (var stmnt in prioBlock.statements)
+                VisitSub(stmnt, prioBlock);
+        }
+
+        public virtual void visit(GuardedCommand guardedCommand)
+        {
+            VisitSub(guardedCommand.guard, guardedCommand);
+            VisitSub(guardedCommand.body, guardedCommand);
+        }
+
+        public virtual void visit(Assignment assignment)
+        {
+            foreach (var vexp in assignment.places)
+                VisitSub(vexp, assignment);
+            foreach (var expr in assignment.values)
+                VisitSub(expr, assignment);
+
+            VisitSub(assignment.nondetExpression, assignment);
+        }
+
+        public virtual void visit(Call call)
+        {
+            VisitSub(call.callExpression, call);
+        }
+
+        public virtual void visit(SkipStatement skipStatement)
+        { }
+
+        public virtual void visit(AbortStatement abortStatement)
+        { }
+
+        public virtual void visit(KillStatement killStatement)
+        {
+            VisitSub(killStatement.someOne, killStatement);
+        }
+
+        public virtual void visit<T>(ValueExpression<T> valueExpression)
+        { }
+
+        public virtual void visit(UnresolvedIdentifierExpression unresolvedIdentifierExpression)
+        {
+            VisitSub(unresolvedIdentifierExpression.type, unresolvedIdentifierExpression);
+        }
+
+        public virtual void visit(IdentifierExpression identifierExpression)
+        {
+            VisitSub(identifierExpression.type, identifierExpression);
+            VisitSub(identifierExpression.identifier, identifierExpression);
+        }
+
+        public virtual void visit(TypeExpression typeExpression)
+        {
+            VisitSub(typeExpression.type, typeExpression);
+        }
+
+        public virtual void visit(ListConstructor listConstructor)
+        {
+            foreach (var lvar in listConstructor.comprehensionVariables.symbolList)
+                VisitSub(lvar, listConstructor);
+
+            foreach (var elems in listConstructor.elements)
+                VisitSub(elems, listConstructor);
+
+            if (listConstructor.comprehension != null)
+                VisitSub(listConstructor.comprehension, listConstructor);
+        }
+
+        public virtual void visit(SetConstructor setConstructor)
+        {
+            foreach (var svar in setConstructor.comprehensionVariables.symbolList)
+                VisitSub(svar, setConstructor);
+
+            foreach (var elems in setConstructor.items)
+                VisitSub(elems, setConstructor);
+
+            VisitSub(setConstructor.comprehension, setConstructor);
+        }
+
+        public virtual void visit(MapConstructor mapConstructor)
+        {
+            /*foreach (var lvar in mapConstructor.localVariables.symbolList)
+                VisitSub(lvar, mapConstructor);*/
+
+            foreach (var elem in mapConstructor.items)
+            {
+                VisitSub(elem.key, mapConstructor);
+                VisitSub(elem.value, mapConstructor);
+            }
+        }
+
+        public virtual void visit(TupleConstructor tupleConstructor)
+        {
+            /*foreach (var lvar in tupleConstructor.localVariables.symbolList)
+                VisitSub(lvar, tupleConstructor);*/
+
+            foreach (var elem in tupleConstructor.values)
+                VisitSub(elem, tupleConstructor);
+        }
+
+        public virtual void visit(AccessExpression accessExpression)
+        {
+            VisitSub(accessExpression.left, accessExpression);
+            VisitSub(accessExpression.right, accessExpression);
+        }
+
+        public virtual void visit(BinaryOperator binaryOperator)
+        {
+            VisitSub(binaryOperator.left, binaryOperator);
+            VisitSub(binaryOperator.right, binaryOperator);
+        }
+
+        public virtual void visit(TernaryOperator ternaryOperator)
+        {
+            VisitSub(ternaryOperator.left, ternaryOperator);
+            VisitSub(ternaryOperator.mid, ternaryOperator);
+            VisitSub(ternaryOperator.right, ternaryOperator);
+        }
+
+        public virtual void visit(TupleMapAccessExpression tupleMapAccessExpression)
+        {
+            VisitSub(tupleMapAccessExpression.argument, tupleMapAccessExpression);
+            VisitSub(tupleMapAccessExpression.child, tupleMapAccessExpression);
+        }
+
+        public virtual void visit(CallExpression callExpression)
+        {
+            if (callExpression.arguments != null)
+                foreach (var arg in callExpression.arguments)
+                    VisitSub(arg, callExpression);
+            VisitSub(callExpression.child, callExpression);
+        }
+
+        public virtual void visit(ForallQuantifier quantifier)
+        {
+            foreach (var lvar in quantifier.symbols.symbolList)
+                VisitSub(lvar, quantifier);
+
+            VisitSub(quantifier.child, quantifier);
+        }
+
+        public virtual void visit(ExistsQuantifier quantifier)
+        {
+            foreach (var lvar in quantifier.symbols.symbolList)
+                VisitSub(lvar, quantifier);
+
+            VisitSub(quantifier.child, quantifier);
+        }
+
+        public virtual void visit(UnaryOperator unaryOperator)
+        {
+            VisitSub(unaryOperator.child, unaryOperator);
+            if (unaryOperator.kind == ExpressionKind.Cast)
+                VisitSub(unaryOperator.type, unaryOperator);
+        }
+
+
+
+        public virtual void visit(CharType charType)
+        {
+        }
+
+        public virtual void visit(IntType intType)
+        {
+        }
+
+        public virtual void visit(BoolType boolType)
+        {
+        }
+
+        public virtual void visit(FloatType floatType)
+        {
+        }
+
+        public virtual void visit(EnumType enumType)
+        {
+            foreach (var sym in enumType.listOfEnumSymbols)
+                VisitSub(sym, enumType);
+        }
+
+        public virtual void visit(ListType listType)
+        {
+            VisitSub(listType.innerType, listType);
+        }
+
+        public virtual void visit(MapType mapType)
+        {
+            VisitSub(mapType.fromType, mapType);
+            VisitSub(mapType.toType, mapType);
+        }
+
+        public virtual void visit(QrType qrType)
+        {
+            foreach (var m in qrType.landmarks)
+                VisitSub(m, qrType);
+        }
+
+        public virtual void visit(TupleType tupleType)
+        {
+            foreach (var t in tupleType.innerTypes)
+                VisitSub(t, tupleType);
+        }
+
+        public virtual void visit(FunctionType functionType)
+        {
+            foreach (var a in functionType.parameter)
+                VisitSub(a, functionType);
+            VisitSub(functionType.returnType, functionType);
+        }
+
+        public virtual void visit(OoActionSystemType ooActionSystemType)
+        {
+            foreach (var s in ooActionSystemType.symbols.symbolList)
+                VisitSub(s, ooActionSystemType);
+
+            VisitSub(ooActionSystemType.doOdBlock, ooActionSystemType);
+        }
+
+        public virtual void visit(OpaqueType opaqueType)
+        {
+            VisitSub(opaqueType.resolvedType, opaqueType);
+        }
+
+        public virtual void visit(NullType nullType)
+        { }
+
+        public virtual void visit(AnyType anyType)
+        { }
+
+        public virtual void visit(ObjectConstructor objectConstructor)
+        {
+            VisitSub(objectConstructor.type, objectConstructor);
+        }
+
+        public virtual void visit(QValConstructor qValConstructor)
+        {
+        }
+
+        public virtual void visit(QualitativeConstraintStatement qalitativeConstraintStatement)
+        {
+            VisitSub(qalitativeConstraintStatement.variable0, qalitativeConstraintStatement);
+            VisitSub(qalitativeConstraintStatement.variable1, qalitativeConstraintStatement);
+            if (qalitativeConstraintStatement.variable2 != null)
+                VisitSub(qalitativeConstraintStatement.variable2, qalitativeConstraintStatement);
+        }
+
+    }
+
+
+
+    /// <summary>
+    /// Visitor that restricts itself to expressions
+    /// </summary>
+    public class OoaExpressionVisitor : OoaCompleteAstTraversalVisitor
+    {
+
+        protected override void VisitAstElement(IAst element, IAst parent)
+        {
+            // we are only interested in an expression.
+            if (element.nodeType == AstNodeTypeEnum.expression)
+                base.VisitAstElement(element, parent);
+        }
+
+        public OoaExpressionVisitor()
+            : base(null)
+        { }
+
+    }
+
+    /// <summary>
+    /// Visitor that restricts itself to statements
+    /// </summary>
+    public class OoaStatementVisitor : OoaCompleteAstTraversalVisitor
+    {
+        protected override void VisitAstElement(IAst element, IAst parent)
+        {
+            // we are only interested in an expression.
+            if (element.nodeType == AstNodeTypeEnum.statement)
+                base.VisitAstElement(element, parent);
+        }
+
+        public OoaStatementVisitor()
+            : base(null)
+        { }
+
+    }
+
+
+
+    /// <summary>
+    /// Visitor that restricts itself to types
+    /// </summary>
+    public class OoaTypeVisitor : OoaCompleteAstTraversalVisitor
+    {
+        protected override void VisitAstElement(IAst element, IAst parent)
+        {
+            // we are only interested in an expression.
+            if (element.nodeType == AstNodeTypeEnum.type)
+                base.VisitAstElement(element, parent);
+        }
+
+        public OoaTypeVisitor()
+            : base(null)
+        { }
+    }
+
+
+    /// <summary>
+    /// Visitor that restricts itself to identifier
+    /// </summary>
+    public class OoaIdentifierVisitor : OoaCompleteAstTraversalVisitor
+    {
+        protected override void VisitAstElement(IAst element, IAst parent)
+        {
+            // we are only interested in an expression.
+            if (element.nodeType == AstNodeTypeEnum.identifier)
+                base.VisitAstElement(element, parent);
+        }
+
+        public OoaIdentifierVisitor()
+            : base(null)
+        { }
+
+    }
+
+
+
+}
Index: branches/compiler/cSharp/ooasCompiler/src/parser/basicTypes.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/basicTypes.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/basicTypes.cs	(revision 3)
@@ -0,0 +1,125 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+//using TUG.Mogentes.Codegen;
+
+namespace TUG.Mogentes
+{
+    public abstract class UlyssesBasicClass
+    { }
+
+
+    public class SymbolTable
+    {
+        private Dictionary<string, Identifier> m_symbols;
+
+        public List<Identifier> symbolList { get { return new List<Identifier>(m_symbols.Values); } }
+
+        public SymbolTable()
+        {
+            m_symbols = new Dictionary<string, Identifier>();
+        }
+
+        public SymbolTable(SymbolTable toCopy)
+        {
+            if (toCopy != null)
+                m_symbols = new Dictionary<string, Identifier>(toCopy.m_symbols);
+            else
+                m_symbols = new Dictionary<string, Identifier>();
+        }
+
+
+        public bool Defined(Identifier aValue)
+        {
+            return ReferenceEquals(aValue,m_symbols[aValue.tokenText]);
+        }
+
+        public bool Defined(string aKey)
+        {
+            return m_symbols.ContainsKey(aKey);
+        }
+
+        public Identifier Get(string aKey)
+        {
+            return m_symbols[aKey];
+        }
+
+        public void AddIdentifier(Identifier anIdent)
+        {
+            if (anIdent != null)
+                m_symbols.Add(anIdent.tokenText, anIdent);
+        }
+
+        public void AddSymbolTable(SymbolTable otherTable)
+        {
+            foreach (var x in otherTable.m_symbols)
+                if (x.Key != "self")
+                    m_symbols.Add(x.Key, x.Value);
+        }
+
+        public void Replace(string aKey, Identifier anIdent)
+        {
+            if (anIdent != null)
+            {
+                m_symbols.Remove(aKey);
+                m_symbols.Add(anIdent.tokenText, anIdent);
+            }
+        }
+
+        public void SetSymbolList(List<Identifier> newList)
+        {
+            newList.Sort();
+            m_symbols = new Dictionary<string, Identifier>();
+            foreach (var x in newList)
+                AddIdentifier(x);
+        }
+
+
+        internal void Sort()
+        {
+            List<Identifier> newList = new List<Identifier>(m_symbols.Values);
+            newList.Sort();
+            m_symbols = new Dictionary<string, Identifier>();
+            foreach (var x in newList)
+                AddIdentifier(x);
+        }
+    }
+
+    /* All AST Elements that define some scope */
+    public interface IScope
+    {
+        Identifier ResolveIdentifier(string aName);
+        IScope GetParentScope();
+        void SetParentScope(IScope parentScope);
+
+        void AddIdentifier(Identifier anIdentifier, object tag);
+    }
+
+    /* All Elements of the AST */
+    public enum AstNodeTypeEnum { type, identifier, expression, statement }
+    public interface IAst
+    {
+        AstNodeTypeEnum nodeType { get; }
+        void Accept(IAstVisitor visitor);
+    }
+
+
+
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/parser/invokeSharpCompiler.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/invokeSharpCompiler.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/invokeSharpCompiler.cs	(revision 3)
@@ -0,0 +1,73 @@
+/*code taken from: http://www.codeproject.com/csharp/RuntimeCompiling.asp*/
+
+using System;
+using System.Text;
+using Microsoft.CSharp;
+using System.CodeDom.Compiler;
+using System.Reflection;
+
+namespace TUG.Mogentes
+{
+    /// <summary>
+    /// This class can be used to execute dynamic uncompiled code at runtime
+    /// This class is not exception safe, all function calls should be exception handled.
+    /// </summary>
+    public class CSharpCodeCompiler
+    {
+        /// <summary>
+        /// This is the main code execution function.
+        /// It allows for any compilable c# code to be executed.
+        /// </summary>
+        /// <param name="code">the code to be compiled then executed</param>
+        /// <param name="namespacename">the name of the namespace to be executed</param>
+        /// <param name="classname">the name of the class of the function in the code that you will execute</param>
+        /// <param name="functionname">the name of the function that you will execute</param>
+        /// <param name="isstatic">True if the function you will execute is static, otherwise false</param>
+        /// <param name="args">any parameters that must be passed to the function</param>
+        /// <returns>what ever the executed function returns, in object form</returns>
+        public static object ExecuteCode(Assembly asm, string namespacename, string classname,
+            string functionname, params object[] args)
+        {
+            // Assembly asm = BuildAssembly(code, new string[] {"System.dll", "SepiasTool.exe"});
+            object instance = null;
+            object returnval = null;
+            Type type = asm.GetType(namespacename + "." + classname);
+            System.Reflection.MethodInfo method = type.GetMethod(functionname);
+            if (!method.IsStatic)
+            {
+                instance = asm.CreateInstance(namespacename + "." + classname);
+            }
+            returnval = method.Invoke(instance, args);
+            return returnval;
+        }
+
+        /// <summary>
+        /// This private function builds the assembly file into memory after compiling the code
+        /// </summary>
+        /// <param name="code">C# code to be compiled</param>
+        /// <returns>the compiled assembly object</returns>
+        /// 
+        public static Assembly BuildAssembly(string [] code, string[] referencedassemblies)
+        {
+            CodeDomProvider provider = new CSharpCodeProvider();
+            CompilerParameters compilerparams = new CompilerParameters();
+            compilerparams.GenerateExecutable = false;
+            compilerparams.GenerateInMemory = true;
+            compilerparams.ReferencedAssemblies.AddRange(referencedassemblies);
+            CompilerResults results = provider.CompileAssemblyFromSource(compilerparams, code);
+            if (results.Errors.HasErrors)
+            {
+                StringBuilder errors = new StringBuilder("Compiler Errors :\r\n");
+                foreach (CompilerError error in results.Errors)
+                {
+                    errors.AppendFormat("Line {0},{1}\t: {2}\n", error.Line, error.Column, error.ErrorText);
+                }
+                throw new UlyssesCompileException(errors.ToString());
+            }
+            else
+            {
+                return results.CompiledAssembly;
+            }
+        }
+    }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/parser/ooaExceptions.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/ooaExceptions.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/ooaExceptions.cs	(revision 3)
@@ -0,0 +1,47 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace TUG.Mogentes
+{
+    public class UlyssesException : Exception
+    {
+        // lacks all the constructors necessary for remoting..
+        public UlyssesException(string message)
+            : base(message)
+        { }
+    }
+
+    public class UlyssesCompileException : UlyssesException 
+    {
+        public UlyssesCompileException(string message)
+            : base(message)
+        { }
+    }
+
+    public class SymbolAlreadyDefinedException : UlyssesException
+    {
+        public SymbolAlreadyDefinedException(string message)
+            : base(message)
+        { }
+    }
+
+}
Index: branches/compiler/cSharp/ooasCompiler/src/parser/ooaExpressions.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/ooaExpressions.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/ooaExpressions.cs	(revision 3)
@@ -0,0 +1,1262 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using Antlr.Runtime;
+
+namespace TUG.Mogentes
+{
+    public enum ExpressionKind
+    {
+        /*tern.*/
+        conditional,
+        /*map binary*/
+        domresby, domresto, rngresby, rngresto, munion,
+        /*set/list binary*/
+        conc, diff, inter, elemin, notelemin, subset, union,
+        /*numeric binary*/
+        div, greater, greaterequal, idiv, less, lessequal, minus, mod, pow, prod, sum,
+        /*bool binary*/
+        and, biimplies, implies, or,
+        /*other binary*/
+        equal, notequal, seqmod_mapoverride,
+        /*map unary*/
+        dom, range, merge,
+        /*set/list unary*/
+        card, dconc, dinter, dunion, elems, head, inds, len, tail,
+        /*unary numberic*/
+        unminus, unplus, not, abs,
+        /*unary quantors*/
+        forall, exists,
+        /*Constructors*/
+        ListConstr, SetConstr, MapConstr, TupleConstr, ObjectConstr, QValConstr,
+        /* constant, identifier */
+        Value, Identifier, UnresolvedIdentifier, Type,
+        /* tuple access and method call */
+        TupleMapAccess, Call,
+        /* point operator */
+        Access,
+        /* primed */
+        Primed,
+        /* cast */
+        Cast,
+        /* fold */
+        foldLR, foldRL
+    }
+
+    /*
+    public enum UnaryOperatorType { unminus, unplus, not, abs }
+    public enum SetListUnaryOperatorType { card, dconc, dinter, dunion, elems, head, inds, len, tail }
+    public enum MapUnaryOperatorType { dom, range, merge }
+    public enum BinaryOperatorType { equal, notequal, seqmod_mapoverride }
+    public enum BoolBinaryOperatorType { and, biimplies, implies, or }
+    public enum NumericBinaryOperatorType { div, greater, greaterequal, idiv, less, lessequal, minus, mod, pow, prod, sum }
+    public enum SetListBinaryOperatorType { conc, diff, inter, elemin, notelemin, subset, union }
+    public enum MapBinaryOperatorType { domresby, domresto, rngresby, rngresto, munion }
+    */
+
+    ///////////////////////////////////////////////
+    ///  Expressions
+    ///
+    /// Note: Since we allow expression of the form
+    /// myTuple(a,b) = hd x, where a and b are newly
+    /// introduced placeholders, the expression knows
+    /// about local variables.
+    /// Scoping: Consider following expression
+    ///     3 > a and myTuple(b,d) = hd e and b < 5
+    /// which gives
+    ///             and
+    ///          /       \   
+    ///         /         and
+    ///        /        /     \ 
+    ///       >        =        <
+    ///      / \      /  \     /  \ 
+    ///     3   a  (b,d)  e   b    5
+    ///  the scope of b and d is defined by the binary
+    ///  expression that has the leaf within its left child
+    ///  (== the second 'and'). 
+    ///  Local variables may only be introduced in constructors
+    ///  of sets, lists, and tuples. Therefore the type is 
+    ///  known.
+
+
+    public abstract class Expression : UlyssesBasicClass, IAst
+    {
+        protected ExpressionKind m_kind;
+        protected UlyssesType m_type;
+        protected int m_line;
+        protected int m_pos;
+        protected SymbolTable m_freeVariables;
+        protected List<FunctionIdentifier> m_callTargets;
+
+        public ExpressionKind kind { get { return m_kind; } }
+        public UlyssesType type { get { return m_type; } }
+        public int line { get { return m_line; } }
+        public int pos { get { return m_pos; } }
+        public SymbolTable freeVariables { get { return m_freeVariables; } }
+        public List<FunctionIdentifier> callTargets { get { return m_callTargets; } }
+
+        public Expression(ExpressionKind aKind, int line, int pos)
+        {
+            m_kind = aKind;
+            m_line = line;
+            m_pos = pos;
+            m_callTargets = new List<FunctionIdentifier>();
+        }
+
+        public Expression(Expression toCopy)
+        {
+            m_kind = toCopy.m_kind;
+            m_line = toCopy.m_line;
+            m_pos = toCopy.m_pos;
+            m_callTargets = new List<FunctionIdentifier>(toCopy.callTargets);
+            m_type = toCopy.m_type;
+            m_freeVariables = new SymbolTable(toCopy.m_freeVariables);
+        }
+
+        public virtual Expression Clone()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void SetType(UlyssesType aType)
+        {
+            if (aType == null)
+                throw new ArgumentException();
+            m_type = aType;
+        }
+
+        public void SetFreeVariables(SymbolTable aSymTab)
+        {
+            m_freeVariables = aSymTab;
+        }
+
+        public List<ExpressionVariableIdentifier> GetUninitializedFreeVariables()
+        {
+            List<ExpressionVariableIdentifier> result = new List<ExpressionVariableIdentifier>();
+            if (m_freeVariables != null)
+                foreach (var v in m_freeVariables.symbolList)
+                {
+                    ExpressionVariableIdentifier id = (ExpressionVariableIdentifier)v;
+                    if (id.initialized == false)
+                        result.Add(id);
+                }
+            return result;
+        }
+
+
+        #region IAst Member
+
+        public AstNodeTypeEnum nodeType { get { return AstNodeTypeEnum.expression; } }
+
+        public virtual void Accept(IAstVisitor visitor)
+        {
+            throw new NotImplementedException();
+        }
+
+        #endregion
+
+
+        /// <summary>
+        /// Calculates the arithmetic cover, i.e. the return type of the operation, given two types.
+        /// This is different from the cover-method defined at the type level.
+        /// Note: We do saturating operations on the type boundaries.
+        /// </summary>
+        public static UlyssesType ArithmeticCover(UlyssesType type1, UlyssesType type2, ExpressionKind op)
+        {
+            if (!type1.IsNumeric() || (type2 != null && !type2.IsNumeric()))
+                throw new ArgumentException();
+
+            if (type1 is ValuedEnumType)
+                type1 = ((ValuedEnumType)type1).getIntType();
+            if (type2 is ValuedEnumType)
+                type2 = ((ValuedEnumType)type2).getIntType();
+
+            AbstractRange result;
+            AbstractRange rangeType1 = null;
+            AbstractRange rangeType2 = null;
+            AbstractOperations operations;
+            bool resultIsFloat = type1.kind == TypeKind.FloatType
+                                || op == ExpressionKind.div
+                                || (type2 != null && type2.kind == TypeKind.FloatType);
+            if (resultIsFloat)
+            {
+                rangeType1 = new DoubleRange(
+                    type1.kind == TypeKind.IntType ? ((IntType)type1).rangeHigh : ((FloatType)type1).high,
+                    type1.kind == TypeKind.IntType ? ((IntType)type1).rangeLow : ((FloatType)type1).low);
+                if (type2 != null)
+                {
+                    rangeType2 = new DoubleRange(
+                        type2.kind == TypeKind.IntType ? ((IntType)type2).rangeHigh : ((FloatType)type2).high,
+                        type2.kind == TypeKind.IntType ? ((IntType)type2).rangeLow : ((FloatType)type2).low);
+                }
+                operations = new SaturatedDoubleOperations();
+            }
+            else
+            {
+                rangeType1 = new IntegerRange(((IntType)type1).rangeHigh, ((IntType)type1).rangeLow);
+                rangeType2 = new IntegerRange(((IntType)type2).rangeHigh, ((IntType)type2).rangeLow);
+                operations = new SaturatedIntegerOperations();
+            }
+
+            switch (op)
+            {
+                case ExpressionKind.pow:
+                case ExpressionKind.prod:
+                case ExpressionKind.unminus:
+                case ExpressionKind.unplus:
+                case ExpressionKind.minus:
+                case ExpressionKind.sum:
+                case ExpressionKind.div:
+                    result = operations.GenericArithmeticCover(rangeType1, rangeType2, op);
+                    break;
+
+                case ExpressionKind.idiv:
+                    if (resultIsFloat)
+                        throw new ArgumentException();
+                    System.Diagnostics.Debug.Assert(type2 != null);
+                    result = operations.GenericArithmeticCover(rangeType1, rangeType2, op);
+                    break;
+                case ExpressionKind.mod:
+                    if (resultIsFloat)
+                        throw new ArgumentException();
+                    System.Diagnostics.Debug.Assert(type2 != null);
+                    result = new IntegerRange(((IntegerRange)rangeType2).max - 1, 0);
+                    break;
+
+                default:
+                    throw new NotImplementedException();
+            }
+
+            if (resultIsFloat)
+                return new FloatType(((DoubleRange)result).min, ((DoubleRange)result).max, FloatType.defaultPrecision, null);
+            else
+                // this is crude, but see whether it works..
+                return new IntType(((IntegerRange)result).min, ((IntegerRange)result).max, null);
+        }
+
+
+        public override string ToString()
+        {
+            OoaPrintVisitor visitor = new OoaPrintVisitor(null);
+            this.Accept(visitor);
+            return visitor.ToString();
+        }
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  === Leaf Expressions ===
+    ///  
+    public enum LeafTypeEnum { unset, boolean, integer, real, chr, qval, reference, identifier, type, complex }
+    public abstract class LeafExpression : Expression
+    {
+        protected LeafTypeEnum m_valueType;
+
+        public LeafTypeEnum valueType { get { return m_valueType; } }
+
+        public LeafExpression(LeafTypeEnum avalueType, ExpressionKind aKind, int line, int pos)
+            : base(aKind, line, pos)
+        {
+            m_valueType = avalueType;
+        }
+
+        public LeafExpression(LeafExpression toCopy)
+            : base(toCopy)
+        {
+            m_valueType = toCopy.m_valueType;
+        }
+    }
+
+
+
+    ///////////////////////////////////////////////
+    ///  Some constant bool, int, float, char,
+    ///  qval or nil value
+    ///  
+    public sealed class ValueExpression<T> : LeafExpression
+    {
+        private T m_value;
+
+        public T value { get { return m_value; } }
+
+        public ValueExpression(T aValue, int line, int pos)
+            : base(LeafTypeEnum.unset, ExpressionKind.Value, line, pos)
+        {
+            m_value = aValue;
+            if (typeof(T) == typeof(int))
+                m_valueType = LeafTypeEnum.integer;
+            else if (typeof(T) == typeof(bool))
+                m_valueType = LeafTypeEnum.boolean;
+            else if (typeof(T) == typeof(double))
+                m_valueType = LeafTypeEnum.real;
+            else if (typeof(T) == typeof(char))
+                m_valueType = LeafTypeEnum.chr;
+            else if (typeof(T).IsSubclassOf(typeof(QrType)))
+                m_valueType = LeafTypeEnum.qval;
+            else if (typeof(T).IsClass)
+                m_valueType = LeafTypeEnum.reference;
+            else
+                throw new ArgumentException();
+        }
+
+        public ValueExpression(ValueExpression<T> toCopy)
+            : base(toCopy)
+        {
+            m_value = toCopy.m_value;
+        }
+
+        public override Expression Clone()
+        {
+            return new ValueExpression<T>(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit<T>(this);
+        }
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Some identifier
+    ///  
+    public class IdentifierExpression : LeafExpression
+    {
+        protected Identifier m_identifier;
+        protected bool m_self;
+
+        public Identifier identifier { get { return m_identifier; } }
+        public bool isSelf { get { return m_self; } }
+
+        public IdentifierExpression(Identifier anIdentifier, int line, int pos)
+            : base(LeafTypeEnum.identifier, ExpressionKind.Identifier, line, pos)
+        {
+            m_identifier = anIdentifier;
+            if (anIdentifier != null)
+                m_type = m_identifier.type;
+            m_self = false;
+        }
+
+        public IdentifierExpression(IdentifierExpression toCopy)
+            : base(toCopy)
+        {
+            m_identifier = toCopy.m_identifier;
+            m_self = toCopy.m_self;
+        }
+
+        public override Expression Clone()
+        {
+            return new IdentifierExpression(this);
+        }
+
+        public void setIsSelf(bool newValue)
+        {
+            m_self = newValue;
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public void SetIdentifier(Identifier newIdentifier)
+        {
+            m_identifier = newIdentifier;
+        }
+    }
+
+    ///////////////////////////////////////////////
+    ///  Some identifier
+    ///  
+    public class TypeExpression : LeafExpression
+    {
+        public TypeExpression(UlyssesType atype, int line, int pos)
+            : base(LeafTypeEnum.type, ExpressionKind.Type, line, pos)
+        {
+            m_type = atype;
+        }
+
+        public TypeExpression(TypeExpression toCopy)
+            : base(toCopy)
+        { }
+
+        public override Expression Clone()
+        {
+            return new TypeExpression(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+    ///////////////////////////////////////////////
+    ///  Some unresolved identifier
+    ///  
+    public sealed class UnresolvedIdentifierExpression : IdentifierExpression
+    {
+        private IScope m_scope;
+        private string m_tokenText;
+
+
+        public string tokenText { get { return m_tokenText; } }
+        public IScope scope { get { return m_scope; } }
+
+        public UnresolvedIdentifierExpression(IToken identifier, IScope aScope)
+            : base(null, identifier.Line, identifier.CharPositionInLine)
+        {
+            m_kind = ExpressionKind.UnresolvedIdentifier;
+            m_tokenText = identifier.Text;
+            m_scope = aScope;
+        }
+
+        public UnresolvedIdentifierExpression(UnresolvedIdentifierExpression toCopy)
+            : base(toCopy)
+        {
+            m_scope = toCopy.m_scope;
+            m_tokenText = toCopy.m_tokenText;
+        }
+
+        public override Expression Clone()
+        {
+            return new UnresolvedIdentifierExpression(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  constructors
+    ///  
+    public abstract class TypeConstructionExpression : LeafExpression
+    {
+        public TypeConstructionExpression(ExpressionKind aKind, int line, int pos)
+            : base(LeafTypeEnum.complex, aKind, line, pos)
+        { }
+        public TypeConstructionExpression(TypeConstructionExpression toCopy)
+            : base(toCopy)
+        { }
+    }
+
+    public sealed class ObjectConstructor : TypeConstructionExpression
+    {
+        private List<OoActionSystemInstance> m_instances;
+        private int m_currentInstance;
+        private string m_fixedObjectName;
+
+        public int currentInstance { get { return m_currentInstance; } }
+        public List<OoActionSystemInstance> instances { get { return m_instances; } }
+        public string givenObjectName { get { return m_fixedObjectName; } }
+        
+        public void ResetCurrentInstance() { m_currentInstance = 0; }
+
+        public ObjectConstructor(OpaqueType aType, int line, int pos)
+            : base(ExpressionKind.ObjectConstr, line, pos)
+        {
+            SetType(aType);
+            m_instances = new List<OoActionSystemInstance>();
+            m_currentInstance = 0;
+        }
+
+        public ObjectConstructor(OpaqueType aType, string aName, int line, int pos)
+            : base(ExpressionKind.ObjectConstr, line, pos)
+        {
+            SetType(aType);
+            m_instances = new List<OoActionSystemInstance>();
+            m_currentInstance = 0;
+            m_fixedObjectName = aName;
+        }
+
+
+        public ObjectConstructor(ObjectConstructor toCopy)
+            : base(toCopy)
+        {
+            m_instances = new List<OoActionSystemInstance>( toCopy.m_instances);
+            m_currentInstance = toCopy.m_currentInstance;
+            m_fixedObjectName = toCopy.m_fixedObjectName;
+        }
+
+        public override Expression Clone()
+        {
+            return new ObjectConstructor(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public void AddInstance(OoActionSystemInstance anInstance)
+        {
+            m_instances.Add(anInstance);
+        }
+
+        public OoActionSystemInstance GetNextInstance()
+        {
+            OoActionSystemInstance result = m_instances[m_currentInstance];
+            m_currentInstance++;
+            return result;
+        }
+    }
+
+    ///////////////////////////////////////////////
+    ///  Constructor: List
+    ///  
+    public sealed class ListConstructor : TypeConstructionExpression, IScope
+    {
+        private List<Expression> m_elements;
+        private IScope m_parentScope;
+        private SymbolTable m_comprehensionVars;
+        private Expression m_comprehension;
+        private bool m_hasComprehension = false;
+
+        public List<Expression> elements { get { return m_elements; } }
+        public Expression comprehension { get { return m_comprehension; } }
+        public bool hasComprehension { get { return m_hasComprehension; } }
+        public SymbolTable comprehensionVariables { get { return m_comprehensionVars; } }
+
+        public ListConstructor(int line, int pos)
+            : base(ExpressionKind.ListConstr, line, pos)
+        {
+            m_elements = new List<Expression>();
+            m_comprehensionVars = new SymbolTable();
+        }
+
+        public ListConstructor(ListConstructor toCopy)
+            : base(toCopy)
+        {
+            m_elements = new List<Expression>(toCopy.m_elements);
+            m_parentScope = toCopy.m_parentScope;
+            m_comprehensionVars = new SymbolTable(toCopy.m_comprehensionVars);
+            m_comprehension = toCopy.m_comprehension;
+            m_hasComprehension = toCopy.m_hasComprehension;
+        }
+
+        public override Expression Clone()
+        {
+            return new ListConstructor(this);
+        }
+
+        public void AddElement(Expression anElement)
+        {
+            m_elements.Add(anElement);
+        }
+
+        public void SetComprehension(Expression comprehension)
+        {
+            m_comprehension = comprehension;
+        }
+
+        public void SetHasComprehension(bool flag)
+        {
+            m_hasComprehension = flag;
+        }
+
+        public Identifier ResolveIdentifier(string aName)
+        {
+            if (m_comprehensionVars.Defined(aName))
+                return m_comprehensionVars.Get(aName);
+            else
+                return null;
+        }
+
+        public IScope GetParentScope()
+        {
+            return m_parentScope;
+        }
+
+        public void SetParentScope(IScope parentScope)
+        {
+            m_parentScope = parentScope;
+        }
+
+        public void AddIdentifier(Identifier anIdentifier, object tag)
+        {
+            m_comprehensionVars.AddIdentifier(anIdentifier);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public void SetElements(List<Expression> newElements)
+        {
+            m_elements = newElements;
+        }
+
+    }
+
+    ///////////////////////////////////////////////
+    ///  Constructor: Set
+    ///  
+    public sealed class SetConstructor : TypeConstructionExpression, IScope
+    {
+        private List<Expression> m_items;
+        private SymbolTable m_comprehensionVars;
+        private IScope m_parentScope;
+        private Expression m_comprehension;
+        private bool m_hasComprehension = false;
+
+        public List<Expression> items { get { return m_items; } }
+        public Expression comprehension { get { return m_comprehension; } }
+        public bool hasComprehension { get { return m_hasComprehension; } }
+        public SymbolTable comprehensionVariables { get { return m_comprehensionVars; } }
+
+        public SetConstructor(int line, int pos)
+            : base(ExpressionKind.SetConstr, line, pos)
+        {
+            m_items = new List<Expression>();
+            m_comprehensionVars = new SymbolTable();
+        }
+
+        public SetConstructor(SetConstructor toCopy)
+            : base(toCopy)
+        {
+            m_items = new List<Expression>(toCopy.m_items);
+            m_comprehensionVars = new SymbolTable(toCopy.m_comprehensionVars);
+            m_parentScope = toCopy.m_parentScope;
+            m_comprehension = toCopy.m_comprehension;
+            m_hasComprehension = toCopy.m_hasComprehension;
+        }
+
+        public override Expression Clone()
+        {
+            return new SetConstructor(this);
+        }
+
+        public void AddItem(Expression anItem)
+        {
+            m_items.Add(anItem);
+        }
+
+        public void SetComprehension(Expression anExpr)
+        {
+            m_comprehension = anExpr;
+        }
+
+        public void SetHasComprehension(bool flag)
+        {
+            m_hasComprehension = flag;
+        }
+
+        public Identifier ResolveIdentifier(string aName)
+        {
+            if (m_comprehensionVars.Defined(aName))
+                return m_comprehensionVars.Get(aName);
+            else
+                return null;
+        }
+
+        public IScope GetParentScope()
+        {
+            return m_parentScope;
+        }
+
+        public void SetParentScope(IScope parentScope)
+        {
+            m_parentScope = parentScope;
+        }
+
+        public void AddIdentifier(Identifier anIdentifier, object tag)
+        {
+            m_comprehensionVars.AddIdentifier(anIdentifier);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public void SetItems(List<Expression> newItems)
+        {
+            m_items = newItems;
+        }
+
+    }
+
+    ///////////////////////////////////////////////
+    ///  Constructor: Map
+    ///  
+    public sealed class MapConstructor : TypeConstructionExpression
+    {
+        public sealed class MapItem
+        {
+            public Expression key;
+            public Expression value;
+            public MapItem(Expression aKey, Expression aValue)
+            {
+                key = aKey;
+                value = aValue;
+            }
+            public MapItem(MapItem toCopy)
+            {
+                key = toCopy.key;
+                value = toCopy.value;
+            }
+        }
+
+        private List<MapItem> m_items;
+
+        public List<MapItem> items { get { return m_items; } }
+
+        public MapConstructor(int line, int pos)
+            : base(ExpressionKind.MapConstr, line, pos)
+        {
+            m_items = new List<MapItem>();
+        }
+
+        public MapConstructor(MapConstructor toCopy)
+            : base(toCopy)
+        {
+            m_items = new List<MapItem>(toCopy.m_items);
+        }
+
+        public override Expression Clone()
+        {
+            return new MapConstructor(this);
+        }
+
+        public void AddItem(Expression mapFrom, Expression mapTo)
+        {
+            MapItem newitem = new MapItem(mapFrom, mapTo);
+            m_items.Add(newitem);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public void SetItems(List<MapItem> newItems)
+        {
+            m_items = newItems;
+        }
+
+    }
+
+    ///////////////////////////////////////////////
+    ///  Constructor: Tuple
+    ///  
+    public sealed class TupleConstructor : TypeConstructionExpression
+    {
+        private List<Expression> m_values;
+        private Identifier m_tupleType;
+        private bool m_matcher;
+
+        public List<Expression> values { get { return m_values; } }
+        public Identifier tupleType { get { return m_tupleType; } }
+        public bool isMatcher { get { return m_matcher; } }
+
+
+        public TupleConstructor(Identifier aType, System.Collections.Generic.List<Expression> exprs, int line, int pos)
+            : base(ExpressionKind.TupleConstr, line, pos)
+        {
+            m_tupleType = aType;
+            m_values = new List<Expression>(exprs);
+            m_matcher = false;
+        }
+
+        public TupleConstructor(TupleConstructor toCopy)
+            : base(toCopy)
+        {
+            m_values = new List<Expression>(toCopy.m_values);
+            m_tupleType = toCopy.m_tupleType;
+            m_matcher = toCopy.m_matcher;
+        }
+
+        public void SetIsMatcher(bool newVal)
+        {
+            m_matcher = newVal;
+        }
+
+        public override Expression Clone()
+        {
+            return new TupleConstructor(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public void SetTupleValues(List<Expression> values)
+        {
+            m_values = values;
+        }
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Constructor: Qualitative Value
+    ///  
+    public enum QValDeriv { DonTCare, Dec, Steady, Inc }
+    public sealed class QValConstructor : TypeConstructionExpression
+    {
+        private Expression[] m_value;
+        private QValDeriv m_derivValue;
+
+        public Expression[] value { get { return m_value; } }
+        public QValDeriv valueDeriv { get { return m_derivValue; } }
+
+
+        public QValConstructor(int line, int pos) :
+            base(ExpressionKind.QValConstr, line, pos)
+        {
+            m_value = new Expression[1];
+            m_value[0] = null;
+            m_derivValue = QValDeriv.DonTCare;
+        }
+
+        public QValConstructor(QValConstructor toCopy)
+            : base(toCopy)
+        {
+            m_value = new Expression[toCopy.m_value.Length];
+            Array.Copy(toCopy.m_value, m_value, m_value.Length);
+            m_derivValue = toCopy.m_derivValue;
+        }
+
+        public override Expression Clone()
+        {
+            return new QValConstructor(this);
+        }
+
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public void SetValue(Expression aval)
+        {
+            m_value[0] = aval;
+        }
+
+        public void AddRange(Expression toRange)
+        {
+            Expression currVal = m_value[0];
+            m_value = new Expression[2];
+            m_value[0] = currVal;
+            m_value[1] = toRange;
+        }
+
+        public void SetDerivation(QValDeriv newValue)
+        {
+            m_derivValue = newValue;
+        }
+    }
+
+
+
+    ///////////////////////////////////////////////
+    ///  === Binary Operator ===
+    ///  
+    public class BinaryOperator : Expression
+    {
+        protected Expression m_left;
+        protected Expression m_right;
+
+        public Expression left { get { return m_left; } }
+        public Expression right { get { return m_right; } }
+
+
+        public BinaryOperator(ExpressionKind aKind, Expression left, Expression right, int line, int pos)
+            : base(aKind, line, pos)
+        {
+            m_left = left;
+            m_right = right;
+        }
+
+        public BinaryOperator(BinaryOperator toCopy)
+            : base(toCopy)
+        {
+            m_left = toCopy.m_left;
+            m_right = toCopy.m_right;
+        }
+
+        public override Expression Clone()
+        {
+            return new BinaryOperator(this);
+        }
+
+        public void SetRightChild(Expression child)
+        {
+            m_right = child;
+        }
+
+        public void SetLeftChild(Expression child)
+        {
+            m_left = child;
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Element Access (Point operator):  a.b 
+    ///  
+    public sealed class AccessExpression : BinaryOperator
+    {
+        public AccessExpression(IdentifierExpression anIdentifier, Expression child, int line, int pos)
+            : base(ExpressionKind.Access, anIdentifier, child, line, pos)
+        { }
+
+        public AccessExpression(Expression anExpression, Expression child, int line, int pos)
+            : base(ExpressionKind.Access, anExpression, child, line, pos)
+        { }
+
+        public AccessExpression(AccessExpression toCopy)
+            : base(toCopy)
+        { }
+
+        public override Expression Clone()
+        {
+            return new AccessExpression(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+    }
+
+
+
+    ///////////////////////////////////////////////
+    ///  === Ternary Operator ===
+    ///  
+    public sealed class TernaryOperator : Expression
+    {
+        private Expression m_left;
+        private Expression m_mid;
+        private Expression m_right;
+        private IScope m_definingScope;
+
+        public Expression left { get { return m_left; } }
+        public Expression mid { get { return m_mid; } }
+        public Expression right { get { return m_right; } }
+        public IScope definingScope { get { return m_definingScope; } }
+
+        public TernaryOperator(ExpressionKind aKind, Expression left, Expression mid, Expression right, int line, int pos, IScope aScope)
+            : base(aKind, line, pos)
+        {
+            m_left = left;
+            m_mid = mid;
+            m_right = right;
+            m_definingScope = aScope;
+        }
+
+        public TernaryOperator(TernaryOperator toCopy)
+            : base(toCopy)
+        {
+            m_left = toCopy.m_left;
+            m_mid = toCopy.m_mid;
+            m_right = toCopy.m_right;
+            m_definingScope = toCopy.definingScope;
+        }
+
+        public override Expression Clone()
+        {
+            return new TernaryOperator(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public void SetLeftChild(Expression newExpression)
+        {
+            m_left = newExpression;
+        }
+        public void SetMidChild(Expression newExpression)
+        {
+            m_mid = newExpression;
+        }
+        public void SetRightChild(Expression newExpression)
+        {
+            m_right = newExpression;
+        }
+
+    }
+
+
+
+
+    ///////////////////////////////////////////////
+    ///  === Unary Operators ===
+    ///  
+    public class UnaryOperator : Expression
+    {
+        private Expression m_child;
+
+        public Expression child { get { return m_child; } }
+
+        public UnaryOperator(ExpressionKind aKind, Expression child, int line, int pos)
+            : base(aKind, line, pos)
+        {
+            m_child = child;
+        }
+
+        public UnaryOperator(UnaryOperator toCopy)
+            : base(toCopy)
+        {
+            m_child = toCopy.m_child;
+        }
+
+        public override Expression Clone()
+        {
+            return new UnaryOperator(this);
+        }
+
+        public void SetChild(Expression child)
+        {
+            m_child = child;
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public static Expression CoerceUp(Expression anExpr, UlyssesType target)
+        {
+            if (target == null)
+                throw new ArgumentException();
+
+            if (anExpr.kind == ExpressionKind.Value
+                && anExpr.type.kind == target.kind)
+            {
+                // if we are widening the range of a type assigned to a value, then just set the
+                // new type and skip constructing a new node.
+                anExpr.SetType(target);
+                return anExpr;
+            }
+            else
+            {
+                UnaryOperator result = new UnaryOperator(ExpressionKind.Cast, anExpr, anExpr.line, anExpr.pos);
+                result.SetType(target);
+                return result;
+            }
+        }
+
+        public static Expression TryCoerceUp(Expression anExpr, UlyssesType target)
+        {
+            if (!UlyssesType.TypeEqual(anExpr.type, target))
+            {
+                return CoerceUp(anExpr, target);
+            }
+            else
+                return anExpr;
+        }
+
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Tuple and Map Access "[...]"
+    ///  
+    public sealed class TupleMapAccessExpression : UnaryOperator
+    {
+        private Expression m_argument;
+
+        public Expression argument { get { return m_argument; } }
+
+        public TupleMapAccessExpression(Expression child, Expression argument, int line, int pos)
+            : base(ExpressionKind.TupleMapAccess, child, line, pos)
+        {
+            m_argument = argument;
+        }
+
+        public TupleMapAccessExpression(TupleMapAccessExpression toCopy)
+            : base(toCopy)
+        {
+            m_argument = toCopy.m_argument;
+        }
+
+
+        public override Expression Clone()
+        {
+            return new TupleMapAccessExpression(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public void SetArgument(Expression newarg)
+        {
+            if (newarg == null)
+                throw new ArgumentException();
+            m_argument = newarg;
+        }
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Method call  "(....)"
+    ///  
+    public sealed class CallExpression : UnaryOperator
+    {
+        private List<Expression> m_arguments;
+        private IScope m_CallScope;
+
+        public List<Expression> arguments { get { return m_arguments; } }
+        public IScope scope { get { return m_CallScope; } }
+
+        public CallExpression(Expression child, List<Expression> arguments, int line, int pos, IScope aScope)
+            : base(ExpressionKind.Call, child, line, pos)
+        {
+            if (arguments != null)
+                m_arguments = arguments;
+            else
+                m_arguments = new List<Expression>();
+            m_CallScope = aScope;
+        }
+
+        public CallExpression(CallExpression toCopy)
+            : base(toCopy)
+        {
+            m_arguments = new List<Expression>(toCopy.m_arguments);
+            m_CallScope = toCopy.m_CallScope;
+        }
+
+        public override Expression Clone()
+        {
+            return new CallExpression(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public void SetArguments(List<Expression> newArgs)
+        {
+            m_arguments = newArgs;
+        }
+    }
+
+
+
+    ///////////////////////////////////////////////
+    ///  Quantifier
+    ///  
+    public abstract class Quantifier : UnaryOperator, IScope
+    {
+        private SymbolTable m_symbols;
+        private IScope m_parentScope;
+
+        public SymbolTable symbols { get { return m_symbols; } }
+
+
+        public Quantifier(ExpressionKind aKind, Expression child, int line, int pos)
+            : base(aKind, child, line, pos)
+        {
+            m_symbols = new SymbolTable();
+        }
+
+        public Quantifier(Quantifier toCopy)
+            : base(toCopy)
+        {
+            m_symbols = new SymbolTable(toCopy.m_symbols);
+            m_parentScope = toCopy.m_parentScope;
+        }
+
+
+        public Identifier ResolveIdentifier(string aName)
+        {
+            if (m_symbols.Defined(aName))
+                return m_symbols.Get(aName);
+            else
+                return null;
+        }
+
+        public IScope GetParentScope()
+        {
+            return m_parentScope;
+        }
+
+        public void SetParentScope(IScope parentScope)
+        {
+            m_parentScope = parentScope;
+        }
+
+        public void AddIdentifier(Identifier anIdentifier, object tag)
+        {
+            m_symbols.AddIdentifier(anIdentifier);
+        }
+
+
+    }
+
+    public sealed class ForallQuantifier : Quantifier
+    {
+        public ForallQuantifier(Expression child, int line, int pos)
+            : base(ExpressionKind.forall, child, line, pos)
+        { }
+
+        public ForallQuantifier(ForallQuantifier toCopy)
+            : base(toCopy) { }
+
+        public override Expression Clone()
+        {
+            return new ForallQuantifier(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+    public sealed class ExistsQuantifier : Quantifier
+    {
+        public ExistsQuantifier(Expression child, int line, int pos)
+            : base(ExpressionKind.exists, child, line, pos)
+        { }
+        public ExistsQuantifier(ExistsQuantifier toCopy)
+            : base(toCopy) { }
+
+        public override Expression Clone()
+        {
+            return new ExistsQuantifier(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+
+}
Index: branches/compiler/cSharp/ooasCompiler/src/parser/ooaParser.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/ooaParser.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/ooaParser.cs	(revision 3)
@@ -0,0 +1,2057 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using Antlr.Runtime;
+using System.Text;
+using System.Collections.Generic;
+using System.Text.RegularExpressions;
+
+namespace TUG.Mogentes
+{
+
+    public class CompilerMessage
+    {
+        private string m_file;
+        private int m_line;
+        private int m_column;
+        private string m_message;
+
+        public CompilerMessage(string aFile, int aLine, int aColumn, string aMessage)
+        {
+            m_file = aFile;
+            m_line = aLine;
+            m_column = aColumn;
+            m_message = aMessage;
+        }
+
+        public CompilerMessage(string aFile, IToken aSymbol, string aMessage)
+        {
+            m_file = aFile;
+            m_line = aSymbol.Line;
+            m_column = aSymbol.CharPositionInLine;
+            m_message = aMessage;
+        }
+
+        public string file { get { return m_file; } }
+        public int line { get { return m_line; } }
+        public int column { get { return m_column; } }
+        public string message { get { return m_message; } }
+
+    }
+
+
+    public class ParserError : CompilerMessage
+    {
+        public ParserError(string aFile, int aLine, int aColumn, string aMessage)
+            : base(aFile, aLine, aColumn, aMessage)
+        { }
+
+        public ParserError(string aFile, IToken aSymbol, string aMessage)
+            : base(aFile, aSymbol, aMessage)
+        { }
+    }
+
+
+    public class ParserWarning : CompilerMessage
+    {
+        public ParserWarning(string aFile, int aLine, int aColumn, string aMessage)
+            : base(aFile, aLine, aColumn, aMessage)
+        { }
+
+        public ParserWarning(string aFile, IToken aSymbol, string aMessage)
+            : base(aFile, aSymbol, aMessage)
+        { }
+    }
+
+    public class ParserMessage : CompilerMessage
+    {
+        public ParserMessage(string aFile, int aLine, int aColumn, string aMessage)
+            : base(aFile, aLine, aColumn, aMessage)
+        { }
+
+        public ParserMessage(string aFile, IToken aSymbol, string aMessage)
+            : base(aFile, aSymbol, aMessage)
+        { }
+    }
+
+
+    public class ParserState
+    {
+        public ooaParser parser;
+        public ooaLexer lexer;
+        public string filename;
+        public string namesTypePrefix = String.Empty;
+        public bool parsingAttributes;
+
+
+        public MainModule ooaSystem;
+
+        public IScope currentScope;
+        public List<ParserError> listOfParserErrors;
+        public List<ParserWarning> listOfParserWarnings;
+        public List<ParserMessage> listOfParserMessages;
+        public List<OpaqueType> typesToFixUp;
+
+        public ParserState(Program.Options options)
+        {
+            listOfParserErrors = new List<ParserError>();
+            listOfParserWarnings = new List<ParserWarning>();
+            listOfParserMessages = new List<ParserMessage>();
+            typesToFixUp = new List<OpaqueType>();
+            this.filename = options.fileToParse;
+            this.namesTypePrefix = options.namedTypePrefix;
+            ICharStream input = new ANTLRFileStream(filename, Encoding.ASCII);
+            lexer = new ooaLexer(input);
+            CommonTokenStream tokens = new CommonTokenStream(lexer);
+            parser = new ooaParser(tokens);
+            parser.pState = this;
+        }
+
+        public void AddErrorMessage(ParserError parserError)
+        {
+            listOfParserErrors.Add(parserError);
+        }
+        public void AddWarningMessage(ParserWarning parserWarning)
+        {
+            listOfParserWarnings.Add(parserWarning);
+        }
+        public void AddMessage(ParserMessage aMessage)
+        {
+            listOfParserMessages.Add(aMessage);
+        }
+
+        public Identifier Lookup(string symbolName, IScope resolveStack)
+        {
+            string lkupname = symbolName;
+            do
+            {
+                Identifier result = resolveStack.ResolveIdentifier(lkupname);
+                if (result != null)
+                    return result;
+                resolveStack = resolveStack.GetParentScope();
+            } while (resolveStack != null);
+
+            return null;
+        }
+        public Identifier Lookup(string symbolName)
+        {
+            return Lookup(symbolName, currentScope);
+        }
+        public Identifier Lookup(IToken symbolName)
+        {
+            if (symbolName != null)
+                return Lookup(symbolName.Text);
+            else
+                return null;
+        }
+
+        public void PushResolveStack(IScope newScope)
+        {
+            // some sanity check.
+            if (newScope is MethodIdentifier)
+                System.Diagnostics.Debug.Assert(currentScope is OoActionSystemType);
+
+            newScope.SetParentScope(currentScope);
+            currentScope = newScope;
+        }
+        public void PopResolveStack()
+        {
+            currentScope = currentScope.GetParentScope();
+        }
+    }
+
+
+    public partial class ooaParser : Parser
+    {
+        public ParserState pState { get; set; }
+
+
+
+
+        public bool IsRightToLeft(ExpressionKind type)
+        {
+            return type == ExpressionKind.implies; // implication has right grouping
+        }
+
+        public int GetOperatorPrecedence(ExpressionKind type)
+        {
+            switch (type)
+            {
+                /*Family of Evaluators*/
+
+                case ExpressionKind.abs:    // T_ABS:
+                case ExpressionKind.card:   // T_CARD:
+                case ExpressionKind.dom:    // T_DOM:
+                case ExpressionKind.range:  // T_RNG:
+                case ExpressionKind.merge:  // T_MERGE:
+                case ExpressionKind.len:    // T_LEN:
+                case ExpressionKind.elems:  // T_ELEMS:
+                case ExpressionKind.head:   // T_HEAD:
+                case ExpressionKind.tail:   // T_TAIL:
+                case ExpressionKind.conc:   // T_CONC:
+                case ExpressionKind.inds:   // T_INDS:
+                case ExpressionKind.dinter: // T_DINTER:
+                case ExpressionKind.dunion: // T_DUNION:
+                    return 1;
+
+                case ExpressionKind.domresby:   // T_DOMRESBY:
+                case ExpressionKind.domresto:   // T_DOMRESTO:
+                case ExpressionKind.rngresby:   // T_RNGRESBY:
+                case ExpressionKind.rngresto:   // T_RNGRESTO:
+                    return 2;
+
+                case ExpressionKind.div:    // T_DIV:
+                case ExpressionKind.idiv:   // T_IDIV:
+                case ExpressionKind.mod:    // T_MOD:
+                case ExpressionKind.prod:   // T_PROD:
+                case ExpressionKind.inter:  // T_INTER:
+                    return 3;
+
+                case ExpressionKind.sum:    // T_SUM:
+                case ExpressionKind.minus:  // T_MINUS:
+                case ExpressionKind.union:  // T_UNION:
+                case ExpressionKind.diff:   // T_DIFF:
+                case ExpressionKind.munion: // T_MUNION:
+                case ExpressionKind.seqmod_mapoverride: // T_SEQMOD_MAPOVERRIDE:
+                    return 4;
+
+                /*Family of Relations*/
+
+                case ExpressionKind.less:
+                case ExpressionKind.lessequal:
+                case ExpressionKind.greater:
+                case ExpressionKind.greaterequal:
+                case ExpressionKind.equal:
+                case ExpressionKind.notequal:
+                case ExpressionKind.subset:
+                case ExpressionKind.elemin:
+                case ExpressionKind.notelemin:
+                    return 5;
+
+                /*Family of Connectives*/
+
+                case ExpressionKind.and:    // T_AND:
+                    return 6;
+
+                case ExpressionKind.or:     // T_OR:
+                    return 7;
+
+                case ExpressionKind.implies:    // T_IMPLIES:
+                    return 8;
+
+                case ExpressionKind.biimplies:  // T_BIIMPLIES:
+                    return 9;
+
+                default:
+                    throw new NotImplementedException("operator not supported: " + type.ToString());
+                // return 0;
+            }
+        }
+
+        /*taken from antlr homepage:
+         http://www.antlr.org/wiki/display/ANTLR3/Operator+precedence+parser
+         */
+        int findPivot(List<BinaryOperator> operators, int startIndex, int stopIndex)
+        {
+            int pivot = startIndex;
+            int pivotRank = GetOperatorPrecedence(operators[pivot].kind);
+            for (int i = startIndex + 1; i <= stopIndex; i++)
+            {
+                ExpressionKind type = operators[i].kind;
+                int current = GetOperatorPrecedence(type);
+                bool rtl = IsRightToLeft(type);
+                if (current > pivotRank || (current == pivotRank && rtl))
+                {
+                    pivot = i;
+                    pivotRank = current;
+                }
+            }
+            return pivot;
+        }
+
+        internal Expression createPrecedenceTree(
+            List<Expression> expressions,
+            List<BinaryOperator> operators,
+            int startIndex,
+            int stopIndex)
+        {
+            if (stopIndex == startIndex)
+                return expressions[startIndex];
+
+            int pivot = findPivot(operators, startIndex, stopIndex - 1);
+
+            BinaryOperator result = operators[pivot];
+            result.SetLeftChild(createPrecedenceTree(expressions, operators, startIndex, pivot));
+            result.SetRightChild(createPrecedenceTree(expressions, operators, pivot + 1, stopIndex));
+
+            return result;
+        }
+
+        internal Expression createPrecedenceTree(List<Expression> expressions, List<BinaryOperator> operators)
+        {
+            return createPrecedenceTree(expressions, operators, 0, expressions.Count - 1);
+        }
+
+
+        /* add error message to state. */
+        private void doError(IToken aToken, string aMessage)
+        {
+            pState.AddErrorMessage(
+                new ParserError(pState.filename, aToken, aMessage));
+        }
+
+        /* add warning message to state */
+        private void doWarning(IToken id1, string p)
+        {
+            pState.AddWarningMessage(new ParserWarning(pState.filename, id1, p));
+        }
+
+        private void doError(string aMessage)
+        {
+            pState.AddErrorMessage(
+                new ParserError(pState.filename, 0, 0, aMessage));
+        }
+
+        /* init global state */
+        internal void initializeTopLevelParserState()
+        {
+            pState.ooaSystem = new MainModule();
+            pState.PushResolveStack(pState.ooaSystem);
+        }
+
+
+        private IScope GetScope()
+        {
+            return pState.currentScope;
+        }
+
+
+        /*create a named constant*/
+        internal void addNamedConst(IToken aName, Expression anExpr)
+        {
+            if (pState.currentScope.ResolveIdentifier(aName.Text) == null)
+            {
+                /* needs to be a constant... */
+                ConstantIdentifier aConst = new ConstantIdentifier(aName, anExpr, GetScope());
+
+                OoaResolveExpressionsVisitor resolver = new OoaResolveExpressionsVisitor(pState);
+                aConst.Accept(resolver);
+
+                if (aConst.Value == null || aConst.Value.type == null || aConst.Value.kind != ExpressionKind.Value)
+                {
+                    doError(aName, String.Format("{0} not a constant!", aName.Text));
+                }
+                else
+                {
+                    aConst.SetType(aConst.Value.type);
+                    pState.currentScope.AddIdentifier(aConst, null);
+                }
+            }
+            else
+                doError(aName, String.Format("{0} already defined!", aName.Text));
+        }
+
+
+
+        /* create a named type; we're on top-level here */
+        internal void createNamedType(IToken aName, UlyssesType aType)
+        {
+            // precond..
+            System.Diagnostics.Debug.Assert(aName != null);
+
+            if (aType == null)
+            {
+                doError(aName, String.Format("{0} lacks a type! (Type not added)", aName.Text));
+                return;
+            }
+
+
+            if (pState.currentScope.ResolveIdentifier(aName.Text) == null)
+            {
+                TypeIdentifier newid = new TypeIdentifier(aName, aType, GetScope());
+                aType.SetTypeIdentifier(newid);
+                pState.currentScope.AddIdentifier(newid, null);
+            }
+            else
+                doError(aName, String.Format("{0} already defined!", aName.Text));
+
+        }
+
+        /* create basic structure for an ooa-system descr. resolve stack TOS is now ooa-system symbols */
+        internal OoActionSystemType createOoaType(IToken refinesSystemName, bool autoCons)
+        {
+            Identifier refinedSystem = pState.Lookup(refinesSystemName);
+            OoActionSystemType refinedSystemType = null;
+            if ((refinedSystem != null) && (refinedSystem.type != null))
+            {
+                if (refinedSystem.type.kind != TypeKind.OoActionSystemType)
+                    doError(refinesSystemName,
+                            String.Format("{0} not an object oriented action system", refinesSystemName.Text));
+                else
+                    refinedSystemType = (OoActionSystemType)refinedSystem.type;
+            }
+            else if (refinesSystemName != null)
+            {
+                pState.AddErrorMessage(
+                    new ParserError(pState.filename, refinesSystemName,
+                        String.Format("Type that's being refined ({0}) not found!", refinesSystemName.Text)));
+            }
+
+            OoActionSystemType result = new OoActionSystemType(autoCons, refinedSystemType, null);
+
+
+            // add 'self' to the symbols.. (self is a keyword, so it can't be defined)
+            result.AddIdentifier(new SelfTypeIdentifier("self", result, GetScope()), null);
+
+
+
+            pState.PushResolveStack(result);
+            return result;
+        }
+
+        /* remove ooa-system symbols from resolve stack TOS */
+        internal void fixupOoaType(OoActionSystemType aTypeSymbol)
+        {
+            if (aTypeSymbol == null)
+                return;
+
+            aTypeSymbol.SetupAnonymousName();
+            if (aTypeSymbol != null)
+                pState.PopResolveStack();
+        }
+
+        internal Expression addCastExpression(Expression e, IToken cid)
+        {
+            System.Diagnostics.Debug.Assert(e != null);
+
+            Expression result = new UnaryOperator(ExpressionKind.Cast, e, cid.Line, cid.CharPositionInLine);
+            result.SetType(new OpaqueType(new TypeIdentifier(cid, null, GetScope())));
+            pState.typesToFixUp.Add((OpaqueType)result.type);
+            return result;
+        }
+
+
+        /* add a new ooa to the list describing the composition of action systems */
+        internal void addToIdentifierList(IdentifierList top, IToken aName)
+        {
+            System.Diagnostics.Debug.Assert(top != null);
+
+            Identifier aSym = pState.Lookup(aName);
+            if (aSym == null)
+            {
+                doError(aName, String.Format("Could not find ooa-system {0}!", aName.Text));
+            }
+            else if ((aSym.type == null) || !(aSym.type.kind == TypeKind.OoActionSystemType))
+            {
+                doError(aName, String.Format("Referenced type ({0}) does not have correct type!", aName.Text));
+            }
+            else
+            {
+                OoActionSystemType aType = (OoActionSystemType)aSym.type;
+                if (aType.isInSystemDescription)
+                    doError(aName, String.Format("Referenced type ({0}) already used in composition!", aName.Text));
+                else
+                    aType.SetIsInSystemDescription(true);
+                top.AddElement(aSym);
+            }
+        }
+
+        /* does a fixup run after parsing */
+        internal void fixUpRun(IdentifierList sysDescr)
+        {
+            // set system descr.
+            pState.ooaSystem.SetSystemDescription(sysDescr);
+
+            // fixup named types
+            FixupNamedTypes();
+        }
+
+        private void FixupNamedTypes()
+        {
+            /*named type refs that could not be resolved in the first run, have to
+              be resolved now. */
+            foreach (var ntype in pState.typesToFixUp)
+            {
+                if (ntype.resolvedType == null)
+                {
+                    //ntype.identifier
+                    Identifier asym = pState.Lookup(ntype.identifier.tokenText, ntype.identifier.definingScope);
+                    if ((asym == null) || (asym.kind != IdentifierKind.TypeIdentifier))
+                    {
+                        ParserError error = new ParserError(pState.filename, ntype.identifier.line, ntype.identifier.column,
+                            String.Format("Can not resolve {0} to a named type", ntype.identifier.tokenText));
+                        pState.AddErrorMessage(error);
+                    }
+                    else
+                        ntype.SetResolvedType(asym.type);
+                }
+            }
+            pState.typesToFixUp.Clear();
+        }
+
+
+        private bool TosIsActionSystem()
+        {
+            return pState.currentScope is OoActionSystemType;
+        }
+
+
+        private int currentLine
+        {
+            get
+            {
+                IToken token = input.LT(-1);
+                return token == null ? 0 : token.Line;
+            }
+        }
+
+        private int currentPos
+        {
+            get
+            {
+                IToken token = input.LT(-1);
+                return token == null ? 0 : token.CharPositionInLine;
+            }
+        }
+
+        /* add var symbol to the current action system */
+        internal void createAttribute(IToken varname, bool isStatic, bool isObs, bool isCtr, UlyssesType aType, Expression anExpr)
+        {
+            if (!TosIsActionSystem())
+                return;
+
+            if (aType == null)
+            {
+                doError(varname, String.Format("{0} lacks type!", varname.Text));
+            }
+            if (anExpr == null)
+            {
+                doError(varname, String.Format("{0} lacks initializer!", varname.Text));
+            }
+            if (isObs == true || isCtr == true)
+                if (aType.kind != TypeKind.QrType)
+                    doError(varname, "'obs' or 'ctr' on attributes only allowed for qualitative types");
+
+
+            AttributeIdentifier var = new AttributeIdentifier(varname, aType, GetScope(), anExpr, isStatic, isObs, isCtr);
+            if (pState.currentScope.ResolveIdentifier(varname.Text) == null)
+                pState.currentScope.AddIdentifier(var, null);
+            else
+                doError(varname, String.Format("Can not add {0}: Symbol already defined!", varname.Text));
+        }
+
+
+        /* create a bool type */
+        internal BoolType createBoolType()
+        {
+            return new BoolType(null);
+        }
+
+        /* create a char type */
+        internal CharType createCharType()
+        {
+            return new CharType(null);
+        }
+
+        /* create an int type */
+        internal UlyssesType createIntType(IToken rangeLow, IToken rangeHigh)
+        {
+            int low = 0;
+            int high = 0;
+
+            if (rangeLow.Type == ooaLexer.T_INFTY)
+                doError(rangeLow, "Infinity not supported.");
+            if (rangeLow.Type == ooaLexer.T_INFTY)
+                doError(rangeHigh, "Infinity not supported.");
+
+            if (rangeLow.Type == ooaLexer.T_IDENTIFIER)
+            {
+                // see whether we can find the constant
+                Identifier aconst = pState.currentScope.ResolveIdentifier(rangeLow.Text);
+                if (aconst == null || aconst.kind != IdentifierKind.Constant)
+                    doError(rangeLow, String.Format("Constant {0} not found", rangeLow.Text));
+                else if (aconst.type.kind != TypeKind.IntType)
+                    doError(rangeLow, "Constant must be integer");
+                else
+                    low = ((ValueExpression<int>)((ConstantIdentifier)aconst).Value).value;
+            }
+            else
+                if (!Int32.TryParse(rangeLow.Text, out low))
+                    doError(rangeLow, "Can not convert to integer");
+
+            if (rangeHigh.Type == ooaLexer.T_IDENTIFIER)
+            {
+                // see whether we can find the constant
+                Identifier aconst = pState.currentScope.ResolveIdentifier(rangeHigh.Text);
+                if (aconst == null || aconst.kind != IdentifierKind.Constant)
+                    doError(rangeHigh, String.Format("Constant {0} not found", rangeHigh.Text));
+                else if (aconst.type.kind != TypeKind.IntType)
+                    doError(rangeHigh, "Constant must be integer");
+                else
+                    high = ((ValueExpression<int>)((ConstantIdentifier)aconst).Value).value;
+            }
+            else
+                if (!Int32.TryParse(rangeHigh.Text, out high))
+                    doError(rangeHigh, "Can not convert to interger");
+
+            if (high < low)
+                doError(rangeHigh, "Lower bound greater than upper bound");
+
+            return new IntType(low, high, null);
+        }
+
+        /* create a float type */
+        internal UlyssesType createFloatType(IToken rangeLow, IToken rangeHigh)
+        {
+            float low = 0;
+            float high = 0;
+
+            if (rangeLow.Type == ooaLexer.T_INFTY)
+                doError(rangeLow, "Infinity not supported.");
+            if (rangeLow.Type == ooaLexer.T_INFTY)
+                doError(rangeHigh, "Infinity not supported.");
+
+            if (rangeLow.Type == ooaLexer.T_IDENTIFIER)
+            {
+                // see whether we can find the constant
+                Identifier aconst = pState.currentScope.ResolveIdentifier(rangeLow.Text);
+                if (aconst == null || aconst.kind != IdentifierKind.Constant)
+                    doError(rangeLow, String.Format("Constant {0} not found", rangeLow.Text));
+                else if (aconst.type.kind != TypeKind.FloatType)
+                    doError(rangeLow, "Constant must be float");
+                else
+                    low = ((ValueExpression<int>)((ConstantIdentifier)aconst).Value).value;
+            }
+            else if (!float.TryParse(rangeLow.Text, out low))
+                doError(rangeLow, "Can not convert to float (single)");
+
+            if (rangeHigh.Type == ooaLexer.T_IDENTIFIER)
+            {
+                // see whether we can find the constant
+                Identifier aconst = pState.currentScope.ResolveIdentifier(rangeHigh.Text);
+                if (aconst == null || aconst.kind != IdentifierKind.Constant)
+                    doError(rangeHigh, String.Format("Constant {0} not found", rangeHigh.Text));
+                else if (aconst.type.kind != TypeKind.FloatType)
+                    doError(rangeHigh, "Constant must be integer");
+                else
+                    high = ((ValueExpression<int>)((ConstantIdentifier)aconst).Value).value;
+            }
+            else if (!float.TryParse(rangeHigh.Text, out high))
+                doError(rangeHigh, "Can not convert to float (single)");
+
+            if (high < low)
+                doError(rangeHigh, "Lower bound greater than upper bound");
+
+            /* precision */
+            float afterc_low = low - (float)Convert.ToInt32(low);
+            float afterc_high = high - (float)Convert.ToInt32(high);
+            float precision = afterc_low < afterc_high ? afterc_low : afterc_high;
+
+            return new FloatType(low, high, precision, null);
+        }
+
+        /* create a list of an enumerated type */
+        internal UlyssesType createListEnumType(IToken alistelem)
+        {
+            EnumType hiddenEnumType = new EnumType(null);
+
+            ListType result = new ListType(hiddenEnumType, 500, null);
+            addToListEnumType(result, alistelem);
+            return result;
+        }
+
+        /* add a new enum symbol to a list with an anonymous enumerated type */
+        internal void addToListEnumType(UlyssesType aTypeSymbol, IToken otherlistelem)
+        {
+            EnumType enumtype = (EnumType)((ListType)aTypeSymbol).innerType;
+            addToEnumType(enumtype, otherlistelem, null);
+        }
+
+        /* create a new enumerated type */
+        internal UlyssesType createEnumType(IToken aRangeValue, IToken anIntegerValue)
+        {
+            EnumType result;
+
+            if (anIntegerValue == null)
+                result = new EnumType(null);
+            else
+                result = new ValuedEnumType(null);
+
+            addToEnumType(result, aRangeValue, anIntegerValue);
+            return result;
+        }
+
+        /* add a new enum symbol to the enumerated type */
+        internal void addToEnumType(UlyssesType aTypeSymbol, IToken otherRangeValue, IToken anIntegerValue)
+        {
+            EnumType anEnum = (EnumType)aTypeSymbol;
+            if (anEnum.symbolTable.Defined(otherRangeValue.Text))
+            {
+                doError(otherRangeValue, String.Format("Element '{0}' already defined!", otherRangeValue.Text));
+                return;
+            }
+
+            /* for now we allow the usage of enum-ids without specifying the actual enum type,
+             * e.g., x = some_enum_id, hence all enum identifier must be globally unique.
+             * This decision could be reverted at later time...
+             */
+            Identifier sym = pState.Lookup(otherRangeValue);
+            if (sym != null)
+            {
+                doError(otherRangeValue, String.Format("Element '{0}' already defined!", otherRangeValue.Text));
+                return;
+            }
+
+            EnumIdentifier enumval;
+            if (anIntegerValue == null)
+            {
+                if (aTypeSymbol is ValuedEnumType)
+                {
+                    doError(otherRangeValue, String.Format("Element '{0}' needs integer value!", otherRangeValue.Text));
+                    return;
+                }
+
+                enumval = new EnumIdentifier(otherRangeValue, (EnumType)aTypeSymbol, GetScope());
+            }
+            else
+            {
+                if (!(aTypeSymbol is ValuedEnumType))
+                {
+                    doError(otherRangeValue, String.Format("Element '{0}' must not have integer value!", otherRangeValue.Text));
+                    return;
+                }
+                enumval = new EnumIdentifier(otherRangeValue, Int32.Parse(anIntegerValue.Text), (EnumType)aTypeSymbol, GetScope());
+            }
+
+            ((EnumType)aTypeSymbol).AddEnumSymbol(enumval);
+
+            /* add the enum id to 'global' state */
+            pState.currentScope.AddIdentifier(enumval, null);
+        }
+
+        /* get a named type */
+        internal UlyssesType getNamedType(IToken aType)
+        {
+            UlyssesType result = null;
+            Identifier sym = pState.Lookup(aType);
+            if (sym == null)
+            {
+                /* we might not have seen this type yet - so do a fixup run later */
+                result = new OpaqueType(new TypeIdentifier(aType, null, GetScope()));
+                pState.typesToFixUp.Add((OpaqueType)result);
+            }
+            else if (sym.kind == IdentifierKind.TypeIdentifier)
+                result = ((TypeIdentifier)sym).type;
+            else
+                doError(aType, "Not a named type symbol!");
+
+            return result;
+        }
+
+        /* create a list type */
+        internal UlyssesType createListType(IToken numOfElements, UlyssesType innertype)
+        {
+            if (innertype == null)
+                doError(numOfElements, "List type lacks proper element type (null)");
+
+            int numElems = 0;
+
+            if (numOfElements.Type == ooaLexer.T_IDENTIFIER)
+            {
+                // see whether we can find the constant
+                Identifier aconst = pState.currentScope.ResolveIdentifier(numOfElements.Text);
+                if (aconst == null || aconst.kind != IdentifierKind.Constant)
+                    doError(numOfElements, String.Format("Constant {0} not found", numOfElements.Text));
+                else if (aconst.type.kind != TypeKind.IntType)
+                    doError(numOfElements, "Constant must be integer");
+                else
+                    numElems = ((ValueExpression<int>)((ConstantIdentifier)aconst).Value).value;
+            }
+            else
+            {
+                if (!Int32.TryParse(numOfElements.Text, out numElems))
+                    doError(numOfElements, "Not an integer");
+                if (numElems <= 0)
+                    doError(numOfElements, "Number of elements in a list must be >= 1");
+            }
+
+            ListType result = new ListType(innertype, numElems, null);
+            return result;
+        }
+
+        /* create a map type */
+        internal UlyssesType createMapType(IToken numOfElements, UlyssesType mapfromtype, UlyssesType maptotype)
+        {
+            if (mapfromtype == null)
+                doError(numOfElements, "Map: From-type not set (null)");
+            if (maptotype == null)
+                doError(numOfElements, "Map: To-type not set (null)");
+
+            int max = 0;
+
+            if (numOfElements.Type == ooaLexer.T_IDENTIFIER)
+            {
+                // see whether we can find the constant
+                Identifier aconst = pState.currentScope.ResolveIdentifier(numOfElements.Text);
+                if (aconst == null || aconst.kind != IdentifierKind.Constant)
+                    doError(numOfElements, String.Format("Constant {0} not found", numOfElements.Text));
+                else if (aconst.type.kind != TypeKind.IntType)
+                    doError(numOfElements, "Constant must be integer");
+                else
+                    max = ((ValueExpression<int>)((ConstantIdentifier)aconst).Value).value;
+            }
+            else
+                if (!Int32.TryParse(numOfElements.Text, out max))
+                    doError(numOfElements, "Not an integer");
+
+            MapType result = new MapType(mapfromtype, maptotype, max, null);
+            return result;
+        }
+
+        /* create a tuple type */
+        internal UlyssesType createTupleType(UlyssesType aType)
+        {
+            TupleType result = new TupleType(null);
+            if (aType == null)
+                doError("Unknown inner type.");
+            else
+                addToTupleType(result, aType);
+            return result;
+        }
+
+        /* add inner type to tuple */
+        internal void addToTupleType(UlyssesType aTypeSymbol, UlyssesType anotherType)
+        {
+            if (anotherType == null)
+                doError("Unknown inner type.");
+            else
+            {
+                TupleType tuple = (TupleType)aTypeSymbol;
+                tuple.AddType(anotherType);
+            }
+        }
+
+        /* create a QR type */
+        internal UlyssesType createQrType(IToken alandmark)
+        {
+            QrType result = new QrType(null);
+            addToQrType(result, alandmark);
+            return result;
+        }
+
+        /* add another landmark to QR type */
+        private void addToQrType(UlyssesType aTypeSymbol, IToken otherlandmark)
+        {
+            Identifier sym = pState.Lookup(otherlandmark);
+            if (sym != null)
+            {
+                doError(otherlandmark, String.Format("Redifinition of {0}", otherlandmark.Text));
+                return;
+            }
+
+            LandmarkIdentifier lndmrk = new LandmarkIdentifier(otherlandmark, (QrType)aTypeSymbol, GetScope());
+            ((QrType)aTypeSymbol).AddLandmark(lndmrk);
+        }
+
+        /* gets called after a simple type has been constructed. used to define an internal name*/
+        internal void fixupSimpleType(UlyssesType aTypeSymbol)
+        {
+            if (aTypeSymbol != null)
+                aTypeSymbol.SetupAnonymousName();
+        }
+
+        /* gets called after a simple or complex type has been constructed. used to define an internal name */
+        internal void fixupComplexType(UlyssesType aTypeSymbol)
+        {
+            if (aTypeSymbol != null)
+                aTypeSymbol.SetupAnonymousName();
+        }
+
+
+        /* create a method symbol */
+        internal FunctionIdentifier createMethodSymbol(IToken mname)
+        {
+            Identifier sym = pState.Lookup(mname);
+            if (sym != null)
+            {
+                doError(mname, String.Format("Redefinition of {0}", mname.Text));
+                return null;
+            }
+
+            FunctionType funtype = new FunctionType(FunctionTypeEnum.Method, new LinkedList<UlyssesType>(), null);
+            MethodIdentifier msym = new MethodIdentifier(mname, funtype, GetScope());
+            funtype.SetTypeIdentifier(msym);
+
+            pState.currentScope.AddIdentifier(msym, null);
+
+            pState.PushResolveStack(msym);
+            return msym;
+        }
+
+        /* remove local method symbols from resolution stack again */
+        private void popResolveStack(FunctionIdentifier newMethod)
+        {
+            if (newMethod != null)
+                pState.PopResolveStack();
+        }
+
+
+        /* add a return type to a method */
+        internal void setMethodReturnType(FunctionIdentifier newMethod, UlyssesType rt)
+        {
+            if (newMethod == null)
+                return;
+
+            if (rt == null)
+                doError(String.Format("Method {0} has no return type (null)", newMethod.tokenText));
+
+            /* set return type */
+            ((FunctionType)newMethod.type).SetReturnType(rt);
+
+
+            /* add hidden return parameter */
+            if (newMethod.symbolTable.Defined("result"))
+            {
+                doError(String.Format("Method {0} defines 'result'", newMethod.tokenText));
+                return;
+            }
+
+            ParameterIdentifier returnval = new ParameterIdentifier("result", rt, GetScope());
+            newMethod.symbolTable.AddIdentifier(returnval);
+        }
+
+        /* add a parameter to a method */
+        internal void addMethodParameter(FunctionIdentifier newMethod, IToken paramName, UlyssesType atype)
+        {
+            if (newMethod == null)
+                return;
+
+            if (atype == null)
+                doError(paramName, "Parameter has no type (null)");
+
+
+            if (newMethod.symbolTable.Defined(paramName.Text) == true)
+            {
+                doError(paramName, String.Format("Parameter {0} already defined", paramName.Text));
+                return;
+            }
+
+            // add parameter to scope
+            ParameterIdentifier param = new ParameterIdentifier(paramName, atype, GetScope());
+            newMethod.AddParameter(param);
+
+            // add type of param to signature
+            FunctionType ftype = (FunctionType)newMethod.type;
+            ftype.AddParameterType(atype);
+        }
+
+        /* set method body of a method */
+        internal void addMethodBody(FunctionIdentifier newMethod, Block statements)
+        {
+            if (newMethod == null)
+                return;
+
+            if (statements == null)
+                doError(String.Format("{0} has empty body (null)",
+                    ((FunctionType)newMethod.type).functionType == FunctionTypeEnum.Method ? "Method" : "Action"));
+
+            newMethod.SetBody(statements);
+        }
+
+        /* create a continuous action */
+        internal FunctionIdentifier createNamedContinuousAction(IToken cactionname, FunctionTypeEnum actionTypeEnum)
+        {
+            return createNamedAction(cactionname, actionTypeEnum);
+        }
+
+        /* create a named action */
+        internal FunctionIdentifier createNamedAction(IToken actionname, FunctionTypeEnum actionType)
+        {
+            Identifier sym = pState.Lookup(actionname);
+            if (sym != null)
+            {
+                doError(actionname, "Symbol already defined.");
+                return null;
+            }
+
+            FunctionType atype = new FunctionType(actionType, new LinkedList<UlyssesType>(), null);
+            NamedActionIdentifier action = new NamedActionIdentifier(actionname, atype, GetScope());
+            atype.SetTypeIdentifier(action);
+
+            pState.currentScope.AddIdentifier(action, null);
+            pState.PushResolveStack(action);
+            return action;
+        }
+
+        /* add body of action */
+        internal void addActionBody(FunctionIdentifier newAction, GuardedCommand body)
+        {
+            // we need a wrapper around the guarded command..
+            Block bdy = new SeqBlock(currentLine, currentPos);
+            bdy.AddStatement(body);
+            addMethodBody(newAction, bdy);
+        }
+
+        /* add constraints of cont. action */
+        internal void addContinuousActionBody(FunctionIdentifier newAction, GuardedCommand constraints)
+        {
+            Block bdy = new SeqBlock(currentLine, currentPos);
+            bdy.AddStatement(constraints);
+            addMethodBody(newAction, bdy);
+        }
+
+        /* create a guarded command */
+        internal GuardedCommand createGuardedCommandStatement(Expression expr, Block bdy)
+        {
+            if (bdy == null)
+                doError("Guarded command without body (null)!");
+
+            if (expr == null)
+                doError("Guarded command without guard (null)!");
+
+            GuardedCommand result = new GuardedCommand(expr, bdy, currentLine, currentPos);
+            return result;
+        }
+        internal GuardedCommand createGuardedCommandStatement(Expression expr, Block bdy, bool isQualitative)
+        {
+            GuardedCommand result = createGuardedCommandStatement(expr, bdy);
+            result.SetIsQualitative(isQualitative);
+            return result;
+        }
+
+        /* add statements to list */
+        internal void addToStatementList(Block top, Statement stmt)
+        {
+            if (stmt == null)
+                doError("Can not add statement: null!");
+
+            top.AddStatement(stmt);
+        }
+
+        /* create a Kill statement */
+        internal Statement createKillStatement(IToken aname)
+        {
+            Identifier sym = pState.Lookup(aname);
+            if (sym == null)
+                doError(aname, "Not defined");
+
+            KillStatement result = new KillStatement(sym, aname.Line, aname.CharPositionInLine);
+            return result;
+        }
+
+        /* create a Skip statement */
+        internal Statement createSkipStatement()
+        {
+            return new SkipStatement(currentLine, currentPos);
+        }
+
+        /* create an Abort statement */
+        internal Statement createAbortStatement()
+        {
+            return new AbortStatement(currentLine, currentPos);
+        }
+
+        /* creates a prioritized composition block */
+        internal Block createPrioBlock(Block top)
+        {
+            return new PrioBlock(top, currentLine, currentPos);
+        }
+
+        /* creates a nondeterministically composed block */
+        internal Block createNondetBlock(Block top)
+        {
+            return new NondetBlock(top, currentLine, currentPos);
+        }
+
+        /* creates a sequentially composed block */
+        internal Block createSeqBlock(Block top)
+        {
+            return new SeqBlock(top, currentLine, currentPos);
+        }
+
+
+        /* adds a filter expression to seq block */
+        private void addSeqBlockExpression(Block seqList, Expression sexpr)
+        {
+            seqList.SetFilter(sexpr); /*gets transformed to guarded command in resolvevisitor!*/
+        }
+
+
+        /* create a self identifier */
+        internal IdentifierExpression createSelfIdentifierExpression(IToken self)
+        {
+            Identifier id = pState.Lookup("self");
+            if (id == null)
+            {
+                doError(self, "Can not resolve 'self'");
+                return null;
+            }
+
+            IdentifierExpression result = new IdentifierExpression(id, self.Line, self.CharPositionInLine);
+            result.setIsSelf(true);
+            return result;
+        }
+
+        /* build up identifier tree... */
+        internal Expression createIdentifierAccessExpression(IdentifierExpression aself, IToken token)
+        {
+            Identifier someid = pState.Lookup(token.Text, GetScope());
+            Identifier self = pState.Lookup("self");
+
+            if (someid != null)
+            {
+                switch (someid.kind)
+                {
+                    /* all method and attribute accesses are prefixed by self */
+                    case IdentifierKind.AttributeIdentifier:
+                    case IdentifierKind.MethodIdentifier:
+                        if (self == null)
+                            doError(token, "Self access of method: Can not find 'self' symbol! (internal error)");
+                        aself = new IdentifierExpression(self, token.Line, token.CharPositionInLine);
+                        aself.setIsSelf(true);
+                        break;
+                    default:
+                        break;
+                }
+            }
+
+            IdentifierExpression ident = new UnresolvedIdentifierExpression(token, GetScope());
+            if (aself != null)
+                return new AccessExpression(aself, ident, token.Line, token.CharPositionInLine);
+            else
+                return ident;
+        }
+
+        internal AccessExpression addIdentifierAccessExpression(Expression parent, IToken token)
+        {
+            IdentifierExpression ident = new UnresolvedIdentifierExpression(token, GetScope());
+            return new AccessExpression(parent, ident, token.Line, token.CharPositionInLine);
+        }
+
+        /* we have a primed id; prime the complete subtree.. */
+        internal void setIdentifierExpressionPrimed(ref Expression result, IToken token)
+        {
+            Expression priming = new UnaryOperator(ExpressionKind.Primed, result, token.Line, token.CharPositionInLine);
+            result = priming;
+        }
+
+        /* create a fold operation */
+        internal Expression createFoldExpression(Expression result, IToken afold, Expression initval, Expression anexpr)
+        {
+            ExpressionKind akind = ExpressionKind.foldLR;
+            if (afold.Type == ooaLexer.T_FOLDLR)
+                akind = ExpressionKind.foldLR;
+            else if (afold.Type == ooaLexer.T_FOLDRL)
+                akind = ExpressionKind.foldRL;
+            else
+                System.Diagnostics.Debug.Assert(false);
+
+            TernaryOperator op = new TernaryOperator(akind, result, initval, anexpr, currentLine, currentPos, GetScope());
+            return op;
+        }
+
+
+        /* create a method access */
+        internal CallExpression createMethodAccessExpression(Expression subexpr, List<Expression> m_params, IToken token)
+        {
+            System.Diagnostics.Debug.Assert(subexpr != null);
+
+            return new CallExpression(subexpr, m_params, token.Line, token.CharPositionInLine, GetScope());
+        }
+
+        /* create a tuple or map access */
+        internal TupleMapAccessExpression createTupleMapAccessExpression(Expression subexpr, Expression ac, IToken token)
+        {
+            System.Diagnostics.Debug.Assert(subexpr != null);
+
+            return new TupleMapAccessExpression(subexpr, ac, token.Line, token.CharPositionInLine);
+        }
+
+        /* create a method call statement; has to be resolved in a second run */
+        internal Statement createCallStatement(Expression aqname)
+        {
+            return new Call(aqname, currentLine, currentPos);
+        }
+
+        /* create a single assignment statement */
+        internal Statement createSingleAssignmentStatement(Expression aqname, Expression aexp)
+        {
+            Assignment result = new Assignment(aqname, aexp, null, currentLine, currentPos);
+            return result;
+        }
+
+        /* create a multi-assignment statement; has to be resolved in a second run */
+        internal Statement createMultipleAssignmentStatementLHS(Expression aqname)
+        {
+            return new Assignment(aqname, null, null, currentLine, currentPos);
+        }
+
+        /* adds an expression to the multi-assign */
+        internal void addMutlipleAssignmentStatementRHS(Statement result, Expression mexp)
+        {
+            ((Assignment)result).AddValue(mexp);
+        }
+
+        /* adds a LHS-var to the multi assign */
+        internal void addMultipleAssignmentStatementLHS(Statement result, Expression malhs)
+        {
+            ((Assignment)result).AddPlace(malhs);
+        }
+
+        /* pop an assignment statement from the resolve stack */
+        internal void popAssignmentOffResolveStack(Statement result)
+        {
+            System.Diagnostics.Debug.Assert(ReferenceEquals(result, pState.currentScope));
+            pState.PopResolveStack();
+        }
+
+        /* pushes the assignment statement onto resolve stack. */
+        internal void pushAssignmentOnResolveStack(Statement result)
+        {
+            System.Diagnostics.Debug.Assert(result is Assignment);
+            pState.PushResolveStack((Assignment)result);
+        }
+
+
+        /* adds a nondet-assignment constraint */
+        internal void addConstraintToAssignment(Statement result, Expression ndexp)
+        {
+            ((Assignment)result).SetNondetExpression(ndexp);
+        }
+
+        /* add a named action call to do-od block */
+        internal void addNamedActionCallToBlockList(Block top, IToken aname, List<Expression> m_params, IToken maptoken, Expression amapexpression)
+        {
+            Identifier id = pState.Lookup(aname);
+            if (id == null)
+            {
+                doError(aname, "Could not find named action");
+                return;
+            }
+            Expression callexpr;
+            if (id.kind == IdentifierKind.MethodIdentifier)
+            {
+                doError(aname, "Method access in do-od block not allowed.");
+                return;
+                // access via self
+                /*
+                Identifier self = pState.Lookup("self");
+                if (self == null)
+                    doError(aname, "Self access of method: Can not find 'self' symbol! (internal error)");
+                IdentifierExpression aself = new IdentifierExpression(self, aname.Line, aname.CharPositionInLine);
+                aself.setIsSelf(true);
+                callexpr = new CallExpression(
+                    new AccessExpression(aself,
+                        new IdentifierExpression(id, aname.Line, aname.CharPositionInLine), aname.Line, aname.CharPositionInLine),
+                        m_params, aname.Line, aname.CharPositionInLine, GetScope());
+                 */
+            }
+            else
+                callexpr = new CallExpression(
+                   new IdentifierExpression(id, aname.Line, aname.CharPositionInLine),
+                       m_params, aname.Line, aname.CharPositionInLine, GetScope());
+
+            if (amapexpression != null)
+            {
+                ExpressionKind akind = ExpressionKind.foldLR;
+                if (maptoken.Type == ooaLexer.T_FOLDLR)
+                    akind = ExpressionKind.foldLR;
+                else if (maptoken.Type == ooaLexer.T_FOLDRL)
+                    akind = ExpressionKind.foldRL;
+                else
+                    System.Diagnostics.Debug.Assert(false);
+
+                callexpr = new TernaryOperator(akind, callexpr, null, amapexpression,
+                    currentLine, currentPos, GetScope());
+            }
+            Call statement = new Call(callexpr, currentLine, currentPos);
+            top.AddStatement(statement);
+        }
+
+        /*adds skip statement instead of call to do-od block*/
+        internal void addSkipStatementToBlockList(Block top)
+        {
+            top.AddStatement(new SkipStatement(currentLine, currentPos));
+        }
+
+
+        /* add anonymous action to do-od block */
+        internal void addToBlockList(Block top, Statement gcmd)
+        {
+            if (gcmd != null)
+                top.AddStatement(gcmd);
+        }
+
+        /* add the do-od block to the action system type */
+        internal void addActionBlock(OoActionSystemType aTypeSymbol, Block bl)
+        {
+            aTypeSymbol.SetDoOdBlock(bl);
+        }
+
+        /* push block */
+        internal void pushBlockToResolveStack(Block toPush)
+        {
+            pState.PushResolveStack(toPush);
+        }
+
+        /* pop block */
+        internal void popBlockFromResolveStack(Block toPop)
+        {
+            if (toPop != null)
+            {
+                object anobject = pState.currentScope as Block;
+                System.Diagnostics.Debug.Assert(Object.ReferenceEquals(anobject, toPop));
+
+                pState.PopResolveStack();
+            }
+        }
+
+        /* add block var */
+        internal void addBlockVariable(Block seqList, IToken varname, UlyssesType aType)
+        {
+            if (aType == null)
+            {
+                doError(varname, String.Format("{0} lacks type!", varname.Text));
+            }
+            try
+            {
+                seqList.AddIdentifier(new LocalVariableIdentifier(varname, aType, GetScope()));
+            }
+            catch (ArgumentException)
+            {
+                doError(varname, String.Format("{0} redefined!", varname.Text));
+            }
+        }
+
+
+        internal QualitativeConstraintStatement createTwoVarConstraintStatement(IToken id1, IToken id2, QualitativeConstraintOperation op)
+        {
+            Identifier var1 = pState.Lookup(id1);
+            if (var1 == null)
+            {
+                var1 = new ExpressionVariableIdentifier(id1.Text, id1.Line, id1.CharPositionInLine);
+                var1.SetType(new AnyType((ExpressionVariableIdentifier)var1));
+
+                GetScope().AddIdentifier(var1, null);
+
+                doWarning(id1, String.Format("Free variable in qualitative constraint: '{0}'.", id1.Text));
+            }
+
+            Identifier var2 = pState.Lookup(id2);
+            if (var2 == null)
+            {
+                var2 = new ExpressionVariableIdentifier(id2.Text, id2.Line, id2.CharPositionInLine);
+                var2.SetType(new AnyType((ExpressionVariableIdentifier)var2));
+
+                GetScope().AddIdentifier(var2, null);
+
+                doWarning(id1, String.Format("Free variable in qualitative constraint: '{0}'.", id2.Text));
+            }
+
+            QualitativeConstraintStatement result = new QualitativeConstraintStatement(var1, var2, op, id1.Line, id1.CharPositionInLine);
+            return result;
+        }
+
+
+        internal QualitativeConstraintStatement createQualEqualConstraintStatement(IToken id1, IToken id2)
+        {
+            return createTwoVarConstraintStatement(id1, id2, QualitativeConstraintOperation.Equal);
+        }
+
+        internal QualitativeConstraintStatement createQualArithConstraintStatement(IToken id1, IToken id2, IToken id3, IToken op)
+        {
+            Identifier var1 = pState.Lookup(id1);
+            if (var1 == null)
+            {
+                var1 = new ExpressionVariableIdentifier(id1.Text, id1.Line, id1.CharPositionInLine);
+                var1.SetType(new AnyType((ExpressionVariableIdentifier)var1));
+
+                GetScope().AddIdentifier(var1, null);
+
+                doWarning(id1, String.Format("Free variable in qualitative constraint: '{0}'.", id1.Text));
+            }
+
+            Identifier var2 = pState.Lookup(id2);
+            if (var2 == null)
+            {
+                var2 = new ExpressionVariableIdentifier(id2.Text, id2.Line, id2.CharPositionInLine);
+                var2.SetType(new AnyType((ExpressionVariableIdentifier)var2));
+
+                GetScope().AddIdentifier(var2, null);
+
+                doWarning(id1, String.Format("Free variable in qualitative constraint: '{0}'.", id2.Text));
+            }
+
+            Identifier var3 = pState.Lookup(id3);
+            if (var3 == null)
+            {
+                var3 = new ExpressionVariableIdentifier(id3.Text, id3.Line, id3.CharPositionInLine);
+                var3.SetType(new AnyType((ExpressionVariableIdentifier)var3));
+
+                GetScope().AddIdentifier(var3, null);
+
+                doWarning(id1, String.Format("Free variable in qualitative constraint: '{0}'.", id3.Text));
+            }
+            QualitativeConstraintOperation operation;
+            switch (op.Type)
+            {
+                case ooaParser.T_SUM:
+                    operation = QualitativeConstraintOperation.Sum;
+                    break;
+                case ooaParser.T_DIFF:
+                    operation = QualitativeConstraintOperation.Diff;
+                    break;
+                case ooaParser.T_PROD:
+                    operation = QualitativeConstraintOperation.Prod;
+                    break;
+                default:
+                    doError(op, String.Format("'{0}' unknown operation", op.Text));
+                    return null;
+            }
+
+            QualitativeConstraintStatement result = new QualitativeConstraintStatement(var1, var2, var3, operation, id1.Line, id1.CharPositionInLine);
+            return result;
+        }
+
+        internal QualitativeConstraintStatement createQualDerivConstraintStatement(IToken id1, IToken derivid)
+        {
+            return createTwoVarConstraintStatement(id1, derivid, QualitativeConstraintOperation.Deriv);
+        }
+
+
+
+        /* creates a general binary operator without any children */
+        internal BinaryOperator createBinaryOperator(ExpressionKind akind)
+        {
+            IToken token = input.LT(-1);
+            return new BinaryOperator(akind, null, null, token.Line, token.CharPositionInLine);
+        }
+
+
+        /* creates a general unary operator without child */
+        internal UnaryOperator createUnaryOperator(ExpressionKind unaryOperatorType)
+        {
+            IToken token = input.LT(-1);
+            return new UnaryOperator(unaryOperatorType, null, token.Line, token.CharPositionInLine);
+        }
+
+        /* create a conditional expression */
+        internal Expression createConditionalExpression(Expression ce, Expression te, Expression ee, IToken ef)
+        {
+            return new TernaryOperator(ExpressionKind.conditional, ce, te, ee, ef.Line, ef.CharPositionInLine, GetScope());
+        }
+
+        /* create a quantifier expression */
+        internal Quantifier createQuantifierExpression(IToken t)
+        {
+            Quantifier result = null;
+            if (t.Type == T_FORALL)
+                result = new ForallQuantifier(null, t.Line, t.CharPositionInLine);
+            else
+                result = new ExistsQuantifier(null, t.Line, t.CharPositionInLine);
+
+
+            pState.PushResolveStack(result);
+            return result;
+        }
+
+        /* add a bound variable to the quantifier */
+        internal void addBoundVarToQuantifierExpression(Quantifier result, IToken id, UlyssesType id_type)
+        {
+            /*note: this might be a bit harsh, but for now it's easier to demand uniquely named vars,
+                    without any hiding. Could be fixed in searching only the first resolve level for
+                    dupes.. 
+             */
+            Identifier sym = pState.Lookup(id);
+            if (sym != null)
+                doError(id, String.Format("{0} already defined!", id.Text));
+            else
+            {
+                if (id_type == null)
+                    doError(id, String.Format("{0} lacks type (null).", id.Text));
+                Identifier newvar = new ExpressionVariableIdentifier(id, id_type, GetScope());
+                result.AddIdentifier(newvar, null);
+            }
+        }
+
+        /* add the expression to the quantifier */
+        internal void addExpressionToQuantifier(Quantifier result, Expression e)
+        {
+            result.SetChild(e);
+        }
+
+        /* remove local variables from resolve stack */
+        internal void removeBoundVarsFromResolveStack(Quantifier result)
+        {
+            if (result != null)
+                pState.PopResolveStack();
+        }
+
+
+        /* create a bool constant */
+        internal LeafExpression createBoolConstant(bool p)
+        {
+            IToken token = input.LT(-1);
+            return new ValueExpression<bool>(p, token.Line, token.CharPositionInLine);
+        }
+
+        /* create a nil */
+        internal LeafExpression createNullPointerConstant()
+        {
+            IToken token = input.LT(-1);
+            return new ValueExpression<object>(null, token.Line, token.CharPositionInLine);
+        }
+
+        /* create a 'self' identifier */
+        internal LeafExpression createSelfPointer()
+        {
+            IToken token = input.LT(-1);
+            Identifier self = pState.Lookup("self");
+            if (self == null)
+            {
+                doError(token, "Could not resolve 'self'");
+                return new UnresolvedIdentifierExpression(token, GetScope());
+            }
+
+            IdentifierExpression result = new IdentifierExpression(self, token.Line, token.CharPositionInLine);
+            result.setIsSelf(true);
+
+            return result;
+        }
+
+        /* create a float const */
+        internal LeafExpression createFloatConstant(IToken t_fl)
+        {
+            return new ValueExpression<double>(double.Parse(t_fl.Text, System.Globalization.CultureInfo.InvariantCulture), t_fl.Line, t_fl.CharPositionInLine);
+        }
+
+        /* create int const */
+        internal LeafExpression createIntConstant(IToken t_in)
+        {
+            return new ValueExpression<int>(int.Parse(t_in.Text), t_in.Line, t_in.CharPositionInLine);
+        }
+
+        /* set children of binary operator*/
+        internal Expression addBinaryExpression(BinaryOperator binexpr, Expression expr, Expression e2)
+        {
+            binexpr.SetLeftChild(expr);
+            binexpr.SetRightChild(e2);
+            return binexpr;
+        }
+
+        /* set child of unary expr */
+        internal Expression addUnaryExpression(UnaryOperator unexpr, Expression e)
+        {
+            if (unexpr != null)
+            {
+                unexpr.SetChild(e);
+                return unexpr;
+            }
+            else
+                return e;
+        }
+
+
+
+        /* create a list */
+        internal ListConstructor createInitializedList()
+        {
+            IToken nexttoken = input.LT(1);
+            return new ListConstructor(nexttoken.Line, nexttoken.CharPositionInLine);
+        }
+
+        /* add an element to the list */
+        internal void addListElement(ListConstructor result, Expression e)
+        {
+            result.AddElement(e);
+        }
+
+        /* push list comprehension vars on resolve stack */
+        internal void pushListVarsOnResolveStack(ListConstructor result)
+        {
+            pState.PushResolveStack(result);
+        }
+
+        /* pop list comprehension vars from resolve stack */
+        internal void popListVarsFromResolveStack(ListConstructor result)
+        {
+            if (result != null)
+                pState.PopResolveStack();
+        }
+
+        /* set list comprehension expression */
+        internal void addListComprExpr(ListConstructor result, Expression e)
+        {
+            result.SetComprehension(e);
+        }
+
+        /* add list comprehension variable */
+        internal void addListComprVar(ListConstructor result, IToken id, UlyssesType t1)
+        {
+            Identifier sym = pState.Lookup(id);
+            if (sym != null)
+            {
+                /* see notes in quantifier*/
+                doError(id, String.Format("{0} already defined.", id.Text));
+            }
+            else
+            {
+                ExpressionVariableIdentifier newvar = new ExpressionVariableIdentifier(id, t1, GetScope());
+                result.AddIdentifier(newvar, null);
+            }
+        }
+
+        /* converts a string into a list of char */
+        internal ListConstructor createStringConstant(IToken t_l)
+        {
+            ListConstructor result = new ListConstructor(t_l.Line, t_l.CharPositionInLine);
+            foreach (char c in t_l.Text.Substring(1, t_l.Text.Length - 2))
+                result.AddElement(new ValueExpression<char>(c, t_l.Line, t_l.CharPositionInLine));
+            return result;
+        }
+
+        /* creates an empty map */
+        internal Expression createEmptyMap()
+        {
+            IToken token = input.LT(-1);
+            return new MapConstructor(token.Line, token.CharPositionInLine);
+        }
+
+        /* create a map and populate it with two items.. */
+        internal Expression createMap(Expression e1, Expression e2, IToken am)
+        {
+            MapConstructor result = new MapConstructor(am.Line, am.CharPositionInLine);
+            result.AddItem(e1, e2);
+            return result;
+        }
+
+        /* add a key/value pair to a map */
+        internal void addToMap(Expression map, Expression e3, Expression e4)
+        {
+            ((MapConstructor)map).AddItem(e3, e4);
+        }
+
+        /* create a set */
+        internal SetConstructor createSet()
+        {
+            IToken nexttoken = input.LT(1);
+            SetConstructor result = new SetConstructor(nexttoken.Line, nexttoken.CharPositionInLine);
+            return result;
+        }
+
+        /* add item to set */
+        internal void addToSet(Expression result, Expression e2)
+        {
+            ((SetConstructor)result).AddItem(e2);
+        }
+
+        /* remove set comprehension variables from resolution stack */
+        internal void popSetVarsFromResolveStack(SetConstructor _set)
+        {
+            if (_set != null)
+                pState.PopResolveStack();
+        }
+
+        /* add set comprehension variables to resolution stack */
+        internal void pushSetVarsOnResolveStack(SetConstructor _set)
+        {
+            pState.PushResolveStack(_set);
+        }
+
+        /* set comprehension expression fro set */
+        internal void addSetComprExpr(SetConstructor _set, Expression epx)
+        {
+            _set.SetComprehension(epx);
+        }
+
+        /* add local set compr. variable */
+        internal void addSetComprVar(SetConstructor _set, IToken id1, UlyssesType t1)
+        {
+            Identifier sym = pState.Lookup(id1);
+            if (sym != null)
+                doError(id1, String.Format("{0} already defined!", id1.Text));
+            else
+            {
+                ExpressionVariableIdentifier newvar = new ExpressionVariableIdentifier(id1, t1, GetScope());
+                _set.AddIdentifier(newvar, null);
+            }
+        }
+
+        /* check whether identifier p is a tuple type */
+        internal bool isTuple(string p)
+        {
+            Identifier sym = pState.Lookup(p);
+            return (sym != null)
+                && (sym.kind == IdentifierKind.TypeIdentifier)
+                && (sym.type.kind == TypeKind.TupleType);
+        }
+
+        /* create an initialized tuple */
+        internal Expression createInitializedTuple(IToken aName, System.Collections.Generic.List<Expression> m_params)
+        {
+            Identifier sym = pState.Lookup(aName);
+            if ((sym == null) || !(sym.type is TupleType))
+            {
+                doError(aName, "Not a tuple type!");
+                return null;
+            }
+
+            TupleType atuple = (TupleType)sym.type;
+            if (atuple.innerTypes.Count != m_params.Count)
+            {
+                doError(aName, "Number of parameters does not match type definition!");
+                return null;
+            }
+
+            return new TupleConstructor(sym, m_params, aName.Line, aName.CharPositionInLine);
+        }
+
+
+        /* create an reference expression: (<expression>).xyz */
+        internal Expression createExpressionReference(Expression e, Expression aref, IToken atoken)
+        {
+            AccessExpression result = new AccessExpression(e, aref, atoken.Line, atoken.CharPositionInLine);
+            return result;
+        }
+
+
+        /* gets called when we are parsing attributes */
+        internal void BeginParsingAttributes()
+        {
+            pState.parsingAttributes = true;
+        }
+
+        /* gets called when we stop parsing attributes */
+        internal void EndParsingAttributes()
+        {
+            pState.parsingAttributes = false;
+        }
+
+        /*dummy*/
+        internal bool notIsAttributeInitialization()
+        {
+            return !pState.parsingAttributes;
+        }
+
+        /* create a new(anid) constructor */
+        private Expression createObject(IToken anid)
+        {
+            if (!pState.parsingAttributes)
+            {
+                doError(anid, "Object creation with 'new' only allowed in variable initializers.");
+                return null;
+            }
+
+
+            OpaqueType atype = new OpaqueType(new TypeIdentifier(anid, null, GetScope()));
+            pState.typesToFixUp.Add(atype);
+            return new ObjectConstructor(atype, anid.Line, anid.CharPositionInLine);
+        }
+
+
+        private Expression createNamedObject(IToken anid, IToken aname)
+        {
+            if (!pState.parsingAttributes)
+            {
+                doError(anid, "Object creation with 'new' only allowed in variable initializers.");
+                return null;
+            }
+
+            Regex validid = new Regex("\"[_]*[a-zA-Z][a-zA-Z0-9_]*\"");
+            if (!validid.IsMatch(aname.Text))
+            {
+                doError(aname, "Not a valid identifier");
+                return null;
+            }
+
+            OpaqueType atype = new OpaqueType(new TypeIdentifier(anid, null, GetScope()));
+            pState.typesToFixUp.Add(atype);
+            return new ObjectConstructor(atype, aname.Text, anid.Line, anid.CharPositionInLine);
+        }
+
+
+        internal void setQualitativeDerivDec(QValConstructor result)
+        {
+            result.SetDerivation(QValDeriv.Dec);
+        }
+
+        internal void setQualitativeDerivInc(QValConstructor result)
+        {
+            result.SetDerivation(QValDeriv.Inc);
+        }
+
+        internal void setQualitativeDerivSteady(QValConstructor result)
+        {
+            result.SetDerivation(QValDeriv.Steady);
+        }
+
+        internal void setQualitativeDerivDontCare(QValConstructor result)
+        {
+            result.SetDerivation(QValDeriv.DonTCare);
+        }
+
+        internal void setQualitativeValueRangeInfinity(QValConstructor result, bool p)
+        {
+            throw new NotImplementedException();
+        }
+
+        internal void setQualitativeValueRange(QValConstructor result, Expression expr2)
+        {
+            result.AddRange(expr2);
+        }
+
+        internal void setQualitativeValueInfinity(QValConstructor result, bool minus)
+        {
+            throw new NotImplementedException();
+        }
+
+        internal void setQualitativeValueLandmark(QValConstructor result, Expression expr)
+        {
+            result.SetValue(expr);
+        }
+
+        internal void setQualitativeValueDontCare(QValConstructor result)
+        {
+            throw new NotImplementedException();
+        }
+
+        internal QValConstructor createQualitativeValue(IToken aval)
+        {
+            return new QValConstructor(aval.Line, aval.CharPositionInLine);
+        }
+
+        /* add a local variable to a named action */
+        internal void addLocalVariableToNamedAction(FunctionIdentifier newMethod, IToken id1, UlyssesType t1)
+        {
+            if (t1 == null)
+            {
+                doError(id1, "Variable lacks type");
+                return;
+            }
+
+            LocalVariableIdentifier lvar = new LocalVariableIdentifier(id1, t1, GetScope());
+            newMethod.AddIdentifier(lvar, null);
+        }
+
+        /* ====== */
+        /* ====== */
+
+        public Dictionary<string, string> readableTokens = new Dictionary<string, string>();
+
+
+        private void SetUpTokenDictionary()
+        {
+            if (readableTokens.Count > 0)
+                return;
+            readableTokens.Add("<invalid>", "<invalid>");
+            readableTokens.Add("<EOR>", "<EOR>");
+            readableTokens.Add("<DOWN>", "<DOWN>");
+            readableTokens.Add("<UP>", "<UP>");
+            readableTokens.Add("T_TYPES", "'types'");
+            readableTokens.Add("T_SYSTEM", "'system'");
+            readableTokens.Add("T_SEMICOLON", "';'");
+            readableTokens.Add("T_IDENTIFIER", "<identifier>");
+            readableTokens.Add("T_EQUAL", "'='");
+            readableTokens.Add("T_PRIO", "'//'");
+            readableTokens.Add("T_NONDET", "'[]'");
+            readableTokens.Add("T_LPAREN", "'('");
+            readableTokens.Add("T_RPAREN", "')'");
+            readableTokens.Add("T_LIST", "'list'");
+            readableTokens.Add("T_LSQPAREN", "'['");
+            readableTokens.Add("T_INTNUMBER", "<integer>");
+            readableTokens.Add("T_RSQPAREN", "']'");
+            readableTokens.Add("T_OF", "'of'");
+            readableTokens.Add("T_COMMA", "','");
+            readableTokens.Add("T_MAP", "'map'");
+            readableTokens.Add("T_TO", "'to'");
+            readableTokens.Add("T_QUANTITY", "'quantity'");
+            readableTokens.Add("T_INFTY", "'inf'");
+            readableTokens.Add("T_BOOL", "'bool'");
+            readableTokens.Add("T_INT", "'int'");
+            readableTokens.Add("T_RANGETO", "'..'");
+            readableTokens.Add("T_FLOAT", "'float'");
+            readableTokens.Add("T_FLOATNUMBER", "<floating point number>");
+            readableTokens.Add("T_CHAR", "'char'");
+            readableTokens.Add("T_CBRL", "'{'");
+            readableTokens.Add("T_CBRR", "'}'");
+            readableTokens.Add("T_AUTOCONS", "'autocons'");
+            readableTokens.Add("T_VAR", "'var'");
+            readableTokens.Add("T_METHODS", "'methods'");
+            readableTokens.Add("T_ACTIONS", "'actions'");
+            readableTokens.Add("T_DO", "'do'");
+            readableTokens.Add("T_OD", "'od'");
+            readableTokens.Add("T_STATIC", "'static'");
+            readableTokens.Add("T_COLON", "':'");
+            readableTokens.Add("T_END", "'end'");
+            readableTokens.Add("T_CONT", "'cont'");
+            readableTokens.Add("T_CTRL", "'ctr'");
+            readableTokens.Add("T_OBS", "'obs'");
+            readableTokens.Add("T_REQUIRES", "'requires'");
+            readableTokens.Add("T_AND", "'and'");
+            readableTokens.Add("T_ABORT", "'abort'");
+            readableTokens.Add("T_SKIP", "'skip'");
+            readableTokens.Add("T_KILL", "'kill'");
+            readableTokens.Add("T_SELF", "'self'");
+            readableTokens.Add("T_ASSIGNMENT", "':='");
+            readableTokens.Add("T_WITH", "'with'");
+            readableTokens.Add("T_IF", "'if'");
+            readableTokens.Add("T_THEN", "'then'");
+            readableTokens.Add("T_ELSE", "'else'");
+            readableTokens.Add("T_FORALL", "'forall'");
+            readableTokens.Add("T_EXISTS", "'exists'");
+            readableTokens.Add("T_TRUE", "'true'");
+            readableTokens.Add("T_FALSE", "'false'");
+            readableTokens.Add("T_NIL", "'nil'");
+            readableTokens.Add("T_STRINGLITERAL", "'\"<string>\"'");
+            readableTokens.Add("T_NEW", "'new'");
+            readableTokens.Add("T_BAR", "'|'");
+            readableTokens.Add("T_MAPS", "'->'");
+            readableTokens.Add("T_PRIMED", "'''");
+            readableTokens.Add("T_POINT", "'.'");
+            readableTokens.Add("T_NOTEQUAL", "'<>'");
+            readableTokens.Add("T_SEQMOD_MAPOVERRIDE", "'++'");
+            readableTokens.Add("T_BIIMPLIES", "'<=>'");
+            readableTokens.Add("T_IMPLIES", "'=>'");
+            readableTokens.Add("T_OR", "'or'");
+            readableTokens.Add("T_ABS", "'abs'");
+            readableTokens.Add("T_DIV", "'/'");
+            readableTokens.Add("T_GREATER", "'>'");
+            readableTokens.Add("T_GREATEREQUAL", "'>='");
+            readableTokens.Add("T_IDIV", "'div'");
+            readableTokens.Add("T_LESS", "'<'");
+            readableTokens.Add("T_LESSEQUAL", "'<='");
+            readableTokens.Add("T_MINUS", "'-'");
+            readableTokens.Add("T_MOD", "'mod'");
+            readableTokens.Add("T_POW", "'**'");
+            readableTokens.Add("T_PROD", "'*'");
+            readableTokens.Add("T_SUM", "'+'");
+            readableTokens.Add("T_CONC", "'^'");
+            readableTokens.Add("T_DIFF", "'\\'");
+            readableTokens.Add("T_INTER", "'inter'");
+            readableTokens.Add("T_IN", "'in'");
+            readableTokens.Add("T_SET", "'set'");
+            readableTokens.Add("T_NOT", "'not'");
+            readableTokens.Add("T_SUBSET", "'subset'");
+            readableTokens.Add("T_UNION", "'union'");
+            readableTokens.Add("T_DOMRESBY", "'<-:'");
+            readableTokens.Add("T_DOMRESTO", "'<:'");
+            readableTokens.Add("T_RNGRESBY", "':->'");
+            readableTokens.Add("T_RNGRESTO", "':>'");
+            readableTokens.Add("T_MUNION", "'munion'");
+            readableTokens.Add("T_CARD", "'card'");
+            readableTokens.Add("T_DCONC", "'conc'");
+            readableTokens.Add("T_DINTER", "'dinter'");
+            readableTokens.Add("T_DUNION", "'dunion'");
+            readableTokens.Add("T_ELEMS", "'elems'");
+            readableTokens.Add("T_HEAD", "'hd'");
+            readableTokens.Add("T_INDS", "'inds'");
+            readableTokens.Add("T_LEN", "'len'");
+            readableTokens.Add("T_TAIL", "'tl'");
+            readableTokens.Add("T_DOM", "'dom'");
+            readableTokens.Add("T_RNG", "'rng'");
+            readableTokens.Add("T_MERGE", "'merge'");
+            readableTokens.Add("T_WS", "<space>");
+            readableTokens.Add("T_COMMENT", "'/*<comment>*/'");
+            readableTokens.Add("LINE_COMMENT", "'#<line comment>'");
+            readableTokens.Add("T_DIGIT", "<0..9>");
+            readableTokens.Add("FLOAT_OR_INT_OR_RANGE", "<float_int_range>");
+            readableTokens.Add("T_LETTER", "<a..z,A..Z>");
+            readableTokens.Add("'|['", "'|['");
+            readableTokens.Add("']|'", "']|'");
+            readableTokens.Add("'add'", "'add'");
+            readableTokens.Add("'mult'", "'mult'");
+            readableTokens.Add("'deriv'", "'deriv'");
+            readableTokens.Add("'mon+'", "'mon+'");
+            readableTokens.Add("'mon-'", "'mon-'");
+            readableTokens.Add("'id'", "'id'");
+            readableTokens.Add("'qval'", "'qval'");
+            readableTokens.Add("'\"'", "'\"'");
+            readableTokens.Add("as", "as");
+        }
+
+        /* override routine that displays recongition errors.. */
+        public override void DisplayRecognitionError(String[] tokenNames, RecognitionException e)
+        {
+            int i;
+            System.Text.StringBuilder result = new System.Text.StringBuilder();
+            SetUpTokenDictionary();
+
+
+            if (e is MismatchedTokenException)
+            {
+                result.Append("Found '");
+                result.Append(e.Token.Text);
+                result.Append("'");
+                i = ((MismatchedTokenException)e).Expecting;
+                result.Append(" Expected: ");
+                result.Append(readableTokens[tokenNames[i]]);
+                result.Append(" ("); result.Append(tokenNames[i]); result.Append(") ");
+
+            }
+            else
+            {
+                /*if (e is NoViableAltException)
+                {
+                    result.Append("Unexpected '");
+                    result.Append(e.Token.Text);
+                    result.Append("' (");
+                    i = ((NoViableAltException)e).UnexpectedType;                    
+                    result.Append(tokenNames[i]);
+                    result.Append(")");
+                }
+                else*/
+                if (e is RecognitionException)
+                {
+                    result.Append("Unexpected '");
+                    result.Append(e.Token.Text);
+                    result.Append("' (");
+                    i = ((RecognitionException)e).UnexpectedType;
+                    result.Append(tokenNames[i]);
+                    result.Append(") ");
+                }
+                else
+                    result.Append(e.Message);
+            }
+
+            pState.AddErrorMessage(new ParserError(pState.filename, e.Line, e.CharPositionInLine, result.ToString()));
+        }
+
+
+        /* just run over once */
+        public static int FirstPass(ParserState pState)
+        {
+            pState.parser.ooActionSystems();
+
+            return pState.listOfParserErrors.Count; // + pState.lexer.NumberOfSyntaxErrors;
+        }
+
+
+
+        /* print syntax tree */
+        public static string PrintSyntaxTree(ParserState pState)
+        {
+            if ((pState != null) && (pState.ooaSystem != null))
+            {
+                return pState.ooaSystem.ToString();
+            }
+            else
+                return String.Empty;
+        }
+    }
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/parser/ooaStatements.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/ooaStatements.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/ooaStatements.cs	(revision 3)
@@ -0,0 +1,592 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+
+
+namespace TUG.Mogentes
+{
+    public enum StatementKind
+    {
+        GuardedCommand,
+        MethodCall,
+        Assignment,
+        SeqBlock,
+        NondetBlock,
+        PrioBlock,
+        Skip, Abort, Kill,
+        QualConstraint
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  basic Statement
+    ///  
+    public abstract class Statement : UlyssesBasicClass, IAst
+    {
+        private StatementKind m_kind;
+        private int m_line;
+        private int m_pos;
+
+        public StatementKind kind { get { return m_kind; } }
+        public int line { get { return m_line; } }
+        public int pos { get { return m_pos; } }
+
+        public Statement(StatementKind aKind, int aline, int apos)
+        {
+            m_kind = aKind;
+            m_line = aline;
+            m_pos = apos;
+        }
+
+        public Statement(Statement toCopy)
+        {
+            m_kind = toCopy.m_kind;
+            m_line = toCopy.m_line;
+            m_pos = toCopy.m_pos;
+        }
+
+        public virtual Statement Clone()
+        {
+            throw new NotImplementedException();
+        }
+
+        public AstNodeTypeEnum nodeType { get { return AstNodeTypeEnum.statement; } }
+
+        public virtual void Accept(IAstVisitor visitor)
+        {
+            throw new NotImplementedException();
+        }
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Qualitative Constraints
+    ///  
+    public enum QualitativeConstraintOperation { Equal, Deriv, Sum, Prod, Diff }
+    public sealed class QualitativeConstraintStatement : Statement
+    {
+        private Identifier m_variable0;
+        private Identifier m_variable1;
+        private Identifier m_variable2;
+        private QualitativeConstraintOperation m_operation;
+        public bool tag = false; // says that this is an obs assignment (important for prolog code target)
+
+        public Identifier variable0 { get { return m_variable0; } }
+        public Identifier variable1 { get { return m_variable1; } }
+        public Identifier variable2 { get { return m_variable2; } }
+        public QualitativeConstraintOperation operation { get { return m_operation; } }
+
+        public QualitativeConstraintStatement(Identifier var0, Identifier var1, QualitativeConstraintOperation op, int aline, int apos)
+            : base(StatementKind.QualConstraint, aline, apos)
+        {
+            if (op == QualitativeConstraintOperation.Diff
+                || op == QualitativeConstraintOperation.Prod
+                || op == QualitativeConstraintOperation.Sum)
+                throw new ArgumentException();
+            m_variable0 = var0;
+            m_variable1 = var1;
+            m_variable2 = null;
+            m_operation = op;
+        }
+
+        public QualitativeConstraintStatement(QualitativeConstraintStatement toCopy)
+            : base(toCopy)
+        {
+            m_variable0 = toCopy.m_variable0;
+            m_variable1 = toCopy.m_variable1;
+            m_variable2 = toCopy.m_variable2;
+            m_operation = toCopy.m_operation;
+            tag = toCopy.tag;
+        }
+
+
+        public QualitativeConstraintStatement(Identifier var0, Identifier var1, Identifier var2, QualitativeConstraintOperation op, int aline, int apos)
+            : base(StatementKind.QualConstraint, aline, apos)
+        {
+            if (op == QualitativeConstraintOperation.Deriv
+                || op == QualitativeConstraintOperation.Equal)
+                throw new ArgumentException();
+            m_variable0 = var0;
+            m_variable1 = var1;
+            m_variable2 = var2;
+            m_operation = op;
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public override Statement Clone()
+        {
+            return new QualitativeConstraintStatement(this);
+        }
+
+        public void SetVariable0(Identifier newVal)
+        {
+            m_variable0 = newVal;
+        }
+
+        public void SetVariable1(Identifier newVal)
+        {
+            m_variable1 = newVal;
+        }
+
+        public void SetVariable2(Identifier newVal)
+        {
+            m_variable2 = newVal;
+        }
+    }
+
+    ///////////////////////////////////////////////
+    ///  Blocks
+    ///  
+    public abstract class Block : Statement, IScope
+    {
+        private SymbolTable m_symbols;
+        private LinkedList<Statement> m_statements;
+        private Expression m_filter; /*gets transformed to guarded command in resolvevisitor!*/
+        private IScope m_parentScope;
+
+        public SymbolTable symbols { get { return m_symbols; } }
+        public LinkedList<Statement> statements { get { return m_statements; } }
+        public Expression filter { get { return m_filter; } }
+
+        public Block(StatementKind aKind, int aline, int apos)
+            : base(aKind, aline, apos)
+        {
+            m_symbols = new SymbolTable();
+            m_statements = new LinkedList<Statement>();
+        }
+
+        public Block(Block toCopy)
+            : base(toCopy)
+        {
+            m_symbols = new SymbolTable(toCopy.m_symbols);
+            m_statements = new LinkedList<Statement>(toCopy.m_statements);
+            m_parentScope = toCopy.m_parentScope;
+            m_filter = toCopy.m_filter;
+        }
+
+        public override Statement Clone()
+        {
+            throw new NotImplementedException();
+        }
+
+        public void AddStatement(Statement toAdd)
+        {
+            m_statements.AddLast(toAdd);
+        }
+
+        public void SetStatements(LinkedList<Statement> newStatements)
+        {
+            m_statements = newStatements;
+        }
+
+        public void AddIdentifier(Identifier anIdentifier)
+        {
+            m_symbols.AddIdentifier(anIdentifier);
+        }
+
+        public Identifier ResolveIdentifier(string aName)
+        {
+            if (m_symbols.Defined(aName))
+                return m_symbols.Get(aName);
+            else
+                return null;
+        }
+
+        public IScope GetParentScope()
+        {
+            return m_parentScope;
+        }
+
+        public void SetParentScope(IScope parentScope)
+        {
+            m_parentScope = parentScope;
+        }
+
+        public void AddIdentifier(Identifier anIdentifier, object tag)
+        {
+            m_symbols.AddIdentifier(anIdentifier);
+        }
+
+
+        internal void SetFilter(Expression sexpr)
+        {
+            m_filter = sexpr;
+        }
+    }
+
+    public sealed class NondetBlock : Block
+    {
+        public NondetBlock(int aline, int apos)
+            : base(StatementKind.NondetBlock, aline, apos)
+        { }
+
+        public NondetBlock(Block aParent, int aline, int apos)
+            : base(StatementKind.NondetBlock, aline, apos)
+        {
+            if (aParent != null)
+                aParent.AddStatement(this);
+        }
+
+        public NondetBlock(NondetBlock toCopy)
+            : base(toCopy)
+        { }
+
+        public override Statement Clone()
+        {
+            return new NondetBlock(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+    public sealed class SeqBlock : Block
+    {
+        public SeqBlock(int aline, int apos)
+            : base(StatementKind.SeqBlock, aline, apos)
+        { }
+
+        public SeqBlock(Block aParent, int aline, int apos)
+            : base(StatementKind.SeqBlock, aline, apos)
+        {
+            if (aParent != null)
+                aParent.AddStatement(this);
+        }
+
+        public SeqBlock(SeqBlock toCopy)
+            : base(toCopy)
+        { }
+
+        public override Statement Clone()
+        {
+            return new SeqBlock(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+    public sealed class PrioBlock : Block
+    {
+        public PrioBlock(int aline, int apos)
+            : base(StatementKind.PrioBlock, aline, apos)
+        { }
+
+        public PrioBlock(Block aParent, int aline, int apos)
+            : base(StatementKind.PrioBlock, aline, apos)
+        {
+            if (aParent != null)
+                aParent.AddStatement(this);
+        }
+
+        public PrioBlock(PrioBlock toCopy)
+            : base(toCopy)
+        { }
+
+        public override Statement Clone()
+        {
+            return new PrioBlock(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+
+
+    ///////////////////////////////////////////////
+    ///  Guarded Command
+    ///  
+    public sealed class GuardedCommand : Statement
+    {
+        private Expression m_guard;
+        private Block m_body;
+        private bool m_isQualitative;
+
+        public Expression guard { get { return m_guard; } }
+        public Block body { get { return m_body; } }
+        public bool isQualitative { get { return m_isQualitative; } }
+
+        public GuardedCommand(Expression aGuard, Block aBlock, int aline, int apos)
+            : base(StatementKind.GuardedCommand, aline, apos)
+        {
+            m_guard = aGuard;
+            m_body = aBlock;
+            m_isQualitative = false;
+        }
+
+        public GuardedCommand(GuardedCommand toCopy)
+            : base(toCopy)
+        {
+            m_guard = toCopy.m_guard;
+            m_body = toCopy.m_body;
+            m_isQualitative = toCopy.m_isQualitative;
+        }
+
+        public override Statement Clone()
+        {
+            return new GuardedCommand(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public void SetGuard(Expression newGuard)
+        {
+            if (newGuard == null)
+                throw new ArgumentException();
+            m_guard = newGuard;
+        }
+
+        public void SetBody(Block newBody)
+        {
+            if (newBody == null)
+                throw new ArgumentException();
+            m_body = newBody;
+        }
+
+        public void SetIsQualitative(bool newVal)
+        {
+            m_isQualitative = newVal;
+        }
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Assignment
+    ///  
+    public sealed class Assignment : Statement, IScope
+    {
+        private LinkedList<Expression> m_places;
+        private LinkedList<Expression> m_values;
+        private Expression m_nondetExpression;
+        private IScope m_prarentScope;
+        private SymbolTable m_symbols; // needed for nondeterminsitic assignment (we most likely will have new variables)
+
+        public LinkedList<Expression> places { get { return m_places; } }
+        public LinkedList<Expression> values { get { return m_values; } }
+        public Expression nondetExpression { get { return m_nondetExpression; } }
+        public SymbolTable symbols { get { return m_symbols; } }
+
+        public Assignment(Expression place, Expression value, Expression nondetExpression, int aline, int apos)
+            : base(StatementKind.Assignment, aline, apos)
+        {
+            m_places = new LinkedList<Expression>();
+            m_values = new LinkedList<Expression>();
+            if (place != null)
+                m_places.AddFirst(place);
+            if (value != null)
+                m_values.AddFirst(value);
+            m_nondetExpression = nondetExpression;
+            m_symbols = new SymbolTable();
+        }
+
+        public Assignment(Assignment toCopy)
+            : base(toCopy)
+        {
+            m_places = new LinkedList<Expression>(toCopy.m_places);
+            m_values = new LinkedList<Expression>(toCopy.m_values);
+            m_nondetExpression = toCopy.m_nondetExpression;
+            m_symbols = new SymbolTable(toCopy.symbols);
+        }
+
+        public override Statement Clone()
+        {
+            return new Assignment(this);
+        }
+
+        public void AddPlace(Expression aPlace)
+        {
+            m_places.AddLast(aPlace);
+        }
+
+        public void AddValue(Expression aValue)
+        {
+            m_values.AddLast(aValue);
+        }
+
+        public void SetNondetExpression(Expression anExpr)
+        {
+            m_nondetExpression = anExpr;
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        #region IScope Member
+
+        public Identifier ResolveIdentifier(string aName)
+        {
+            if (m_symbols.Defined(aName))
+                return m_symbols.Get(aName);
+            else
+                return null;
+        }
+
+        public IScope GetParentScope()
+        {
+            return m_prarentScope;
+        }
+
+        public void SetParentScope(IScope parentScope)
+        {
+            m_prarentScope = parentScope;
+        }
+
+        public void AddIdentifier(Identifier anIdentifier, object tag)
+        {
+            m_symbols.AddIdentifier(anIdentifier);
+        }
+
+        #endregion
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Methodcall
+    ///  
+    public sealed class Call : Statement
+    {
+        private Expression m_callExpression;
+
+        public Expression callExpression { get { return m_callExpression; } }
+
+        public Call(Expression callExpression, int aline, int apos)
+            : base(StatementKind.MethodCall, aline, apos)
+        {
+            m_callExpression = callExpression;
+        }
+
+        public Call(Call toCopy)
+            : base(toCopy)
+        {
+            m_callExpression = toCopy.m_callExpression;
+        }
+
+        public override Statement Clone()
+        {
+            return new Call(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public void SetCallExpression(Expression newExpression)
+        {
+            //if (newExpression == null)
+            //    throw new ArgumentException();
+            m_callExpression = newExpression;
+        }
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Simple Statements
+    ///  
+    public sealed class SkipStatement : Statement
+    {
+        public SkipStatement(int aline, int apos)
+            : base(StatementKind.Skip, aline, apos)
+        { }
+
+        public SkipStatement(SkipStatement copy)
+            : base(copy)
+        { }
+
+        public override Statement Clone()
+        {
+            return new SkipStatement(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+    public sealed class AbortStatement : Statement
+    {
+        public AbortStatement(int aline, int apos)
+            : base(StatementKind.Abort, aline, apos)
+        { }
+
+        public AbortStatement(AbortStatement toCopy)
+            : base(toCopy)
+        { }
+
+        public override Statement Clone()
+        {
+            return new AbortStatement(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+    public sealed class KillStatement : Statement
+    {
+        public Identifier someOne;
+
+        public KillStatement(Identifier toKill, int aline, int apos)
+            : base(StatementKind.Kill, aline, apos)
+        {
+            someOne = toKill;
+        }
+
+        public KillStatement(KillStatement toCopy)
+            : base(toCopy)
+        {
+            someOne = toCopy.someOne;
+        }
+
+        public override Statement Clone()
+        {
+            return new KillStatement(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public void SetIdentifier(Identifier target)
+        {
+            someOne = target;
+        }
+    }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/parser/ooaSymbols.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/ooaSymbols.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/ooaSymbols.cs	(revision 3)
@@ -0,0 +1,824 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+//using TUG.Mogentes.Codegen;
+using Antlr.Runtime;
+
+namespace TUG.Mogentes
+{
+
+    public enum IdentifierKind
+    {
+        TypeIdentifier,         // some named type
+        EnumIdentifier,         // identifier of enumerated type
+        LandmarkIdentifier,     // landmark
+        AttributeIdentifier,    // global attribute
+        LocalVariableIdentifier,// local variable
+        ParameterIdentifier,     // method/named action argument
+        ExpressionVariableIdentifier, // var in an expression
+        MethodIdentifier,       // a method
+        NamedActionIdentifier,  // a named action
+        Module,                 // the main module - actually this has no name...
+        List,
+        Constant
+    }
+
+
+    /* ABSTRACT class Identifier.
+     * */
+    public abstract class Identifier : UlyssesBasicClass, IAst, IComparable
+    {
+        protected int m_line;
+        protected int m_column;
+        protected IScope m_definingScope;
+        protected IdentifierKind m_identifierKind;
+        protected string m_tokenText;
+        protected UlyssesType m_Type;
+
+        // basic attributes of an Identifier
+        public IdentifierKind kind { get { return m_identifierKind; } } // kind of identifier
+        public UlyssesType type { get { return m_Type; } }   // type of identifier
+        public IScope definingScope { get { return m_definingScope; } } // scope where it's defined
+
+        // from lexer
+        public string tokenText { get { return m_tokenText; } }
+        public int line { get { return m_line; } }
+        public int column { get { return m_column; } }
+
+        public AstNodeTypeEnum nodeType { get { return AstNodeTypeEnum.identifier; } }
+
+
+        public Identifier(IToken aToken,
+                          UlyssesType aType,
+                          IdentifierKind aKind,
+                          IScope aDefiningScope)
+        {
+            m_tokenText = aToken.Text;
+            m_line = aToken.Line;
+            m_column = aToken.CharPositionInLine;
+            m_Type = aType;
+            m_identifierKind = aKind;
+            m_definingScope = aDefiningScope;
+        }
+
+        public Identifier(string name, UlyssesType aType, IdentifierKind aKind, IScope aDefiningScope)
+        {
+            m_tokenText = name;
+            m_line = 0;
+            m_column = 0;
+            m_Type = aType;
+            m_identifierKind = aKind;
+            m_definingScope = aDefiningScope;
+        }
+
+        public Identifier(Identifier toCopy)
+        {
+            m_tokenText = toCopy.m_tokenText;
+            m_line = toCopy.m_line;
+            m_column = toCopy.m_column;
+            m_Type = toCopy.m_Type;
+            m_identifierKind = toCopy.m_identifierKind;
+            m_definingScope = toCopy.m_definingScope;
+        }
+
+        public virtual Identifier Clone()
+        {
+            throw new NotImplementedException();
+        }
+
+
+        public virtual void Accept(IAstVisitor visitor)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void SetType(UlyssesType aType)
+        {
+            if (aType == null)
+                throw new ArgumentException("New type can not be null.");
+
+            m_Type = aType;
+        }
+
+        public void SetTokenText(string aText)
+        {
+            m_tokenText = aText;
+        }
+
+        public override string ToString()
+        {
+            return tokenText;
+        }
+
+        public int CompareTo(object obj)
+        {
+            if (obj is Identifier)
+                return tokenText.CompareTo(obj.ToString());
+            else
+                throw new InvalidCastException();
+        }
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Value Identifiers
+    ///  
+    public abstract class ValueIdentifier : Identifier
+    {
+        public ValueIdentifier(IToken aToken,
+                          UlyssesType aType,
+                          IdentifierKind aKind,
+                          IScope aDefiningScope)
+            : base(aToken, aType, aKind, aDefiningScope)
+        { }
+
+        public ValueIdentifier(ValueIdentifier toCopy)
+            : base(toCopy)
+        { }
+    }
+
+
+    public sealed class ConstantIdentifier : ValueIdentifier
+    {
+        private Expression m_value;
+
+        public Expression Value { get { return m_value; } }
+
+        public ConstantIdentifier(IToken aToken,
+                          Expression value,
+                          IScope aDefiningScope)
+            : base(aToken, null, IdentifierKind.Constant, aDefiningScope)
+        {
+            m_value = value;
+        }
+
+        public ConstantIdentifier(ConstantIdentifier toCopy)
+            : base(toCopy)
+        {
+            m_value = toCopy.m_value;
+        }
+
+        public void SetValue(Expression aValue)
+        {
+            m_value = aValue;
+        }
+
+        public override Identifier Clone()
+        {
+            return this;
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+    public sealed class EnumIdentifier : ValueIdentifier
+    {
+        private int value;
+        private bool haveValue;
+
+        public int Value { get { return value; } }
+        public bool HaveValue { get { return haveValue; } }
+
+
+        public EnumIdentifier(IToken aToken,
+                          EnumType aType,
+                          IScope aDefiningScope)
+            : base(aToken, aType, IdentifierKind.EnumIdentifier, aDefiningScope)
+        {
+            haveValue = false;
+        }
+
+
+        public EnumIdentifier(IToken aToken,
+                          int aValue,
+                          EnumType aType,
+                          IScope aDefiningScope)
+            : base(aToken, aType, IdentifierKind.EnumIdentifier, aDefiningScope)
+        {
+            haveValue = true;
+            value = aValue;
+        }
+
+
+        public EnumIdentifier(EnumIdentifier toCopy)
+            : base(toCopy)
+        {
+            value = toCopy.value;
+            haveValue = toCopy.haveValue;
+        }
+
+
+        public override Identifier Clone()
+        {
+            return this;
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+
+    public sealed class LandmarkIdentifier : ValueIdentifier
+    {
+        public LandmarkIdentifier(IToken aToken,
+                          QrType aType,
+                          IScope aDefiningScope)
+            : base(aToken, aType, IdentifierKind.LandmarkIdentifier, aDefiningScope)
+        { }
+
+        public LandmarkIdentifier(LandmarkIdentifier toCopy)
+            : base(toCopy)
+        { }
+
+        public override Identifier Clone()
+        {
+            return this;
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+
+
+
+    ///////////////////////////////////////////////
+    ///  Variable Identifiers
+    ///  
+
+    public abstract class ValueReferenceIdentifier : Identifier
+    {
+        public ValueReferenceIdentifier(IToken aToken,
+                          UlyssesType aType,
+                          IdentifierKind aKind,
+                          IScope aDefiningScope)
+            : base(aToken, aType, aKind, aDefiningScope)
+        { }
+
+        public ValueReferenceIdentifier(ValueReferenceIdentifier toCopy)
+            : base(toCopy)
+        { }
+
+        public ValueReferenceIdentifier(string name, UlyssesType aType, IdentifierKind aKind, IScope aDefiningScope) :
+            base(name, aType, aKind, aDefiningScope)
+        { }
+
+    }
+
+
+    public sealed class AttributeIdentifier : ValueReferenceIdentifier
+    {
+        private Expression m_initializer;
+        private bool m_isStatic;
+        private bool m_isObservable;    // used for qualitative values
+        private bool m_isControllable;  // used for qualitative values
+
+        public Expression initializer { get { return m_initializer; } }
+        public bool isStatic { get { return m_isStatic; } }
+        public bool isObservable { get { return m_isObservable; } }
+        public bool isControllable { get { return m_isControllable; } }
+
+        public AttributeIdentifier(IToken aToken,
+                          UlyssesType aType,
+                          IScope aDefiningScope,
+                          Expression anInitializer,
+                          bool isStatic,
+                          bool isObservable,
+                          bool isControllable)
+            : base(aToken, aType, IdentifierKind.AttributeIdentifier, aDefiningScope)
+        {
+            m_initializer = anInitializer;
+            m_isStatic = isStatic;
+            m_isControllable = isControllable;
+            m_isObservable = isObservable;
+        }
+
+        public AttributeIdentifier(AttributeIdentifier toCopy)
+            : base(toCopy)
+        {
+            m_initializer = toCopy.initializer;
+            m_isStatic = toCopy.m_isStatic;
+            m_isControllable = toCopy.m_isControllable;
+            m_isObservable = toCopy.m_isObservable;
+        }
+
+
+        public override Identifier Clone()
+        {
+            return new AttributeIdentifier(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public void SetInitializer(Expression newExpr)
+        {
+            if (newExpr == null)
+                throw new ArgumentException();
+            m_initializer = newExpr;
+        }
+    }
+
+
+    public class LocalVariableIdentifier : ValueReferenceIdentifier
+    {
+        public LocalVariableIdentifier(IToken aToken,
+                          UlyssesType aType,
+                          IScope aDefiningScope)
+            : base(aToken, aType, IdentifierKind.LocalVariableIdentifier, aDefiningScope)
+        { }
+
+        public LocalVariableIdentifier(LocalVariableIdentifier toCopy)
+            : base(toCopy)
+        { }
+
+        public override Identifier Clone()
+        {
+            return new LocalVariableIdentifier(this);
+        }
+
+        public LocalVariableIdentifier(string name, UlyssesType aType, IdentifierKind aKind, IScope aDefiningScope)
+            : base(name, aType, aKind, aDefiningScope)
+        { }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+    }
+
+
+    public sealed class ParameterIdentifier : LocalVariableIdentifier
+    {
+        public ParameterIdentifier(IToken aToken,
+                          UlyssesType aType,
+                          IScope aDefiningScope)
+            : base(aToken, aType, aDefiningScope)
+        {
+            m_identifierKind = IdentifierKind.ParameterIdentifier;
+        }
+
+        public ParameterIdentifier(string name, UlyssesType aType, IScope aDefiningScope)
+            : base(name, aType, IdentifierKind.ParameterIdentifier, aDefiningScope)
+        { }
+
+        public ParameterIdentifier(ParameterIdentifier toCopy)
+            : base(toCopy)
+        { }
+
+        public override Identifier Clone()
+        {
+            return new ParameterIdentifier(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+    }
+
+
+    public sealed class ExpressionVariableIdentifier : LocalVariableIdentifier
+    {
+        private bool m_isInitialized;
+
+        public bool initialized { get { return m_isInitialized; } }
+
+        public ExpressionVariableIdentifier(IToken aToken,
+                          UlyssesType aType,
+                          IScope aDefiningScope)
+            : base(aToken, aType, aDefiningScope)
+        {
+            m_identifierKind = IdentifierKind.ExpressionVariableIdentifier;
+        }
+
+        public ExpressionVariableIdentifier(string name, int line, int col)
+            : base(name, null, IdentifierKind.ExpressionVariableIdentifier, null)
+        {
+            m_line = line;
+            m_column = col;
+            m_isInitialized = false;
+        }
+
+        public ExpressionVariableIdentifier(ExpressionVariableIdentifier toCopy)
+            : base(toCopy)
+        {
+            m_line = toCopy.m_line;
+            m_column = toCopy.m_column;
+            m_isInitialized = toCopy.m_isInitialized;
+        }
+
+        public override Identifier Clone()
+        {
+            return new ExpressionVariableIdentifier(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public void SetInitialized(bool newValue)
+        {
+            m_isInitialized = newValue;
+        }
+
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Type Identifier
+    ///  
+
+    public class TypeIdentifier : Identifier
+    {
+        public string prefix;
+
+        protected TypeIdentifier(IToken aToken,
+                          UlyssesType aType,
+                            IdentifierKind someKind,
+                          IScope aDefiningScope)
+            : base(aToken, aType, someKind, aDefiningScope)
+        { }
+
+        protected TypeIdentifier(string aToken,
+                          UlyssesType aType,
+                            IdentifierKind someKind,
+                          IScope aDefiningScope)
+            : base(aToken, aType, someKind, aDefiningScope)
+        { }
+
+
+        public TypeIdentifier(IToken aToken,
+                          UlyssesType aType,
+                          IScope aDefiningScope)
+            : base(aToken, aType, IdentifierKind.TypeIdentifier, aDefiningScope)
+        { }
+
+
+        public TypeIdentifier(string aName,
+                          UlyssesType aType,
+                          IScope aDefiningScope)
+            : base(aName, aType, IdentifierKind.TypeIdentifier, aDefiningScope)
+        { }
+
+        public TypeIdentifier(TypeIdentifier toCopy)
+            : base(toCopy)
+        {
+            this.prefix = toCopy.prefix;
+        }
+
+        public override Identifier Clone()
+        {
+            return new TypeIdentifier(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+    public sealed class SelfTypeIdentifier : TypeIdentifier
+    {
+        public SelfTypeIdentifier(string aName,
+                          UlyssesType aType,
+                          IScope aDefiningScope)
+            : base(aName, aType, aDefiningScope)
+        { }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Scope Identifiers
+    ///  
+    public abstract class Scope : TypeIdentifier, IScope
+    {
+        protected SymbolTable m_symbolTable;
+
+        public Scope(IToken aToken,
+                     UlyssesType aType,
+                     IdentifierKind aKind,
+                     IScope aDefiningScope)
+            : base(aToken, aType, aKind, aDefiningScope)
+        {
+            m_symbolTable = new SymbolTable();
+        }
+
+
+        public Scope(string aName,
+                     UlyssesType aType,
+                     IdentifierKind aKind,
+                     IScope aDefiningScope)
+            : base(aName, aType, aKind, aDefiningScope)
+        {
+            m_symbolTable = new SymbolTable();
+        }
+
+        public Scope(Scope toCopy)
+            : base(toCopy)
+        {
+            m_symbolTable = toCopy.symbolTable;
+        }
+
+
+        public SymbolTable symbolTable { get { return m_symbolTable; } }
+
+        public IScope GetParentScope()
+        {
+            return m_definingScope;
+        }
+
+        public void SetParentScope(IScope parentScope)
+        {
+            m_definingScope = parentScope;
+        }
+
+        public virtual void AddIdentifier(Identifier anIdentifier, object tag)
+        {
+            m_symbolTable.AddIdentifier(anIdentifier);
+        }
+
+        public Identifier ResolveIdentifier(string aName)
+        {
+            if (m_symbolTable.Defined(aName))
+                return m_symbolTable.Get(aName);
+            else
+                return null;
+        }
+
+    }
+
+    public abstract class FunctionIdentifier : Scope
+    {
+        private Block m_body;
+        private List<ParameterIdentifier> m_parameter = new List<ParameterIdentifier>();
+
+        public Block body { get { return m_body; } }
+        public List<ParameterIdentifier> parameter { get { return m_parameter; } }
+
+
+        public FunctionIdentifier(IToken aToken,
+                          UlyssesType aType,
+                          IdentifierKind aKind,
+                          IScope aDefiningScope)
+            : base(aToken, aType, aKind, aDefiningScope)
+        { }
+
+        public FunctionIdentifier(FunctionIdentifier toCopy)
+            : base(toCopy)
+        {
+            m_body = toCopy.m_body;
+            m_parameter = new List<ParameterIdentifier>(toCopy.m_parameter);
+        }
+
+        public void SetBody(Block body)
+        {
+            m_body = body;
+        }
+
+        public void AddParameter(ParameterIdentifier aParameter)
+        {
+            m_parameter.Add(aParameter);
+            AddIdentifier(aParameter, null);
+        }
+    }
+
+
+    public sealed class MethodIdentifier : FunctionIdentifier
+    {
+        public MethodIdentifier(IToken aToken,
+                          UlyssesType aType,
+                          IScope aDefiningScope)
+            : base(aToken, aType, IdentifierKind.MethodIdentifier, aDefiningScope)
+        { }
+
+        public MethodIdentifier(MethodIdentifier toCopy)
+            : base(toCopy)
+        { }
+
+        public override Identifier Clone()
+        {
+            return new MethodIdentifier(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+    public sealed class NamedActionIdentifier : FunctionIdentifier
+    {
+        public NamedActionIdentifier(IToken aToken,
+                          UlyssesType aType,
+                          IScope aDefiningScope)
+            : base(aToken, aType, IdentifierKind.NamedActionIdentifier, aDefiningScope)
+        { }
+
+        public NamedActionIdentifier(NamedActionIdentifier toCopy)
+            : base(toCopy)
+        { }
+
+        public override Identifier Clone()
+        {
+            return new NamedActionIdentifier(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+    public class Module : Scope
+    {
+        //protected List<OpaqueType> m_typesToFixUp;
+        //protected List<Expression> m_referencesToResolve;
+
+        //public List<OpaqueType> typesToFixUp { get { return m_typesToFixUp; } }
+        //public List<Expression> referencesToResolve { get { return m_referencesToResolve; } }
+
+        public Module()
+            : base("@Module", null, IdentifierKind.Module, null)
+        {
+            //m_typesToFixUp = new List<OpaqueType>();
+            // m_referencesToResolve = new List<Expression>();
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+    public sealed class MainModule : Module
+    {
+        private IdentifierList m_systemDescription;
+        private ActionSystem m_instance;
+
+        public IdentifierList systemDescription { get { return m_systemDescription; } }
+        public ActionSystem instance { get { return m_instance; } }
+
+        public MainModule()
+            : base()
+        {
+            m_systemDescription = null;
+        }
+
+        public void SetSystemDescription(IdentifierList aDescr)
+        {
+            m_systemDescription = aDescr;
+        }
+
+        public void SetInstance(ActionSystem anObject)
+        {
+            m_instance = anObject;
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+
+
+    ///////////////////////////////////////////////
+    ///  Identifier List
+    ///  
+    public enum IdentifierListType { normal, nondeterministic, seqential, prioritized }
+    public abstract class IdentifierList : Identifier
+    {
+        private LinkedList<Identifier> m_list;
+        private IdentifierListType m_type;
+
+        public LinkedList<Identifier> identifiers { get { return m_list; } }
+        public IdentifierListType listType { get { return m_type; } }
+
+        public IdentifierList(IdentifierListType aConcatType)
+            : base("list", null, IdentifierKind.List, null)
+        {
+            m_list = new LinkedList<Identifier>();
+            m_type = aConcatType;
+        }
+
+        public void AddElement(Identifier toAdd)
+        {
+            m_list.AddLast(toAdd);
+        }
+    }
+
+
+    public sealed class NondetIdentifierList : IdentifierList
+    {
+        public NondetIdentifierList()
+            : base(IdentifierListType.nondeterministic)
+        { }
+
+        public NondetIdentifierList(IdentifierList aParent)
+            : base(IdentifierListType.nondeterministic)
+        {
+            if (aParent != null)
+                aParent.AddElement(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+    public sealed class SeqIdentifierList : IdentifierList
+    {
+        public SeqIdentifierList()
+            : base(IdentifierListType.seqential)
+        { }
+
+        public SeqIdentifierList(IdentifierList aParent)
+            : base(IdentifierListType.seqential)
+        {
+            if (aParent != null)
+                aParent.AddElement(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+    }
+
+    public sealed class PrioIdentifierList : IdentifierList
+    {
+        public PrioIdentifierList()
+            : base(IdentifierListType.prioritized)
+        { }
+
+        public PrioIdentifierList(IdentifierList aParent)
+            : base(IdentifierListType.prioritized)
+        {
+            if (aParent != null)
+                aParent.AddElement(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+    public sealed class UnspecIdentifierList : IdentifierList
+    {
+        public UnspecIdentifierList()
+            : base(IdentifierListType.normal)
+        { }
+        public UnspecIdentifierList(IdentifierList aParent)
+            : base(IdentifierListType.normal)
+        {
+            if (aParent != null)
+                aParent.AddElement(this);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+
+
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/parser/ooaTypes.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/parser/ooaTypes.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/parser/ooaTypes.cs	(revision 3)
@@ -0,0 +1,1279 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Globalization;
+using TUG.Mogentes.Codegen;
+
+namespace TUG.Mogentes
+{
+
+    public enum TypeKind
+    {
+        IntType,
+        BoolType,
+        FloatType,
+        EnumeratedType,
+        ListType,
+        MapType,
+        QrType,
+        TupleType,
+        FunctionType,
+        OoActionSystemType,
+        OpaqueType,
+        Null, Any
+    }
+
+    public abstract class UlyssesType : UlyssesBasicClass, IAst
+    {
+        protected TypeKind m_kind;
+        protected TypeIdentifier m_identifier;
+        protected int m_hash;
+        protected long TimeStamp = DateTime.Now.Ticks;
+
+
+        public TypeKind kind { get { return m_kind; } }
+        public TypeIdentifier identifier { get { lock (this) { if (m_identifier == null)  SetupAnonymousName(); } return m_identifier; } }
+        public bool isAnonymousType { get { return AnonymousName() == m_identifier.tokenText; } }
+
+        protected UlyssesType(TypeKind aKind, TypeIdentifier anIdentifier)
+            : base()
+        {
+            m_kind = aKind;
+            m_identifier = anIdentifier;
+            m_hash = Enum.GetName(typeof(TypeKind), aKind).GetHashCode();
+        }
+
+        public override string ToString()
+        {
+            return identifier.tokenText;
+        }
+
+        public virtual string AnonymousName()
+        {
+            throw new NotImplementedException();
+        }
+
+
+        public void SetTypeIdentifier(TypeIdentifier anId)
+        {
+            m_identifier = anId;
+        }
+
+        public void SetupAnonymousName()
+        {
+            if (m_identifier == null)
+            {
+                string anonymousName = this.AnonymousName();
+                m_identifier = new TypeIdentifier(anonymousName, this, null);
+            }
+        }
+
+
+        #region IAst Member
+        public AstNodeTypeEnum nodeType { get { return AstNodeTypeEnum.type; } }
+
+        public virtual void Accept(IAstVisitor visitor)
+        {
+            throw new NotImplementedException();
+        }
+
+        #endregion
+
+
+        public bool IsNumeric()
+        {
+            return (m_kind == TypeKind.IntType) ||
+                   (m_kind == TypeKind.FloatType) ||
+                   (m_kind == TypeKind.EnumeratedType && this is ValuedEnumType);
+        }
+
+        public bool IsQualitative()
+        {
+            return (m_kind == TypeKind.QrType);
+        }
+
+
+
+        public static string High(UlyssesType atype)
+        {
+            switch (atype.kind)
+            {
+                case TypeKind.BoolType:
+                    return "1";
+                case TypeKind.EnumeratedType:
+                    return (((EnumType)atype).listOfEnumSymbols.Count - 1).ToString();
+                case TypeKind.IntType:
+                    return ((IntType)atype).rangeHigh.ToString();
+                case TypeKind.FloatType:
+                    return ((FloatType)atype).high.ToString();
+                //                case TypeKind.QrType:
+                //                    return (((QrType)atype).landmarks.Count - 1).ToString();
+                default:
+                    throw new NotImplementedException();
+            }
+        }
+
+        public static string Low(UlyssesType atype)
+        {
+            switch (atype.kind)
+            {
+                case TypeKind.BoolType:
+                    return "0";
+                case TypeKind.EnumeratedType:
+                    return "0";
+                case TypeKind.IntType:
+                    return ((IntType)atype).rangeLow.ToString();
+                case TypeKind.FloatType:
+                    return ((FloatType)atype).low.ToString();
+                //                case TypeKind.QrType:
+                //                    return "0";
+                default:
+                    throw new NotImplementedException();
+            }
+        }
+
+
+        /// <summary>
+        ///  Returns a cover for two types (if possible).
+        ///  note the cover type for two ints, floats, etc. will have max/min values
+        ///  that reflect the maximum of the two operands. 
+        /// </summary>
+
+        public static UlyssesType CoverType(UlyssesType type1, UlyssesType type2)
+        {
+            /*first some sanity checks*/
+            if (type1 == null)
+                throw new ArgumentException("type1 null");
+            if (type2 == null)
+                throw new ArgumentException("type2 null");
+
+            if (type1.kind == TypeKind.OpaqueType)
+                throw new ArgumentException("type1 opaque type");
+            if (type2.kind == TypeKind.OpaqueType)
+                throw new ArgumentException("type2 opaque type");
+
+            if (ReferenceEquals(type1, type2))
+                return type1;
+            if (UlyssesType.TypeEqual(type1, type2))
+                return type1;
+
+            TypeKind tk1 = type1.kind;
+            TypeKind tk2 = type2.kind;
+
+
+
+            if (tk1 != tk2)
+            {
+                // the only notion we support here is int->float and valenum -> int
+                if ((tk1 == TypeKind.IntType || tk2 == TypeKind.IntType)
+                    && (tk1 == TypeKind.FloatType || tk2 == TypeKind.FloatType))
+                {
+                    IntType aInt = tk1 == TypeKind.IntType ? (IntType)type1 : (IntType)type2;
+                    FloatType aFloat = tk1 == TypeKind.IntType ? (FloatType)type2 : (FloatType)type1;
+
+                    double low = (double)aInt.rangeLow < aFloat.low ? (double)aInt.rangeLow : aFloat.low;
+                    double high = (double)aInt.rangeHigh < aFloat.high ? aFloat.high : (double)aInt.rangeHigh;
+                    double precision = aFloat.precision > 1 ? 1.0 : aFloat.precision;
+
+                    return new FloatType(low, high, precision, null);
+
+                }
+                else if ((tk1 == TypeKind.IntType || tk2 == TypeKind.IntType)
+                    && (tk1 == TypeKind.EnumeratedType || tk2 == TypeKind.EnumeratedType))
+                {
+                    IntType intt1 = tk1 == TypeKind.IntType ? (IntType)type1 : (IntType)type2;
+                    EnumType anEnum = tk1 == TypeKind.IntType ? (EnumType)type2 : (EnumType)type1;
+
+                    if (anEnum is ValuedEnumType)
+                    {
+                        IntType intt2 = (IntType)((ValuedEnumType)anEnum).getIntType();
+                        int low = intt1.rangeLow < intt2.rangeLow ? intt1.rangeLow : intt2.rangeLow;
+                        int high = intt1.rangeHigh > intt2.rangeHigh ? intt1.rangeHigh : intt2.rangeHigh;
+                        return new IntType(low, high, null);
+                    }
+                    else
+                        return null;
+                }
+                else if (tk1 == TypeKind.Any || tk2 == TypeKind.Any)
+                {
+                    AnyType freeVar = tk1 == TypeKind.Any ? (AnyType)type1 : (AnyType)type2;
+                    UlyssesType fixedType = tk1 == TypeKind.Any ? type2 : type1;
+                    UlyssesType newcover = freeVar.VariableIdentifier.type.kind == TypeKind.Any
+                        ? fixedType : CoverType(fixedType, freeVar.VariableIdentifier.type);
+                    freeVar.VariableIdentifier.SetType(newcover);
+                    return newcover;
+                }
+                else if (tk1 == TypeKind.OoActionSystemType && tk2 == TypeKind.Null)
+                {
+                    return type1;
+                }
+                else if (tk2 == TypeKind.OoActionSystemType && tk1 == TypeKind.Null)
+                {
+                    return type2;
+                }
+
+                else
+                    return null;
+            }
+            else
+            {
+                switch (tk1)
+                {
+                    case TypeKind.Any:
+                        return type1;
+
+                    case TypeKind.IntType:
+                        IntType intt1 = (IntType)type1;
+                        IntType intt2 = (IntType)type2;
+                        int low = intt1.rangeLow < intt2.rangeLow ? intt1.rangeLow : intt2.rangeLow;
+                        int high = intt1.rangeHigh > intt2.rangeHigh ? intt1.rangeHigh : intt2.rangeHigh;
+                        return new IntType(low, high, null);
+                    case TypeKind.BoolType:
+                        return type1;
+                    case TypeKind.FloatType:
+                        FloatType floatt1 = (FloatType)type1;
+                        FloatType floatt2 = (FloatType)type2;
+                        double flow = floatt1.low < floatt2.low ? floatt1.low : floatt2.low;
+                        double fhigh = floatt1.high > floatt2.high ? floatt1.high : floatt2.high;
+                        double fprec = floatt1.precision < floatt2.precision ? floatt1.precision : floatt2.precision;
+                        return new FloatType(flow, fhigh, fprec, null);
+                    case TypeKind.EnumeratedType:
+                        return null;
+                    case TypeKind.ListType:
+                        ListType listt1 = (ListType)type1;
+                        ListType listt2 = (ListType)type2;
+                        int maxelems = listt1.maxNumberOfElements > listt2.maxNumberOfElements ?
+                            listt1.maxNumberOfElements : listt2.maxNumberOfElements;
+                        // empty lists lack type, so take the other one
+                        if ((listt1.innerType.kind == TypeKind.Null) && (listt2.innerType.kind != TypeKind.Null))
+                            return listt2;
+                        else if ((listt2.innerType.kind == TypeKind.Null) && (listt1.innerType.kind != TypeKind.Null))
+                            return listt1;
+                        else if (listt1.innerType.kind == TypeKind.Null && listt2.innerType.kind == TypeKind.Null)
+                            return listt1;
+                        else
+                        {
+                            UlyssesType subtype = UlyssesType.CoverType(listt1.innerType, listt2.innerType);
+                            if (subtype != null)
+                                return new ListType(subtype, maxelems, null);
+                            else
+                                return null;
+                        }
+                    case TypeKind.MapType:
+                        MapType mapt1 = (MapType)type1;
+                        MapType mapt2 = (MapType)type2;
+                        // empty maps lack type, so take the other one.
+                        if ((mapt1.fromType.kind == TypeKind.Null && mapt1.toType.kind == TypeKind.Null)
+                             && (mapt2.fromType.kind != TypeKind.Null && mapt2.toType.kind != TypeKind.Null))
+                            return mapt2;
+                        else if ((mapt2.fromType.kind == TypeKind.Null && mapt2.toType.kind == TypeKind.Null)
+                                 && (mapt1.fromType.kind != TypeKind.Null && mapt1.toType.kind != TypeKind.Null))
+                            return mapt1;
+                        else if ((mapt2.fromType.kind == TypeKind.Null && mapt2.toType.kind == TypeKind.Null)
+                                 && (mapt1.fromType.kind == TypeKind.Null && mapt1.toType.kind == TypeKind.Null))
+                            return mapt1;
+                        else
+                        {
+                            UlyssesType sub1 = UlyssesType.CoverType(mapt1.fromType, mapt2.fromType);
+                            UlyssesType sub2 = UlyssesType.CoverType(mapt2.toType, mapt2.toType);
+                            maxelems = mapt1.maxNumberOfElements > mapt2.maxNumberOfElements ?
+                                mapt1.maxNumberOfElements : mapt2.maxNumberOfElements;
+                            if (sub1 != null && sub2 != null)
+                                return new MapType(sub1, sub2, maxelems, null);
+                            else
+                                return null;
+                        }
+                    case TypeKind.QrType:
+                        return null; /*if refs are equal, we do not reach this statement! see above..*/
+                    case TypeKind.TupleType:
+                        TupleType tuplet1 = (TupleType)type1;
+                        TupleType tuplet2 = (TupleType)type2;
+                        TupleType result = new TupleType(null);
+                        LinkedListNode<UlyssesType> innert1 = tuplet1.innerTypes.First;
+                        LinkedListNode<UlyssesType> innert2 = tuplet2.innerTypes.First;
+                        while (innert1 != null)
+                        {
+                            UlyssesType newinner = UlyssesType.CoverType(innert1.Value, innert2.Value);
+                            if (newinner == null)
+                                return null;
+                            result.AddType(newinner);
+
+                            innert1 = innert1.Next;
+                            innert2 = innert2.Next;
+                        }
+                        return result;
+                    case TypeKind.OoActionSystemType:
+                        if (type1.kind == TypeKind.Null && type2.kind != TypeKind.Null)
+                            return type2;
+                        else if (type2.kind == TypeKind.Null && type1.kind != TypeKind.Null)
+                            return type1;
+                        else if (type1.kind == TypeKind.Null && type2.kind == TypeKind.Null)
+                            return type2;
+                        else if (ReferenceEquals(type1, type2))
+                            return type1;
+                        else
+                            return ClassBaseType((OoActionSystemType)type1, (OoActionSystemType)type2);
+                    case TypeKind.OpaqueType:
+                        System.Diagnostics.Debug.Assert(false);
+                        return null;
+                    default:
+                        throw new NotImplementedException();
+                }
+            }
+        }
+
+        private static UlyssesType ClassBaseType(OoActionSystemType type1, OoActionSystemType type2)
+        {
+            // this is rather inefficient.. should be done differently
+            OoActionSystemType typea = type1;
+            OoActionSystemType typeb = type2;
+            OoActionSystemType basea = type1;
+            OoActionSystemType baseb = type2;
+            while (basea != null)
+            {
+                if (ReferenceEquals(basea, typeb))
+                    return basea;
+                basea = basea.baseType;
+            }
+            while (baseb != null)
+            {
+                if (ReferenceEquals(baseb, typea))
+                    return baseb;
+                baseb = baseb.baseType;
+            }
+            return null;
+        }
+
+        public static bool FirstTypeLessRange(UlyssesType type1, UlyssesType type2)
+        {
+            TypeKind tk1 = type1.kind;
+            TypeKind tk2 = type2.kind;
+
+            if (tk1 != tk2)
+                throw new ArgumentException("Types need to be equal");
+
+            switch (tk1)
+            {
+                case TypeKind.IntType:
+                    IntType Int1 = (IntType)type1;
+                    IntType Int2 = (IntType)type2;
+                    return Int1.rangeLow > Int2.rangeLow ||
+                           Int1.rangeHigh < Int2.rangeHigh;
+                case TypeKind.BoolType:
+                    return false;
+                case TypeKind.FloatType:
+                    FloatType Float1 = (FloatType)type1;
+                    FloatType Float2 = (FloatType)type2;
+                    return Float1.low > Float2.low
+                        || Float1.high < Float2.high
+                        || Float1.precision > Float2.precision;
+                case TypeKind.EnumeratedType:
+                    return false;
+                case TypeKind.ListType:
+                    ListType listt1 = (ListType)type1;
+                    ListType listt2 = (ListType)type2;
+                    return (listt1.maxNumberOfElements < listt2.maxNumberOfElements) ||
+                        UlyssesType.FirstTypeLessRange(listt1.innerType, listt2.innerType);
+                case TypeKind.MapType:
+                    MapType mapt1 = (MapType)type1;
+                    MapType mapt2 = (MapType)type2;
+                    return (mapt1.maxNumberOfElements < mapt2.maxNumberOfElements) ||
+                        UlyssesType.FirstTypeLessRange(mapt1.fromType, mapt2.fromType) ||
+                        UlyssesType.FirstTypeLessRange(mapt1.toType, mapt2.toType);
+                case TypeKind.QrType:
+                    return false;
+                case TypeKind.TupleType:
+                    TupleType tuplet1 = (TupleType)type1;
+                    TupleType tuplet2 = (TupleType)type2;
+                    if (tuplet1.innerTypes.Count != tuplet2.innerTypes.Count)
+                        return false;
+                    LinkedListNode<UlyssesType> innert1 = tuplet1.innerTypes.First;
+                    LinkedListNode<UlyssesType> innert2 = tuplet2.innerTypes.First;
+                    while (innert1 != null)
+                    {
+                        if (UlyssesType.FirstTypeLessRange(innert1.Value, innert2.Value))
+                            return true;
+                        innert1 = innert1.Next;
+                        innert2 = innert2.Next;
+                    }
+                    return false;
+                case TypeKind.OoActionSystemType:
+                    return false;
+                case TypeKind.OpaqueType:
+                    System.Diagnostics.Debug.Assert(false);
+                    return false;
+                default:
+                    throw new NotImplementedException();
+            }
+        }
+
+        public static bool TypeEqualByKind(UlyssesType type1, UlyssesType type2)
+        {
+            if ((type1 == null) || (type2 == null))
+                return false;
+
+            TypeKind tk1 = type1.kind;
+            TypeKind tk2 = type2.kind;
+
+            // if of different kind, then return false..
+            if (tk1 != tk2)
+                return false;
+
+            // if same kind, make a rigorous check
+            switch (tk1)
+            {
+                case TypeKind.IntType:
+                case TypeKind.BoolType:
+                case TypeKind.FloatType:
+                    return true;
+                case TypeKind.EnumeratedType:
+                    return ReferenceEquals(type1, type2);
+                case TypeKind.ListType:
+                    ListType listt1 = (ListType)type1;
+                    ListType listt2 = (ListType)type2;
+                    return UlyssesType.TypeEqualByKind(listt1.innerType, listt2.innerType);
+                case TypeKind.MapType:
+                    MapType mapt1 = (MapType)type1;
+                    MapType mapt2 = (MapType)type2;
+                    return UlyssesType.TypeEqualByKind(mapt1.fromType, mapt2.fromType) &&
+                        UlyssesType.TypeEqualByKind(mapt1.toType, mapt2.toType);
+                case TypeKind.QrType:
+                    QrType qr1 = (QrType)type1;
+                    QrType qr2 = (QrType)type2;
+                    return ReferenceEquals(qr1, qr2);
+                case TypeKind.TupleType:
+                    TupleType tuplet1 = (TupleType)type1;
+                    TupleType tuplet2 = (TupleType)type2;
+                    if (tuplet1.innerTypes.Count != tuplet2.innerTypes.Count)
+                        return false;
+                    LinkedListNode<UlyssesType> innert1 = tuplet1.innerTypes.First;
+                    LinkedListNode<UlyssesType> innert2 = tuplet2.innerTypes.First;
+                    while (innert1 != null)
+                    {
+                        if (!UlyssesType.TypeEqualByKind(innert1.Value, innert2.Value))
+                            return false;
+                        innert1 = innert1.Next;
+                        innert2 = innert2.Next;
+                    }
+                    return true;
+                case TypeKind.OoActionSystemType:
+                    return ReferenceEquals(type1, type2);
+                case TypeKind.OpaqueType:
+                    System.Diagnostics.Debug.Assert(false);
+                    return false;
+                default:
+                    throw new NotImplementedException();
+            }
+        }
+
+
+        public static bool TypeEqual(UlyssesType type1, UlyssesType type2)
+        {
+            // this will also work with opaque types...
+            while (type1 is OpaqueType)
+                type1 = ((OpaqueType)type1).resolvedType;
+            while (type2 is OpaqueType)
+                type2 = ((OpaqueType)type2).resolvedType;
+
+            if ((type1 == null) || (type2 == null))
+                return false;
+
+            TypeKind tk1 = type1.kind;
+            TypeKind tk2 = type2.kind;
+
+            // if of different kind, then return false..
+            if (tk1 != tk2)
+                return false;
+
+            // if same kind, make a rigorous check
+            switch (tk1)
+            {
+                case TypeKind.IntType:
+                    IntType intt1 = (IntType)type1;
+                    IntType intt2 = (IntType)type2;
+                    return intt1.rangeLow == intt2.rangeLow &&
+                        intt1.rangeHigh == intt2.rangeHigh;
+                case TypeKind.BoolType:
+                    return true;
+                case TypeKind.FloatType:
+                    FloatType floatt1 = (FloatType)type1;
+                    FloatType floatt2 = (FloatType)type2;
+                    return floatt1.low == floatt2.low &&
+                        floatt1.high == floatt2.high &&
+                        floatt1.precision == floatt2.precision;
+                case TypeKind.EnumeratedType:
+                    return ReferenceEquals(type1, type2);
+                case TypeKind.ListType:
+                    ListType listt1 = (ListType)type1;
+                    ListType listt2 = (ListType)type2;
+                    // an empty list can be of any type.. 
+                    /*if ((listt1.innerType.kind == TypeKind.Null) || (listt2.innerType.kind == TypeKind.Null))
+                        return true;
+                    else*/
+                    return UlyssesType.TypeEqual(listt1.innerType, listt2.innerType) &&
+                        listt1.maxNumberOfElements == listt2.maxNumberOfElements; // need this because of covertype
+                case TypeKind.MapType:
+                    MapType mapt1 = (MapType)type1;
+                    MapType mapt2 = (MapType)type2;
+                    return UlyssesType.TypeEqual(mapt1.fromType, mapt2.fromType) &&
+                        UlyssesType.TypeEqual(mapt1.toType, mapt2.toType) &&
+                        mapt1.maxNumberOfElements == mapt2.maxNumberOfElements; // need this because of covertype
+                case TypeKind.QrType:
+                    QrType qr1 = (QrType)type1;
+                    QrType qr2 = (QrType)type2;
+                    return ReferenceEquals(qr1, qr2);
+                case TypeKind.TupleType:
+                    TupleType tuplet1 = (TupleType)type1;
+                    TupleType tuplet2 = (TupleType)type2;
+                    if (tuplet1.innerTypes.Count != tuplet2.innerTypes.Count)
+                        return false;
+                    LinkedListNode<UlyssesType> innert1 = tuplet1.innerTypes.First;
+                    LinkedListNode<UlyssesType> innert2 = tuplet2.innerTypes.First;
+                    while (innert1 != null)
+                    {
+                        if (!UlyssesType.TypeEqual(innert1.Value, innert2.Value))
+                            return false;
+                        innert1 = innert1.Next;
+                        innert2 = innert2.Next;
+                    }
+                    return true;
+                case TypeKind.OoActionSystemType:
+                    return ReferenceEquals(type1, type2);// || Covariance((OoActionSystemType)type1, (OoActionSystemType)type2);
+                case TypeKind.OpaqueType:
+                    System.Diagnostics.Debug.Assert(false);
+                    return false;
+                case TypeKind.Null:
+                case TypeKind.Any:
+                    return true;
+                default:
+                    throw new NotImplementedException();
+            }
+        }
+
+        /// <summary>
+        /// checks if type 2 is a desc. of type 1
+        /// </summary>
+        public static bool Covariance(OoActionSystemType ooActionSystemType, OoActionSystemType ooActionSystemType_2)
+        {
+            // check if type 2 is a desc. of type 1
+            while (!ReferenceEquals(ooActionSystemType, ooActionSystemType_2) && ooActionSystemType_2.baseType != null)
+                ooActionSystemType_2 = ooActionSystemType_2.baseType;
+
+            return ReferenceEquals(ooActionSystemType, ooActionSystemType_2);
+        }
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Special type: null
+    ///  
+    public sealed class NullType : UlyssesType
+    {
+        public NullType()
+            : base(TypeKind.Null, null)
+        { }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public override string AnonymousName()
+        {
+            return "null";
+        }
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Special type: any  (used for free variables)
+    ///  
+    public sealed class AnyType : UlyssesType
+    {
+        private ExpressionVariableIdentifier m_variableIdentifier;
+
+        public ExpressionVariableIdentifier VariableIdentifier { get { return m_variableIdentifier; } }
+
+        public AnyType(ExpressionVariableIdentifier freeVariable)
+            : base(TypeKind.Any, null)
+        {
+            m_variableIdentifier = freeVariable;
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public override string AnonymousName()
+        {
+            return "any";
+        }
+
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Simple Type: Int
+    ///  
+    public class IntType : UlyssesType
+    {
+        protected int m_low;
+        protected int m_high;
+
+        public int rangeLow { get { return m_low; } }
+        public int rangeHigh { get { return m_high; } }
+
+        public IntType(int low, int high, TypeIdentifier anIdentifier)
+            : base(TypeKind.IntType, anIdentifier)
+        {
+            m_low = low;
+            m_high = high;
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public override string AnonymousName()
+        {
+            return String.Format("int_{0}_{1}", m_low < 0 ? "m" + Convert.ToString(m_low * (-1)) : Convert.ToString(m_low), m_high);
+        }
+
+    }
+
+    public sealed class CharType : IntType
+    {
+        public CharType(TypeIdentifier anIdentifier)
+            : base(0, 255, anIdentifier)
+        { }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+    }
+
+
+
+    ///////////////////////////////////////////////
+    ///  Simple Type: Bool
+    ///  
+    public sealed class BoolType : UlyssesType
+    {
+        public BoolType(TypeIdentifier anIdentifier)
+            : base(TypeKind.BoolType, anIdentifier)
+        { }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public override string AnonymousName()
+        {
+            return "bool";
+        }
+    }
+
+    ///////////////////////////////////////////////
+    ///  Simple Type: Float (fixed point)
+    ///  
+    public sealed class FloatType : UlyssesType
+    {
+        private double m_low;
+        private double m_high;
+        private double m_precision;
+
+        public double low { get { return m_low; } }
+        public double high { get { return m_high; } }
+        public double precision { get { return m_precision; } }
+        public static double defaultPrecision { get { return double.Epsilon; } }
+
+        public FloatType(double low, double high, double precision, TypeIdentifier anIdentifier)
+            : base(TypeKind.FloatType, anIdentifier)
+        {
+            m_low = low;
+            m_high = high;
+            m_precision = precision;
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public override string AnonymousName()
+        {
+            string name = String.Format("float_{0}_{1}_{2}", m_low < 0 ? "m" + Math.Abs(m_low).ToString(CultureInfo.InvariantCulture) : m_low.ToString(CultureInfo.InvariantCulture), m_high.ToString(CultureInfo.InvariantCulture), m_precision.ToString(CultureInfo.InvariantCulture));
+            name = name.Replace(".", String.Empty);
+            return name;
+        }
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Simple Type: Enumeration
+    ///  
+    public class EnumType : UlyssesType
+    {
+        protected SymbolTable m_enumSymbols;
+        protected List<EnumIdentifier> m_listOfEnumSymbols;
+
+        public SymbolTable symbolTable { get { return m_enumSymbols; } }
+        public List<EnumIdentifier> listOfEnumSymbols { get { return m_listOfEnumSymbols; } }
+
+        public EnumType(TypeIdentifier anIdentifier)
+            : base(TypeKind.EnumeratedType, anIdentifier)
+        {
+            m_enumSymbols = new SymbolTable();
+            m_listOfEnumSymbols = new List<EnumIdentifier>();
+        }
+
+        public void AddEnumSymbol(EnumIdentifier aSymbol)
+        {
+            if (m_enumSymbols.Defined(aSymbol.tokenText))
+                throw new SymbolAlreadyDefinedException(aSymbol.tokenText);
+
+            m_enumSymbols.AddIdentifier(aSymbol);
+            m_listOfEnumSymbols.Add(aSymbol);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public override string AnonymousName()
+        {
+            StringBuilder result = new StringBuilder();
+            result.Append("enum_");
+            foreach (var sym in m_listOfEnumSymbols)
+            {
+                result.Append(sym.tokenText);
+                result.Append("_");
+            }
+            return result.ToString();
+        }
+    }
+
+    public class ValuedEnumType : EnumType
+    {
+        private IntType intType = null;
+
+        public ValuedEnumType(TypeIdentifier anIdentifier)
+            : base(anIdentifier) { }
+
+        public IntType getIntType()
+        {
+            if (intType == null)
+            {
+                int min = Int32.MaxValue; int max = Int32.MinValue;
+                foreach (var x in symbolTable.symbolList)
+                {
+                    EnumIdentifier id = (EnumIdentifier)x;
+                    if (id.Value > max)
+                        max = id.Value;
+                    if (id.Value < min)
+                        min = id.Value;
+                }
+                intType = new IntType(min, max, null);
+            }
+            return intType;
+        }
+
+        public override string AnonymousName()
+        {
+            StringBuilder result = new StringBuilder();
+            result.Append("enum_");
+            foreach (var sym in m_listOfEnumSymbols)
+            {
+                result.Append(sym.tokenText);
+                if (sym.Value < 0)
+                {
+                    result.Append("m");
+                    result.Append(sym.Value * (-1));
+                }
+                else
+                    result.Append(sym.Value);
+                result.Append("_");
+            }
+            return result.ToString();
+        }
+    }
+
+
+
+
+    ///////////////////////////////////////////////
+    ///  Complex Type: QrType
+    ///  behaves somewhat similar to an enumerated type..
+    ///  
+    public sealed class QrType : UlyssesType
+    {
+        private SymbolTable m_qspaceSymbols;
+        private List<LandmarkIdentifier> m_listOfQspaceSymbols;
+
+        public SymbolTable symbolTable { get { return m_qspaceSymbols; } }
+        public List<LandmarkIdentifier> landmarks { get { return m_listOfQspaceSymbols; } }
+
+        public QrType(TypeIdentifier anIdentifier)
+            : base(TypeKind.QrType, anIdentifier)
+        {
+            m_listOfQspaceSymbols = new List<LandmarkIdentifier>();
+            m_qspaceSymbols = new SymbolTable();
+        }
+
+        public void AddLandmark(LandmarkIdentifier aLandmark)
+        {
+            if (m_qspaceSymbols.Defined(aLandmark.tokenText))
+                throw new SymbolAlreadyDefinedException(aLandmark.tokenText);
+
+            m_qspaceSymbols.AddIdentifier(aLandmark);
+            m_listOfQspaceSymbols.Add(aLandmark);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public override string AnonymousName()
+        {
+            StringBuilder result = new StringBuilder();
+            result.Append("qr_");
+            foreach (var sym in m_listOfQspaceSymbols)
+            {
+                result.Append(sym.tokenText);
+                result.Append("_");
+            }
+            return result.ToString();
+        }
+
+    }
+
+
+
+    ///////////////////////////////////////////////
+    ///  Complex Type: List
+    ///  
+    public sealed class ListType : UlyssesType
+    {
+        private UlyssesType m_innerType;
+        private int m_maxNumberOfElements;
+
+        public UlyssesType innerType { get { return m_innerType; } }
+        public int maxNumberOfElements { get { return m_maxNumberOfElements; } }
+
+        public ListType(UlyssesType elemType, int max, TypeIdentifier anIdentifier)
+            : base(TypeKind.ListType, anIdentifier)
+        {
+            m_innerType = elemType;
+            m_maxNumberOfElements = max;
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public void SetInnerType(UlyssesType newType)
+        {
+            if (newType == null)
+                throw new ArgumentException();
+            m_innerType = newType;
+        }
+
+        public override string AnonymousName()
+        {
+            return String.Format("list_{0}_{1}", m_maxNumberOfElements, m_innerType != null ? m_innerType.ToString() : "uninit");
+        }
+
+    }
+
+    ///////////////////////////////////////////////
+    ///  Complex Type: Map
+    ///  
+    public sealed class MapType : UlyssesType
+    {
+        private UlyssesType m_fromType;
+        private UlyssesType m_toType;
+        private int m_maxNumberOfElements;
+
+        public UlyssesType fromType { get { return m_fromType; } }
+        public UlyssesType toType { get { return m_toType; } }
+        public int maxNumberOfElements { get { return m_maxNumberOfElements; } }
+
+        public MapType(UlyssesType from, UlyssesType to, int max, TypeIdentifier anIdentifier)
+            : base(TypeKind.MapType, anIdentifier)
+        {
+            m_fromType = from;
+            m_toType = to;
+            m_maxNumberOfElements = max;
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public void SetFromType(UlyssesType newType)
+        {
+            if (newType == null)
+                throw new ArgumentException();
+            m_fromType = newType;
+        }
+
+        public void SetToType(UlyssesType newType)
+        {
+            if (newType == null)
+                throw new ArgumentException();
+            m_toType = newType;
+        }
+
+        public override string AnonymousName()
+        {
+            return String.Format("map_{0}_{1}_{2}", m_maxNumberOfElements, m_fromType != null ? m_fromType.ToString() : "uninit", m_toType != null ? m_toType.ToString() : "uninit");
+        }
+
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Complex Type: TupleType
+    ///  
+    public sealed class TupleType : UlyssesType
+    {
+        private LinkedList<UlyssesType> m_innerTypes;
+
+        public LinkedList<UlyssesType> innerTypes { get { return m_innerTypes; } }
+
+        public TupleType(TypeIdentifier anIdentifier)
+            : base(TypeKind.TupleType, anIdentifier)
+        {
+            m_innerTypes = new LinkedList<UlyssesType>();
+        }
+
+        public void AddType(UlyssesType aType)
+        {
+            m_innerTypes.AddLast(aType);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public override string AnonymousName()
+        {
+            StringBuilder result = new StringBuilder();
+            result.Append("tuple_");
+            foreach (var inner in m_innerTypes)
+            {
+                result.Append(inner == null ? "<null>" : inner.ToString());
+                result.Append("_");
+            }
+            return result.ToString();
+        }
+
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Complex Type: Function
+    ///  
+    public enum FunctionTypeEnum { Observable, Controllable, Continuous, Internal, Method }
+    public sealed class FunctionType : UlyssesType
+    {
+        private bool? m_miracleSafe;
+        private bool m_pure;
+        private LinkedList<UlyssesType> m_parameter;
+        private UlyssesType m_returnType;
+        private FunctionTypeEnum m_functionType;
+
+        public bool? isMiracleSafe { get { return m_miracleSafe; } }
+        public bool isPureFunction { get { return m_pure; } }
+        public LinkedList<UlyssesType> parameter { get { return m_parameter; } }
+        public UlyssesType returnType { get { return m_returnType; } }
+        public FunctionTypeEnum functionType { get { return m_functionType; } }
+
+        public FunctionType(FunctionTypeEnum functionType, LinkedList<UlyssesType> parameter, UlyssesType returnType)
+            : base(TypeKind.FunctionType, null)
+        {
+            if (parameter != null)
+                m_parameter = parameter;
+            else
+                m_parameter = new LinkedList<UlyssesType>();
+            m_returnType = returnType;
+            m_functionType = functionType;
+            m_miracleSafe = null;
+            m_pure = false;
+        }
+
+
+        public void AddParameterType(UlyssesType aType)
+        {
+            m_parameter.AddLast(aType);
+        }
+
+        public void SetReturnType(UlyssesType aType)
+        {
+            m_returnType = aType;
+        }
+
+        public void SetMiracleSafe(bool newValue)
+        {
+            m_miracleSafe = newValue;
+        }
+
+        public void SetIsPureFunction(bool newValue)
+        {
+            m_pure = newValue;
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public override string AnonymousName()
+        {
+            StringBuilder result = new StringBuilder();
+            result.Append("fun_");
+            result.Append(m_functionType.ToString());
+            result.Append("_");
+            foreach (var sym in m_parameter)
+            {
+                result.Append(sym.ToString());
+                result.Append("_");
+            }
+            result.Append("_");
+            if (m_returnType != null)
+                result.Append(m_returnType.ToString());
+            else
+                result.Append("void");
+            result.Append("_");
+            result.Append(m_pure);
+            return result.ToString();
+        }
+
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Complex Type: OoActionSystem
+    ///  
+
+    public sealed class OoActionSystemInstance
+    {
+        // pointer to type
+        public OoActionSystemType Type;
+        // name of the current object
+        public string Name;
+        // counts the number of objects that have been created by this object
+        public int numberOfCreatedObjects;
+        // pointer to a C# instance of this object
+        public TUG.Mogentes.Codegen.CSharp.UlyssesActionSystemClass Instance;
+        // pointer to the object that created us
+        public OoActionSystemInstance ParentObject;
+
+        public OoActionSystemInstance(string aName, OoActionSystemType aType, TUG.Mogentes.Codegen.CSharp.UlyssesActionSystemClass anInstance, OoActionSystemInstance aParentObj)
+        {
+            Name = aName;
+            Type = aType;
+            ParentObject = aParentObj;
+            Instance = anInstance;
+            numberOfCreatedObjects = 0;
+            if (ParentObject != null)
+                ParentObject.numberOfCreatedObjects++;
+        }
+    }
+
+    public class OoActionSystemType : UlyssesType, IScope
+    {
+        private bool m_autoCons;
+        private OoActionSystemType m_baseType;
+        private Block m_doOdBlock;
+        private IScope m_parentScope;
+        private SymbolTable m_symbols;
+        private List<OoActionSystemInstance> m_objects;
+        private List<OoActionSystemInstance> m_derivedObjects;
+        private bool m_isInSystemDescription;
+
+        public Block doOdBlock { get { return m_doOdBlock; } }
+        public bool autoConstruction { get { return m_autoCons; } }
+        public OoActionSystemType baseType { get { return m_baseType; } }
+        public SymbolTable symbols { get { return m_symbols; } }
+        public List<OoActionSystemInstance> objects { get { return m_objects; } }
+        public List<OoActionSystemInstance> derivedObjects { get { return m_derivedObjects; } }
+        public bool isInSystemDescription { get { return m_isInSystemDescription; } }
+
+        public OoActionSystemType(
+                bool autoCons,
+                OoActionSystemType refinedSystem,
+                TypeIdentifier typeName)
+            : base(TypeKind.OoActionSystemType, typeName)
+        {
+            m_symbols = new SymbolTable();
+            m_autoCons = autoCons;
+            m_baseType = refinedSystem;
+            m_objects = new List<OoActionSystemInstance>();
+            m_derivedObjects = new List<OoActionSystemInstance>();
+            m_isInSystemDescription = false;
+        }
+
+        public void SetDoOdBlock(Block anArg)
+        {
+            m_doOdBlock = anArg;
+        }
+
+
+        public IScope GetParentScope()
+        {
+            return m_parentScope;
+        }
+
+        public void SetParentScope(IScope parentScope)
+        {
+            m_parentScope = parentScope;
+        }
+
+        public Identifier ResolveLocal(string aName)
+        {
+            if (m_symbols.Defined(aName))
+                return m_symbols.Get(aName);
+            else
+                return null;
+        }
+
+        public Identifier ResolveIdentifier(string aName)
+        {
+            Identifier result = ResolveLocal(aName);
+            if ((result == null) && (m_baseType != null))
+                result = m_baseType.ResolveIdentifier(aName);
+            return result;
+        }
+
+        public void AddIdentifier(Identifier anIdentifier, object tag)
+        {
+            m_symbols.AddIdentifier(anIdentifier);
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public void SetBaseType(OoActionSystemType newType)
+        {
+            if (newType == null)
+                throw new ArgumentException();
+            m_baseType = newType;
+        }
+
+        public SymbolTable getAllSymbols()
+        {
+            OoActionSystemType system;
+            List<OoActionSystemType> inheritance = new List<OoActionSystemType>();
+            system = this;
+            while (system != null)
+            {
+                inheritance.Insert(0, system);
+                system = system.baseType;
+            }
+            SymbolTable result = new SymbolTable();
+            foreach (var ooas in inheritance)
+                result.AddSymbolTable(ooas.symbols);
+            result.Replace("self", this.symbols.Get("self"));
+            return result;
+        }
+
+        public override string AnonymousName()
+        {
+            return String.Format("class_{0}", (uint)this.GetHashCode());
+        }
+
+        internal void SetIsInSystemDescription(bool p)
+        {
+            m_isInSystemDescription = p;
+        }
+    }
+
+
+    ///////////////////////////////////////////////
+    ///  Opaque Type..
+    ///  
+    public class OpaqueType : UlyssesType
+    {
+        private UlyssesType m_resolvedType;
+
+        public UlyssesType resolvedType { get { return m_resolvedType; } }
+
+        public OpaqueType(TypeIdentifier reference)
+            : base(TypeKind.OpaqueType, reference)
+        { }
+
+        public void SetResolvedType(UlyssesType aType)
+        {
+            m_resolvedType = aType;
+        }
+
+        public override void Accept(IAstVisitor visitor)
+        {
+            visitor.visit(this);
+        }
+
+        public override string AnonymousName()
+        {
+            if (m_resolvedType == null)
+                return "undef";
+            else
+                return m_resolvedType.ToString();
+        }
+    }
+
+
+
+    ///////////////////////////////////////////////
+    ///  Not really a type - this is the structure for the instantiated action system
+    ///  (all the objects flattened)
+    ///  
+
+    public sealed class ActionSystem : OoActionSystemType
+    {
+        private List<OoActionSystemType> m_types;
+
+        public List<OoActionSystemType> types { get { return m_types; } }
+
+
+        public ActionSystem()
+            : base(false, null, null)
+        {
+            m_types = new List<OoActionSystemType>();
+            m_identifier = new TypeIdentifier("__system", this, null);
+        }
+
+    }
+
+
+
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/Argos.csproj
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/Argos.csproj	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/Argos.csproj	(revision 3)
@@ -0,0 +1,150 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
+  <PropertyGroup>
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+    <ProductVersion>9.0.21022</ProductVersion>
+    <SchemaVersion>2.0</SchemaVersion>
+    <ProjectGuid>{5EE180FC-E804-48C1-8FF3-0C62D43A7855}</ProjectGuid>
+    <OutputType>Exe</OutputType>
+    <AppDesignerFolder>Properties</AppDesignerFolder>
+    <RootNamespace>TUG.Mogentes</RootNamespace>
+    <AssemblyName>argos</AssemblyName>
+    <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
+    <FileAlignment>512</FileAlignment>
+    <StartupObject>TUG.Mogentes.Program</StartupObject>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
+    <FileUpgradeFlags>
+    </FileUpgradeFlags>
+    <UpgradeBackupLocation>
+    </UpgradeBackupLocation>
+    <OldToolsVersion>3.5</OldToolsVersion>
+    <PublishUrl>publish\</PublishUrl>
+    <Install>true</Install>
+    <InstallFrom>Disk</InstallFrom>
+    <UpdateEnabled>false</UpdateEnabled>
+    <UpdateMode>Foreground</UpdateMode>
+    <UpdateInterval>7</UpdateInterval>
+    <UpdateIntervalUnits>Days</UpdateIntervalUnits>
+    <UpdatePeriodically>false</UpdatePeriodically>
+    <UpdateRequired>false</UpdateRequired>
+    <MapFileExtensions>true</MapFileExtensions>
+    <ApplicationRevision>0</ApplicationRevision>
+    <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
+    <UseApplicationTrust>false</UseApplicationTrust>
+    <BootstrapperEnabled>true</BootstrapperEnabled>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <DebugSymbols>true</DebugSymbols>
+    <DebugType>full</DebugType>
+    <Optimize>false</Optimize>
+    <OutputPath>..\bin\Debug\</OutputPath>
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>3</WarningLevel>
+    <Commandlineparameters>-p -oCondTest.pl ../../../examples/CondTest.ooa</Commandlineparameters>
+    <ConsolePause>false</ConsolePause>
+  </PropertyGroup>
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+    <DebugType>pdbonly</DebugType>
+    <Optimize>true</Optimize>
+    <OutputPath>..\bin\Release\</OutputPath>
+    <DefineConstants>TRACE</DefineConstants>
+    <ErrorReport>prompt</ErrorReport>
+    <WarningLevel>4</WarningLevel>
+  </PropertyGroup>
+  <ItemGroup>
+    <Reference Include="Antlr3.Runtime, Version=3.1.3.42154, Culture=neutral, PublicKeyToken=3a9cab8f8d22bfb7">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>libs\Antlr3.Runtime.dll</HintPath>
+    </Reference>
+    <Reference Include="C5, Version=1.1.0.0, Culture=neutral, PublicKeyToken=06a1b38866503b69, processorArchitecture=MSIL">
+      <SpecificVersion>False</SpecificVersion>
+      <HintPath>libs\c5\C5.dll</HintPath>
+    </Reference>
+    <Reference Include="System" />
+    <Reference Include="System.Configuration" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Xml" />
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="codegen\CSharp\ooaCSharpCodeGen.cs" />
+    <Compile Include="codegen\CSharp\ooaCSharpInitVisitor.cs" />
+    <Compile Include="codegen\CSharp\ooaCSharpRuntime.cs" />
+    <Compile Include="codegen\ooaCodeEmitter.cs" />
+    <Compile Include="codegen\PrologSymbolic\ooaPrologSymbolicStatement.cs" />
+    <Compile Include="codegen\PrologSymbolic\ooaPrologSymbolicType.cs" />
+    <Compile Include="codegen\PrologSymbolic\ooaPrologSymbolicExpression.cs" />
+    <Compile Include="codegen\PrologSymbolic\ooaPrologSymbolicVisitor.cs" />
+    <Compile Include="codegen\Prolog\ooaPrologExpression.cs" />
+    <Compile Include="codegen\Prolog\ooaPrologStatement.cs" />
+    <Compile Include="codegen\Prolog\ooaPrologIdentifier.cs" />
+    <Compile Include="codegen\Prolog\ooaPrologType.cs" />
+    <Compile Include="codegen\Prolog\ooaPrologVisitor.cs" />
+    <Compile Include="parser\invokeSharpCompiler.cs" />
+    <Compile Include="parser\visitors\ooaActionClassifierVisitor.cs" />
+    <Compile Include="parser\visitors\ooaCloneVisitor.cs" />
+    <Compile Include="parser\visitors\ooaMethodPureClassifier.cs" />
+    <Compile Include="parser\visitors\ooaObjectsInstantiateVisitor.cs" />
+    <Compile Include="parser\visitors\ooaMethodCallVisitor.cs" />
+    <Compile Include="parser\visitors\ooaPrintVisitor.cs" />
+    <Compile Include="math\Operations.cs" />
+    <Compile Include="math\Range.cs" />
+    <Compile Include="parser\ooaExceptions.cs" />
+    <Compile Include="ooaLexer.cs" />
+    <Compile Include="ooaParser.cs" />
+    <Compile Include="parser\basicTypes.cs" />
+    <Compile Include="parser\ooaExpressions.cs" />
+    <Compile Include="parser\ooaParser.cs" />
+    <Compile Include="parser\visitors\ooaOpaqueVisitor.cs" />
+    <Compile Include="parser\visitors\ooaPrioritizedCompositionVisitor.cs" />
+    <Compile Include="parser\visitors\ooaResolveVisitor.cs" />
+    <Compile Include="parser\ooaStatements.cs" />
+    <Compile Include="parser\ooaSymbols.cs" />
+    <Compile Include="parser\visitors\ooaTypeCheckVisitor.cs" />
+    <Compile Include="parser\visitors\ooaTypeRenameVisitor.cs" />
+    <Compile Include="parser\visitors\ooaTypesVisitor.cs" />
+    <Compile Include="parser\visitors\ooaVisitor.cs" />
+    <Compile Include="parser\ooaTypes.cs" />
+    <Compile Include="Program.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs" />
+  </ItemGroup>
+  <ItemGroup>
+    <BootstrapperPackage Include="Microsoft.Net.Client.3.5">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.2.0">
+      <Visible>False</Visible>
+      <ProductName>
+      </ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.0">
+      <Visible>False</Visible>
+      <ProductName>
+      </ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5">
+      <Visible>False</Visible>
+      <ProductName>
+      </ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+    <BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
+      <Visible>False</Visible>
+      <ProductName>.NET Framework 3.5 SP1</ProductName>
+      <Install>false</Install>
+    </BootstrapperPackage>
+  </ItemGroup>
+  <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
+       Other similar extension points exist, see Microsoft.Common.targets.
+  <Target Name="BeforeBuild">
+  </Target>
+  <Target Name="AfterBuild">
+  </Target>
+  -->
+</Project>
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/Argos.csproj.user
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/Argos.csproj.user	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/Argos.csproj.user	(revision 3)
@@ -0,0 +1,21 @@
+﻿<?xml version="1.0" encoding="utf-8"?>
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+    <StartArguments>-pSym -d100 -oD:\tmp\out.pl C:\Users\KrennW\Desktop\bug.ooas</StartArguments>
+    <StartAction>Project</StartAction>
+  </PropertyGroup>
+  <PropertyGroup>
+    <PublishUrlHistory>publish\</PublishUrlHistory>
+    <InstallUrlHistory />
+    <SupportUrlHistory />
+    <UpdateUrlHistory />
+    <BootstrapperUrlHistory />
+    <ErrorReportUrlHistory />
+    <FallbackCulture>en-US</FallbackCulture>
+    <VerifyUploadedFiles>false</VerifyUploadedFiles>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|AnyCPU'">
+    <StartArguments>
+    </StartArguments>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/Program.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/Program.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/Program.cs	(revision 3)
@@ -0,0 +1,494 @@
+﻿/**
+  *
+  *                      OOAS Compiler (Deprecated)
+  *
+  * Copyright 2015, Institute for Software Technology, Graz University of
+  * Technology. Portions are copyright 2015 by the AIT Austrian Institute
+  * of Technology. All rights reserved.
+  *
+  * SEE THE "LICENSE" FILE FOR THE TERMS UNDER WHICH THIS FILE IS PROVIDED.
+  *
+  * Please notice that this version of the OOAS compiler is considered de-
+  * precated. Only the Java version is maintained.
+  *
+  * Contributors:
+  *               Willibald Krenn (TU Graz/AIT)
+  *               Stefan Tiran (TU Graz/AIT)
+  */
+
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Configuration;
+using Antlr.Runtime;
+using TUG.Mogentes.Codegen;
+
+namespace TUG.Mogentes
+{
+    [Serializable()]
+    public struct ArgosVersion
+    {
+        public int ParserMajor;
+        public int ParserMinor;
+        public int ParserRevision;
+
+        public int GrammarMajor;
+        public int GrammarMinor;
+
+        public override string ToString()
+        {
+            StringBuilder result = new StringBuilder();
+            result.Append("          Version: ");
+            result.Append(ParserMajor); result.Append("."); result.Append(String.Format("{0:00}",ParserMinor));
+            result.Append(" ("); result.Append(ParserRevision); result.AppendLine(")");
+            result.Append("  Grammar-Version: ");
+            result.Append(GrammarMajor); result.Append("."); result.Append(String.Format("{0:00}",GrammarMinor));
+            return result.ToString();
+        }
+    }
+
+
+    public abstract class ConfigurationElementCollection<T> : ConfigurationElementCollection
+            where T : ConfigurationElement
+    {
+        protected override ConfigurationElement CreateNewElement()
+        {
+            return (ConfigurationElement)Activator.CreateInstance(typeof(T));
+        }
+
+        public void Add(T elem)
+        {
+            BaseAdd(elem);
+        }
+
+        public T this[int index]
+        {
+            get { return (T)base.BaseGet(index); }
+            set
+            {
+                if (base.BaseGet(index) != null)
+                {
+                    base.BaseRemoveAt(index);
+                }
+                this.BaseAdd(index, value);
+            }
+        }
+
+        public new T this[string key]
+        {
+            get { return (T)base.BaseGet(key); }
+        }
+    }
+
+    public class BackEndConfig : ConfigurationElement
+    {
+        [ConfigurationProperty("switch", IsRequired = true)]
+        public string Switch
+        {
+            get { return (string)base["switch"]; }
+            set { base["switch"] = value; }
+        }
+        [ConfigurationProperty("file", IsRequired = true)]
+        public string File
+        {
+            get { return (string)base["file"]; }
+            set { base["file"] = value; }
+        }
+        [ConfigurationProperty("class", IsRequired = true)]
+        public string Class
+        {
+            get { return (string)base["class"]; }
+            set { base["class"] = value; }
+        }
+        [ConfigurationProperty("descr", IsRequired = true)]
+        public string Descr
+        {
+            get { return (string)base["descr"]; }
+            set { base["descr"] = value; }
+        }
+
+        public BackEndConfig(string aSwitch, string aFile, string aClass, string aDescr)
+            : base()
+        {
+            Switch = aSwitch;
+            File = aFile;
+            Class = aClass;
+            Descr = aDescr;
+        }
+
+        public BackEndConfig(BackEndConfig toCopy)
+        {
+            Switch = toCopy.Switch;
+            File = toCopy.File;
+            Class = toCopy.Class;
+            Descr = toCopy.Descr;
+        }
+
+        public BackEndConfig() { }
+    }
+
+    public class InstantiatedBackEndConfig : BackEndConfig
+    {
+        public Type Visitor;
+        public System.Reflection.ConstructorInfo Constr;
+
+        public CreateVisitor GetConstructor()
+        {
+            return p => (IAstVisitor)Constr.Invoke(new Object[] { p });
+        }
+
+        public InstantiatedBackEndConfig(BackEndConfig toInstantiate)
+            : base(toInstantiate)
+        {
+            if (toInstantiate.File != String.Empty)
+            {
+                string filename = System.IO.Path.GetFullPath(toInstantiate.File);
+                if (!System.IO.File.Exists(filename))
+                {
+                    filename = new Uri(System.Reflection.Assembly.GetExecutingAssembly().Location).LocalPath;
+                    filename = System.IO.Path.GetDirectoryName(filename) + System.IO.Path.DirectorySeparatorChar + toInstantiate.File;
+                    if (!System.IO.File.Exists(filename))
+                    {
+                        throw new ArgumentException(String.Format("Not found: {0}", toInstantiate.File));
+                    }
+                }
+                this.File = filename;
+
+
+                System.Reflection.Assembly backend = System.Reflection.Assembly.LoadFile(File);
+                Visitor = backend.GetType(toInstantiate.Class);
+                if (Visitor == null)
+                    throw new ArgumentException(String.Format("Cannot find type {0}", toInstantiate.Class));
+            }
+            else
+            {
+                Visitor = System.Reflection.Assembly.GetExecutingAssembly().GetType(toInstantiate.Class);
+                if (Visitor == null)
+                    throw new ArgumentException(String.Format("Cannot find type {0}", toInstantiate.Class));
+            }
+
+            Constr = Visitor.GetConstructor(new Type[] { typeof(ParserState) });
+            if (Constr == null)
+                throw new ArgumentException(String.Format("Cannot get constructor of type {0}", toInstantiate.Class));
+
+        }
+
+    }
+
+
+    [ConfigurationCollection(typeof(BackEndConfig))]
+    public class BackendSettingsCollection : ConfigurationElementCollection<BackEndConfig>
+    {
+        protected override object GetElementKey(ConfigurationElement element)
+        {
+            return ((BackEndConfig)element).Switch;
+        }
+    }
+
+
+
+    public class ArgosConfigData : ConfigurationSection
+    {
+        public ArgosConfigData()
+        {
+        }
+
+        [ConfigurationProperty("backends")]
+        public BackendSettingsCollection BackendSettings
+        {
+            get { return (BackendSettingsCollection)this["backends"]; }
+            set { this["backends"] = value; }
+        }
+    }
+
+
+    public class Program
+    {
+
+        public class Options
+        {
+            public static string searchDepth = "35";
+            internal bool quiet = false;
+            internal string fileToParse = String.Empty;
+            internal string outputToFile = String.Empty;
+            internal string namedTypePrefix = String.Empty;
+            public static string nameSpace = "as";
+            internal List<CreateVisitor> pipeLine = new List<CreateVisitor>();
+        }
+
+        public static List<InstantiatedBackEndConfig> BackEnds = new List<InstantiatedBackEndConfig>();
+        public static readonly string BackEndSectionName = "BackEnds";
+
+        static void CreateSection()
+        {
+            try
+            {
+                ArgosConfigData customSection;
+
+                // Get the current configuration file.
+                System.Configuration.Configuration config =
+                        ConfigurationManager.OpenExeConfiguration(
+                        ConfigurationUserLevel.None);
+
+                // Create the section entry  
+                // in the <configSections> and the 
+                // related target section in <configuration>.
+                if (config.Sections[BackEndSectionName] == null)
+                {
+                    customSection = new ArgosConfigData();
+                    customSection.BackendSettings.Add(new BackEndConfig("a", String.Empty, "TUG.Mogentes.OoaPrintVisitor", "create psuedo-action system code"));
+                    customSection.BackendSettings.Add(new BackEndConfig("p", String.Empty, "TUG.Mogentes.Codegen.OoaPrologVisitor", "create prolog code"));
+                    customSection.BackendSettings.Add(new BackEndConfig("psym", String.Empty, "TUG.Mogentes.Codegen.PrologSymbolic.OoaPrologSymbolicVisitor", "create symbolic prolog code"));
+                    config.Sections.Add(BackEndSectionName, customSection);
+                    customSection.SectionInformation.ForceSave = true;
+                    config.Save(ConfigurationSaveMode.Full);
+                }
+            }
+            catch (ConfigurationErrorsException err)
+            {
+                Console.WriteLine(err.ToString());
+            }
+        }
+        public static ArgosVersion GetProgramVersion()
+        {
+            Version ver = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version;
+            ArgosVersion result;
+            result.ParserMajor = ver.Major;
+            result.ParserMinor = ver.Minor;
+            result.ParserRevision = ver.Revision;
+
+            result.GrammarMajor = (ver.Build / 100);
+            result.GrammarMinor = (ver.Build % 100);
+            return result;
+        }
+        static void displayTitle()
+        {
+            ArgosVersion ver = Program.GetProgramVersion();
+            Console.WriteLine();
+            Console.WriteLine("          >> Mogentes OO-Action System Parser <<");
+            Console.WriteLine();
+            Console.WriteLine(ver.ToString());
+            Console.WriteLine();
+        }
+
+        /* display some help screen */
+        static void displayHelp()
+        {
+            string programName = String.Empty;
+            programName = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name.ToString();
+
+            displayTitle();
+            Console.WriteLine("Usage:    " + programName + " [options] <oo-actionsystem-file>");
+            Console.WriteLine("Options:");
+            Console.WriteLine("     -o<name>   ... write output to file <name> (overwrites!)");
+            Console.WriteLine("     -n<name>   ... use namespace <name> (default: as)");
+            Console.WriteLine("     -d<depth>  ... set max. search depth (default: 35)");
+            Console.WriteLine("     -q         ... \"quiet\" mode: doesn't print Warnings to console");
+            Console.WriteLine();
+            foreach (var x in BackEnds)
+            {
+                Console.WriteLine(String.Format("     -{0}         ... {1}", x.Switch, x.Descr));
+            }
+        }
+
+        /* fire up the parser */
+        static int runAntlrParser(Options options)
+        {
+            ParserState pState = new ParserState(options);
+            int result = ooaParser.FirstPass(pState);
+
+
+            displayTitle();
+
+            if (result > 0)
+            {
+                Console.WriteLine("The parser returned {0} errors:", result);
+                foreach (var error in pState.listOfParserErrors)
+                    Console.WriteLine("ERROR ({0}): {1},{2}; {3}", error.file, error.line, error.column, error.message);
+            }
+            else
+            {
+                Console.WriteLine("   Passed: OoaParser");
+                if (options.pipeLine.Count > 0)
+                {
+
+                    IAstVisitor visitor = null;
+                    foreach (var item in options.pipeLine)
+                    {
+                        visitor = item(pState);
+                        pState.ooaSystem.Accept(visitor);
+                        if (pState.listOfParserErrors.Count > 0)
+                        {
+                            Console.WriteLine("The parser ({0}) returned {1} errors:",
+                                visitor.GetType().Name, pState.listOfParserErrors.Count);
+                            foreach (var error in pState.listOfParserErrors)
+                                Console.WriteLine("ERROR ({0}): {1},{2}; {3}",
+                                    error.file, error.line, error.column, error.message);
+                            return pState.listOfParserErrors.Count;
+                        }
+                        else
+                        {
+                            Console.Write("   Passed: ");
+                            Console.WriteLine(visitor.GetType().Name);
+                        }
+                    }
+                    Console.WriteLine();
+                    Console.WriteLine("File {0} successfully parsed.", pState.filename);
+                    Console.WriteLine("");
+
+                    if (pState.listOfParserMessages.Count > 0 && !(options.quiet))
+                    {
+                        Console.WriteLine(String.Format("Parser returned {0} messages:", pState.listOfParserMessages.Count));
+                        foreach (var message in pState.listOfParserMessages)
+                            Console.WriteLine("Message ({0}): {1},{2}; {3}",
+                                message.file, message.line, message.column, message.message);
+                        Console.WriteLine();
+                        Console.WriteLine();
+                    }
+
+                    if (pState.listOfParserWarnings.Count > 0 && !(options.quiet))
+                    {
+                        Console.WriteLine(String.Format("Parser returned {0} warnings:", pState.listOfParserWarnings.Count));
+                        foreach (var warning in pState.listOfParserWarnings)
+                            Console.WriteLine("Warning ({0}): {1},{2}; {3}",
+                                warning.file, warning.line, warning.column, warning.message);
+                        Console.WriteLine("");
+                        Console.WriteLine("");
+                    }
+
+                    if (options.outputToFile != String.Empty)
+                    {
+                        Console.WriteLine("Writing output to {0}.", options.outputToFile);
+                        System.IO.File.WriteAllText(options.outputToFile, visitor.ToString(), System.Text.Encoding.ASCII);
+                    }
+                    else
+                        Console.WriteLine(visitor.ToString());
+                }
+                else
+                {
+                    Console.WriteLine();
+                    Console.WriteLine("File {0} successfully parsed.", pState.filename);
+                    Console.WriteLine("");
+                }
+            }
+
+            return result;
+        }
+
+
+
+
+        /* entry point */
+        static int Main(string[] args)
+        {
+            CreateSection();
+            Program.Options options = new Program.Options();
+
+            /*load backends..*/
+            ArgosConfigData backends = ConfigurationManager.GetSection(BackEndSectionName) as ArgosConfigData;
+            foreach (var x in backends.BackendSettings)
+            {
+                BackEndConfig cnfg = (BackEndConfig)x;
+                //try
+                //{
+                InstantiatedBackEndConfig icnfg = new InstantiatedBackEndConfig(cnfg);
+                BackEnds.Add(icnfg);
+                //}
+                //catch (ArgumentException)
+                //{ }
+            }
+
+
+
+            if ((args.Length == 0) || (!System.IO.File.Exists(args[args.Length - 1])))
+            {
+                displayHelp();
+#if DEBUG
+                Console.ReadLine();
+#endif
+                return 0;
+            }
+
+            /*do some argument 'parsing'*/
+            for (int i = 0; i < args.Length; i++)
+            {
+                if (args[i].StartsWith("-"))
+                    ParserOption(args[i], options);
+                else
+                {
+                    options.fileToParse = args[i];
+                    break;
+                }
+            }
+
+            /* c# really lacks meta-classes :-((
+             * but lambdas are a nice feature too :-)
+             */
+            int index = 0;
+            options.pipeLine.Insert(index++, p => new OoaSymbolSortVisitor(p));
+            options.pipeLine.Insert(index++, p => new OoaReplaceOpaqueVisitor(p));
+            options.pipeLine.Insert(index++, p => new OoaTypesVisitor(p));
+            options.pipeLine.Insert(index++, p => new OoaResolveExpressionsVisitor(p));
+            options.pipeLine.Insert(index++, p => new OoaMethodPureClassifierVisitor(p));
+            options.pipeLine.Insert(index++, p => new OoaTypeCheckVisitor(p));
+
+            if (options.namedTypePrefix != String.Empty)
+            {
+                options.pipeLine.Insert(index++, p => new OoaTypeRenameVisitor(p));
+            }
+
+            options.pipeLine.Insert(index++, aParser => new OoaRemoveTrivialPrioritizedCompositionVisitor(aParser));
+            options.pipeLine.Insert(index++, p => new OoaActionClassifierVisitor(p));
+            options.pipeLine.Insert(index++, p => new OoaObjectInstantiationVisitor(p));
+
+
+
+
+            Console.WriteLine("Parsing {0}.", options.fileToParse);
+            int result = runAntlrParser(options);
+#if DEBUG
+            Console.ReadLine();
+#endif
+            return result;
+        }
+
+        private static void ParserOption(string p, Options options)
+        {
+            string p_lower = p.ToLower();
+
+            
+
+            if (p_lower.StartsWith("-o"))
+                options.outputToFile = p.Remove(0, 2);
+            if (p_lower.StartsWith("-t"))
+                options.namedTypePrefix = p.Remove(0, 2);
+            if (p_lower.StartsWith("-n"))
+            {
+
+                TUG.Mogentes.Program.Options.nameSpace = p.Remove(0, 2);
+            }
+            if (p_lower.StartsWith("-q"))
+            {
+                p.Remove(0, 2);
+                options.quiet = true;
+            }
+
+            if (p_lower.StartsWith("-d"))
+            {
+                TUG.Mogentes.Program.Options.searchDepth = p.Remove(0, 2);
+            }
+
+
+            else
+                foreach (var x in BackEnds)
+                {
+                    if (p_lower.Equals(String.Format("-{0}", x.Switch)))
+                    {
+                        options.pipeLine.Add(x.GetConstructor());
+                        return;
+                    }
+                }
+
+        }
+    }
+}
Index: branches/compiler/cSharp/ooasCompiler/src/antlr-3.2.jar
===================================================================
Cannot display: file marked as a binary type.
svn:mime-type = application/octet-stream
Index: branches/compiler/cSharp/ooasCompiler/src/antlr-3.2.jar
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/antlr-3.2.jar	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/antlr-3.2.jar	(revision 3)

Property changes on: branches/compiler/cSharp/ooasCompiler/src/antlr-3.2.jar
___________________________________________________________________
Added: svn:mime-type
## -0,0 +1 ##
+application/octet-stream
\ No newline at end of property
Index: branches/compiler/cSharp/ooasCompiler/src/argos.sln
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/argos.sln	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/argos.sln	(revision 3)
@@ -0,0 +1,37 @@
+﻿
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Express 2012 for Windows Desktop
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Argos", "Argos.csproj", "{5EE180FC-E804-48C1-8FF3-0C62D43A7855}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Debug|Mixed Platforms = Debug|Mixed Platforms
+		Debug|Win32 = Debug|Win32
+		Debug|x86 = Debug|x86
+		Release|Any CPU = Release|Any CPU
+		Release|Mixed Platforms = Release|Mixed Platforms
+		Release|Win32 = Release|Win32
+		Release|x86 = Release|x86
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{5EE180FC-E804-48C1-8FF3-0C62D43A7855}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{5EE180FC-E804-48C1-8FF3-0C62D43A7855}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{5EE180FC-E804-48C1-8FF3-0C62D43A7855}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU
+		{5EE180FC-E804-48C1-8FF3-0C62D43A7855}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU
+		{5EE180FC-E804-48C1-8FF3-0C62D43A7855}.Debug|Win32.ActiveCfg = Debug|Any CPU
+		{5EE180FC-E804-48C1-8FF3-0C62D43A7855}.Debug|x86.ActiveCfg = Debug|Any CPU
+		{5EE180FC-E804-48C1-8FF3-0C62D43A7855}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{5EE180FC-E804-48C1-8FF3-0C62D43A7855}.Release|Any CPU.Build.0 = Release|Any CPU
+		{5EE180FC-E804-48C1-8FF3-0C62D43A7855}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU
+		{5EE180FC-E804-48C1-8FF3-0C62D43A7855}.Release|Mixed Platforms.Build.0 = Release|Any CPU
+		{5EE180FC-E804-48C1-8FF3-0C62D43A7855}.Release|Win32.ActiveCfg = Release|Any CPU
+		{5EE180FC-E804-48C1-8FF3-0C62D43A7855}.Release|x86.ActiveCfg = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(MonoDevelopProperties) = preSolution
+		StartupItem = argos.csproj
+	EndGlobalSection
+EndGlobal
Index: branches/compiler/cSharp/ooasCompiler/src/ooa.g
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/ooa.g	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/ooa.g	(revision 3)
@@ -0,0 +1,1203 @@
+/*  
+			ANTLR Grammar for OO-Action Systems
+			 (C) Willibald Krenn, 2009 - 2010
+
+
+  Notes
+  ~~~~~
+  	(*) No recursion
+  	(*) float acutally is fixed-point!
+	(*) Named actions can only be "called" within the do-od block 
+	(*) Methods can be called from within an action and a method.
+	    Attention: Mutual Recursion not supported!
+
+  FixMe
+  ~~~~~
+  	(*) List-Enum: Length Restriction! (Defaults to 500 for now)
+	(*) subseteq missing
+	
+
+			 
+  History
+  ~~~~~~~
+  Changes 1.03 to 1.04
+  	~ Fix bug with set constuctor: set with only one element produced wrong AST (inner element wasn't added correctly).
+
+  Changes 1.02 to 1.03
+  	+ option to name objects when they are constructed: new (<class>,"<name>")
+  
+  Changes 1.00 to 1.02
+  	+ cast operator for objects ( ... as <typename> )
+
+  Changes 1.00 to 1.01
+  	+ enum-type with fixed integer values
+  
+  Changes 0.99b to 1.00
+  	+ constant section added (consts a=4; b=4)
+  	+ limits of simple types and lists can be const
+  	+ local vars allowed in methods (... = var... begin...end)
+  	+ prioritized composition on statement level
+  	+ skip in do-od block
+  	+ filter expression in do-od block sequential var statement
+  	+ fold operator
+  	
+  Changes 0.99 to 0.99b
+        - disabled sequential composition of action systems (remains in grammar, though out-commented)
+        
+  Changes 0.98 to 0.99
+        ~ changed QR syntax.
+  
+  Changes 0.97 to 0.98
+  	~ changed syntax for list and set comprehension
+  	  list comprehension:
+  	  '[' expression '|' 'var' id ':' type (';' id ':' type)* ('&' expression)? ']'
+  	  set comprehension
+  	  '{' expression '|' 'var' id ':' type (';' id ':' type)* ('&' expression)? '}'
+  	  
+  	  Usage: defined variables will sweep over value-range. If the latter expression
+  	  (after '&') evaluates to true (hence this expression must return a bool) with
+  	  the current valuation of the defined vars, the values are used to evaluate the
+  	  first expression, which has to return a value of the correct type.
+  	  
+  	  Example:
+  	  type
+  	    myint = int [0..300000];
+  	    mytuple = (myint, myint)
+  	  var
+  	     l_tuple : list of mytuple = [nil];
+  	     l_int : list of myint = [nil];
+  	    ...
+  	      l_int := [l_tuple[x][0] | var x: myint & x < len l_tuple ]
+  	  
+  	  
+  	+ list element access by '[int]' allowed!
+
+
+  Changes 0.96 to 0.97
+  	+ tuple-type initialization now properly supported
+  	+ binary operator precedence handling
+  	+ local variables in named actions
+  	+ support for (<expression>).<reference> and
+  	              (<expression>).<accessExpression>
+  	~ conditional expression: End required.
+  	- remove support for power-operator 
+  	  (may be we need to do calculation backwards)
+
+  Changes 0.95 to 0.96
+  	~ string literals now ".."
+  	~ priming of identifier access only supported at the end of the
+  	  expression
+
+  Changes 0.9 to 0.95
+  	+ composition of action systems in 'system' block
+  	~ Produce C# code
+  	~ Operator Precedence
+  	~ vars in action composition
+  	~ forall/extists now with colon instead of in
+
+
+  Earlier changes  removed.
+			 
+*/
+
+
+grammar ooa;
+
+options {	
+  language = CSharp2;
+  k = 2;
+//  output = AST;
+}
+
+
+@lexer::namespace { TUG.Mogentes }
+
+@lexer::header
+{
+/*
+    Ulysses OO-Action System Parser
+
+    Copyright Willibald Krenn 2009
+
+ */
+}
+
+@parser::namespace { TUG.Mogentes } 
+
+@parser::header
+{
+/*
+    Ulysses OO-Action System Parser
+
+    Copyright Willibald Krenn 2009
+
+ */
+}
+
+ooActionSystems 
+	:	{initializeTopLevelParserState();}
+
+	         (T_CONSTS namedConstList)?
+		
+		 T_TYPES 
+		  	namedTypeList
+		 T_SYSTEM
+			comp=asTypeComposition[null]
+			{fixUpRun(comp);}
+	;
+
+
+
+//
+//  ------------   named consts  ------------ 
+//
+
+namedConstList
+	:	namedConst (T_SEMICOLON namedConst)*
+	;
+	
+namedConst
+	:	aName=T_IDENTIFIER
+		T_EQUAL
+		anExpr=expression
+		{addNamedConst(aName,anExpr);}
+	;
+
+
+//
+//  ------------   named types  ------------ 
+//
+namedTypeList 
+	:	namedType (T_SEMICOLON namedType)*
+	;
+
+namedType 
+	:	aName=T_IDENTIFIER 
+		T_EQUAL 
+		(
+			aType=complexType 	 {createNamedType(aName,aType);}
+		|	anOoaType=ooActionSystem {createNamedType(aName,anOoaType);}
+		)		
+		
+	;
+
+
+asTypeComposition [IdentifierList top]
+	returns [IdentifierList prioList]
+	:  	{prioList = new PrioIdentifierList(top);}
+		asTypeCompositionParallel[prioList]  (T_PRIO asTypeCompositionParallel[prioList] )*
+	;
+
+asTypeCompositionParallel [IdentifierList top]
+	:  	{IdentifierList parList = new NondetIdentifierList(top);}
+		asTypeCompositionSequential[parList] (T_NONDET asTypeCompositionSequential[parList])*
+	;
+
+asTypeCompositionSequential [IdentifierList top]
+	:  	{IdentifierList seqList = new SeqIdentifierList(top);}
+		asTypeCompositionBlockParen[seqList] //(T_SEMICOLON asTypeCompositionBlockParen[seqList])*
+	;
+
+asTypeCompositionBlockParen [IdentifierList top]
+	: T_LPAREN asTypeComposition[top] T_RPAREN
+	| aName=T_IDENTIFIER {addToIdentifierList(top,aName);}
+	;
+	
+
+//
+//  ------------   basic types    ------------ 
+//
+
+complexType 
+	returns [UlyssesType aTypeSymbol]
+	@init{ 
+		aTypeSymbol = null;
+		alandmark = null;
+	}	
+	:	T_LIST  T_LSQPAREN numOfElements=(T_INTNUMBER|T_IDENTIFIER) T_RSQPAREN T_OF  innertype=complexType 
+			{aTypeSymbol = createListType(numOfElements,innertype);}
+
+		// list type with predefined elements (dupes of each element as many as needed) FIXME: Length Restriction!
+	|	T_LSQPAREN alistelem=T_IDENTIFIER {aTypeSymbol = createListEnumType(alistelem);} 
+			(T_COMMA otherlistelem=T_IDENTIFIER {addToListEnumType(aTypeSymbol,otherlistelem);})* T_RSQPAREN // set of identifiers..
+
+		// maps do not really need a length restriction, as simpleType already is restricted..
+	|	T_MAP   (T_LSQPAREN numOfElements=(T_INTNUMBER|T_IDENTIFIER) T_RSQPAREN)? mapfromtype=simpleType T_TO maptotype=complexType 
+			{aTypeSymbol = createMapType(numOfElements,mapfromtype,maptotype);}
+		// quantity space
+	|	T_QUANTITY T_OF	T_LSQPAREN (alandmark=T_IDENTIFIER| alandmark=T_MINUS T_INFTY) {aTypeSymbol = createQrType(alandmark);} 
+			(T_COMMA (otherlandmark=T_IDENTIFIER|otherlandmark=T_INFTY) {addToQrType(aTypeSymbol,otherlandmark);})* T_RSQPAREN 
+		// tuple
+	|	 T_LPAREN aType=complexType {aTypeSymbol = createTupleType(aType);} 
+			(T_COMMA anotherType=complexType {addToTupleType(aTypeSymbol,anotherType);})*  T_RPAREN
+		
+		// some simple type (note that this includes identifiers, which may be complex object types..)	
+	|	r=simpleType {aTypeSymbol = r;}
+	;
+	finally
+		{fixupComplexType(aTypeSymbol);}
+
+	
+simpleType 
+	returns [UlyssesType aTypeSymbol]
+	@init{ 
+		aTypeSymbol = null;
+	}
+	:	T_BOOL  {aTypeSymbol = createBoolType();}
+	
+		// ints plus subtypes
+	|	T_INT T_LSQPAREN rangeLow=(T_INTNUMBER|T_INFTY|T_IDENTIFIER) T_RANGETO rangeHigh=(T_INTNUMBER|T_INFTY|T_IDENTIFIER) T_RSQPAREN  
+			{aTypeSymbol = createIntType(rangeLow,rangeHigh);}
+			
+		// floats plus subtypes
+	|	T_FLOAT  T_LSQPAREN rangeLow=(T_FLOATNUMBER|T_INFTY|T_IDENTIFIER) T_RANGETO rangeHigh=(T_FLOATNUMBER|T_INFTY|T_IDENTIFIER) T_RSQPAREN 
+			{aTypeSymbol = createFloatType(rangeLow,rangeHigh);}
+			
+		// char
+	|	T_CHAR {aTypeSymbol = createCharType();}
+		
+		// simple type, domain restricted to the values within the given set. (operators supported: equal, not equal) - may be casted to integer if
+		// explicit int values are given
+	|	T_CBRL aRangeValue=T_IDENTIFIER (T_EQUAL optVal=T_INTNUMBER)? {aTypeSymbol = createEnumType(aRangeValue, optVal);} 
+			(T_COMMA otherRangeValue=T_IDENTIFIER (T_EQUAL otherOptVal=T_INTNUMBER)? {addToEnumType(aTypeSymbol,otherRangeValue,otherOptVal); otherOptVal=null;})* T_CBRR
+			
+	|	aType=T_IDENTIFIER {aTypeSymbol = getNamedType(aType);} // alias could be simple type - otherwise, it's a complex type!!
+	;
+	finally
+		{fixupSimpleType(aTypeSymbol);}
+
+
+
+
+
+
+ooActionSystem 
+	returns [OoActionSystemType aTypeSymbol]
+	@init{ 
+		bool autoCons = false; 
+		aTypeSymbol = null;
+		refinesSystemName = null;
+	}
+	:      (T_AUTOCONS {autoCons = true;})? 
+		T_SYSTEM (T_LPAREN refinesSystemName=T_IDENTIFIER T_RPAREN)?		 
+		{aTypeSymbol = createOoaType(refinesSystemName,autoCons);}
+		'|['
+			(T_VAR attrList)?
+			(T_METHODS methodList)?
+			(T_ACTIONS namedActionList)?
+			(T_DO (bl=actionBlock[null] {addActionBlock(aTypeSymbol,bl);})? T_OD)?
+		']|'
+	;
+	finally
+		{fixupOoaType(aTypeSymbol);}
+	
+
+
+	
+//
+//  ------------   variables (objects and simple types)    ------------ 
+//
+attrList
+	:	{BeginParsingAttributes();}
+	 	attr (T_SEMICOLON attr)*
+	;
+	finally {
+		EndParsingAttributes();
+	}
+
+attr
+	@init{ 
+		bool isStatic = false; 
+		bool isCtr = false;
+		bool isObs = false;				
+		
+	}
+	: 	(T_STATIC {isStatic = true;})? (T_OBS {isObs = true;} | T_CTRL {isCtr = true;})? 
+		varname=T_IDENTIFIER  T_COLON aType=complexType (T_EQUAL anExpr=expression)?
+		{createAttribute(varname, isStatic, isObs, isCtr, aType, anExpr);}
+	;
+
+//
+//  ------------   methods    ------------ 
+//	
+methodList 
+	: 	method (T_SEMICOLON method)*
+	;
+
+method	
+	@init {	
+		FunctionIdentifier newMethod = null;
+	}
+	:	mname=T_IDENTIFIER  {newMethod = createMethodSymbol(mname);}
+		(T_LPAREN methodParameterList[newMethod]  T_RPAREN)? 
+		(T_COLON rt=complexType {setMethodReturnType(newMethod,rt);})?	// actions can not have a return type!!					
+		 T_EQUAL 
+		 (T_VAR localActionVars[newMethod] 'begin')? 
+		statements=actionBody[null] {addMethodBody(newMethod,statements);} 
+		T_END		
+	;
+	finally
+		{popResolveStack(newMethod);}
+
+methodParameterList[FunctionIdentifier newMethod]
+	:	 paramName=T_IDENTIFIER T_COLON atype=complexType {addMethodParameter(newMethod,paramName,atype);}
+			(T_COMMA otherparam=T_IDENTIFIER T_COLON othertype=complexType
+			{addMethodParameter(newMethod,otherparam,othertype);} )*		
+	;
+
+
+//
+//  ------------   named, anonymous actions    ------------ 
+//	
+
+namedActionList 
+	:	namedAction (T_SEMICOLON namedAction)*
+	;
+
+namedAction 
+	@init {
+		FunctionTypeEnum actionType;
+		FunctionIdentifier newAction = null;
+	}
+	:	T_CONT cactionname=T_IDENTIFIER  {newAction = createNamedContinuousAction(cactionname, FunctionTypeEnum.Continuous);}
+		(T_LPAREN methodParameterList[newAction]  T_RPAREN)? 
+		T_EQUAL	constraints=continuousActionBody {addContinuousActionBody(newAction,constraints);}
+		
+	|	{actionType = FunctionTypeEnum.Internal;}
+		(T_CTRL {actionType = FunctionTypeEnum.Controllable;}| T_OBS {actionType = FunctionTypeEnum.Observable;}| )
+		 actionname=T_IDENTIFIER  {newAction = createNamedAction(actionname,actionType);}
+		(T_LPAREN methodParameterList[newAction]  T_RPAREN)? 
+		T_EQUAL	
+		(T_VAR localActionVars[newAction] )? 
+		body=discreteActionBody  
+		{addActionBody(newAction,body);}
+	;	
+	finally
+		{popResolveStack(newAction);}
+
+
+localActionVars[FunctionIdentifier newMethod]
+	:	// a named, discrete action may have local variables.
+		id1=T_IDENTIFIER T_COLON t1=complexType  {addLocalVariableToNamedAction(newMethod,id1,t1);}
+		 (T_SEMICOLON id2=T_IDENTIFIER T_COLON t2=complexType
+		 {addLocalVariableToNamedAction(newMethod,id2,t2);} )*
+	;	
+
+
+
+anonymousAction 
+	returns [GuardedCommand result]
+	:	a=continuousActionBody {result = a;}
+	|	b=discreteActionBody {result = b;}
+	;
+
+continuousActionBody 
+	returns [GuardedCommand result]
+	@init {
+		result = null;
+	}
+	:	T_CONT T_REQUIRES expr=expression T_COLON
+			bdy=qualConstraintList	
+		T_END
+		{result = createGuardedCommandStatement(expr,bdy,true);}
+	;
+	
+qualConstraintList
+	returns [Block result]
+	@init{
+		result = createSeqBlock(null);
+		pushBlockToResolveStack(result);
+	}
+	:	stmt=qualConstraint {addToBlockList(result,stmt);}
+		(T_COMMA ostmt=qualConstraint {addToBlockList(result,ostmt);})*
+	;
+	finally
+		{popBlockFromResolveStack(result);}
+
+
+
+qualConstraint
+	returns [QualitativeConstraintStatement result]
+	:	id1=T_IDENTIFIER T_EQUAL 
+		(	T_DERIV derivid=T_IDENTIFIER 
+			{result = createQualDerivConstraintStatement(id1,derivid);}
+		
+	        |	
+	        	id2=T_IDENTIFIER 
+	        	( 
+	        		(	op=T_SUM
+	        		|	op=T_DIFF
+	        		|	op=T_PROD
+	        		) 
+	        		id3=T_IDENTIFIER
+	        		{result = createQualArithConstraintStatement(id1,id2,id3,op);}
+	        	|
+	        		{result = createQualEqualConstraintStatement(id1,id2);}
+	        	)
+	        )
+	;
+
+
+	
+
+discreteActionBody 
+	returns [GuardedCommand result]
+	@init{
+		result = null;
+	}
+	:	
+		T_REQUIRES expr=expression T_COLON
+			bdy=actionBody[null]
+		T_END
+		{result = createGuardedCommandStatement(expr,bdy);}
+	;
+	
+	
+//
+//  ------------   do-od block    ------------ 
+//	
+
+actionBlock [Block top]
+	returns [Block prioList]
+	:  	{prioList = createPrioBlock(top);}
+		 actionBlockParallel[prioList] (T_PRIO actionBlockParallel[prioList])* 
+	;	
+	
+actionBlockParallel [Block top]
+	:  	{Block parList = createNondetBlock(top);}
+		actionBlockSequential[parList] (T_NONDET actionBlockSequential[parList])*
+	;	
+	
+// atomic sequential composition of actions	
+actionBlockSequential [Block top]
+	@init  	{
+			Block seqList = createSeqBlock(top);
+			pushBlockToResolveStack(seqList);
+		}
+	:	 (T_VAR syms=blockvarlist[seqList] ('&' sexpr=expression {addSeqBlockExpression(seqList,sexpr);} )? T_COLON )? 
+		 actionBlockParen[seqList] (T_SEMICOLON actionBlockParen[seqList])*
+	;	
+	finally
+		{popBlockFromResolveStack(seqList);}
+
+actionBlockParen [Block top]
+	:	T_LPAREN actionBlock[top] T_RPAREN
+	|	anonymousOrNamedAction[top]
+	;	
+
+anonymousOrNamedAction [Block top]
+	:	gcmd=anonymousAction {addToBlockList(top,gcmd);}
+	|	aname=T_IDENTIFIER 
+	         (T_LPAREN  m_params=methodCallParams T_RPAREN)? 
+	         (amap=(T_FOLDLR|T_FOLDRL) '(' amapexpr=expression ')')?
+		{addNamedActionCallToBlockList(top,aname,m_params,amap,amapexpr);}
+	|	T_SKIP	{addSkipStatementToBlockList(top);}
+	;
+
+
+blockvarlist [Block seqList]
+	:	blockvar[seqList]  (T_SEMICOLON blockvar[seqList] )*
+	;
+
+blockvar [Block seqList]
+	: 	varname=T_IDENTIFIER  T_COLON aType=complexType 
+		{addBlockVariable(seqList,varname,aType);}
+	;
+
+		
+
+//
+//  ------------  action body  of non-continuous actions ------------ 
+//
+	
+actionBody[Block top]
+	returns [Block result]
+	:	{result = createPrioBlock(top);}
+		actionBodyParallel[result] (T_PRIO actionBodyParallel[result])? 
+	;  
+	
+actionBodyParallel[Block top]
+	returns [Block result]
+	:	{result = createNondetBlock(top);}
+		actionBodySequential[result]
+		(T_NONDET olst=actionBodySequential[result])*
+	;	
+	
+// seq binds stronger than nondet, i.e. a;b;cd;e is read as (a;b;c)[](d;e)	
+actionBodySequential[Block top]
+	returns [Block result]
+	:	{result = createSeqBlock(top);}
+		actionBodyParen[result] (T_SEMICOLON actionBodyParen[result])*
+	;	
+	
+actionBodyParen [Block top]
+	:	T_LPAREN actionBody[top] T_RPAREN
+	|	stmt=statement
+		{addToStatementList(top,stmt);}
+	;	
+
+
+statement
+	returns [Statement result]
+	@init {
+		bool popFromResolveStack = false;
+		result = null;
+	}
+	:	T_ABORT {result = createAbortStatement();}
+	|	T_SKIP	{result = createSkipStatement();}
+	|	T_KILL T_LPAREN aname=(T_IDENTIFIER | T_SELF) T_RPAREN	{result = createKillStatement(aname);}
+	| 	gc=discreteActionBody {result = gc;}
+	|	aqname=reference 
+			   ( 	    // single assignment			   	    
+			   	    T_ASSIGNMENT  aexp=expression  {result = createSingleAssignmentStatement(aqname,aexp);}
+			           (T_WITH ndexp=expression {addConstraintToAssignment(result,ndexp);})? // nondet assignment
+			           
+			           // multi assignment
+				|  {result = createMultipleAssignmentStatementLHS(aqname);}
+				  (T_COMMA malhs=reference  {addMultipleAssignmentStatementLHS(result,malhs);})+ 
+				   T_ASSIGNMENT 
+				   {pushAssignmentOnResolveStack(result); popFromResolveStack = true;} 
+				   mexp=expression
+				   {addMutlipleAssignmentStatementRHS(result,mexp);}
+				   (T_COMMA mexp2=expression {addMutlipleAssignmentStatementRHS(result,mexp2);})+
+				   (T_WITH ndex2=expression {addConstraintToAssignment(result,ndex2);})? // nondet assignment
+				   
+				   // just a call of a method.
+				| {result = createCallStatement(aqname);}
+		     	    )
+	;	
+	finally {
+	       if (popFromResolveStack == true)
+	            popAssignmentOffResolveStack(result);
+	}
+
+//
+//  ------------   expression    ------------ 
+//
+expression
+	returns [Expression expr]
+	@init{
+		System.Collections.Generic.List<BinaryOperator> operators = new System.Collections.Generic.List<BinaryOperator>();
+		System.Collections.Generic.List<Expression> expressions = new System.Collections.Generic.List<Expression>();		
+	}
+	:	left=atomExpression	
+		{expressions.Add(left);}
+		( op=binoperator
+		  right=atomExpression
+		  {
+		  	operators.Add(op);
+		  	expressions.Add(right);
+		  }
+		)*
+		{expr = createPrecedenceTree(expressions,operators);}
+	;
+
+
+binoperator	
+	returns [BinaryOperator binop]
+	:	T_BIIMPLIES
+		{binop = createBinaryOperator(ExpressionKind.biimplies);}
+	|	T_GREATER	
+		{binop = createBinaryOperator(ExpressionKind.greater);}
+	|	T_GREATEREQUAL
+		{binop = createBinaryOperator(ExpressionKind.greaterequal);}
+	|	T_LESS	
+		{binop = createBinaryOperator(ExpressionKind.less);}
+	|	T_LESSEQUAL
+		{binop = createBinaryOperator(ExpressionKind.lessequal);}
+	|	T_EQUAL			// bool, numeric, char, lists, maps
+		{binop = createBinaryOperator(ExpressionKind.equal);}
+	|	T_NOTEQUAL		// bool, numeric, char, lists, maps
+		{binop = createBinaryOperator(ExpressionKind.notequal);}
+	|	T_IMPLIES
+		{binop = createBinaryOperator(ExpressionKind.implies);}
+	|	T_MINUS	
+		{binop = createBinaryOperator(ExpressionKind.minus);}
+	|	T_SUM	
+		{binop = createBinaryOperator(ExpressionKind.sum);}
+	|	T_IN T_SET?	// A * list of A -> bool
+		{binop = createBinaryOperator(ExpressionKind.elemin);}
+	|	T_NOT T_IN T_SET?	// A * list of A -> bool
+		{binop = createBinaryOperator(ExpressionKind.notelemin);}
+	|	T_SUBSET	// list of A * list of A -> bool (does not respect dupes)
+		{binop = createBinaryOperator(ExpressionKind.subset);}
+	|	T_OR
+		{binop = createBinaryOperator(ExpressionKind.or);}
+	|	T_DIV
+		{binop = createBinaryOperator(ExpressionKind.div);}
+	|	T_PROD	
+		{binop = createBinaryOperator(ExpressionKind.prod);}
+	|	T_IDIV	
+		{binop = createBinaryOperator(ExpressionKind.idiv);}
+	|	T_MOD	
+		{binop = createBinaryOperator(ExpressionKind.mod);}
+	|	T_UNION		// list of A * list of A -> list of A (does not respect dupes)
+		{binop = createBinaryOperator(ExpressionKind.union);}
+	|	T_DIFF		// list of A * list of A -> list of A (does not respect dupes)
+		{binop = createBinaryOperator(ExpressionKind.diff);}
+	|	T_INTER		// list of A * list of A -> list of A (does not respect dupes)
+		{binop = createBinaryOperator(ExpressionKind.inter);}
+	|	T_AND  
+		{binop = createBinaryOperator(ExpressionKind.and);}				
+	|	T_POW  
+		{binop = createBinaryOperator(ExpressionKind.pow);}				
+	|	T_CONC	// list of A * list of A -> list of A
+		{binop = createBinaryOperator(ExpressionKind.conc);}			
+	|	T_DOMRESBY	// list of A * map A to B -> map A to B
+		{binop = createBinaryOperator(ExpressionKind.domresby);}
+	|	T_DOMRESTO	// list of A * map A to B -> map A to B
+		{binop = createBinaryOperator(ExpressionKind.domresto);}
+	|	T_RNGRESBY	// map A to B * list of B -> map A to B
+		{binop = createBinaryOperator(ExpressionKind.rngresby);}
+	|	T_RNGRESTO	// map A to B * list of B -> map A to B
+		{binop = createBinaryOperator(ExpressionKind.rngresto);}
+	|	T_MUNION	// map A to B * map A to B -> map A to B
+		{binop = createBinaryOperator(ExpressionKind.munion);}
+	|	T_SEQMOD_MAPOVERRIDE	// list of A * map int to A -> list of A or
+					// map A to B * map A to B -> map A to B
+		{binop = createBinaryOperator(ExpressionKind.seqmod_mapoverride);}
+	;
+
+	
+atomExpression
+	returns [Expression expr]
+	@init {
+		expr = null;
+	}
+	:	(unexpr=op_un? (   
+		     e=identifierExpression
+		  |  e=qvalExpression
+		  |  e=constant
+		  |  e=initializedComplexType 
+		  |  e=quantifierExpression
+		  |  T_LPAREN e=expression T_RPAREN		   
+		     ( 
+			  (T_POINT 
+			    idn=T_IDENTIFIER 
+			    {e = addIdentifierAccessExpression(e,idn);})+
+			    (res=accessExpression[e] {e=res;})?
+			| 
+			  e=accessExpression[e]
+		      )?
+		) ('as' cid=T_IDENTIFIER {e=addCastExpression(e,cid);})?
+		{expr = addUnaryExpression(unexpr,e);}
+		)
+		|  ie=T_IF ce=expression T_THEN te=expression T_ELSE ee=expression T_END
+		{expr = createConditionalExpression(ce,te,ee,ie);}
+	;	
+	
+
+quantifierExpression
+	returns [Quantifier result]
+	@init {
+		result = null;
+	}
+	: 	t=(T_FORALL | T_EXISTS)
+		{result = createQuantifierExpression(t);}
+		(id=T_IDENTIFIER (T_COLON id_type=simpleType {addBoundVarToQuantifierExpression(result,id,id_type);}) 
+		  (T_COMMA id2=T_IDENTIFIER (T_COLON id_type2=simpleType){addBoundVarToQuantifierExpression(result,id2,id_type2);})*) 
+		T_COLON T_LPAREN e=expression T_RPAREN
+		{addExpressionToQuantifier(result,e);}
+	;
+	finally
+		{removeBoundVarsFromResolveStack(result);}
+
+constant
+	returns [LeafExpression result]
+	@init {
+		result = null;
+	}
+	: 	T_TRUE  {result = createBoolConstant(true);}
+	|	T_FALSE {result = createBoolConstant(false);}
+	|	T_NIL 	{result = createNullPointerConstant();}
+	|	T_SELF  {result = createSelfPointer();}
+	| 	t_fl=T_FLOATNUMBER {result = createFloatConstant(t_fl);}
+	|	t_in=T_INTNUMBER {result = createIntConstant(t_in);}
+	|	t_l=T_STRINGLITERAL {result = createStringConstant(t_l);}
+	;
+	
+initializedComplexType
+	returns [Expression result]
+	@init {
+		result = null;
+	}
+	:	res=initializedListType {result = res;}
+	|	res=initializedSetType {result = res;}
+	| 	T_NEW T_LPAREN anid=T_IDENTIFIER 
+			(
+				T_COMMA  aname=T_STRINGLITERAL T_RPAREN {result = createNamedObject(anid, aname);}
+			|	T_RPAREN {result = createObject(anid);}	// constructor call..
+			)
+	;
+	
+initializedListType
+	returns [ListConstructor result]
+	@init {
+		result = createInitializedList();
+		pushListVarsOnResolveStack(result); // need this here for list comprehension
+	}
+	:	T_LSQPAREN e=expression {addListElement(result,e);} ( 
+			(T_COMMA e2=expression {addListElement(result,e2);})+ 
+		| 	listComprehension[result]
+		)? T_RSQPAREN  
+	;		
+	finally
+		{popListVarsFromResolveStack(result);}
+
+listComprehension [ListConstructor result]
+	@init{	
+		result.SetHasComprehension(true);
+	}
+	:
+		T_BAR T_VAR
+		id=T_IDENTIFIER  T_COLON t1=complexType {addListComprVar(result,id,t1);} 
+			(T_SEMICOLON id2=T_IDENTIFIER  t2=complexType {addListComprVar(result,id2,t2);})* 
+		('&'
+		e=expression {addListComprExpr(result,e);})?
+	;
+	
+initializedSetType
+	returns[Expression result]
+	@init {
+		result = null;
+	}
+	:	T_CBRL T_MAPS T_CBRR {result = createEmptyMap();}  // empty map
+	|	res=initializedSet {result = res;}
+	;	
+	
+initializedSet
+	returns [Expression result]
+	@init {
+		SetConstructor theset = createSet(); 
+		pushSetVarsOnResolveStack(theset); // need this here for set comprehension
+		result = theset;
+	}
+	:	T_CBRL e1=expression 
+	        (    			// set constructor; empty set: {nil}
+			{addToSet(result,e1);}
+			(T_COMMA e2=expression {addToSet(result,e2);})*			  // set constructor for sets > 1 elem
+		| 	m=map[result, e1] {result = m;}  // we have a set in the resolution stack, but this should be fine (no syms)
+		|	{addToSet(result,e1);} setComprehension[(SetConstructor)result]   // set comprehension
+		) T_CBRR 
+	;	
+	finally
+		{popSetVarsFromResolveStack(theset);}
+
+		
+map[Expression _map, Expression e1]	
+	returns [Expression result]
+	@init {
+		result = null;
+	}
+	:	am=T_MAPS e2=expression  {result = createMap(e1,e2,am);}   (T_COMMA e3=expression T_MAPS e4=expression {addToMap(result,e3,e4);})*
+	;
+
+setComprehension[SetConstructor _set]
+	@init {
+		_set.SetHasComprehension(true);
+	}
+	:	T_BAR T_VAR (id1=T_IDENTIFIER  T_COLON t1=complexType 
+		{ addSetComprVar(_set, id1, t1); }
+		T_SEMICOLON id2=T_IDENTIFIER T_COLON t2=complexType
+		 { addSetComprVar(_set, id2, t2); })*  
+		('&'
+		epx=expression
+		{ addSetComprExpr(_set,epx); })?
+	;
+
+
+qvalExpression 
+	returns [QValConstructor result]
+	@init {
+		bool minus = false;
+		result = null;		
+	}
+	:	// constructor for qualitative values
+		aval='qval' T_LPAREN 
+		{result = createQualitativeValue(aval);}
+		(
+			T_NIL
+			{setQualitativeValueDontCare(result);}
+		| 		
+			(	expr=qualifiedIdentifier
+			 	{setQualitativeValueLandmark(result,expr);}
+			|
+				('-' {minus = true;})? T_INFTY
+				{setQualitativeValueInfinity(result,minus);}
+			) 
+			(T_RANGETO 
+			(	expr2=qualifiedIdentifier
+				{setQualitativeValueRange(result,expr2);}
+			| 
+				T_INFTY
+				{setQualitativeValueRangeInfinity(result,false);}
+			) )?  
+		)
+		T_COMMA 
+		(
+			T_NIL
+			{setQualitativeDerivDontCare(result);}
+		|
+			(	'steady'
+				{setQualitativeDerivSteady(result);}
+			|	'inc'
+				{setQualitativeDerivInc(result);}
+			|	'dec'
+				{setQualitativeDerivDec(result);}
+			) 		
+		)
+		T_RPAREN  
+	;
+
+
+identifierExpression
+	returns [Expression result]
+	:  	// if next token is a tuple-type then create an initialized tuple!
+		{isTuple(input.LT(1).Text)}? 		
+		aName=T_IDENTIFIER T_LPAREN m_params=methodCallParams T_RPAREN
+		{result = createInitializedTuple(aName,m_params);}
+	| 	// is some sort of reference
+		res=reference
+	  	{result = res;}	
+	;
+
+
+reference 
+	returns [Expression  result]
+	@init {
+		result = null;
+		init = null;
+	}
+	:	{!isTuple(input.LT(1).Text)}? // check that the next token is not a reference to a tuple-type
+		aName=qualifiedIdentifier {result = aName;}		
+		(	output=accessExpression[result] {result = output;}
+			// call expression
+		|	// variable access or method call that takes no params? (do we allow for that? - answer: no!)
+		)
+		( 	pr=T_PRIMED {setIdentifierExpressionPrimed(ref result,pr);} 
+		 |	
+		 	('::' T_LPAREN init=expression T_RPAREN)? afold=(T_FOLDLR|T_FOLDRL) T_LPAREN anexpr=expression T_RPAREN 
+		 	{result = createFoldExpression(result,afold,init,anexpr);}
+		)?
+	;
+
+accessExpression[Expression subexpr]
+	returns [Expression result]
+	@init{
+		UnaryOperator newExpr = null;
+		result = subexpr;
+	}
+	:	
+    		(	tcall=T_LSQPAREN ac=expression T_RSQPAREN 			// access tuples, maps 
+    			{ result = createTupleMapAccessExpression(result,ac,tcall); } 
+		|     	bcall=T_LPAREN m_params=methodCallParams T_RPAREN // access method
+			{ result = createMethodAccessExpression(result,m_params,bcall); }
+		)+
+		(	// a[1].c.e()...
+			(T_POINT 
+			idn=T_IDENTIFIER 
+			{result = addIdentifierAccessExpression(result,idn);})+
+			(res=accessExpression[result] {result=res;})?
+		)?	
+	;
+	
+qualifiedIdentifier
+	returns [Expression top]
+	@init {
+		IdentifierExpression selfexpr = null;
+		top = null;
+	}
+	:
+		(self=T_SELF T_POINT		{selfexpr = createSelfIdentifierExpression(self);})? 
+		idb=T_IDENTIFIER 		{top = createIdentifierAccessExpression(selfexpr,idb);}
+		(T_POINT idd=T_IDENTIFIER 	{top = addIdentifierAccessExpression(top,idd);})* 
+	;
+	
+
+methodCallParams
+	returns [System.Collections.Generic.List<Expression> result]
+	@init {
+		result = new System.Collections.Generic.List<Expression>();
+	}
+	:	(expa=expression {result.Add(expa);} (T_COMMA expb=expression {result.Add(expb);})*)?
+	;
+
+
+
+//
+//  ------------  unary  Operators    ------------ 
+//
+	
+	
+op_un
+	returns [UnaryOperator expr]
+	@init {
+		expr = null;
+	}
+	:	r=op_un_set_list {expr = r;}
+	|	r2=op_un_map 	{expr = r2;}
+	|	T_MINUS 	{expr = createUnaryOperator(ExpressionKind.unminus);}
+	|	T_NOT		{expr = createUnaryOperator(ExpressionKind.not);}
+	|	T_ABS		{expr = createUnaryOperator(ExpressionKind.abs);}
+	;	
+
+
+op_un_set_list
+	returns [UnaryOperator expr]
+	@init {
+		expr = null;
+	}
+	:	T_CARD		// list of A -> int (does not respect dupes, i.e. dupes do not count)
+		{expr = createUnaryOperator(ExpressionKind.card);}
+	|	T_DCONC		// list of list of A -> list of A
+		{expr = createUnaryOperator(ExpressionKind.dconc);}
+	|	T_DINTER	// list of list of A -> list of A (intersection, does not respect dupes)
+		{expr = createUnaryOperator(ExpressionKind.dinter);}
+	|	T_DUNION	// list of list of A -> list of A (union, does not respect dupes)
+		{expr = createUnaryOperator(ExpressionKind.dunion);}
+	|	T_ELEMS		// list of A -> list of A (does not respect dupes)
+		{expr = createUnaryOperator(ExpressionKind.elems);}
+	|	T_HEAD		// list of A -> A
+		{expr = createUnaryOperator(ExpressionKind.head);}
+	|	T_INDS		// list of A -> list of int
+		{expr = createUnaryOperator(ExpressionKind.inds);}
+	|	T_LEN		// list of A -> int (dupes count)
+		{expr = createUnaryOperator(ExpressionKind.len);}
+	|	T_TAIL		// list of A -> list of A	
+		{expr = createUnaryOperator(ExpressionKind.tail);}
+	;
+
+
+op_un_map
+	returns [UnaryOperator expr]
+	@init {
+		expr = null;
+	}
+	:	T_DOM		// map A to B -> list of A
+		{expr = createUnaryOperator(ExpressionKind.dom);}
+	|	T_RNG		// map A to B -> list of B
+		{expr = createUnaryOperator(ExpressionKind.range);}
+	|	T_MERGE		// list of map A to B -> map A to B
+		{expr = createUnaryOperator(ExpressionKind.merge);}
+	;
+
+
+
+
+
+
+//
+//  ==============   LEXER   =================
+//
+T_WS  	: (' '|'\r'|'\t'|'\u000C'|'\n') {$channel=HIDDEN;}
+    	;
+    	
+T_COMMENT
+    	: '/*' .* '*/' {$channel=HIDDEN;}
+    	;
+    	
+LINE_COMMENT
+    	: '#' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
+    	;
+
+T_PRIMED
+	:	'\'';
+
+T_STRINGLITERAL
+	:	'"' 
+		(
+     			( '"' '"' )=>  '"' 
+      		|  	~'"'
+  		)*
+ 		'"'
+	;
+
+
+T_ABORT	:	'abort';
+T_ACTIONS
+	:	'actions';
+T_ASSIGNMENT
+	:	':=';
+T_AUTOCONS:	'autocons';
+T_BAR	:	'|';
+T_BOOL	:	'bool';
+T_CBRL	:	'{';
+T_CBRR	:	'}';
+T_COLON	:	':';
+T_COMMA	:	',';
+T_CONT	:	'qual';
+T_CHAR	:	'char';
+T_CTRL 	:	'ctr';
+T_SYSTEM
+	:	'system';
+T_DO	:	'do';
+T_ELSE	:	'else';
+T_END	:	'end';
+T_EQUAL	:	'=';
+T_EXISTS:	'exists';
+T_FLOAT	:	'float';
+T_FORALL:	'forall';
+T_FALSE :	'false';	
+T_IF	:	'if';
+T_IN	:	'in';
+T_INT	:	'int';
+T_KILL	:	'kill';
+T_LIST	:	'list';
+T_LPAREN:	'(';
+T_LSQPAREN:	'[';
+T_MAP	:	'map';
+T_MAPS	:	'->';
+T_METHODS
+	:	'methods';
+T_NEW	:	'new';
+T_NIL	:	'nil';
+T_NONDET:	'[]';
+T_OBS	:	'obs';
+T_OD	:	'od';
+T_OF	:	'of';
+T_PRIO	:	'//';
+T_REQUIRES
+	:	'requires';
+T_RPAREN:	')';
+T_RSQPAREN:	']';
+T_QUANTITY
+	:	'qspace';
+T_SELF	:	'self';
+T_SET 	:	'set';
+T_SEMICOLON
+	:	';';
+T_STATIC:	'static';	
+T_SKIP	:	'skip';
+T_THEN	:	'then';
+T_TRUE  :	'true';
+T_TO	:	'to';
+T_TYPES	:	'types';
+T_VAR	:	'var';
+T_WITH	:	'with';     // for nondet assignment
+
+
+//T_ACTION:	'action';
+
+//BOOL
+T_AND	:	'and';
+T_BIIMPLIES
+	:	'<=>';
+T_IMPLIES
+	:	'=>';  //VDM-Style
+T_NOT	:	'not'; //VDM-Style
+T_NOTEQUAL:	'<>';  //VDM-Style
+T_OR	:	'or';
+
+//Numeric (equal, not equal same as in BOOL)
+T_ABS	:	'abs';
+T_DIV	:	'/';
+T_GREATER
+	:	'>';
+T_GREATEREQUAL
+	:	'>=';
+T_IDIV	:	'div';
+T_LESS	:	'<';
+T_LESSEQUAL
+	:	'<='; //VDM-Style
+T_MOD	:	'mod'; //VDM-Style
+T_POW	:	'**';
+T_PROD	:	'*';
+T_DERIV	:	'dt';
+
+// set/list
+T_CARD	:	'card';
+T_CONC	:	'^'; 
+T_DCONC	:	'conc';
+T_DIFF	:	'\\';
+T_DINTER:	'dinter';
+T_DUNION:	'dunion';
+T_ELEMS	:	'elems';
+T_HEAD	:	'hd';
+T_INDS	:	'inds';
+T_INTER	:	'inter';
+T_LEN	:	'len'; // differs from T_CARD, as card does not count dupes..
+T_SEQMOD_MAPOVERRIDE
+	:	'++';
+T_SUBSET:	'subset';
+T_TAIL	:	'tl';
+T_UNION	:	'union';
+T_FOLDLR	
+	:	':>:';
+T_FOLDRL
+	:	':<:';
+
+
+// maps
+T_DOM	:	'dom';
+T_DOMRESBY
+	:	'<-:';
+T_DOMRESTO
+	:	'<:';		
+T_RNG	:	'rng';
+T_RNGRESBY
+	:	':->';
+T_RNGRESTO
+	:	':>';
+T_MERGE	:	'merge';
+T_MUNION:	'munion';
+
+T_CONSTS:	'consts';
+
+// numbers
+
+T_INFTY	:	(T_MINUS|T_SUM)? 'inf'
+	;	
+
+
+// INTNUMBER, FLOATNUMBER, RANGETO, T_MINUS, T_PLUS are set within
+// FLOAT_OR_INT_OR_RANGE
+fragment T_INTNUMBER
+	:	;
+fragment T_FLOATNUMBER
+	:	;
+fragment T_RANGETO	
+	:	;
+
+FLOAT_OR_INT_OR_RANGE
+	: 	(T_MINUS|T_SUM)? T_DIGIT+
+		( // at this stage, we could face an int, int..int (=range), int.exp (=float), int.exp..int.exp (=float range) etc..
+				(T_POINT T_POINT) => {$type=T_INTNUMBER;}
+			|	(T_POINT T_DIGIT) => T_POINT T_DIGIT+ (('e'|'E') (T_MINUS|T_SUM)? T_DIGIT+)? {$type=T_FLOATNUMBER;}				
+			|	{$type=T_INTNUMBER;}
+		)
+	|	T_POINT
+		( // could be point or range..
+				T_POINT {$type=T_RANGETO;}
+			| 	      {$type=T_POINT;}
+		)
+	|	T_MINUS	{$type=T_MINUS;}
+	|	T_SUM	{$type=T_SUM;}
+	;	
+
+
+
+fragment T_MINUS:	'-';
+fragment T_SUM	:	'+';
+fragment T_POINT:	'.';
+
+
+
+// identifiers
+T_IDENTIFIER
+	:	T_LETTER (T_LETTER|T_DIGIT)* 
+	;
+	
+//T_PRIMEDIDENTIFIER
+//	:	T_IDENTIFIER '\'';
+	
+fragment
+T_LETTER
+	:	'$'
+	|	'A'..'Z'
+	|	'a'..'z'
+	|	'_'
+	;
+
+fragment 
+T_DIGIT:	'0'..'9';
+
Index: branches/compiler/cSharp/ooasCompiler/src/ooa.tokens
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/ooa.tokens	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/ooa.tokens	(revision 3)
@@ -0,0 +1,136 @@
+T_FLOATNUMBER=29
+T_SYSTEM=6
+T_ELSE=87
+T_LPAREN=12
+T_DUNION=102
+T_BOOL=25
+T_METHODS=35
+T_INDS=105
+T_OR=69
+T_OD=38
+T_AND=75
+T_OF=18
+T_STRINGLITERAL=93
+T_SET=66
+T_SKIP=52
+T_WITH=57
+T_DOM=108
+T_WS=111
+T_VAR=34
+T_SUM=47
+T_REQUIRES=45
+T_DINTER=101
+T_HEAD=104
+T_AUTOCONS=33
+T_END=43
+T_TRUE=90
+T_LSQPAREN=15
+T_PRIMED=97
+T_MAPS=96
+T_NIL=92
+T_INFTY=24
+T_IF=85
+LINE_COMMENT=113
+T_THEN=86
+T_FLOAT=28
+T_TAIL=107
+T_SELF=55
+T_MERGE=110
+T_DIFF=48
+T_FOLDRL=51
+T_QUANTITY=22
+T_IN=65
+T_MUNION=82
+T__126=126
+T__125=125
+T_INTER=74
+T_SEMICOLON=7
+T_FOLDLR=50
+T_CARD=99
+T_FALSE=91
+T_CONT=44
+T_SUBSET=68
+T_COMMA=19
+T_RANGETO=27
+T_MINUS=23
+T_CONC=77
+T_IDIV=71
+T_FORALL=88
+T_DERIV=46
+T_CONSTS=4
+T_TYPES=5
+T_GREATEREQUAL=60
+T__118=118
+T_RNG=109
+T__119=119
+T_MOD=72
+T__117=117
+T_SEQMOD_MAPOVERRIDE=83
+T__124=124
+T__123=123
+T_ELEMS=103
+T__122=122
+T__121=121
+T_IMPLIES=64
+T__120=120
+T_EXISTS=89
+T_POW=76
+T_COMMENT=112
+T_RPAREN=13
+T_PRIO=10
+T_RNGRESBY=80
+T_ABS=98
+T_DIV=70
+T_LIST=14
+T_CBRL=31
+T_DCONC=100
+T_ABORT=53
+T_CHAR=30
+T_POINT=84
+T_STATIC=39
+T_CBRR=32
+T_INT=26
+T_COLON=42
+T_PROD=49
+T_ACTIONS=36
+T_DIGIT=114
+T_LESS=61
+T_BAR=95
+T_TO=21
+T_NONDET=11
+T_DOMRESBY=78
+T_DOMRESTO=79
+T_EQUAL=9
+T_GREATER=59
+T_KILL=54
+T_RNGRESTO=81
+T_RSQPAREN=17
+T_NEW=94
+T_INTNUMBER=16
+T_UNION=73
+T_OBS=40
+T_BIIMPLIES=58
+T_NOTEQUAL=63
+T_IDENTIFIER=8
+T_DO=37
+FLOAT_OR_INT_OR_RANGE=115
+T_LEN=106
+T_NOT=67
+T_ASSIGNMENT=56
+T_LETTER=116
+T_MAP=20
+T_LESSEQUAL=62
+T_CTRL=41
+']|'=118
+'begin'=119
+'as'=121
+'dec'=125
+'|['=117
+'qval'=122
+'('=12
+'::'=126
+'-'=23
+')'=13
+'&'=120
+'steady'=123
+'inc'=124
Index: branches/compiler/cSharp/ooasCompiler/src/ooaLexer.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/ooaLexer.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/ooaLexer.cs	(revision 3)
@@ -0,0 +1,5236 @@
+// $ANTLR 3.2 Sep 23, 2009 12:02:23 ooa.g 2013-10-10 13:45:32
+
+// The variable 'variable' is assigned but its value is never used.
+#pragma warning disable 168, 219
+// Unreachable code detected.
+#pragma warning disable 162
+
+
+/*
+    Ulysses OO-Action System Parser
+
+    Copyright Willibald Krenn 2009
+
+ */
+
+
+using System;
+using Antlr.Runtime;
+using IList 		= System.Collections.IList;
+using ArrayList 	= System.Collections.ArrayList;
+using Stack 		= Antlr.Runtime.Collections.StackList;
+
+using IDictionary	= System.Collections.IDictionary;
+using Hashtable 	= System.Collections.Hashtable;
+namespace  TUG.Mogentes 
+{
+public partial class ooaLexer : Lexer {
+    public const int T_FLOATNUMBER = 29;
+    public const int T_SYSTEM = 6;
+    public const int T_ELSE = 87;
+    public const int T_LPAREN = 12;
+    public const int T_DUNION = 102;
+    public const int T_BOOL = 25;
+    public const int T_METHODS = 35;
+    public const int T_INDS = 105;
+    public const int T_OR = 69;
+    public const int EOF = -1;
+    public const int T_OD = 38;
+    public const int T_AND = 75;
+    public const int T_OF = 18;
+    public const int T_STRINGLITERAL = 93;
+    public const int T_SET = 66;
+    public const int T_SKIP = 52;
+    public const int T_WITH = 57;
+    public const int T_DOM = 108;
+    public const int T_WS = 111;
+    public const int T_VAR = 34;
+    public const int T_SUM = 47;
+    public const int T_REQUIRES = 45;
+    public const int T_DINTER = 101;
+    public const int T_AUTOCONS = 33;
+    public const int T_HEAD = 104;
+    public const int T_END = 43;
+    public const int T_TRUE = 90;
+    public const int T_LSQPAREN = 15;
+    public const int T_MAPS = 96;
+    public const int T_PRIMED = 97;
+    public const int T_INFTY = 24;
+    public const int T_NIL = 92;
+    public const int T_IF = 85;
+    public const int LINE_COMMENT = 113;
+    public const int T_THEN = 86;
+    public const int T_FLOAT = 28;
+    public const int T_SELF = 55;
+    public const int T_TAIL = 107;
+    public const int T_DIFF = 48;
+    public const int T_MERGE = 110;
+    public const int T_FOLDRL = 51;
+    public const int T_QUANTITY = 22;
+    public const int T_IN = 65;
+    public const int T_MUNION = 82;
+    public const int T__126 = 126;
+    public const int T__125 = 125;
+    public const int T_INTER = 74;
+    public const int T_SEMICOLON = 7;
+    public const int T_FOLDLR = 50;
+    public const int T_CARD = 99;
+    public const int T_FALSE = 91;
+    public const int T_CONT = 44;
+    public const int T_SUBSET = 68;
+    public const int T_COMMA = 19;
+    public const int T_RANGETO = 27;
+    public const int T_MINUS = 23;
+    public const int T_CONC = 77;
+    public const int T_IDIV = 71;
+    public const int T_FORALL = 88;
+    public const int T_DERIV = 46;
+    public const int T_CONSTS = 4;
+    public const int T_TYPES = 5;
+    public const int T_GREATEREQUAL = 60;
+    public const int T__118 = 118;
+    public const int T_RNG = 109;
+    public const int T__119 = 119;
+    public const int T_MOD = 72;
+    public const int T__117 = 117;
+    public const int T_SEQMOD_MAPOVERRIDE = 83;
+    public const int T__124 = 124;
+    public const int T__123 = 123;
+    public const int T_ELEMS = 103;
+    public const int T__122 = 122;
+    public const int T__121 = 121;
+    public const int T_IMPLIES = 64;
+    public const int T__120 = 120;
+    public const int T_EXISTS = 89;
+    public const int T_POW = 76;
+    public const int T_COMMENT = 112;
+    public const int T_RPAREN = 13;
+    public const int T_PRIO = 10;
+    public const int T_RNGRESBY = 80;
+    public const int T_ABS = 98;
+    public const int T_DIV = 70;
+    public const int T_LIST = 14;
+    public const int T_CBRL = 31;
+    public const int T_DCONC = 100;
+    public const int T_ABORT = 53;
+    public const int T_CHAR = 30;
+    public const int T_STATIC = 39;
+    public const int T_POINT = 84;
+    public const int T_INT = 26;
+    public const int T_CBRR = 32;
+    public const int T_PROD = 49;
+    public const int T_COLON = 42;
+    public const int T_ACTIONS = 36;
+    public const int T_LESS = 61;
+    public const int T_DIGIT = 114;
+    public const int T_BAR = 95;
+    public const int T_TO = 21;
+    public const int T_NONDET = 11;
+    public const int T_DOMRESBY = 78;
+    public const int T_DOMRESTO = 79;
+    public const int T_EQUAL = 9;
+    public const int T_GREATER = 59;
+    public const int T_KILL = 54;
+    public const int T_RNGRESTO = 81;
+    public const int T_RSQPAREN = 17;
+    public const int T_NEW = 94;
+    public const int T_INTNUMBER = 16;
+    public const int T_UNION = 73;
+    public const int T_OBS = 40;
+    public const int T_BIIMPLIES = 58;
+    public const int T_NOTEQUAL = 63;
+    public const int T_IDENTIFIER = 8;
+    public const int T_DO = 37;
+    public const int FLOAT_OR_INT_OR_RANGE = 115;
+    public const int T_NOT = 67;
+    public const int T_LEN = 106;
+    public const int T_ASSIGNMENT = 56;
+    public const int T_LETTER = 116;
+    public const int T_LESSEQUAL = 62;
+    public const int T_MAP = 20;
+    public const int T_CTRL = 41;
+
+    // delegates
+    // delegators
+
+    public ooaLexer() 
+    {
+		InitializeCyclicDFAs();
+    }
+    public ooaLexer(ICharStream input)
+		: this(input, null) {
+    }
+    public ooaLexer(ICharStream input, RecognizerSharedState state)
+		: base(input, state) {
+		InitializeCyclicDFAs(); 
+
+    }
+    
+    override public string GrammarFileName
+    {
+    	get { return "ooa.g";} 
+    }
+
+    // $ANTLR start "T__117"
+    public void mT__117() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__117;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:17:8: ( '|[' )
+            // ooa.g:17:10: '|['
+            {
+            	Match("|["); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__117"
+
+    // $ANTLR start "T__118"
+    public void mT__118() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__118;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:18:8: ( ']|' )
+            // ooa.g:18:10: ']|'
+            {
+            	Match("]|"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__118"
+
+    // $ANTLR start "T__119"
+    public void mT__119() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__119;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:19:8: ( 'begin' )
+            // ooa.g:19:10: 'begin'
+            {
+            	Match("begin"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__119"
+
+    // $ANTLR start "T__120"
+    public void mT__120() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__120;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:20:8: ( '&' )
+            // ooa.g:20:10: '&'
+            {
+            	Match('&'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__120"
+
+    // $ANTLR start "T__121"
+    public void mT__121() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__121;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:21:8: ( 'as' )
+            // ooa.g:21:10: 'as'
+            {
+            	Match("as"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__121"
+
+    // $ANTLR start "T__122"
+    public void mT__122() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__122;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:22:8: ( 'qval' )
+            // ooa.g:22:10: 'qval'
+            {
+            	Match("qval"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__122"
+
+    // $ANTLR start "T__123"
+    public void mT__123() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__123;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:23:8: ( 'steady' )
+            // ooa.g:23:10: 'steady'
+            {
+            	Match("steady"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__123"
+
+    // $ANTLR start "T__124"
+    public void mT__124() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__124;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:24:8: ( 'inc' )
+            // ooa.g:24:10: 'inc'
+            {
+            	Match("inc"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__124"
+
+    // $ANTLR start "T__125"
+    public void mT__125() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__125;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:25:8: ( 'dec' )
+            // ooa.g:25:10: 'dec'
+            {
+            	Match("dec"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__125"
+
+    // $ANTLR start "T__126"
+    public void mT__126() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T__126;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:26:8: ( '::' )
+            // ooa.g:26:10: '::'
+            {
+            	Match("::"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T__126"
+
+    // $ANTLR start "T_WS"
+    public void mT_WS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_WS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:992:8: ( ( ' ' | '\\r' | '\\t' | '\\u000C' | '\\n' ) )
+            // ooa.g:992:10: ( ' ' | '\\r' | '\\t' | '\\u000C' | '\\n' )
+            {
+            	if ( (input.LA(1) >= '\t' && input.LA(1) <= '\n') || (input.LA(1) >= '\f' && input.LA(1) <= '\r') || input.LA(1) == ' ' ) 
+            	{
+            	    input.Consume();
+            	state.failed = false;
+            	}
+            	else 
+            	{
+            	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+            	    MismatchedSetException mse = new MismatchedSetException(null,input);
+            	    Recover(mse);
+            	    throw mse;}
+
+            	if ( (state.backtracking==0) )
+            	{
+            	  _channel=HIDDEN;
+            	}
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_WS"
+
+    // $ANTLR start "T_COMMENT"
+    public void mT_COMMENT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_COMMENT;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:996:6: ( '/*' ( . )* '*/' )
+            // ooa.g:996:8: '/*' ( . )* '*/'
+            {
+            	Match("/*"); if (state.failed) return ;
+
+            	// ooa.g:996:13: ( . )*
+            	do 
+            	{
+            	    int alt1 = 2;
+            	    int LA1_0 = input.LA(1);
+
+            	    if ( (LA1_0 == '*') )
+            	    {
+            	        int LA1_1 = input.LA(2);
+
+            	        if ( (LA1_1 == '/') )
+            	        {
+            	            alt1 = 2;
+            	        }
+            	        else if ( ((LA1_1 >= '\u0000' && LA1_1 <= '.') || (LA1_1 >= '0' && LA1_1 <= '\uFFFF')) )
+            	        {
+            	            alt1 = 1;
+            	        }
+
+
+            	    }
+            	    else if ( ((LA1_0 >= '\u0000' && LA1_0 <= ')') || (LA1_0 >= '+' && LA1_0 <= '\uFFFF')) )
+            	    {
+            	        alt1 = 1;
+            	    }
+
+
+            	    switch (alt1) 
+            		{
+            			case 1 :
+            			    // ooa.g:996:13: .
+            			    {
+            			    	MatchAny(); if (state.failed) return ;
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop1;
+            	    }
+            	} while (true);
+
+            	loop1:
+            		;	// Stops C# compiler whining that label 'loop1' has no statements
+
+            	Match("*/"); if (state.failed) return ;
+
+            	if ( (state.backtracking==0) )
+            	{
+            	  _channel=HIDDEN;
+            	}
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_COMMENT"
+
+    // $ANTLR start "LINE_COMMENT"
+    public void mLINE_COMMENT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = LINE_COMMENT;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1000:6: ( '#' (~ ( '\\n' | '\\r' ) )* ( '\\r' )? '\\n' )
+            // ooa.g:1000:8: '#' (~ ( '\\n' | '\\r' ) )* ( '\\r' )? '\\n'
+            {
+            	Match('#'); if (state.failed) return ;
+            	// ooa.g:1000:12: (~ ( '\\n' | '\\r' ) )*
+            	do 
+            	{
+            	    int alt2 = 2;
+            	    int LA2_0 = input.LA(1);
+
+            	    if ( ((LA2_0 >= '\u0000' && LA2_0 <= '\t') || (LA2_0 >= '\u000B' && LA2_0 <= '\f') || (LA2_0 >= '\u000E' && LA2_0 <= '\uFFFF')) )
+            	    {
+            	        alt2 = 1;
+            	    }
+
+
+            	    switch (alt2) 
+            		{
+            			case 1 :
+            			    // ooa.g:1000:12: ~ ( '\\n' | '\\r' )
+            			    {
+            			    	if ( (input.LA(1) >= '\u0000' && input.LA(1) <= '\t') || (input.LA(1) >= '\u000B' && input.LA(1) <= '\f') || (input.LA(1) >= '\u000E' && input.LA(1) <= '\uFFFF') ) 
+            			    	{
+            			    	    input.Consume();
+            			    	state.failed = false;
+            			    	}
+            			    	else 
+            			    	{
+            			    	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+            			    	    MismatchedSetException mse = new MismatchedSetException(null,input);
+            			    	    Recover(mse);
+            			    	    throw mse;}
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop2;
+            	    }
+            	} while (true);
+
+            	loop2:
+            		;	// Stops C# compiler whining that label 'loop2' has no statements
+
+            	// ooa.g:1000:26: ( '\\r' )?
+            	int alt3 = 2;
+            	int LA3_0 = input.LA(1);
+
+            	if ( (LA3_0 == '\r') )
+            	{
+            	    alt3 = 1;
+            	}
+            	switch (alt3) 
+            	{
+            	    case 1 :
+            	        // ooa.g:1000:26: '\\r'
+            	        {
+            	        	Match('\r'); if (state.failed) return ;
+
+            	        }
+            	        break;
+
+            	}
+
+            	Match('\n'); if (state.failed) return ;
+            	if ( (state.backtracking==0) )
+            	{
+            	  _channel=HIDDEN;
+            	}
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "LINE_COMMENT"
+
+    // $ANTLR start "T_PRIMED"
+    public void mT_PRIMED() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_PRIMED;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1004:2: ( '\\'' )
+            // ooa.g:1004:4: '\\''
+            {
+            	Match('\''); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_PRIMED"
+
+    // $ANTLR start "T_STRINGLITERAL"
+    public void mT_STRINGLITERAL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_STRINGLITERAL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1007:2: ( '\"' ( ( '\"' '\"' )=> '\"' | ~ '\"' )* '\"' )
+            // ooa.g:1007:4: '\"' ( ( '\"' '\"' )=> '\"' | ~ '\"' )* '\"'
+            {
+            	Match('\"'); if (state.failed) return ;
+            	// ooa.g:1008:3: ( ( '\"' '\"' )=> '\"' | ~ '\"' )*
+            	do 
+            	{
+            	    int alt4 = 3;
+            	    int LA4_0 = input.LA(1);
+
+            	    if ( (LA4_0 == '\"') )
+            	    {
+            	        int LA4_1 = input.LA(2);
+
+            	        if ( (LA4_1 == '\"') && (synpred1_ooa()) )
+            	        {
+            	            alt4 = 1;
+            	        }
+            	        else if ( ((LA4_1 >= '\u0000' && LA4_1 <= '!') || (LA4_1 >= '#' && LA4_1 <= '\uFFFF')) && (synpred1_ooa()) )
+            	        {
+            	            alt4 = 1;
+            	        }
+
+
+            	    }
+            	    else if ( ((LA4_0 >= '\u0000' && LA4_0 <= '!') || (LA4_0 >= '#' && LA4_0 <= '\uFFFF')) )
+            	    {
+            	        alt4 = 2;
+            	    }
+
+
+            	    switch (alt4) 
+            		{
+            			case 1 :
+            			    // ooa.g:1009:9: ( '\"' '\"' )=> '\"'
+            			    {
+            			    	Match('\"'); if (state.failed) return ;
+
+            			    }
+            			    break;
+            			case 2 :
+            			    // ooa.g:1010:13: ~ '\"'
+            			    {
+            			    	if ( (input.LA(1) >= '\u0000' && input.LA(1) <= '!') || (input.LA(1) >= '#' && input.LA(1) <= '\uFFFF') ) 
+            			    	{
+            			    	    input.Consume();
+            			    	state.failed = false;
+            			    	}
+            			    	else 
+            			    	{
+            			    	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+            			    	    MismatchedSetException mse = new MismatchedSetException(null,input);
+            			    	    Recover(mse);
+            			    	    throw mse;}
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop4;
+            	    }
+            	} while (true);
+
+            	loop4:
+            		;	// Stops C# compiler whining that label 'loop4' has no statements
+
+            	Match('\"'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_STRINGLITERAL"
+
+    // $ANTLR start "T_ABORT"
+    public void mT_ABORT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_ABORT;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1016:9: ( 'abort' )
+            // ooa.g:1016:11: 'abort'
+            {
+            	Match("abort"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_ABORT"
+
+    // $ANTLR start "T_ACTIONS"
+    public void mT_ACTIONS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_ACTIONS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1018:2: ( 'actions' )
+            // ooa.g:1018:4: 'actions'
+            {
+            	Match("actions"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_ACTIONS"
+
+    // $ANTLR start "T_ASSIGNMENT"
+    public void mT_ASSIGNMENT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_ASSIGNMENT;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1020:2: ( ':=' )
+            // ooa.g:1020:4: ':='
+            {
+            	Match(":="); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_ASSIGNMENT"
+
+    // $ANTLR start "T_AUTOCONS"
+    public void mT_AUTOCONS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_AUTOCONS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1021:11: ( 'autocons' )
+            // ooa.g:1021:13: 'autocons'
+            {
+            	Match("autocons"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_AUTOCONS"
+
+    // $ANTLR start "T_BAR"
+    public void mT_BAR() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_BAR;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1022:7: ( '|' )
+            // ooa.g:1022:9: '|'
+            {
+            	Match('|'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_BAR"
+
+    // $ANTLR start "T_BOOL"
+    public void mT_BOOL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_BOOL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1023:8: ( 'bool' )
+            // ooa.g:1023:10: 'bool'
+            {
+            	Match("bool"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_BOOL"
+
+    // $ANTLR start "T_CBRL"
+    public void mT_CBRL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_CBRL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1024:8: ( '{' )
+            // ooa.g:1024:10: '{'
+            {
+            	Match('{'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_CBRL"
+
+    // $ANTLR start "T_CBRR"
+    public void mT_CBRR() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_CBRR;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1025:8: ( '}' )
+            // ooa.g:1025:10: '}'
+            {
+            	Match('}'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_CBRR"
+
+    // $ANTLR start "T_COLON"
+    public void mT_COLON() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_COLON;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1026:9: ( ':' )
+            // ooa.g:1026:11: ':'
+            {
+            	Match(':'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_COLON"
+
+    // $ANTLR start "T_COMMA"
+    public void mT_COMMA() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_COMMA;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1027:9: ( ',' )
+            // ooa.g:1027:11: ','
+            {
+            	Match(','); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_COMMA"
+
+    // $ANTLR start "T_CONT"
+    public void mT_CONT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_CONT;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1028:8: ( 'qual' )
+            // ooa.g:1028:10: 'qual'
+            {
+            	Match("qual"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_CONT"
+
+    // $ANTLR start "T_CHAR"
+    public void mT_CHAR() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_CHAR;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1029:8: ( 'char' )
+            // ooa.g:1029:10: 'char'
+            {
+            	Match("char"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_CHAR"
+
+    // $ANTLR start "T_CTRL"
+    public void mT_CTRL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_CTRL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1030:9: ( 'ctr' )
+            // ooa.g:1030:11: 'ctr'
+            {
+            	Match("ctr"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_CTRL"
+
+    // $ANTLR start "T_SYSTEM"
+    public void mT_SYSTEM() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_SYSTEM;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1032:2: ( 'system' )
+            // ooa.g:1032:4: 'system'
+            {
+            	Match("system"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_SYSTEM"
+
+    // $ANTLR start "T_DO"
+    public void mT_DO() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DO;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1033:6: ( 'do' )
+            // ooa.g:1033:8: 'do'
+            {
+            	Match("do"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DO"
+
+    // $ANTLR start "T_ELSE"
+    public void mT_ELSE() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_ELSE;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1034:8: ( 'else' )
+            // ooa.g:1034:10: 'else'
+            {
+            	Match("else"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_ELSE"
+
+    // $ANTLR start "T_END"
+    public void mT_END() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_END;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1035:7: ( 'end' )
+            // ooa.g:1035:9: 'end'
+            {
+            	Match("end"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_END"
+
+    // $ANTLR start "T_EQUAL"
+    public void mT_EQUAL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_EQUAL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1036:9: ( '=' )
+            // ooa.g:1036:11: '='
+            {
+            	Match('='); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_EQUAL"
+
+    // $ANTLR start "T_EXISTS"
+    public void mT_EXISTS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_EXISTS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1037:9: ( 'exists' )
+            // ooa.g:1037:11: 'exists'
+            {
+            	Match("exists"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_EXISTS"
+
+    // $ANTLR start "T_FLOAT"
+    public void mT_FLOAT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_FLOAT;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1038:9: ( 'float' )
+            // ooa.g:1038:11: 'float'
+            {
+            	Match("float"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_FLOAT"
+
+    // $ANTLR start "T_FORALL"
+    public void mT_FORALL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_FORALL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1039:9: ( 'forall' )
+            // ooa.g:1039:11: 'forall'
+            {
+            	Match("forall"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_FORALL"
+
+    // $ANTLR start "T_FALSE"
+    public void mT_FALSE() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_FALSE;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1040:9: ( 'false' )
+            // ooa.g:1040:11: 'false'
+            {
+            	Match("false"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_FALSE"
+
+    // $ANTLR start "T_IF"
+    public void mT_IF() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_IF;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1041:6: ( 'if' )
+            // ooa.g:1041:8: 'if'
+            {
+            	Match("if"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_IF"
+
+    // $ANTLR start "T_IN"
+    public void mT_IN() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_IN;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1042:6: ( 'in' )
+            // ooa.g:1042:8: 'in'
+            {
+            	Match("in"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_IN"
+
+    // $ANTLR start "T_INT"
+    public void mT_INT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_INT;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1043:7: ( 'int' )
+            // ooa.g:1043:9: 'int'
+            {
+            	Match("int"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_INT"
+
+    // $ANTLR start "T_KILL"
+    public void mT_KILL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_KILL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1044:8: ( 'kill' )
+            // ooa.g:1044:10: 'kill'
+            {
+            	Match("kill"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_KILL"
+
+    // $ANTLR start "T_LIST"
+    public void mT_LIST() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_LIST;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1045:8: ( 'list' )
+            // ooa.g:1045:10: 'list'
+            {
+            	Match("list"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_LIST"
+
+    // $ANTLR start "T_LPAREN"
+    public void mT_LPAREN() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_LPAREN;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1046:9: ( '(' )
+            // ooa.g:1046:11: '('
+            {
+            	Match('('); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_LPAREN"
+
+    // $ANTLR start "T_LSQPAREN"
+    public void mT_LSQPAREN() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_LSQPAREN;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1047:11: ( '[' )
+            // ooa.g:1047:13: '['
+            {
+            	Match('['); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_LSQPAREN"
+
+    // $ANTLR start "T_MAP"
+    public void mT_MAP() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_MAP;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1048:7: ( 'map' )
+            // ooa.g:1048:9: 'map'
+            {
+            	Match("map"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_MAP"
+
+    // $ANTLR start "T_MAPS"
+    public void mT_MAPS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_MAPS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1049:8: ( '->' )
+            // ooa.g:1049:10: '->'
+            {
+            	Match("->"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_MAPS"
+
+    // $ANTLR start "T_METHODS"
+    public void mT_METHODS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_METHODS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1051:2: ( 'methods' )
+            // ooa.g:1051:4: 'methods'
+            {
+            	Match("methods"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_METHODS"
+
+    // $ANTLR start "T_NEW"
+    public void mT_NEW() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_NEW;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1052:7: ( 'new' )
+            // ooa.g:1052:9: 'new'
+            {
+            	Match("new"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_NEW"
+
+    // $ANTLR start "T_NIL"
+    public void mT_NIL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_NIL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1053:7: ( 'nil' )
+            // ooa.g:1053:9: 'nil'
+            {
+            	Match("nil"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_NIL"
+
+    // $ANTLR start "T_NONDET"
+    public void mT_NONDET() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_NONDET;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1054:9: ( '[]' )
+            // ooa.g:1054:11: '[]'
+            {
+            	Match("[]"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_NONDET"
+
+    // $ANTLR start "T_OBS"
+    public void mT_OBS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_OBS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1055:7: ( 'obs' )
+            // ooa.g:1055:9: 'obs'
+            {
+            	Match("obs"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_OBS"
+
+    // $ANTLR start "T_OD"
+    public void mT_OD() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_OD;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1056:6: ( 'od' )
+            // ooa.g:1056:8: 'od'
+            {
+            	Match("od"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_OD"
+
+    // $ANTLR start "T_OF"
+    public void mT_OF() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_OF;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1057:6: ( 'of' )
+            // ooa.g:1057:8: 'of'
+            {
+            	Match("of"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_OF"
+
+    // $ANTLR start "T_PRIO"
+    public void mT_PRIO() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_PRIO;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1058:8: ( '//' )
+            // ooa.g:1058:10: '//'
+            {
+            	Match("//"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_PRIO"
+
+    // $ANTLR start "T_REQUIRES"
+    public void mT_REQUIRES() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_REQUIRES;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1060:2: ( 'requires' )
+            // ooa.g:1060:4: 'requires'
+            {
+            	Match("requires"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_REQUIRES"
+
+    // $ANTLR start "T_RPAREN"
+    public void mT_RPAREN() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_RPAREN;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1061:9: ( ')' )
+            // ooa.g:1061:11: ')'
+            {
+            	Match(')'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_RPAREN"
+
+    // $ANTLR start "T_RSQPAREN"
+    public void mT_RSQPAREN() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_RSQPAREN;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1062:11: ( ']' )
+            // ooa.g:1062:13: ']'
+            {
+            	Match(']'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_RSQPAREN"
+
+    // $ANTLR start "T_QUANTITY"
+    public void mT_QUANTITY() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_QUANTITY;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1064:2: ( 'qspace' )
+            // ooa.g:1064:4: 'qspace'
+            {
+            	Match("qspace"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_QUANTITY"
+
+    // $ANTLR start "T_SELF"
+    public void mT_SELF() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_SELF;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1065:8: ( 'self' )
+            // ooa.g:1065:10: 'self'
+            {
+            	Match("self"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_SELF"
+
+    // $ANTLR start "T_SET"
+    public void mT_SET() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_SET;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1066:8: ( 'set' )
+            // ooa.g:1066:10: 'set'
+            {
+            	Match("set"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_SET"
+
+    // $ANTLR start "T_SEMICOLON"
+    public void mT_SEMICOLON() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_SEMICOLON;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1068:2: ( ';' )
+            // ooa.g:1068:4: ';'
+            {
+            	Match(';'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_SEMICOLON"
+
+    // $ANTLR start "T_STATIC"
+    public void mT_STATIC() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_STATIC;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1069:9: ( 'static' )
+            // ooa.g:1069:11: 'static'
+            {
+            	Match("static"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_STATIC"
+
+    // $ANTLR start "T_SKIP"
+    public void mT_SKIP() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_SKIP;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1070:8: ( 'skip' )
+            // ooa.g:1070:10: 'skip'
+            {
+            	Match("skip"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_SKIP"
+
+    // $ANTLR start "T_THEN"
+    public void mT_THEN() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_THEN;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1071:8: ( 'then' )
+            // ooa.g:1071:10: 'then'
+            {
+            	Match("then"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_THEN"
+
+    // $ANTLR start "T_TRUE"
+    public void mT_TRUE() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_TRUE;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1072:9: ( 'true' )
+            // ooa.g:1072:11: 'true'
+            {
+            	Match("true"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_TRUE"
+
+    // $ANTLR start "T_TO"
+    public void mT_TO() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_TO;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1073:6: ( 'to' )
+            // ooa.g:1073:8: 'to'
+            {
+            	Match("to"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_TO"
+
+    // $ANTLR start "T_TYPES"
+    public void mT_TYPES() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_TYPES;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1074:9: ( 'types' )
+            // ooa.g:1074:11: 'types'
+            {
+            	Match("types"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_TYPES"
+
+    // $ANTLR start "T_VAR"
+    public void mT_VAR() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_VAR;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1075:7: ( 'var' )
+            // ooa.g:1075:9: 'var'
+            {
+            	Match("var"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_VAR"
+
+    // $ANTLR start "T_WITH"
+    public void mT_WITH() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_WITH;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1076:8: ( 'with' )
+            // ooa.g:1076:10: 'with'
+            {
+            	Match("with"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_WITH"
+
+    // $ANTLR start "T_AND"
+    public void mT_AND() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_AND;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1082:7: ( 'and' )
+            // ooa.g:1082:9: 'and'
+            {
+            	Match("and"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_AND"
+
+    // $ANTLR start "T_BIIMPLIES"
+    public void mT_BIIMPLIES() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_BIIMPLIES;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1084:2: ( '<=>' )
+            // ooa.g:1084:4: '<=>'
+            {
+            	Match("<=>"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_BIIMPLIES"
+
+    // $ANTLR start "T_IMPLIES"
+    public void mT_IMPLIES() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_IMPLIES;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1086:2: ( '=>' )
+            // ooa.g:1086:4: '=>'
+            {
+            	Match("=>"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_IMPLIES"
+
+    // $ANTLR start "T_NOT"
+    public void mT_NOT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_NOT;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1087:7: ( 'not' )
+            // ooa.g:1087:9: 'not'
+            {
+            	Match("not"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_NOT"
+
+    // $ANTLR start "T_NOTEQUAL"
+    public void mT_NOTEQUAL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_NOTEQUAL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1088:11: ( '<>' )
+            // ooa.g:1088:13: '<>'
+            {
+            	Match("<>"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_NOTEQUAL"
+
+    // $ANTLR start "T_OR"
+    public void mT_OR() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_OR;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1089:6: ( 'or' )
+            // ooa.g:1089:8: 'or'
+            {
+            	Match("or"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_OR"
+
+    // $ANTLR start "T_ABS"
+    public void mT_ABS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_ABS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1092:7: ( 'abs' )
+            // ooa.g:1092:9: 'abs'
+            {
+            	Match("abs"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_ABS"
+
+    // $ANTLR start "T_DIV"
+    public void mT_DIV() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DIV;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1093:7: ( '/' )
+            // ooa.g:1093:9: '/'
+            {
+            	Match('/'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DIV"
+
+    // $ANTLR start "T_GREATER"
+    public void mT_GREATER() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_GREATER;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1095:2: ( '>' )
+            // ooa.g:1095:4: '>'
+            {
+            	Match('>'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_GREATER"
+
+    // $ANTLR start "T_GREATEREQUAL"
+    public void mT_GREATEREQUAL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_GREATEREQUAL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1097:2: ( '>=' )
+            // ooa.g:1097:4: '>='
+            {
+            	Match(">="); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_GREATEREQUAL"
+
+    // $ANTLR start "T_IDIV"
+    public void mT_IDIV() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_IDIV;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1098:8: ( 'div' )
+            // ooa.g:1098:10: 'div'
+            {
+            	Match("div"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_IDIV"
+
+    // $ANTLR start "T_LESS"
+    public void mT_LESS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_LESS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1099:8: ( '<' )
+            // ooa.g:1099:10: '<'
+            {
+            	Match('<'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_LESS"
+
+    // $ANTLR start "T_LESSEQUAL"
+    public void mT_LESSEQUAL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_LESSEQUAL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1101:2: ( '<=' )
+            // ooa.g:1101:4: '<='
+            {
+            	Match("<="); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_LESSEQUAL"
+
+    // $ANTLR start "T_MOD"
+    public void mT_MOD() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_MOD;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1102:7: ( 'mod' )
+            // ooa.g:1102:9: 'mod'
+            {
+            	Match("mod"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_MOD"
+
+    // $ANTLR start "T_POW"
+    public void mT_POW() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_POW;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1103:7: ( '**' )
+            // ooa.g:1103:9: '**'
+            {
+            	Match("**"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_POW"
+
+    // $ANTLR start "T_PROD"
+    public void mT_PROD() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_PROD;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1104:8: ( '*' )
+            // ooa.g:1104:10: '*'
+            {
+            	Match('*'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_PROD"
+
+    // $ANTLR start "T_DERIV"
+    public void mT_DERIV() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DERIV;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1105:9: ( 'dt' )
+            // ooa.g:1105:11: 'dt'
+            {
+            	Match("dt"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DERIV"
+
+    // $ANTLR start "T_CARD"
+    public void mT_CARD() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_CARD;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1108:8: ( 'card' )
+            // ooa.g:1108:10: 'card'
+            {
+            	Match("card"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_CARD"
+
+    // $ANTLR start "T_CONC"
+    public void mT_CONC() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_CONC;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1109:8: ( '^' )
+            // ooa.g:1109:10: '^'
+            {
+            	Match('^'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_CONC"
+
+    // $ANTLR start "T_DCONC"
+    public void mT_DCONC() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DCONC;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1110:9: ( 'conc' )
+            // ooa.g:1110:11: 'conc'
+            {
+            	Match("conc"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DCONC"
+
+    // $ANTLR start "T_DIFF"
+    public void mT_DIFF() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DIFF;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1111:8: ( '\\\\' )
+            // ooa.g:1111:10: '\\\\'
+            {
+            	Match('\\'); if (state.failed) return ;
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DIFF"
+
+    // $ANTLR start "T_DINTER"
+    public void mT_DINTER() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DINTER;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1112:9: ( 'dinter' )
+            // ooa.g:1112:11: 'dinter'
+            {
+            	Match("dinter"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DINTER"
+
+    // $ANTLR start "T_DUNION"
+    public void mT_DUNION() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DUNION;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1113:9: ( 'dunion' )
+            // ooa.g:1113:11: 'dunion'
+            {
+            	Match("dunion"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DUNION"
+
+    // $ANTLR start "T_ELEMS"
+    public void mT_ELEMS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_ELEMS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1114:9: ( 'elems' )
+            // ooa.g:1114:11: 'elems'
+            {
+            	Match("elems"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_ELEMS"
+
+    // $ANTLR start "T_HEAD"
+    public void mT_HEAD() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_HEAD;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1115:8: ( 'hd' )
+            // ooa.g:1115:10: 'hd'
+            {
+            	Match("hd"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_HEAD"
+
+    // $ANTLR start "T_INDS"
+    public void mT_INDS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_INDS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1116:8: ( 'inds' )
+            // ooa.g:1116:10: 'inds'
+            {
+            	Match("inds"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_INDS"
+
+    // $ANTLR start "T_INTER"
+    public void mT_INTER() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_INTER;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1117:9: ( 'inter' )
+            // ooa.g:1117:11: 'inter'
+            {
+            	Match("inter"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_INTER"
+
+    // $ANTLR start "T_LEN"
+    public void mT_LEN() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_LEN;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1118:7: ( 'len' )
+            // ooa.g:1118:9: 'len'
+            {
+            	Match("len"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_LEN"
+
+    // $ANTLR start "T_SEQMOD_MAPOVERRIDE"
+    public void mT_SEQMOD_MAPOVERRIDE() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_SEQMOD_MAPOVERRIDE;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1120:2: ( '++' )
+            // ooa.g:1120:4: '++'
+            {
+            	Match("++"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_SEQMOD_MAPOVERRIDE"
+
+    // $ANTLR start "T_SUBSET"
+    public void mT_SUBSET() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_SUBSET;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1121:9: ( 'subset' )
+            // ooa.g:1121:11: 'subset'
+            {
+            	Match("subset"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_SUBSET"
+
+    // $ANTLR start "T_TAIL"
+    public void mT_TAIL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_TAIL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1122:8: ( 'tl' )
+            // ooa.g:1122:10: 'tl'
+            {
+            	Match("tl"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_TAIL"
+
+    // $ANTLR start "T_UNION"
+    public void mT_UNION() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_UNION;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1123:9: ( 'union' )
+            // ooa.g:1123:11: 'union'
+            {
+            	Match("union"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_UNION"
+
+    // $ANTLR start "T_FOLDLR"
+    public void mT_FOLDLR() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_FOLDLR;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1125:2: ( ':>:' )
+            // ooa.g:1125:4: ':>:'
+            {
+            	Match(":>:"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_FOLDLR"
+
+    // $ANTLR start "T_FOLDRL"
+    public void mT_FOLDRL() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_FOLDRL;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1127:2: ( ':<:' )
+            // ooa.g:1127:4: ':<:'
+            {
+            	Match(":<:"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_FOLDRL"
+
+    // $ANTLR start "T_DOM"
+    public void mT_DOM() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DOM;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1131:7: ( 'dom' )
+            // ooa.g:1131:9: 'dom'
+            {
+            	Match("dom"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DOM"
+
+    // $ANTLR start "T_DOMRESBY"
+    public void mT_DOMRESBY() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DOMRESBY;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1133:2: ( '<-:' )
+            // ooa.g:1133:4: '<-:'
+            {
+            	Match("<-:"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DOMRESBY"
+
+    // $ANTLR start "T_DOMRESTO"
+    public void mT_DOMRESTO() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_DOMRESTO;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1135:2: ( '<:' )
+            // ooa.g:1135:4: '<:'
+            {
+            	Match("<:"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DOMRESTO"
+
+    // $ANTLR start "T_RNG"
+    public void mT_RNG() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_RNG;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1136:7: ( 'rng' )
+            // ooa.g:1136:9: 'rng'
+            {
+            	Match("rng"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_RNG"
+
+    // $ANTLR start "T_RNGRESBY"
+    public void mT_RNGRESBY() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_RNGRESBY;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1138:2: ( ':->' )
+            // ooa.g:1138:4: ':->'
+            {
+            	Match(":->"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_RNGRESBY"
+
+    // $ANTLR start "T_RNGRESTO"
+    public void mT_RNGRESTO() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_RNGRESTO;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1140:2: ( ':>' )
+            // ooa.g:1140:4: ':>'
+            {
+            	Match(":>"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_RNGRESTO"
+
+    // $ANTLR start "T_MERGE"
+    public void mT_MERGE() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_MERGE;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1141:9: ( 'merge' )
+            // ooa.g:1141:11: 'merge'
+            {
+            	Match("merge"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_MERGE"
+
+    // $ANTLR start "T_MUNION"
+    public void mT_MUNION() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_MUNION;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1142:9: ( 'munion' )
+            // ooa.g:1142:11: 'munion'
+            {
+            	Match("munion"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_MUNION"
+
+    // $ANTLR start "T_CONSTS"
+    public void mT_CONSTS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_CONSTS;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1144:9: ( 'consts' )
+            // ooa.g:1144:11: 'consts'
+            {
+            	Match("consts"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_CONSTS"
+
+    // $ANTLR start "T_INFTY"
+    public void mT_INFTY() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_INFTY;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1148:9: ( ( T_MINUS | T_SUM )? 'inf' )
+            // ooa.g:1148:11: ( T_MINUS | T_SUM )? 'inf'
+            {
+            	// ooa.g:1148:11: ( T_MINUS | T_SUM )?
+            	int alt5 = 2;
+            	int LA5_0 = input.LA(1);
+
+            	if ( (LA5_0 == '+' || LA5_0 == '-') )
+            	{
+            	    alt5 = 1;
+            	}
+            	switch (alt5) 
+            	{
+            	    case 1 :
+            	        // ooa.g:
+            	        {
+            	        	if ( input.LA(1) == '+' || input.LA(1) == '-' ) 
+            	        	{
+            	        	    input.Consume();
+            	        	state.failed = false;
+            	        	}
+            	        	else 
+            	        	{
+            	        	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+            	        	    MismatchedSetException mse = new MismatchedSetException(null,input);
+            	        	    Recover(mse);
+            	        	    throw mse;}
+
+
+            	        }
+            	        break;
+
+            	}
+
+            	Match("inf"); if (state.failed) return ;
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_INFTY"
+
+    // $ANTLR start "T_INTNUMBER"
+    public void mT_INTNUMBER() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            // ooa.g:1155:2: ()
+            // ooa.g:1155:4: 
+            {
+            }
+
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_INTNUMBER"
+
+    // $ANTLR start "T_FLOATNUMBER"
+    public void mT_FLOATNUMBER() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            // ooa.g:1157:2: ()
+            // ooa.g:1157:4: 
+            {
+            }
+
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_FLOATNUMBER"
+
+    // $ANTLR start "T_RANGETO"
+    public void mT_RANGETO() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            // ooa.g:1159:2: ()
+            // ooa.g:1159:4: 
+            {
+            }
+
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_RANGETO"
+
+    // $ANTLR start "FLOAT_OR_INT_OR_RANGE"
+    public void mFLOAT_OR_INT_OR_RANGE() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = FLOAT_OR_INT_OR_RANGE;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1162:2: ( ( T_MINUS | T_SUM )? ( T_DIGIT )+ ( ( T_POINT T_POINT )=> | ( T_POINT T_DIGIT )=> T_POINT ( T_DIGIT )+ ( ( 'e' | 'E' ) ( T_MINUS | T_SUM )? ( T_DIGIT )+ )? | ) | T_POINT ( T_POINT | ) | T_MINUS | T_SUM )
+            int alt14 = 4;
+            switch ( input.LA(1) ) 
+            {
+            case '-':
+            	{
+                int LA14_1 = input.LA(2);
+
+                if ( ((LA14_1 >= '0' && LA14_1 <= '9')) )
+                {
+                    alt14 = 1;
+                }
+                else 
+                {
+                    alt14 = 3;}
+                }
+                break;
+            case '0':
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+            	{
+                alt14 = 1;
+                }
+                break;
+            case '.':
+            	{
+                alt14 = 2;
+                }
+                break;
+            case '+':
+            	{
+                int LA14_4 = input.LA(2);
+
+                if ( ((LA14_4 >= '0' && LA14_4 <= '9')) )
+                {
+                    alt14 = 1;
+                }
+                else 
+                {
+                    alt14 = 4;}
+                }
+                break;
+            	default:
+            	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+            	    NoViableAltException nvae_d14s0 =
+            	        new NoViableAltException("", 14, 0, input);
+
+            	    throw nvae_d14s0;
+            }
+
+            switch (alt14) 
+            {
+                case 1 :
+                    // ooa.g:1162:5: ( T_MINUS | T_SUM )? ( T_DIGIT )+ ( ( T_POINT T_POINT )=> | ( T_POINT T_DIGIT )=> T_POINT ( T_DIGIT )+ ( ( 'e' | 'E' ) ( T_MINUS | T_SUM )? ( T_DIGIT )+ )? | )
+                    {
+                    	// ooa.g:1162:5: ( T_MINUS | T_SUM )?
+                    	int alt6 = 2;
+                    	int LA6_0 = input.LA(1);
+
+                    	if ( (LA6_0 == '+' || LA6_0 == '-') )
+                    	{
+                    	    alt6 = 1;
+                    	}
+                    	switch (alt6) 
+                    	{
+                    	    case 1 :
+                    	        // ooa.g:
+                    	        {
+                    	        	if ( input.LA(1) == '+' || input.LA(1) == '-' ) 
+                    	        	{
+                    	        	    input.Consume();
+                    	        	state.failed = false;
+                    	        	}
+                    	        	else 
+                    	        	{
+                    	        	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+                    	        	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	        	    Recover(mse);
+                    	        	    throw mse;}
+
+
+                    	        }
+                    	        break;
+
+                    	}
+
+                    	// ooa.g:1162:22: ( T_DIGIT )+
+                    	int cnt7 = 0;
+                    	do 
+                    	{
+                    	    int alt7 = 2;
+                    	    int LA7_0 = input.LA(1);
+
+                    	    if ( ((LA7_0 >= '0' && LA7_0 <= '9')) )
+                    	    {
+                    	        alt7 = 1;
+                    	    }
+
+
+                    	    switch (alt7) 
+                    		{
+                    			case 1 :
+                    			    // ooa.g:1162:22: T_DIGIT
+                    			    {
+                    			    	mT_DIGIT(); if (state.failed) return ;
+
+                    			    }
+                    			    break;
+
+                    			default:
+                    			    if ( cnt7 >= 1 ) goto loop7;
+                    			    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+                    		            EarlyExitException eee7 =
+                    		                new EarlyExitException(7, input);
+                    		            throw eee7;
+                    	    }
+                    	    cnt7++;
+                    	} while (true);
+
+                    	loop7:
+                    		;	// Stops C# compiler whining that label 'loop7' has no statements
+
+                    	// ooa.g:1163:3: ( ( T_POINT T_POINT )=> | ( T_POINT T_DIGIT )=> T_POINT ( T_DIGIT )+ ( ( 'e' | 'E' ) ( T_MINUS | T_SUM )? ( T_DIGIT )+ )? | )
+                    	int alt12 = 3;
+                    	int LA12_0 = input.LA(1);
+
+                    	if ( (LA12_0 == '.') && (synpred3_ooa()) )
+                    	{
+                    	    alt12 = 2;
+                    	}
+                    	else if ( (synpred2_ooa()) )
+                    	{
+                    	    alt12 = 1;
+                    	}
+                    	else if ( (true) )
+                    	{
+                    	    alt12 = 3;
+                    	}
+                    	else 
+                    	{
+                    	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+                    	    NoViableAltException nvae_d12s0 =
+                    	        new NoViableAltException("", 12, 0, input);
+
+                    	    throw nvae_d12s0;
+                    	}
+                    	switch (alt12) 
+                    	{
+                    	    case 1 :
+                    	        // ooa.g:1164:5: ( T_POINT T_POINT )=>
+                    	        {
+                    	        	if ( (state.backtracking==0) )
+                    	        	{
+                    	        	  _type=T_INTNUMBER;
+                    	        	}
+
+                    	        }
+                    	        break;
+                    	    case 2 :
+                    	        // ooa.g:1165:6: ( T_POINT T_DIGIT )=> T_POINT ( T_DIGIT )+ ( ( 'e' | 'E' ) ( T_MINUS | T_SUM )? ( T_DIGIT )+ )?
+                    	        {
+                    	        	mT_POINT(); if (state.failed) return ;
+                    	        	// ooa.g:1165:35: ( T_DIGIT )+
+                    	        	int cnt8 = 0;
+                    	        	do 
+                    	        	{
+                    	        	    int alt8 = 2;
+                    	        	    int LA8_0 = input.LA(1);
+
+                    	        	    if ( ((LA8_0 >= '0' && LA8_0 <= '9')) )
+                    	        	    {
+                    	        	        alt8 = 1;
+                    	        	    }
+
+
+                    	        	    switch (alt8) 
+                    	        		{
+                    	        			case 1 :
+                    	        			    // ooa.g:1165:35: T_DIGIT
+                    	        			    {
+                    	        			    	mT_DIGIT(); if (state.failed) return ;
+
+                    	        			    }
+                    	        			    break;
+
+                    	        			default:
+                    	        			    if ( cnt8 >= 1 ) goto loop8;
+                    	        			    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+                    	        		            EarlyExitException eee8 =
+                    	        		                new EarlyExitException(8, input);
+                    	        		            throw eee8;
+                    	        	    }
+                    	        	    cnt8++;
+                    	        	} while (true);
+
+                    	        	loop8:
+                    	        		;	// Stops C# compiler whining that label 'loop8' has no statements
+
+                    	        	// ooa.g:1165:44: ( ( 'e' | 'E' ) ( T_MINUS | T_SUM )? ( T_DIGIT )+ )?
+                    	        	int alt11 = 2;
+                    	        	int LA11_0 = input.LA(1);
+
+                    	        	if ( (LA11_0 == 'E' || LA11_0 == 'e') )
+                    	        	{
+                    	        	    alt11 = 1;
+                    	        	}
+                    	        	switch (alt11) 
+                    	        	{
+                    	        	    case 1 :
+                    	        	        // ooa.g:1165:45: ( 'e' | 'E' ) ( T_MINUS | T_SUM )? ( T_DIGIT )+
+                    	        	        {
+                    	        	        	if ( input.LA(1) == 'E' || input.LA(1) == 'e' ) 
+                    	        	        	{
+                    	        	        	    input.Consume();
+                    	        	        	state.failed = false;
+                    	        	        	}
+                    	        	        	else 
+                    	        	        	{
+                    	        	        	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+                    	        	        	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	        	        	    Recover(mse);
+                    	        	        	    throw mse;}
+
+                    	        	        	// ooa.g:1165:55: ( T_MINUS | T_SUM )?
+                    	        	        	int alt9 = 2;
+                    	        	        	int LA9_0 = input.LA(1);
+
+                    	        	        	if ( (LA9_0 == '+' || LA9_0 == '-') )
+                    	        	        	{
+                    	        	        	    alt9 = 1;
+                    	        	        	}
+                    	        	        	switch (alt9) 
+                    	        	        	{
+                    	        	        	    case 1 :
+                    	        	        	        // ooa.g:
+                    	        	        	        {
+                    	        	        	        	if ( input.LA(1) == '+' || input.LA(1) == '-' ) 
+                    	        	        	        	{
+                    	        	        	        	    input.Consume();
+                    	        	        	        	state.failed = false;
+                    	        	        	        	}
+                    	        	        	        	else 
+                    	        	        	        	{
+                    	        	        	        	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+                    	        	        	        	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	        	        	        	    Recover(mse);
+                    	        	        	        	    throw mse;}
+
+
+                    	        	        	        }
+                    	        	        	        break;
+
+                    	        	        	}
+
+                    	        	        	// ooa.g:1165:72: ( T_DIGIT )+
+                    	        	        	int cnt10 = 0;
+                    	        	        	do 
+                    	        	        	{
+                    	        	        	    int alt10 = 2;
+                    	        	        	    int LA10_0 = input.LA(1);
+
+                    	        	        	    if ( ((LA10_0 >= '0' && LA10_0 <= '9')) )
+                    	        	        	    {
+                    	        	        	        alt10 = 1;
+                    	        	        	    }
+
+
+                    	        	        	    switch (alt10) 
+                    	        	        		{
+                    	        	        			case 1 :
+                    	        	        			    // ooa.g:1165:72: T_DIGIT
+                    	        	        			    {
+                    	        	        			    	mT_DIGIT(); if (state.failed) return ;
+
+                    	        	        			    }
+                    	        	        			    break;
+
+                    	        	        			default:
+                    	        	        			    if ( cnt10 >= 1 ) goto loop10;
+                    	        	        			    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+                    	        	        		            EarlyExitException eee10 =
+                    	        	        		                new EarlyExitException(10, input);
+                    	        	        		            throw eee10;
+                    	        	        	    }
+                    	        	        	    cnt10++;
+                    	        	        	} while (true);
+
+                    	        	        	loop10:
+                    	        	        		;	// Stops C# compiler whining that label 'loop10' has no statements
+
+
+                    	        	        }
+                    	        	        break;
+
+                    	        	}
+
+                    	        	if ( (state.backtracking==0) )
+                    	        	{
+                    	        	  _type=T_FLOATNUMBER;
+                    	        	}
+
+                    	        }
+                    	        break;
+                    	    case 3 :
+                    	        // ooa.g:1166:6: 
+                    	        {
+                    	        	if ( (state.backtracking==0) )
+                    	        	{
+                    	        	  _type=T_INTNUMBER;
+                    	        	}
+
+                    	        }
+                    	        break;
+
+                    	}
+
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:1168:4: T_POINT ( T_POINT | )
+                    {
+                    	mT_POINT(); if (state.failed) return ;
+                    	// ooa.g:1169:3: ( T_POINT | )
+                    	int alt13 = 2;
+                    	int LA13_0 = input.LA(1);
+
+                    	if ( (LA13_0 == '.') )
+                    	{
+                    	    alt13 = 1;
+                    	}
+                    	else 
+                    	{
+                    	    alt13 = 2;}
+                    	switch (alt13) 
+                    	{
+                    	    case 1 :
+                    	        // ooa.g:1170:5: T_POINT
+                    	        {
+                    	        	mT_POINT(); if (state.failed) return ;
+                    	        	if ( (state.backtracking==0) )
+                    	        	{
+                    	        	  _type=T_RANGETO;
+                    	        	}
+
+                    	        }
+                    	        break;
+                    	    case 2 :
+                    	        // ooa.g:1171:13: 
+                    	        {
+                    	        	if ( (state.backtracking==0) )
+                    	        	{
+                    	        	  _type=T_POINT;
+                    	        	}
+
+                    	        }
+                    	        break;
+
+                    	}
+
+
+                    }
+                    break;
+                case 3 :
+                    // ooa.g:1173:4: T_MINUS
+                    {
+                    	mT_MINUS(); if (state.failed) return ;
+                    	if ( (state.backtracking==0) )
+                    	{
+                    	  _type=T_MINUS;
+                    	}
+
+                    }
+                    break;
+                case 4 :
+                    // ooa.g:1174:4: T_SUM
+                    {
+                    	mT_SUM(); if (state.failed) return ;
+                    	if ( (state.backtracking==0) )
+                    	{
+                    	  _type=T_SUM;
+                    	}
+
+                    }
+                    break;
+
+            }
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "FLOAT_OR_INT_OR_RANGE"
+
+    // $ANTLR start "T_MINUS"
+    public void mT_MINUS() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            // ooa.g:1179:17: ( '-' )
+            // ooa.g:1179:19: '-'
+            {
+            	Match('-'); if (state.failed) return ;
+
+            }
+
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_MINUS"
+
+    // $ANTLR start "T_SUM"
+    public void mT_SUM() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            // ooa.g:1180:16: ( '+' )
+            // ooa.g:1180:18: '+'
+            {
+            	Match('+'); if (state.failed) return ;
+
+            }
+
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_SUM"
+
+    // $ANTLR start "T_POINT"
+    public void mT_POINT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            // ooa.g:1181:17: ( '.' )
+            // ooa.g:1181:19: '.'
+            {
+            	Match('.'); if (state.failed) return ;
+
+            }
+
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_POINT"
+
+    // $ANTLR start "T_IDENTIFIER"
+    public void mT_IDENTIFIER() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            int _type = T_IDENTIFIER;
+    	int _channel = DEFAULT_TOKEN_CHANNEL;
+            // ooa.g:1187:2: ( T_LETTER ( T_LETTER | T_DIGIT )* )
+            // ooa.g:1187:4: T_LETTER ( T_LETTER | T_DIGIT )*
+            {
+            	mT_LETTER(); if (state.failed) return ;
+            	// ooa.g:1187:13: ( T_LETTER | T_DIGIT )*
+            	do 
+            	{
+            	    int alt15 = 2;
+            	    int LA15_0 = input.LA(1);
+
+            	    if ( (LA15_0 == '$' || (LA15_0 >= '0' && LA15_0 <= '9') || (LA15_0 >= 'A' && LA15_0 <= 'Z') || LA15_0 == '_' || (LA15_0 >= 'a' && LA15_0 <= 'z')) )
+            	    {
+            	        alt15 = 1;
+            	    }
+
+
+            	    switch (alt15) 
+            		{
+            			case 1 :
+            			    // ooa.g:
+            			    {
+            			    	if ( input.LA(1) == '$' || (input.LA(1) >= '0' && input.LA(1) <= '9') || (input.LA(1) >= 'A' && input.LA(1) <= 'Z') || input.LA(1) == '_' || (input.LA(1) >= 'a' && input.LA(1) <= 'z') ) 
+            			    	{
+            			    	    input.Consume();
+            			    	state.failed = false;
+            			    	}
+            			    	else 
+            			    	{
+            			    	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+            			    	    MismatchedSetException mse = new MismatchedSetException(null,input);
+            			    	    Recover(mse);
+            			    	    throw mse;}
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop15;
+            	    }
+            	} while (true);
+
+            	loop15:
+            		;	// Stops C# compiler whining that label 'loop15' has no statements
+
+
+            }
+
+            state.type = _type;
+            state.channel = _channel;
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_IDENTIFIER"
+
+    // $ANTLR start "T_LETTER"
+    public void mT_LETTER() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            // ooa.g:1195:2: ( '$' | 'A' .. 'Z' | 'a' .. 'z' | '_' )
+            // ooa.g:
+            {
+            	if ( input.LA(1) == '$' || (input.LA(1) >= 'A' && input.LA(1) <= 'Z') || input.LA(1) == '_' || (input.LA(1) >= 'a' && input.LA(1) <= 'z') ) 
+            	{
+            	    input.Consume();
+            	state.failed = false;
+            	}
+            	else 
+            	{
+            	    if ( state.backtracking > 0 ) {state.failed = true; return ;}
+            	    MismatchedSetException mse = new MismatchedSetException(null,input);
+            	    Recover(mse);
+            	    throw mse;}
+
+
+            }
+
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_LETTER"
+
+    // $ANTLR start "T_DIGIT"
+    public void mT_DIGIT() // throws RecognitionException [2]
+    {
+    		try
+    		{
+            // ooa.g:1202:8: ( '0' .. '9' )
+            // ooa.g:1202:10: '0' .. '9'
+            {
+            	MatchRange('0','9'); if (state.failed) return ;
+
+            }
+
+        }
+        finally 
+    	{
+        }
+    }
+    // $ANTLR end "T_DIGIT"
+
+    override public void mTokens() // throws RecognitionException 
+    {
+        // ooa.g:1:8: ( T__117 | T__118 | T__119 | T__120 | T__121 | T__122 | T__123 | T__124 | T__125 | T__126 | T_WS | T_COMMENT | LINE_COMMENT | T_PRIMED | T_STRINGLITERAL | T_ABORT | T_ACTIONS | T_ASSIGNMENT | T_AUTOCONS | T_BAR | T_BOOL | T_CBRL | T_CBRR | T_COLON | T_COMMA | T_CONT | T_CHAR | T_CTRL | T_SYSTEM | T_DO | T_ELSE | T_END | T_EQUAL | T_EXISTS | T_FLOAT | T_FORALL | T_FALSE | T_IF | T_IN | T_INT | T_KILL | T_LIST | T_LPAREN | T_LSQPAREN | T_MAP | T_MAPS | T_METHODS | T_NEW | T_NIL | T_NONDET | T_OBS | T_OD | T_OF | T_PRIO | T_REQUIRES | T_RPAREN | T_RSQPAREN | T_QUANTITY | T_SELF | T_SET | T_SEMICOLON | T_STATIC | T_SKIP | T_THEN | T_TRUE | T_TO | T_TYPES | T_VAR | T_WITH | T_AND | T_BIIMPLIES | T_IMPLIES | T_NOT | T_NOTEQUAL | T_OR | T_ABS | T_DIV | T_GREATER | T_GREATEREQUAL | T_IDIV | T_LESS | T_LESSEQUAL | T_MOD | T_POW | T_PROD | T_DERIV | T_CARD | T_CONC | T_DCONC | T_DIFF | T_DINTER | T_DUNION | T_ELEMS | T_HEAD | T_INDS | T_INTER | T_LEN | T_SEQMOD_MAPOVERRIDE | T_SUBSET | T_TAIL | T_UNION | T_FOLDLR | T_FOLDRL | T_DOM | T_DOMRESBY | T_DOMRESTO | T_RNG | T_RNGRESBY | T_RNGRESTO | T_MERGE | T_MUNION | T_CONSTS | T_INFTY | FLOAT_OR_INT_OR_RANGE | T_IDENTIFIER )
+        int alt16 = 115;
+        alt16 = dfa16.Predict(input);
+        switch (alt16) 
+        {
+            case 1 :
+                // ooa.g:1:10: T__117
+                {
+                	mT__117(); if (state.failed) return ;
+
+                }
+                break;
+            case 2 :
+                // ooa.g:1:17: T__118
+                {
+                	mT__118(); if (state.failed) return ;
+
+                }
+                break;
+            case 3 :
+                // ooa.g:1:24: T__119
+                {
+                	mT__119(); if (state.failed) return ;
+
+                }
+                break;
+            case 4 :
+                // ooa.g:1:31: T__120
+                {
+                	mT__120(); if (state.failed) return ;
+
+                }
+                break;
+            case 5 :
+                // ooa.g:1:38: T__121
+                {
+                	mT__121(); if (state.failed) return ;
+
+                }
+                break;
+            case 6 :
+                // ooa.g:1:45: T__122
+                {
+                	mT__122(); if (state.failed) return ;
+
+                }
+                break;
+            case 7 :
+                // ooa.g:1:52: T__123
+                {
+                	mT__123(); if (state.failed) return ;
+
+                }
+                break;
+            case 8 :
+                // ooa.g:1:59: T__124
+                {
+                	mT__124(); if (state.failed) return ;
+
+                }
+                break;
+            case 9 :
+                // ooa.g:1:66: T__125
+                {
+                	mT__125(); if (state.failed) return ;
+
+                }
+                break;
+            case 10 :
+                // ooa.g:1:73: T__126
+                {
+                	mT__126(); if (state.failed) return ;
+
+                }
+                break;
+            case 11 :
+                // ooa.g:1:80: T_WS
+                {
+                	mT_WS(); if (state.failed) return ;
+
+                }
+                break;
+            case 12 :
+                // ooa.g:1:85: T_COMMENT
+                {
+                	mT_COMMENT(); if (state.failed) return ;
+
+                }
+                break;
+            case 13 :
+                // ooa.g:1:95: LINE_COMMENT
+                {
+                	mLINE_COMMENT(); if (state.failed) return ;
+
+                }
+                break;
+            case 14 :
+                // ooa.g:1:108: T_PRIMED
+                {
+                	mT_PRIMED(); if (state.failed) return ;
+
+                }
+                break;
+            case 15 :
+                // ooa.g:1:117: T_STRINGLITERAL
+                {
+                	mT_STRINGLITERAL(); if (state.failed) return ;
+
+                }
+                break;
+            case 16 :
+                // ooa.g:1:133: T_ABORT
+                {
+                	mT_ABORT(); if (state.failed) return ;
+
+                }
+                break;
+            case 17 :
+                // ooa.g:1:141: T_ACTIONS
+                {
+                	mT_ACTIONS(); if (state.failed) return ;
+
+                }
+                break;
+            case 18 :
+                // ooa.g:1:151: T_ASSIGNMENT
+                {
+                	mT_ASSIGNMENT(); if (state.failed) return ;
+
+                }
+                break;
+            case 19 :
+                // ooa.g:1:164: T_AUTOCONS
+                {
+                	mT_AUTOCONS(); if (state.failed) return ;
+
+                }
+                break;
+            case 20 :
+                // ooa.g:1:175: T_BAR
+                {
+                	mT_BAR(); if (state.failed) return ;
+
+                }
+                break;
+            case 21 :
+                // ooa.g:1:181: T_BOOL
+                {
+                	mT_BOOL(); if (state.failed) return ;
+
+                }
+                break;
+            case 22 :
+                // ooa.g:1:188: T_CBRL
+                {
+                	mT_CBRL(); if (state.failed) return ;
+
+                }
+                break;
+            case 23 :
+                // ooa.g:1:195: T_CBRR
+                {
+                	mT_CBRR(); if (state.failed) return ;
+
+                }
+                break;
+            case 24 :
+                // ooa.g:1:202: T_COLON
+                {
+                	mT_COLON(); if (state.failed) return ;
+
+                }
+                break;
+            case 25 :
+                // ooa.g:1:210: T_COMMA
+                {
+                	mT_COMMA(); if (state.failed) return ;
+
+                }
+                break;
+            case 26 :
+                // ooa.g:1:218: T_CONT
+                {
+                	mT_CONT(); if (state.failed) return ;
+
+                }
+                break;
+            case 27 :
+                // ooa.g:1:225: T_CHAR
+                {
+                	mT_CHAR(); if (state.failed) return ;
+
+                }
+                break;
+            case 28 :
+                // ooa.g:1:232: T_CTRL
+                {
+                	mT_CTRL(); if (state.failed) return ;
+
+                }
+                break;
+            case 29 :
+                // ooa.g:1:239: T_SYSTEM
+                {
+                	mT_SYSTEM(); if (state.failed) return ;
+
+                }
+                break;
+            case 30 :
+                // ooa.g:1:248: T_DO
+                {
+                	mT_DO(); if (state.failed) return ;
+
+                }
+                break;
+            case 31 :
+                // ooa.g:1:253: T_ELSE
+                {
+                	mT_ELSE(); if (state.failed) return ;
+
+                }
+                break;
+            case 32 :
+                // ooa.g:1:260: T_END
+                {
+                	mT_END(); if (state.failed) return ;
+
+                }
+                break;
+            case 33 :
+                // ooa.g:1:266: T_EQUAL
+                {
+                	mT_EQUAL(); if (state.failed) return ;
+
+                }
+                break;
+            case 34 :
+                // ooa.g:1:274: T_EXISTS
+                {
+                	mT_EXISTS(); if (state.failed) return ;
+
+                }
+                break;
+            case 35 :
+                // ooa.g:1:283: T_FLOAT
+                {
+                	mT_FLOAT(); if (state.failed) return ;
+
+                }
+                break;
+            case 36 :
+                // ooa.g:1:291: T_FORALL
+                {
+                	mT_FORALL(); if (state.failed) return ;
+
+                }
+                break;
+            case 37 :
+                // ooa.g:1:300: T_FALSE
+                {
+                	mT_FALSE(); if (state.failed) return ;
+
+                }
+                break;
+            case 38 :
+                // ooa.g:1:308: T_IF
+                {
+                	mT_IF(); if (state.failed) return ;
+
+                }
+                break;
+            case 39 :
+                // ooa.g:1:313: T_IN
+                {
+                	mT_IN(); if (state.failed) return ;
+
+                }
+                break;
+            case 40 :
+                // ooa.g:1:318: T_INT
+                {
+                	mT_INT(); if (state.failed) return ;
+
+                }
+                break;
+            case 41 :
+                // ooa.g:1:324: T_KILL
+                {
+                	mT_KILL(); if (state.failed) return ;
+
+                }
+                break;
+            case 42 :
+                // ooa.g:1:331: T_LIST
+                {
+                	mT_LIST(); if (state.failed) return ;
+
+                }
+                break;
+            case 43 :
+                // ooa.g:1:338: T_LPAREN
+                {
+                	mT_LPAREN(); if (state.failed) return ;
+
+                }
+                break;
+            case 44 :
+                // ooa.g:1:347: T_LSQPAREN
+                {
+                	mT_LSQPAREN(); if (state.failed) return ;
+
+                }
+                break;
+            case 45 :
+                // ooa.g:1:358: T_MAP
+                {
+                	mT_MAP(); if (state.failed) return ;
+
+                }
+                break;
+            case 46 :
+                // ooa.g:1:364: T_MAPS
+                {
+                	mT_MAPS(); if (state.failed) return ;
+
+                }
+                break;
+            case 47 :
+                // ooa.g:1:371: T_METHODS
+                {
+                	mT_METHODS(); if (state.failed) return ;
+
+                }
+                break;
+            case 48 :
+                // ooa.g:1:381: T_NEW
+                {
+                	mT_NEW(); if (state.failed) return ;
+
+                }
+                break;
+            case 49 :
+                // ooa.g:1:387: T_NIL
+                {
+                	mT_NIL(); if (state.failed) return ;
+
+                }
+                break;
+            case 50 :
+                // ooa.g:1:393: T_NONDET
+                {
+                	mT_NONDET(); if (state.failed) return ;
+
+                }
+                break;
+            case 51 :
+                // ooa.g:1:402: T_OBS
+                {
+                	mT_OBS(); if (state.failed) return ;
+
+                }
+                break;
+            case 52 :
+                // ooa.g:1:408: T_OD
+                {
+                	mT_OD(); if (state.failed) return ;
+
+                }
+                break;
+            case 53 :
+                // ooa.g:1:413: T_OF
+                {
+                	mT_OF(); if (state.failed) return ;
+
+                }
+                break;
+            case 54 :
+                // ooa.g:1:418: T_PRIO
+                {
+                	mT_PRIO(); if (state.failed) return ;
+
+                }
+                break;
+            case 55 :
+                // ooa.g:1:425: T_REQUIRES
+                {
+                	mT_REQUIRES(); if (state.failed) return ;
+
+                }
+                break;
+            case 56 :
+                // ooa.g:1:436: T_RPAREN
+                {
+                	mT_RPAREN(); if (state.failed) return ;
+
+                }
+                break;
+            case 57 :
+                // ooa.g:1:445: T_RSQPAREN
+                {
+                	mT_RSQPAREN(); if (state.failed) return ;
+
+                }
+                break;
+            case 58 :
+                // ooa.g:1:456: T_QUANTITY
+                {
+                	mT_QUANTITY(); if (state.failed) return ;
+
+                }
+                break;
+            case 59 :
+                // ooa.g:1:467: T_SELF
+                {
+                	mT_SELF(); if (state.failed) return ;
+
+                }
+                break;
+            case 60 :
+                // ooa.g:1:474: T_SET
+                {
+                	mT_SET(); if (state.failed) return ;
+
+                }
+                break;
+            case 61 :
+                // ooa.g:1:480: T_SEMICOLON
+                {
+                	mT_SEMICOLON(); if (state.failed) return ;
+
+                }
+                break;
+            case 62 :
+                // ooa.g:1:492: T_STATIC
+                {
+                	mT_STATIC(); if (state.failed) return ;
+
+                }
+                break;
+            case 63 :
+                // ooa.g:1:501: T_SKIP
+                {
+                	mT_SKIP(); if (state.failed) return ;
+
+                }
+                break;
+            case 64 :
+                // ooa.g:1:508: T_THEN
+                {
+                	mT_THEN(); if (state.failed) return ;
+
+                }
+                break;
+            case 65 :
+                // ooa.g:1:515: T_TRUE
+                {
+                	mT_TRUE(); if (state.failed) return ;
+
+                }
+                break;
+            case 66 :
+                // ooa.g:1:522: T_TO
+                {
+                	mT_TO(); if (state.failed) return ;
+
+                }
+                break;
+            case 67 :
+                // ooa.g:1:527: T_TYPES
+                {
+                	mT_TYPES(); if (state.failed) return ;
+
+                }
+                break;
+            case 68 :
+                // ooa.g:1:535: T_VAR
+                {
+                	mT_VAR(); if (state.failed) return ;
+
+                }
+                break;
+            case 69 :
+                // ooa.g:1:541: T_WITH
+                {
+                	mT_WITH(); if (state.failed) return ;
+
+                }
+                break;
+            case 70 :
+                // ooa.g:1:548: T_AND
+                {
+                	mT_AND(); if (state.failed) return ;
+
+                }
+                break;
+            case 71 :
+                // ooa.g:1:554: T_BIIMPLIES
+                {
+                	mT_BIIMPLIES(); if (state.failed) return ;
+
+                }
+                break;
+            case 72 :
+                // ooa.g:1:566: T_IMPLIES
+                {
+                	mT_IMPLIES(); if (state.failed) return ;
+
+                }
+                break;
+            case 73 :
+                // ooa.g:1:576: T_NOT
+                {
+                	mT_NOT(); if (state.failed) return ;
+
+                }
+                break;
+            case 74 :
+                // ooa.g:1:582: T_NOTEQUAL
+                {
+                	mT_NOTEQUAL(); if (state.failed) return ;
+
+                }
+                break;
+            case 75 :
+                // ooa.g:1:593: T_OR
+                {
+                	mT_OR(); if (state.failed) return ;
+
+                }
+                break;
+            case 76 :
+                // ooa.g:1:598: T_ABS
+                {
+                	mT_ABS(); if (state.failed) return ;
+
+                }
+                break;
+            case 77 :
+                // ooa.g:1:604: T_DIV
+                {
+                	mT_DIV(); if (state.failed) return ;
+
+                }
+                break;
+            case 78 :
+                // ooa.g:1:610: T_GREATER
+                {
+                	mT_GREATER(); if (state.failed) return ;
+
+                }
+                break;
+            case 79 :
+                // ooa.g:1:620: T_GREATEREQUAL
+                {
+                	mT_GREATEREQUAL(); if (state.failed) return ;
+
+                }
+                break;
+            case 80 :
+                // ooa.g:1:635: T_IDIV
+                {
+                	mT_IDIV(); if (state.failed) return ;
+
+                }
+                break;
+            case 81 :
+                // ooa.g:1:642: T_LESS
+                {
+                	mT_LESS(); if (state.failed) return ;
+
+                }
+                break;
+            case 82 :
+                // ooa.g:1:649: T_LESSEQUAL
+                {
+                	mT_LESSEQUAL(); if (state.failed) return ;
+
+                }
+                break;
+            case 83 :
+                // ooa.g:1:661: T_MOD
+                {
+                	mT_MOD(); if (state.failed) return ;
+
+                }
+                break;
+            case 84 :
+                // ooa.g:1:667: T_POW
+                {
+                	mT_POW(); if (state.failed) return ;
+
+                }
+                break;
+            case 85 :
+                // ooa.g:1:673: T_PROD
+                {
+                	mT_PROD(); if (state.failed) return ;
+
+                }
+                break;
+            case 86 :
+                // ooa.g:1:680: T_DERIV
+                {
+                	mT_DERIV(); if (state.failed) return ;
+
+                }
+                break;
+            case 87 :
+                // ooa.g:1:688: T_CARD
+                {
+                	mT_CARD(); if (state.failed) return ;
+
+                }
+                break;
+            case 88 :
+                // ooa.g:1:695: T_CONC
+                {
+                	mT_CONC(); if (state.failed) return ;
+
+                }
+                break;
+            case 89 :
+                // ooa.g:1:702: T_DCONC
+                {
+                	mT_DCONC(); if (state.failed) return ;
+
+                }
+                break;
+            case 90 :
+                // ooa.g:1:710: T_DIFF
+                {
+                	mT_DIFF(); if (state.failed) return ;
+
+                }
+                break;
+            case 91 :
+                // ooa.g:1:717: T_DINTER
+                {
+                	mT_DINTER(); if (state.failed) return ;
+
+                }
+                break;
+            case 92 :
+                // ooa.g:1:726: T_DUNION
+                {
+                	mT_DUNION(); if (state.failed) return ;
+
+                }
+                break;
+            case 93 :
+                // ooa.g:1:735: T_ELEMS
+                {
+                	mT_ELEMS(); if (state.failed) return ;
+
+                }
+                break;
+            case 94 :
+                // ooa.g:1:743: T_HEAD
+                {
+                	mT_HEAD(); if (state.failed) return ;
+
+                }
+                break;
+            case 95 :
+                // ooa.g:1:750: T_INDS
+                {
+                	mT_INDS(); if (state.failed) return ;
+
+                }
+                break;
+            case 96 :
+                // ooa.g:1:757: T_INTER
+                {
+                	mT_INTER(); if (state.failed) return ;
+
+                }
+                break;
+            case 97 :
+                // ooa.g:1:765: T_LEN
+                {
+                	mT_LEN(); if (state.failed) return ;
+
+                }
+                break;
+            case 98 :
+                // ooa.g:1:771: T_SEQMOD_MAPOVERRIDE
+                {
+                	mT_SEQMOD_MAPOVERRIDE(); if (state.failed) return ;
+
+                }
+                break;
+            case 99 :
+                // ooa.g:1:792: T_SUBSET
+                {
+                	mT_SUBSET(); if (state.failed) return ;
+
+                }
+                break;
+            case 100 :
+                // ooa.g:1:801: T_TAIL
+                {
+                	mT_TAIL(); if (state.failed) return ;
+
+                }
+                break;
+            case 101 :
+                // ooa.g:1:808: T_UNION
+                {
+                	mT_UNION(); if (state.failed) return ;
+
+                }
+                break;
+            case 102 :
+                // ooa.g:1:816: T_FOLDLR
+                {
+                	mT_FOLDLR(); if (state.failed) return ;
+
+                }
+                break;
+            case 103 :
+                // ooa.g:1:825: T_FOLDRL
+                {
+                	mT_FOLDRL(); if (state.failed) return ;
+
+                }
+                break;
+            case 104 :
+                // ooa.g:1:834: T_DOM
+                {
+                	mT_DOM(); if (state.failed) return ;
+
+                }
+                break;
+            case 105 :
+                // ooa.g:1:840: T_DOMRESBY
+                {
+                	mT_DOMRESBY(); if (state.failed) return ;
+
+                }
+                break;
+            case 106 :
+                // ooa.g:1:851: T_DOMRESTO
+                {
+                	mT_DOMRESTO(); if (state.failed) return ;
+
+                }
+                break;
+            case 107 :
+                // ooa.g:1:862: T_RNG
+                {
+                	mT_RNG(); if (state.failed) return ;
+
+                }
+                break;
+            case 108 :
+                // ooa.g:1:868: T_RNGRESBY
+                {
+                	mT_RNGRESBY(); if (state.failed) return ;
+
+                }
+                break;
+            case 109 :
+                // ooa.g:1:879: T_RNGRESTO
+                {
+                	mT_RNGRESTO(); if (state.failed) return ;
+
+                }
+                break;
+            case 110 :
+                // ooa.g:1:890: T_MERGE
+                {
+                	mT_MERGE(); if (state.failed) return ;
+
+                }
+                break;
+            case 111 :
+                // ooa.g:1:898: T_MUNION
+                {
+                	mT_MUNION(); if (state.failed) return ;
+
+                }
+                break;
+            case 112 :
+                // ooa.g:1:907: T_CONSTS
+                {
+                	mT_CONSTS(); if (state.failed) return ;
+
+                }
+                break;
+            case 113 :
+                // ooa.g:1:916: T_INFTY
+                {
+                	mT_INFTY(); if (state.failed) return ;
+
+                }
+                break;
+            case 114 :
+                // ooa.g:1:924: FLOAT_OR_INT_OR_RANGE
+                {
+                	mFLOAT_OR_INT_OR_RANGE(); if (state.failed) return ;
+
+                }
+                break;
+            case 115 :
+                // ooa.g:1:946: T_IDENTIFIER
+                {
+                	mT_IDENTIFIER(); if (state.failed) return ;
+
+                }
+                break;
+
+        }
+
+    }
+
+    // $ANTLR start "synpred1_ooa"
+    public void synpred1_ooa_fragment() {
+        // ooa.g:1009:9: ( '\"' '\"' )
+        // ooa.g:1009:11: '\"' '\"'
+        {
+        	Match('\"'); if (state.failed) return ;
+        	Match('\"'); if (state.failed) return ;
+
+        }
+    }
+    // $ANTLR end "synpred1_ooa"
+
+    // $ANTLR start "synpred2_ooa"
+    public void synpred2_ooa_fragment() {
+        // ooa.g:1164:5: ( T_POINT T_POINT )
+        // ooa.g:1164:6: T_POINT T_POINT
+        {
+        	mT_POINT(); if (state.failed) return ;
+        	mT_POINT(); if (state.failed) return ;
+
+        }
+    }
+    // $ANTLR end "synpred2_ooa"
+
+    // $ANTLR start "synpred3_ooa"
+    public void synpred3_ooa_fragment() {
+        // ooa.g:1165:6: ( T_POINT T_DIGIT )
+        // ooa.g:1165:7: T_POINT T_DIGIT
+        {
+        	mT_POINT(); if (state.failed) return ;
+        	mT_DIGIT(); if (state.failed) return ;
+
+        }
+    }
+    // $ANTLR end "synpred3_ooa"
+
+   	public bool synpred2_ooa() 
+   	{
+   	    state.backtracking++;
+   	    int start = input.Mark();
+   	    try 
+   	    {
+   	        synpred2_ooa_fragment(); // can never throw exception
+   	    }
+   	    catch (RecognitionException re) 
+   	    {
+   	        Console.Error.WriteLine("impossible: "+re);
+   	    }
+   	    bool success = !state.failed;
+   	    input.Rewind(start);
+   	    state.backtracking--;
+   	    state.failed = false;
+   	    return success;
+   	}
+   	public bool synpred1_ooa() 
+   	{
+   	    state.backtracking++;
+   	    int start = input.Mark();
+   	    try 
+   	    {
+   	        synpred1_ooa_fragment(); // can never throw exception
+   	    }
+   	    catch (RecognitionException re) 
+   	    {
+   	        Console.Error.WriteLine("impossible: "+re);
+   	    }
+   	    bool success = !state.failed;
+   	    input.Rewind(start);
+   	    state.backtracking--;
+   	    state.failed = false;
+   	    return success;
+   	}
+   	public bool synpred3_ooa() 
+   	{
+   	    state.backtracking++;
+   	    int start = input.Mark();
+   	    try 
+   	    {
+   	        synpred3_ooa_fragment(); // can never throw exception
+   	    }
+   	    catch (RecognitionException re) 
+   	    {
+   	        Console.Error.WriteLine("impossible: "+re);
+   	    }
+   	    bool success = !state.failed;
+   	    input.Rewind(start);
+   	    state.backtracking--;
+   	    state.failed = false;
+   	    return success;
+   	}
+
+
+    protected DFA16 dfa16;
+	private void InitializeCyclicDFAs()
+	{
+	    this.dfa16 = new DFA16(this);
+	}
+
+    const string DFA16_eotS =
+        "\x01\uffff\x01\x30\x01\x32\x01\x2e\x01\uffff\x05\x2e\x01\x4e\x01"+
+        "\uffff\x01\x51\x06\uffff\x02\x2e\x01\x5a\x03\x2e\x01\uffff\x01\x62"+
+        "\x01\x2e\x01\x2d\x03\x2e\x02\uffff\x03\x2e\x01\x7d\x01\x7f\x01\u0081"+
+        "\x02\uffff\x01\x2e\x01\x2d\x01\x2e\x06\uffff\x02\x2e\x01\u0087\x0c"+
+        "\x2e\x01\u009b\x01\u009c\x01\x2e\x01\u009f\x01\x2e\x01\u00a2\x01"+
+        "\x2e\x02\uffff\x01\u00a5\x06\uffff\x07\x2e\x02\uffff\x06\x2e\x02"+
+        "\uffff\x04\x2e\x02\uffff\x04\x2e\x01\u00bd\x01\u00be\x01\u00bf\x04"+
+        "\x2e\x01\u00c4\x01\x2e\x01\u00c6\x02\x2e\x01\u00ca\x08\uffff\x01"+
+        "\u00cb\x01\uffff\x03\x2e\x01\uffff\x01\x2e\x01\u00d0\x02\x2e\x01"+
+        "\u00d3\x07\x2e\x01\u00db\x02\x2e\x01\u00de\x01\u00e0\x01\x2e\x01"+
+        "\x68\x02\uffff\x01\u00e2\x01\u00e3\x01\uffff\x01\u00e4\x01\x2e\x01"+
+        "\uffff\x01\x2e\x02\uffff\x01\x2e\x01\u00e8\x04\x2e\x01\u00ee\x06"+
+        "\x2e\x01\u00f5\x01\u00f6\x02\x2e\x01\u00f9\x01\x2e\x01\u00fb\x01"+
+        "\u00fc\x01\u00fd\x01\u00fe\x03\uffff\x01\x2e\x01\u0100\x02\x2e\x01"+
+        "\uffff\x01\x2e\x01\uffff\x01\u0104\x01\x2e\x03\uffff\x02\x2e\x01"+
+        "\u0108\x01\x2e\x01\uffff\x02\x2e\x01\uffff\x01\u010c\x01\u010d\x04"+
+        "\x2e\x01\u0112\x01\uffff\x01\u0113\x01\x2e\x01\uffff\x01\x2e\x01"+
+        "\uffff\x01\u0116\x03\uffff\x02\x2e\x01\u0119\x01\uffff\x01\u011a"+
+        "\x01\u011b\x01\x2e\x01\u011d\x01\x2e\x01\uffff\x04\x2e\x01\u0123"+
+        "\x01\u0124\x02\uffff\x02\x2e\x01\uffff\x01\x2e\x04\uffff\x01\x2e"+
+        "\x01\uffff\x01\u0129\x01\u012a\x01\x2e\x01\uffff\x01\u012c\x01\x2e"+
+        "\x01\u012e\x01\uffff\x01\u012f\x02\x2e\x02\uffff\x04\x2e\x02\uffff"+
+        "\x01\x2e\x01\u0137\x01\uffff\x02\x2e\x03\uffff\x01\x2e\x01\uffff"+
+        "\x01\u013b\x01\x2e\x01\u013d\x01\x2e\x01\u013f\x02\uffff\x01\x2e"+
+        "\x01\u0141\x02\x2e\x02\uffff\x01\u0144\x01\uffff\x01\u0145\x02\uffff"+
+        "\x02\x2e\x01\u0148\x01\u0149\x01\u014a\x01\u014b\x01\u014c\x01\uffff"+
+        "\x01\u014d\x01\u014e\x01\u014f\x01\uffff\x01\u0150\x01\uffff\x01"+
+        "\u0151\x01\uffff\x01\x2e\x01\uffff\x01\u0153\x01\x2e\x02\uffff\x01"+
+        "\u0155\x01\x2e\x0a\uffff\x01\u0157\x01\uffff\x01\x2e\x01\uffff\x01"+
+        "\u0159\x01\uffff\x01\u015a\x02\uffff";
+    const string DFA16_eofS =
+        "\u015b\uffff";
+    const string DFA16_minS =
+        "\x01\x09\x01\x5b\x01\x7c\x01\x65\x01\uffff\x01\x62\x01\x73\x01"+
+        "\x65\x01\x66\x01\x65\x01\x2d\x01\uffff\x01\x2a\x06\uffff\x01\x61"+
+        "\x01\x6c\x01\x3e\x01\x61\x01\x69\x01\x65\x01\uffff\x01\x5d\x01\x61"+
+        "\x01\x3e\x01\x65\x01\x62\x01\x65\x02\uffff\x01\x68\x01\x61\x01\x69"+
+        "\x01\x2d\x01\x3d\x01\x2a\x02\uffff\x01\x64\x01\x2b\x01\x6e\x06\uffff"+
+        "\x01\x67\x01\x6f\x01\x24\x01\x6f\x02\x74\x01\x64\x02\x61\x01\x70"+
+        "\x01\x61\x01\x73\x01\x6c\x01\x69\x01\x62\x02\x24\x01\x63\x01\x24"+
+        "\x01\x6e\x01\x24\x01\x6e\x02\uffff\x01\x3a\x06\uffff\x01\x61\x02"+
+        "\x72\x01\x6e\x01\x65\x01\x64\x01\x69\x02\uffff\x01\x6f\x01\x72\x02"+
+        "\x6c\x01\x73\x01\x6e\x02\uffff\x01\x70\x01\x72\x01\x64\x01\x6e\x02"+
+        "\uffff\x01\x77\x01\x6c\x01\x74\x01\x73\x03\x24\x01\x71\x01\x67\x01"+
+        "\x65\x01\x75\x01\x24\x01\x70\x01\x24\x01\x72\x01\x74\x01\x3e\x08"+
+        "\uffff\x01\x24\x01\uffff\x02\x69\x01\x6c\x01\uffff\x01\x72\x01\x24"+
+        "\x01\x69\x01\x6f\x01\x24\x02\x6c\x02\x61\x02\x74\x01\x66\x01\x24"+
+        "\x01\x70\x01\x73\x02\x24\x01\x73\x01\x24\x02\uffff\x02\x24\x01\uffff"+
+        "\x01\x24\x01\x74\x01\uffff\x01\x69\x02\uffff\x01\x72\x01\x24\x01"+
+        "\x64\x01\x63\x01\x65\x01\x6d\x01\x24\x01\x73\x02\x61\x01\x73\x01"+
+        "\x6c\x01\x74\x02\x24\x01\x68\x01\x67\x01\x24\x01\x69\x04\x24\x03"+
+        "\uffff\x01\x75\x01\x24\x01\x6e\x01\x65\x01\uffff\x01\x65\x01\uffff"+
+        "\x01\x24\x01\x68\x03\uffff\x01\x6f\x01\x6e\x01\x24\x01\x74\x01\uffff"+
+        "\x01\x6f\x01\x63\x01\uffff\x02\x24\x01\x63\x01\x64\x01\x69\x01\x65"+
+        "\x01\x24\x01\uffff\x01\x24\x01\x65\x01\uffff\x01\x72\x01\uffff\x01"+
+        "\x24\x03\uffff\x01\x65\x01\x6f\x01\x24\x01\uffff\x02\x24\x01\x74"+
+        "\x01\x24\x01\x73\x01\uffff\x02\x74\x01\x6c\x01\x65\x02\x24\x02\uffff"+
+        "\x01\x6f\x01\x65\x01\uffff\x01\x6f\x04\uffff\x01\x69\x01\uffff\x02"+
+        "\x24\x01\x73\x01\uffff\x01\x24\x01\x6e\x01\x24\x01\uffff\x01\x24"+
+        "\x01\x6e\x01\x6f\x02\uffff\x01\x65\x01\x79\x01\x63\x01\x6d\x02\uffff"+
+        "\x01\x74\x01\x24\x01\uffff\x01\x72\x01\x6e\x03\uffff\x01\x73\x01"+
+        "\uffff\x01\x24\x01\x73\x01\x24\x01\x6c\x01\x24\x02\uffff\x01\x64"+
+        "\x01\x24\x01\x6e\x01\x72\x02\uffff\x01\x24\x01\uffff\x01\x24\x02"+
+        "\uffff\x01\x73\x01\x6e\x05\x24\x01\uffff\x03\x24\x01\uffff\x01\x24"+
+        "\x01\uffff\x01\x24\x01\uffff\x01\x73\x01\uffff\x01\x24\x01\x65\x02"+
+        "\uffff\x01\x24\x01\x73\x0a\uffff\x01\x24\x01\uffff\x01\x73\x01\uffff"+
+        "\x01\x24\x01\uffff\x01\x24\x02\uffff";
+    const string DFA16_maxS =
+        "\x01\x7d\x01\x5b\x01\x7c\x01\x6f\x01\uffff\x01\x75\x01\x76\x01"+
+        "\x79\x01\x6e\x01\x75\x01\x3e\x01\uffff\x01\x2f\x06\uffff\x01\x74"+
+        "\x01\x78\x01\x3e\x01\x6f\x02\x69\x01\uffff\x01\x5d\x01\x75\x01\x69"+
+        "\x01\x6f\x01\x72\x01\x6e\x02\uffff\x01\x79\x01\x61\x01\x69\x01\x3e"+
+        "\x01\x3d\x01\x2a\x02\uffff\x01\x64\x01\x69\x01\x6e\x06\uffff\x01"+
+        "\x67\x01\x6f\x01\x7a\x01\x73\x02\x74\x01\x64\x02\x61\x01\x70\x01"+
+        "\x65\x01\x73\x01\x74\x01\x69\x01\x62\x02\x7a\x01\x63\x01\x7a\x01"+
+        "\x76\x01\x7a\x01\x6e\x02\uffff\x01\x3a\x06\uffff\x01\x61\x02\x72"+
+        "\x01\x6e\x01\x73\x01\x64\x01\x69\x02\uffff\x01\x6f\x01\x72\x02\x6c"+
+        "\x01\x73\x01\x6e\x02\uffff\x01\x70\x01\x74\x01\x64\x01\x6e\x02\uffff"+
+        "\x01\x77\x01\x6c\x01\x74\x01\x73\x03\x7a\x01\x71\x01\x67\x01\x65"+
+        "\x01\x75\x01\x7a\x01\x70\x01\x7a\x01\x72\x01\x74\x01\x3e\x08\uffff"+
+        "\x01\x7a\x01\uffff\x02\x69\x01\x6c\x01\uffff\x01\x72\x01\x7a\x01"+
+        "\x69\x01\x6f\x01\x7a\x02\x6c\x02\x61\x02\x74\x01\x66\x01\x7a\x01"+
+        "\x70\x01\x73\x02\x7a\x01\x73\x01\x7a\x02\uffff\x02\x7a\x01\uffff"+
+        "\x01\x7a\x01\x74\x01\uffff\x01\x69\x02\uffff\x01\x72\x01\x7a\x01"+
+        "\x64\x01\x73\x01\x65\x01\x6d\x01\x7a\x01\x73\x02\x61\x01\x73\x01"+
+        "\x6c\x01\x74\x02\x7a\x01\x68\x01\x67\x01\x7a\x01\x69\x04\x7a\x03"+
+        "\uffff\x01\x75\x01\x7a\x01\x6e\x01\x65\x01\uffff\x01\x65\x01\uffff"+
+        "\x01\x7a\x01\x68\x03\uffff\x01\x6f\x01\x6e\x01\x7a\x01\x74\x01\uffff"+
+        "\x01\x6f\x01\x63\x01\uffff\x02\x7a\x01\x63\x01\x64\x01\x69\x01\x65"+
+        "\x01\x7a\x01\uffff\x01\x7a\x01\x65\x01\uffff\x01\x72\x01\uffff\x01"+
+        "\x7a\x03\uffff\x01\x65\x01\x6f\x01\x7a\x01\uffff\x02\x7a\x01\x74"+
+        "\x01\x7a\x01\x73\x01\uffff\x02\x74\x01\x6c\x01\x65\x02\x7a\x02\uffff"+
+        "\x01\x6f\x01\x65\x01\uffff\x01\x6f\x04\uffff\x01\x69\x01\uffff\x02"+
+        "\x7a\x01\x73\x01\uffff\x01\x7a\x01\x6e\x01\x7a\x01\uffff\x01\x7a"+
+        "\x01\x6e\x01\x6f\x02\uffff\x01\x65\x01\x79\x01\x63\x01\x6d\x02\uffff"+
+        "\x01\x74\x01\x7a\x01\uffff\x01\x72\x01\x6e\x03\uffff\x01\x73\x01"+
+        "\uffff\x01\x7a\x01\x73\x01\x7a\x01\x6c\x01\x7a\x02\uffff\x01\x64"+
+        "\x01\x7a\x01\x6e\x01\x72\x02\uffff\x01\x7a\x01\uffff\x01\x7a\x02"+
+        "\uffff\x01\x73\x01\x6e\x05\x7a\x01\uffff\x03\x7a\x01\uffff\x01\x7a"+
+        "\x01\uffff\x01\x7a\x01\uffff\x01\x73\x01\uffff\x01\x7a\x01\x65\x02"+
+        "\uffff\x01\x7a\x01\x73\x0a\uffff\x01\x7a\x01\uffff\x01\x73\x01\uffff"+
+        "\x01\x7a\x01\uffff\x01\x7a\x02\uffff";
+    const string DFA16_acceptS =
+        "\x04\uffff\x01\x04\x06\uffff\x01\x0b\x01\uffff\x01\x0d\x01\x0e"+
+        "\x01\x0f\x01\x16\x01\x17\x01\x19\x06\uffff\x01\x2b\x06\uffff\x01"+
+        "\x38\x01\x3d\x06\uffff\x01\x58\x01\x5a\x03\uffff\x01\x72\x01\x73"+
+        "\x01\x01\x01\x14\x01\x02\x01\x39\x16\uffff\x01\x0a\x01\x12\x01\uffff"+
+        "\x01\x67\x01\x6c\x01\x18\x01\x0c\x01\x36\x01\x4d\x07\uffff\x01\x48"+
+        "\x01\x21\x06\uffff\x01\x32\x01\x2c\x04\uffff\x01\x2e\x01\x71\x11"+
+        "\uffff\x01\x4a\x01\x69\x01\x6a\x01\x51\x01\x4f\x01\x4e\x01\x54\x01"+
+        "\x55\x01\uffff\x01\x62\x03\uffff\x01\x05\x13\uffff\x01\x27\x01\x26"+
+        "\x02\uffff\x01\x1e\x02\uffff\x01\x56\x01\uffff\x01\x66\x01\x6d\x17"+
+        "\uffff\x01\x34\x01\x35\x01\x4b\x04\uffff\x01\x42\x01\uffff\x01\x64"+
+        "\x02\uffff\x01\x47\x01\x52\x01\x5e\x04\uffff\x01\x4c\x02\uffff\x01"+
+        "\x46\x07\uffff\x01\x3c\x02\uffff\x01\x08\x01\uffff\x01\x28\x01\uffff"+
+        "\x01\x09\x01\x68\x01\x50\x03\uffff\x01\x1c\x05\uffff\x01\x20\x06"+
+        "\uffff\x01\x61\x01\x2d\x02\uffff\x01\x53\x01\uffff\x01\x30\x01\x31"+
+        "\x01\x49\x01\x33\x01\uffff\x01\x6b\x03\uffff\x01\x44\x03\uffff\x01"+
+        "\x15\x03\uffff\x01\x06\x01\x1a\x04\uffff\x01\x3b\x01\x3f\x02\uffff"+
+        "\x01\x5f\x02\uffff\x01\x1b\x01\x57\x01\x59\x01\uffff\x01\x1f\x05"+
+        "\uffff\x01\x29\x01\x2a\x04\uffff\x01\x40\x01\x41\x01\uffff\x01\x45"+
+        "\x01\uffff\x01\x03\x01\x10\x07\uffff\x01\x60\x03\uffff\x01\x5d\x01"+
+        "\uffff\x01\x23\x01\uffff\x01\x25\x01\uffff\x01\x6e\x02\uffff\x01"+
+        "\x43\x01\x65\x02\uffff\x01\x3a\x01\x07\x01\x3e\x01\x1d\x01\x63\x01"+
+        "\x5b\x01\x5c\x01\x70\x01\x22\x01\x24\x01\uffff\x01\x6f\x01\uffff"+
+        "\x01\x11\x01\uffff\x01\x2f\x01\uffff\x01\x13\x01\x37";
+    const string DFA16_specialS =
+        "\u015b\uffff}>";
+    static readonly string[] DFA16_transitionS = {
+            "\x02\x0b\x01\uffff\x02\x0b\x12\uffff\x01\x0b\x01\uffff\x01"+
+            "\x0f\x01\x0d\x01\x2e\x01\uffff\x01\x04\x01\x0e\x01\x19\x01\x20"+
+            "\x01\x27\x01\x2b\x01\x12\x01\x1c\x01\x2d\x01\x0c\x0a\x2d\x01"+
+            "\x0a\x01\x21\x01\x25\x01\x15\x01\x26\x02\uffff\x1a\x2e\x01\x1a"+
+            "\x01\x29\x01\x02\x01\x28\x01\x2e\x01\uffff\x01\x05\x01\x03\x01"+
+            "\x13\x01\x09\x01\x14\x01\x16\x01\x2e\x01\x2a\x01\x08\x01\x2e"+
+            "\x01\x17\x01\x18\x01\x1b\x01\x1d\x01\x1e\x01\x2e\x01\x06\x01"+
+            "\x1f\x01\x07\x01\x22\x01\x2c\x01\x23\x01\x24\x03\x2e\x01\x10"+
+            "\x01\x01\x01\x11",
+            "\x01\x2f",
+            "\x01\x31",
+            "\x01\x33\x09\uffff\x01\x34",
+            "",
+            "\x01\x36\x01\x37\x0a\uffff\x01\x39\x04\uffff\x01\x35\x01\uffff"+
+            "\x01\x38",
+            "\x01\x3c\x01\uffff\x01\x3b\x01\x3a",
+            "\x01\x3f\x05\uffff\x01\x40\x08\uffff\x01\x3d\x01\x41\x03\uffff"+
+            "\x01\x3e",
+            "\x01\x43\x07\uffff\x01\x42",
+            "\x01\x44\x03\uffff\x01\x46\x05\uffff\x01\x45\x04\uffff\x01"+
+            "\x47\x01\x48",
+            "\x01\x4d\x0c\uffff\x01\x49\x01\uffff\x01\x4c\x01\x4a\x01\x4b",
+            "",
+            "\x01\x4f\x04\uffff\x01\x50",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "\x01\x54\x06\uffff\x01\x52\x06\uffff\x01\x55\x04\uffff\x01"+
+            "\x53",
+            "\x01\x56\x01\uffff\x01\x57\x09\uffff\x01\x58",
+            "\x01\x59",
+            "\x01\x5d\x0a\uffff\x01\x5b\x02\uffff\x01\x5c",
+            "\x01\x5e",
+            "\x01\x60\x03\uffff\x01\x5f",
+            "",
+            "\x01\x61",
+            "\x01\x63\x03\uffff\x01\x64\x09\uffff\x01\x65\x05\uffff\x01"+
+            "\x66",
+            "\x01\x67\x2a\uffff\x01\x68",
+            "\x01\x69\x03\uffff\x01\x6a\x05\uffff\x01\x6b",
+            "\x01\x6c\x01\uffff\x01\x6d\x01\uffff\x01\x6e\x0b\uffff\x01"+
+            "\x6f",
+            "\x01\x70\x08\uffff\x01\x71",
+            "",
+            "",
+            "\x01\x72\x03\uffff\x01\x76\x02\uffff\x01\x74\x02\uffff\x01"+
+            "\x73\x06\uffff\x01\x75",
+            "\x01\x77",
+            "\x01\x78",
+            "\x01\x7b\x0c\uffff\x01\x7c\x02\uffff\x01\x79\x01\x7a",
+            "\x01\x7e",
+            "\x01\u0080",
+            "",
+            "",
+            "\x01\u0082",
+            "\x01\u0083\x3d\uffff\x01\x68",
+            "\x01\u0084",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "\x01\u0085",
+            "\x01\u0086",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u0088\x03\uffff\x01\u0089",
+            "\x01\u008a",
+            "\x01\u008b",
+            "\x01\u008c",
+            "\x01\u008d",
+            "\x01\u008e",
+            "\x01\u008f",
+            "\x01\u0091\x03\uffff\x01\u0090",
+            "\x01\u0092",
+            "\x01\u0093\x07\uffff\x01\u0094",
+            "\x01\u0095",
+            "\x01\u0096",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x02\x2e\x01\u0097\x01\u0099\x01\x2e\x01\u009a"+
+            "\x0d\x2e\x01\u0098\x06\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u009d",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x0c\x2e\x01\u009e\x0d\x2e",
+            "\x01\u00a1\x07\uffff\x01\u00a0",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00a3",
+            "",
+            "",
+            "\x01\u00a4",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "\x01\u00a6",
+            "\x01\u00a7",
+            "\x01\u00a8",
+            "\x01\u00a9",
+            "\x01\u00ab\x0d\uffff\x01\u00aa",
+            "\x01\u00ac",
+            "\x01\u00ad",
+            "",
+            "",
+            "\x01\u00ae",
+            "\x01\u00af",
+            "\x01\u00b0",
+            "\x01\u00b1",
+            "\x01\u00b2",
+            "\x01\u00b3",
+            "",
+            "",
+            "\x01\u00b4",
+            "\x01\u00b6\x01\uffff\x01\u00b5",
+            "\x01\u00b7",
+            "\x01\u00b8",
+            "",
+            "",
+            "\x01\u00b9",
+            "\x01\u00ba",
+            "\x01\u00bb",
+            "\x01\u00bc",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00c0",
+            "\x01\u00c1",
+            "\x01\u00c2",
+            "\x01\u00c3",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00c5",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00c7",
+            "\x01\u00c8",
+            "\x01\u00c9",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\u00cc",
+            "\x01\u00cd",
+            "\x01\u00ce",
+            "",
+            "\x01\u00cf",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00d1",
+            "\x01\u00d2",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00d4",
+            "\x01\u00d5",
+            "\x01\u00d6",
+            "\x01\u00d7",
+            "\x01\u00d8",
+            "\x01\u00d9",
+            "\x01\u00da",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00dc",
+            "\x01\u00dd",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x04\x2e\x01\u00df\x15\x2e",
+            "\x01\u00e1",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00e5",
+            "",
+            "\x01\u00e6",
+            "",
+            "",
+            "\x01\u00e7",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00e9",
+            "\x01\u00ea\x0f\uffff\x01\u00eb",
+            "\x01\u00ec",
+            "\x01\u00ed",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00ef",
+            "\x01\u00f0",
+            "\x01\u00f1",
+            "\x01\u00f2",
+            "\x01\u00f3",
+            "\x01\u00f4",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00f7",
+            "\x01\u00f8",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u00fa",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "",
+            "",
+            "\x01\u00ff",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u0101",
+            "\x01\u0102",
+            "",
+            "\x01\u0103",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u0105",
+            "",
+            "",
+            "",
+            "\x01\u0106",
+            "\x01\u0107",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u0109",
+            "",
+            "\x01\u010a",
+            "\x01\u010b",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u010e",
+            "\x01\u010f",
+            "\x01\u0110",
+            "\x01\u0111",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u0114",
+            "",
+            "\x01\u0115",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "",
+            "",
+            "\x01\u0117",
+            "\x01\u0118",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u011c",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u011e",
+            "",
+            "\x01\u011f",
+            "\x01\u0120",
+            "\x01\u0121",
+            "\x01\u0122",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "",
+            "\x01\u0125",
+            "\x01\u0126",
+            "",
+            "\x01\u0127",
+            "",
+            "",
+            "",
+            "",
+            "\x01\u0128",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u012b",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u012d",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u0130",
+            "\x01\u0131",
+            "",
+            "",
+            "\x01\u0132",
+            "\x01\u0133",
+            "\x01\u0134",
+            "\x01\u0135",
+            "",
+            "",
+            "\x01\u0136",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\u0138",
+            "\x01\u0139",
+            "",
+            "",
+            "",
+            "\x01\u013a",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u013c",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u013e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "",
+            "\x01\u0140",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u0142",
+            "\x01\u0143",
+            "",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "",
+            "\x01\u0146",
+            "\x01\u0147",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\u0152",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u0154",
+            "",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "\x01\u0156",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\u0158",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            "\x01\x2e\x0b\uffff\x0a\x2e\x07\uffff\x1a\x2e\x04\uffff\x01"+
+            "\x2e\x01\uffff\x1a\x2e",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA16_eot = DFA.UnpackEncodedString(DFA16_eotS);
+    static readonly short[] DFA16_eof = DFA.UnpackEncodedString(DFA16_eofS);
+    static readonly char[] DFA16_min = DFA.UnpackEncodedStringToUnsignedChars(DFA16_minS);
+    static readonly char[] DFA16_max = DFA.UnpackEncodedStringToUnsignedChars(DFA16_maxS);
+    static readonly short[] DFA16_accept = DFA.UnpackEncodedString(DFA16_acceptS);
+    static readonly short[] DFA16_special = DFA.UnpackEncodedString(DFA16_specialS);
+    static readonly short[][] DFA16_transition = DFA.UnpackEncodedStringArray(DFA16_transitionS);
+
+    protected class DFA16 : DFA
+    {
+        public DFA16(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 16;
+            this.eot = DFA16_eot;
+            this.eof = DFA16_eof;
+            this.min = DFA16_min;
+            this.max = DFA16_max;
+            this.accept = DFA16_accept;
+            this.special = DFA16_special;
+            this.transition = DFA16_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "1:1: Tokens : ( T__117 | T__118 | T__119 | T__120 | T__121 | T__122 | T__123 | T__124 | T__125 | T__126 | T_WS | T_COMMENT | LINE_COMMENT | T_PRIMED | T_STRINGLITERAL | T_ABORT | T_ACTIONS | T_ASSIGNMENT | T_AUTOCONS | T_BAR | T_BOOL | T_CBRL | T_CBRR | T_COLON | T_COMMA | T_CONT | T_CHAR | T_CTRL | T_SYSTEM | T_DO | T_ELSE | T_END | T_EQUAL | T_EXISTS | T_FLOAT | T_FORALL | T_FALSE | T_IF | T_IN | T_INT | T_KILL | T_LIST | T_LPAREN | T_LSQPAREN | T_MAP | T_MAPS | T_METHODS | T_NEW | T_NIL | T_NONDET | T_OBS | T_OD | T_OF | T_PRIO | T_REQUIRES | T_RPAREN | T_RSQPAREN | T_QUANTITY | T_SELF | T_SET | T_SEMICOLON | T_STATIC | T_SKIP | T_THEN | T_TRUE | T_TO | T_TYPES | T_VAR | T_WITH | T_AND | T_BIIMPLIES | T_IMPLIES | T_NOT | T_NOTEQUAL | T_OR | T_ABS | T_DIV | T_GREATER | T_GREATEREQUAL | T_IDIV | T_LESS | T_LESSEQUAL | T_MOD | T_POW | T_PROD | T_DERIV | T_CARD | T_CONC | T_DCONC | T_DIFF | T_DINTER | T_DUNION | T_ELEMS | T_HEAD | T_INDS | T_INTER | T_LEN | T_SEQMOD_MAPOVERRIDE | T_SUBSET | T_TAIL | T_UNION | T_FOLDLR | T_FOLDRL | T_DOM | T_DOMRESBY | T_DOMRESTO | T_RNG | T_RNGRESBY | T_RNGRESTO | T_MERGE | T_MUNION | T_CONSTS | T_INFTY | FLOAT_OR_INT_OR_RANGE | T_IDENTIFIER );"; }
+        }
+
+    }
+
+ 
+    
+}
+}
\ No newline at end of file
Index: branches/compiler/cSharp/ooasCompiler/src/ooaParser.cs
===================================================================
--- branches/compiler/cSharp/ooasCompiler/src/ooaParser.cs	(nonexistent)
+++ branches/compiler/cSharp/ooasCompiler/src/ooaParser.cs	(revision 3)
@@ -0,0 +1,9643 @@
+// $ANTLR 3.2 Sep 23, 2009 12:02:23 ooa.g 2013-10-10 13:45:31
+
+// The variable 'variable' is assigned but its value is never used.
+#pragma warning disable 168, 219
+// Unreachable code detected.
+#pragma warning disable 162
+
+
+/*
+    Ulysses OO-Action System Parser
+
+    Copyright Willibald Krenn 2009
+
+ */
+
+
+using System;
+using Antlr.Runtime;
+using IList 		= System.Collections.IList;
+using ArrayList 	= System.Collections.ArrayList;
+using Stack 		= Antlr.Runtime.Collections.StackList;
+
+
+namespace  TUG.Mogentes 
+{
+public partial class ooaParser : Parser
+{
+    public static readonly string[] tokenNames = new string[] 
+	{
+        "<invalid>", 
+		"<EOR>", 
+		"<DOWN>", 
+		"<UP>", 
+		"T_CONSTS", 
+		"T_TYPES", 
+		"T_SYSTEM", 
+		"T_SEMICOLON", 
+		"T_IDENTIFIER", 
+		"T_EQUAL", 
+		"T_PRIO", 
+		"T_NONDET", 
+		"T_LPAREN", 
+		"T_RPAREN", 
+		"T_LIST", 
+		"T_LSQPAREN", 
+		"T_INTNUMBER", 
+		"T_RSQPAREN", 
+		"T_OF", 
+		"T_COMMA", 
+		"T_MAP", 
+		"T_TO", 
+		"T_QUANTITY", 
+		"T_MINUS", 
+		"T_INFTY", 
+		"T_BOOL", 
+		"T_INT", 
+		"T_RANGETO", 
+		"T_FLOAT", 
+		"T_FLOATNUMBER", 
+		"T_CHAR", 
+		"T_CBRL", 
+		"T_CBRR", 
+		"T_AUTOCONS", 
+		"T_VAR", 
+		"T_METHODS", 
+		"T_ACTIONS", 
+		"T_DO", 
+		"T_OD", 
+		"T_STATIC", 
+		"T_OBS", 
+		"T_CTRL", 
+		"T_COLON", 
+		"T_END", 
+		"T_CONT", 
+		"T_REQUIRES", 
+		"T_DERIV", 
+		"T_SUM", 
+		"T_DIFF", 
+		"T_PROD", 
+		"T_FOLDLR", 
+		"T_FOLDRL", 
+		"T_SKIP", 
+		"T_ABORT", 
+		"T_KILL", 
+		"T_SELF", 
+		"T_ASSIGNMENT", 
+		"T_WITH", 
+		"T_BIIMPLIES", 
+		"T_GREATER", 
+		"T_GREATEREQUAL", 
+		"T_LESS", 
+		"T_LESSEQUAL", 
+		"T_NOTEQUAL", 
+		"T_IMPLIES", 
+		"T_IN", 
+		"T_SET", 
+		"T_NOT", 
+		"T_SUBSET", 
+		"T_OR", 
+		"T_DIV", 
+		"T_IDIV", 
+		"T_MOD", 
+		"T_UNION", 
+		"T_INTER", 
+		"T_AND", 
+		"T_POW", 
+		"T_CONC", 
+		"T_DOMRESBY", 
+		"T_DOMRESTO", 
+		"T_RNGRESBY", 
+		"T_RNGRESTO", 
+		"T_MUNION", 
+		"T_SEQMOD_MAPOVERRIDE", 
+		"T_POINT", 
+		"T_IF", 
+		"T_THEN", 
+		"T_ELSE", 
+		"T_FORALL", 
+		"T_EXISTS", 
+		"T_TRUE", 
+		"T_FALSE", 
+		"T_NIL", 
+		"T_STRINGLITERAL", 
+		"T_NEW", 
+		"T_BAR", 
+		"T_MAPS", 
+		"T_PRIMED", 
+		"T_ABS", 
+		"T_CARD", 
+		"T_DCONC", 
+		"T_DINTER", 
+		"T_DUNION", 
+		"T_ELEMS", 
+		"T_HEAD", 
+		"T_INDS", 
+		"T_LEN", 
+		"T_TAIL", 
+		"T_DOM", 
+		"T_RNG", 
+		"T_MERGE", 
+		"T_WS", 
+		"T_COMMENT", 
+		"LINE_COMMENT", 
+		"T_DIGIT", 
+		"FLOAT_OR_INT_OR_RANGE", 
+		"T_LETTER", 
+		"'|['", 
+		"']|'", 
+		"'begin'", 
+		"'&'", 
+		"'as'", 
+		"'qval'", 
+		"'steady'", 
+		"'inc'", 
+		"'dec'", 
+		"'::'"
+    };
+
+    public const int T_FLOATNUMBER = 29;
+    public const int T_SYSTEM = 6;
+    public const int T_ELSE = 87;
+    public const int T_LPAREN = 12;
+    public const int T_DUNION = 102;
+    public const int T_BOOL = 25;
+    public const int T_METHODS = 35;
+    public const int T_INDS = 105;
+    public const int T_OR = 69;
+    public const int EOF = -1;
+    public const int T_OD = 38;
+    public const int T_AND = 75;
+    public const int T_OF = 18;
+    public const int T_STRINGLITERAL = 93;
+    public const int T_SET = 66;
+    public const int T_SKIP = 52;
+    public const int T_WITH = 57;
+    public const int T_DOM = 108;
+    public const int T_WS = 111;
+    public const int T_VAR = 34;
+    public const int T_SUM = 47;
+    public const int T_REQUIRES = 45;
+    public const int T_DINTER = 101;
+    public const int T_HEAD = 104;
+    public const int T_AUTOCONS = 33;
+    public const int T_END = 43;
+    public const int T_TRUE = 90;
+    public const int T_LSQPAREN = 15;
+    public const int T_PRIMED = 97;
+    public const int T_MAPS = 96;
+    public const int T_NIL = 92;
+    public const int T_INFTY = 24;
+    public const int T_IF = 85;
+    public const int LINE_COMMENT = 113;
+    public const int T_THEN = 86;
+    public const int T_FLOAT = 28;
+    public const int T_TAIL = 107;
+    public const int T_SELF = 55;
+    public const int T_MERGE = 110;
+    public const int T_DIFF = 48;
+    public const int T_FOLDRL = 51;
+    public const int T_QUANTITY = 22;
+    public const int T_IN = 65;
+    public const int T_MUNION = 82;
+    public const int T__126 = 126;
+    public const int T__125 = 125;
+    public const int T_INTER = 74;
+    public const int T_SEMICOLON = 7;
+    public const int T_FOLDLR = 50;
+    public const int T_CARD = 99;
+    public const int T_FALSE = 91;
+    public const int T_CONT = 44;
+    public const int T_SUBSET = 68;
+    public const int T_COMMA = 19;
+    public const int T_RANGETO = 27;
+    public const int T_MINUS = 23;
+    public const int T_CONC = 77;
+    public const int T_IDIV = 71;
+    public const int T_FORALL = 88;
+    public const int T_DERIV = 46;
+    public const int T_CONSTS = 4;
+    public const int T_TYPES = 5;
+    public const int T_GREATEREQUAL = 60;
+    public const int T__118 = 118;
+    public const int T_RNG = 109;
+    public const int T__119 = 119;
+    public const int T_MOD = 72;
+    public const int T__117 = 117;
+    public const int T_SEQMOD_MAPOVERRIDE = 83;
+    public const int T__124 = 124;
+    public const int T__123 = 123;
+    public const int T_ELEMS = 103;
+    public const int T__122 = 122;
+    public const int T__121 = 121;
+    public const int T_IMPLIES = 64;
+    public const int T__120 = 120;
+    public const int T_EXISTS = 89;
+    public const int T_POW = 76;
+    public const int T_COMMENT = 112;
+    public const int T_RPAREN = 13;
+    public const int T_PRIO = 10;
+    public const int T_RNGRESBY = 80;
+    public const int T_ABS = 98;
+    public const int T_DIV = 70;
+    public const int T_LIST = 14;
+    public const int T_CBRL = 31;
+    public const int T_DCONC = 100;
+    public const int T_ABORT = 53;
+    public const int T_CHAR = 30;
+    public const int T_POINT = 84;
+    public const int T_STATIC = 39;
+    public const int T_CBRR = 32;
+    public const int T_INT = 26;
+    public const int T_COLON = 42;
+    public const int T_PROD = 49;
+    public const int T_ACTIONS = 36;
+    public const int T_DIGIT = 114;
+    public const int T_LESS = 61;
+    public const int T_BAR = 95;
+    public const int T_TO = 21;
+    public const int T_NONDET = 11;
+    public const int T_DOMRESBY = 78;
+    public const int T_DOMRESTO = 79;
+    public const int T_EQUAL = 9;
+    public const int T_GREATER = 59;
+    public const int T_KILL = 54;
+    public const int T_RNGRESTO = 81;
+    public const int T_RSQPAREN = 17;
+    public const int T_NEW = 94;
+    public const int T_INTNUMBER = 16;
+    public const int T_UNION = 73;
+    public const int T_OBS = 40;
+    public const int T_BIIMPLIES = 58;
+    public const int T_NOTEQUAL = 63;
+    public const int T_IDENTIFIER = 8;
+    public const int T_DO = 37;
+    public const int FLOAT_OR_INT_OR_RANGE = 115;
+    public const int T_LEN = 106;
+    public const int T_NOT = 67;
+    public const int T_ASSIGNMENT = 56;
+    public const int T_LETTER = 116;
+    public const int T_MAP = 20;
+    public const int T_LESSEQUAL = 62;
+    public const int T_CTRL = 41;
+
+    // delegates
+    // delegators
+
+
+
+        public ooaParser(ITokenStream input)
+    		: this(input, new RecognizerSharedState()) {
+        }
+
+        public ooaParser(ITokenStream input, RecognizerSharedState state)
+    		: base(input, state) {
+            InitializeCyclicDFAs();
+
+             
+        }
+        
+
+    override public string[] TokenNames {
+		get { return ooaParser.tokenNames; }
+    }
+
+    override public string GrammarFileName {
+		get { return "ooa.g"; }
+    }
+
+
+
+    // $ANTLR start "ooActionSystems"
+    // ooa.g:137:1: ooActionSystems : ( T_CONSTS namedConstList )? T_TYPES namedTypeList T_SYSTEM comp= asTypeComposition[null] ;
+    public void ooActionSystems() // throws RecognitionException [1]
+    {   
+        IdentifierList comp = default(IdentifierList);
+
+
+        try 
+    	{
+            // ooa.g:138:2: ( ( T_CONSTS namedConstList )? T_TYPES namedTypeList T_SYSTEM comp= asTypeComposition[null] )
+            // ooa.g:138:4: ( T_CONSTS namedConstList )? T_TYPES namedTypeList T_SYSTEM comp= asTypeComposition[null]
+            {
+            	initializeTopLevelParserState();
+            	// ooa.g:140:11: ( T_CONSTS namedConstList )?
+            	int alt1 = 2;
+            	int LA1_0 = input.LA(1);
+
+            	if ( (LA1_0 == T_CONSTS) )
+            	{
+            	    alt1 = 1;
+            	}
+            	switch (alt1) 
+            	{
+            	    case 1 :
+            	        // ooa.g:140:12: T_CONSTS namedConstList
+            	        {
+            	        	Match(input,T_CONSTS,FOLLOW_T_CONSTS_in_ooActionSystems93); 
+            	        	PushFollow(FOLLOW_namedConstList_in_ooActionSystems95);
+            	        	namedConstList();
+            	        	state.followingStackPointer--;
+
+
+            	        }
+            	        break;
+
+            	}
+
+            	Match(input,T_TYPES,FOLLOW_T_TYPES_in_ooActionSystems105); 
+            	PushFollow(FOLLOW_namedTypeList_in_ooActionSystems113);
+            	namedTypeList();
+            	state.followingStackPointer--;
+
+            	Match(input,T_SYSTEM,FOLLOW_T_SYSTEM_in_ooActionSystems118); 
+            	PushFollow(FOLLOW_asTypeComposition_in_ooActionSystems125);
+            	comp = asTypeComposition(null);
+            	state.followingStackPointer--;
+
+            	fixUpRun(comp);
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "ooActionSystems"
+
+
+    // $ANTLR start "namedConstList"
+    // ooa.g:155:1: namedConstList : namedConst ( T_SEMICOLON namedConst )* ;
+    public void namedConstList() // throws RecognitionException [1]
+    {   
+        try 
+    	{
+            // ooa.g:156:2: ( namedConst ( T_SEMICOLON namedConst )* )
+            // ooa.g:156:4: namedConst ( T_SEMICOLON namedConst )*
+            {
+            	PushFollow(FOLLOW_namedConst_in_namedConstList148);
+            	namedConst();
+            	state.followingStackPointer--;
+
+            	// ooa.g:156:15: ( T_SEMICOLON namedConst )*
+            	do 
+            	{
+            	    int alt2 = 2;
+            	    int LA2_0 = input.LA(1);
+
+            	    if ( (LA2_0 == T_SEMICOLON) )
+            	    {
+            	        alt2 = 1;
+            	    }
+
+
+            	    switch (alt2) 
+            		{
+            			case 1 :
+            			    // ooa.g:156:16: T_SEMICOLON namedConst
+            			    {
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_namedConstList151); 
+            			    	PushFollow(FOLLOW_namedConst_in_namedConstList153);
+            			    	namedConst();
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop2;
+            	    }
+            	} while (true);
+
+            	loop2:
+            		;	// Stops C# compiler whining that label 'loop2' has no statements
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "namedConstList"
+
+
+    // $ANTLR start "namedConst"
+    // ooa.g:159:1: namedConst : aName= T_IDENTIFIER T_EQUAL anExpr= expression ;
+    public void namedConst() // throws RecognitionException [1]
+    {   
+        IToken aName = null;
+        Expression anExpr = default(Expression);
+
+
+        try 
+    	{
+            // ooa.g:160:2: (aName= T_IDENTIFIER T_EQUAL anExpr= expression )
+            // ooa.g:160:4: aName= T_IDENTIFIER T_EQUAL anExpr= expression
+            {
+            	aName=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_namedConst169); 
+            	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_namedConst173); 
+            	PushFollow(FOLLOW_expression_in_namedConst179);
+            	anExpr = expression();
+            	state.followingStackPointer--;
+
+            	addNamedConst(aName,anExpr);
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "namedConst"
+
+
+    // $ANTLR start "namedTypeList"
+    // ooa.g:170:1: namedTypeList : namedType ( T_SEMICOLON namedType )* ;
+    public void namedTypeList() // throws RecognitionException [1]
+    {   
+        try 
+    	{
+            // ooa.g:171:2: ( namedType ( T_SEMICOLON namedType )* )
+            // ooa.g:171:4: namedType ( T_SEMICOLON namedType )*
+            {
+            	PushFollow(FOLLOW_namedType_in_namedTypeList199);
+            	namedType();
+            	state.followingStackPointer--;
+
+            	// ooa.g:171:14: ( T_SEMICOLON namedType )*
+            	do 
+            	{
+            	    int alt3 = 2;
+            	    int LA3_0 = input.LA(1);
+
+            	    if ( (LA3_0 == T_SEMICOLON) )
+            	    {
+            	        alt3 = 1;
+            	    }
+
+
+            	    switch (alt3) 
+            		{
+            			case 1 :
+            			    // ooa.g:171:15: T_SEMICOLON namedType
+            			    {
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_namedTypeList202); 
+            			    	PushFollow(FOLLOW_namedType_in_namedTypeList204);
+            			    	namedType();
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop3;
+            	    }
+            	} while (true);
+
+            	loop3:
+            		;	// Stops C# compiler whining that label 'loop3' has no statements
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "namedTypeList"
+
+
+    // $ANTLR start "namedType"
+    // ooa.g:174:1: namedType : aName= T_IDENTIFIER T_EQUAL (aType= complexType | anOoaType= ooActionSystem ) ;
+    public void namedType() // throws RecognitionException [1]
+    {   
+        IToken aName = null;
+        UlyssesType aType = default(UlyssesType);
+
+        OoActionSystemType anOoaType = default(OoActionSystemType);
+
+
+        try 
+    	{
+            // ooa.g:175:2: (aName= T_IDENTIFIER T_EQUAL (aType= complexType | anOoaType= ooActionSystem ) )
+            // ooa.g:175:4: aName= T_IDENTIFIER T_EQUAL (aType= complexType | anOoaType= ooActionSystem )
+            {
+            	aName=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_namedType220); 
+            	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_namedType225); 
+            	// ooa.g:177:3: (aType= complexType | anOoaType= ooActionSystem )
+            	int alt4 = 2;
+            	alt4 = dfa4.Predict(input);
+            	switch (alt4) 
+            	{
+            	    case 1 :
+            	        // ooa.g:178:4: aType= complexType
+            	        {
+            	        	PushFollow(FOLLOW_complexType_in_namedType237);
+            	        	aType = complexType();
+            	        	state.followingStackPointer--;
+
+            	        	createNamedType(aName,aType);
+
+            	        }
+            	        break;
+            	    case 2 :
+            	        // ooa.g:179:5: anOoaType= ooActionSystem
+            	        {
+            	        	PushFollow(FOLLOW_ooActionSystem_in_namedType249);
+            	        	anOoaType = ooActionSystem();
+            	        	state.followingStackPointer--;
+
+            	        	createNamedType(aName,anOoaType);
+
+            	        }
+            	        break;
+
+            	}
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "namedType"
+
+
+    // $ANTLR start "asTypeComposition"
+    // ooa.g:185:1: asTypeComposition[IdentifierList top] returns [IdentifierList prioList] : asTypeCompositionParallel[prioList] ( T_PRIO asTypeCompositionParallel[prioList] )* ;
+    public IdentifierList asTypeComposition(IdentifierList top) // throws RecognitionException [1]
+    {   
+        IdentifierList prioList = default(IdentifierList);
+
+        try 
+    	{
+            // ooa.g:187:2: ( asTypeCompositionParallel[prioList] ( T_PRIO asTypeCompositionParallel[prioList] )* )
+            // ooa.g:187:6: asTypeCompositionParallel[prioList] ( T_PRIO asTypeCompositionParallel[prioList] )*
+            {
+            	prioList = new PrioIdentifierList(top);
+            	PushFollow(FOLLOW_asTypeCompositionParallel_in_asTypeComposition285);
+            	asTypeCompositionParallel(prioList);
+            	state.followingStackPointer--;
+
+            	// ooa.g:188:40: ( T_PRIO asTypeCompositionParallel[prioList] )*
+            	do 
+            	{
+            	    int alt5 = 2;
+            	    int LA5_0 = input.LA(1);
+
+            	    if ( (LA5_0 == T_PRIO) )
+            	    {
+            	        alt5 = 1;
+            	    }
+
+
+            	    switch (alt5) 
+            		{
+            			case 1 :
+            			    // ooa.g:188:41: T_PRIO asTypeCompositionParallel[prioList]
+            			    {
+            			    	Match(input,T_PRIO,FOLLOW_T_PRIO_in_asTypeComposition290); 
+            			    	PushFollow(FOLLOW_asTypeCompositionParallel_in_asTypeComposition292);
+            			    	asTypeCompositionParallel(prioList);
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop5;
+            	    }
+            	} while (true);
+
+            	loop5:
+            		;	// Stops C# compiler whining that label 'loop5' has no statements
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return prioList;
+    }
+    // $ANTLR end "asTypeComposition"
+
+
+    // $ANTLR start "asTypeCompositionParallel"
+    // ooa.g:191:1: asTypeCompositionParallel[IdentifierList top] : asTypeCompositionSequential[parList] ( T_NONDET asTypeCompositionSequential[parList] )* ;
+    public void asTypeCompositionParallel(IdentifierList top) // throws RecognitionException [1]
+    {   
+        try 
+    	{
+            // ooa.g:192:2: ( asTypeCompositionSequential[parList] ( T_NONDET asTypeCompositionSequential[parList] )* )
+            // ooa.g:192:6: asTypeCompositionSequential[parList] ( T_NONDET asTypeCompositionSequential[parList] )*
+            {
+            	IdentifierList parList = new NondetIdentifierList(top);
+            	PushFollow(FOLLOW_asTypeCompositionSequential_in_asTypeCompositionParallel315);
+            	asTypeCompositionSequential(parList);
+            	state.followingStackPointer--;
+
+            	// ooa.g:193:40: ( T_NONDET asTypeCompositionSequential[parList] )*
+            	do 
+            	{
+            	    int alt6 = 2;
+            	    int LA6_0 = input.LA(1);
+
+            	    if ( (LA6_0 == T_NONDET) )
+            	    {
+            	        alt6 = 1;
+            	    }
+
+
+            	    switch (alt6) 
+            		{
+            			case 1 :
+            			    // ooa.g:193:41: T_NONDET asTypeCompositionSequential[parList]
+            			    {
+            			    	Match(input,T_NONDET,FOLLOW_T_NONDET_in_asTypeCompositionParallel319); 
+            			    	PushFollow(FOLLOW_asTypeCompositionSequential_in_asTypeCompositionParallel321);
+            			    	asTypeCompositionSequential(parList);
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop6;
+            	    }
+            	} while (true);
+
+            	loop6:
+            		;	// Stops C# compiler whining that label 'loop6' has no statements
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "asTypeCompositionParallel"
+
+
+    // $ANTLR start "asTypeCompositionSequential"
+    // ooa.g:196:1: asTypeCompositionSequential[IdentifierList top] : asTypeCompositionBlockParen[seqList] ;
+    public void asTypeCompositionSequential(IdentifierList top) // throws RecognitionException [1]
+    {   
+        try 
+    	{
+            // ooa.g:197:2: ( asTypeCompositionBlockParen[seqList] )
+            // ooa.g:197:6: asTypeCompositionBlockParen[seqList]
+            {
+            	IdentifierList seqList = new SeqIdentifierList(top);
+            	PushFollow(FOLLOW_asTypeCompositionBlockParen_in_asTypeCompositionSequential343);
+            	asTypeCompositionBlockParen(seqList);
+            	state.followingStackPointer--;
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "asTypeCompositionSequential"
+
+
+    // $ANTLR start "asTypeCompositionBlockParen"
+    // ooa.g:201:1: asTypeCompositionBlockParen[IdentifierList top] : ( T_LPAREN asTypeComposition[top] T_RPAREN | aName= T_IDENTIFIER );
+    public void asTypeCompositionBlockParen(IdentifierList top) // throws RecognitionException [1]
+    {   
+        IToken aName = null;
+
+        try 
+    	{
+            // ooa.g:202:2: ( T_LPAREN asTypeComposition[top] T_RPAREN | aName= T_IDENTIFIER )
+            int alt7 = 2;
+            int LA7_0 = input.LA(1);
+
+            if ( (LA7_0 == T_LPAREN) )
+            {
+                alt7 = 1;
+            }
+            else if ( (LA7_0 == T_IDENTIFIER) )
+            {
+                alt7 = 2;
+            }
+            else 
+            {
+                NoViableAltException nvae_d7s0 =
+                    new NoViableAltException("", 7, 0, input);
+
+                throw nvae_d7s0;
+            }
+            switch (alt7) 
+            {
+                case 1 :
+                    // ooa.g:202:4: T_LPAREN asTypeComposition[top] T_RPAREN
+                    {
+                    	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_asTypeCompositionBlockParen358); 
+                    	PushFollow(FOLLOW_asTypeComposition_in_asTypeCompositionBlockParen360);
+                    	asTypeComposition(top);
+                    	state.followingStackPointer--;
+
+                    	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_asTypeCompositionBlockParen363); 
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:203:4: aName= T_IDENTIFIER
+                    {
+                    	aName=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_asTypeCompositionBlockParen370); 
+                    	addToIdentifierList(top,aName);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "asTypeCompositionBlockParen"
+
+
+    // $ANTLR start "complexType"
+    // ooa.g:211:1: complexType returns [UlyssesType aTypeSymbol] : ( T_LIST T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN T_OF innertype= complexType | T_LSQPAREN alistelem= T_IDENTIFIER ( T_COMMA otherlistelem= T_IDENTIFIER )* T_RSQPAREN | T_MAP ( T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN )? mapfromtype= simpleType T_TO maptotype= complexType | T_QUANTITY T_OF T_LSQPAREN (alandmark= T_IDENTIFIER | alandmark= T_MINUS T_INFTY ) ( T_COMMA (otherlandmark= T_IDENTIFIER | otherlandmark= T_INFTY ) )* T_RSQPAREN | T_LPAREN aType= complexType ( T_COMMA anotherType= complexType )* T_RPAREN | r= simpleType );
+    public UlyssesType complexType() // throws RecognitionException [1]
+    {   
+        UlyssesType aTypeSymbol = default(UlyssesType);
+
+        IToken numOfElements = null;
+        IToken alistelem = null;
+        IToken otherlistelem = null;
+        IToken alandmark = null;
+        IToken otherlandmark = null;
+        UlyssesType innertype = default(UlyssesType);
+
+        UlyssesType mapfromtype = default(UlyssesType);
+
+        UlyssesType maptotype = default(UlyssesType);
+
+        UlyssesType aType = default(UlyssesType);
+
+        UlyssesType anotherType = default(UlyssesType);
+
+        UlyssesType r = default(UlyssesType);
+
+
+         
+        		aTypeSymbol = null;
+        		alandmark = null;
+        	
+        try 
+    	{
+            // ooa.g:217:2: ( T_LIST T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN T_OF innertype= complexType | T_LSQPAREN alistelem= T_IDENTIFIER ( T_COMMA otherlistelem= T_IDENTIFIER )* T_RSQPAREN | T_MAP ( T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN )? mapfromtype= simpleType T_TO maptotype= complexType | T_QUANTITY T_OF T_LSQPAREN (alandmark= T_IDENTIFIER | alandmark= T_MINUS T_INFTY ) ( T_COMMA (otherlandmark= T_IDENTIFIER | otherlandmark= T_INFTY ) )* T_RSQPAREN | T_LPAREN aType= complexType ( T_COMMA anotherType= complexType )* T_RPAREN | r= simpleType )
+            int alt14 = 6;
+            alt14 = dfa14.Predict(input);
+            switch (alt14) 
+            {
+                case 1 :
+                    // ooa.g:217:4: T_LIST T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN T_OF innertype= complexType
+                    {
+                    	Match(input,T_LIST,FOLLOW_T_LIST_in_complexType401); 
+                    	Match(input,T_LSQPAREN,FOLLOW_T_LSQPAREN_in_complexType404); 
+                    	numOfElements = (IToken)input.LT(1);
+                    	if ( input.LA(1) == T_IDENTIFIER || input.LA(1) == T_INTNUMBER ) 
+                    	{
+                    	    input.Consume();
+                    	    state.errorRecovery = false;
+                    	}
+                    	else 
+                    	{
+                    	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	    throw mse;
+                    	}
+
+                    	Match(input,T_RSQPAREN,FOLLOW_T_RSQPAREN_in_complexType414); 
+                    	Match(input,T_OF,FOLLOW_T_OF_in_complexType416); 
+                    	PushFollow(FOLLOW_complexType_in_complexType421);
+                    	innertype = complexType();
+                    	state.followingStackPointer--;
+
+                    	aTypeSymbol = createListType(numOfElements,innertype);
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:221:4: T_LSQPAREN alistelem= T_IDENTIFIER ( T_COMMA otherlistelem= T_IDENTIFIER )* T_RSQPAREN
+                    {
+                    	Match(input,T_LSQPAREN,FOLLOW_T_LSQPAREN_in_complexType436); 
+                    	alistelem=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_complexType440); 
+                    	aTypeSymbol = createListEnumType(alistelem);
+                    	// ooa.g:222:4: ( T_COMMA otherlistelem= T_IDENTIFIER )*
+                    	do 
+                    	{
+                    	    int alt8 = 2;
+                    	    int LA8_0 = input.LA(1);
+
+                    	    if ( (LA8_0 == T_COMMA) )
+                    	    {
+                    	        alt8 = 1;
+                    	    }
+
+
+                    	    switch (alt8) 
+                    		{
+                    			case 1 :
+                    			    // ooa.g:222:5: T_COMMA otherlistelem= T_IDENTIFIER
+                    			    {
+                    			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_complexType449); 
+                    			    	otherlistelem=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_complexType453); 
+                    			    	addToListEnumType(aTypeSymbol,otherlistelem);
+
+                    			    }
+                    			    break;
+
+                    			default:
+                    			    goto loop8;
+                    	    }
+                    	} while (true);
+
+                    	loop8:
+                    		;	// Stops C# compiler whining that label 'loop8' has no statements
+
+                    	Match(input,T_RSQPAREN,FOLLOW_T_RSQPAREN_in_complexType459); 
+
+                    }
+                    break;
+                case 3 :
+                    // ooa.g:225:4: T_MAP ( T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN )? mapfromtype= simpleType T_TO maptotype= complexType
+                    {
+                    	Match(input,T_MAP,FOLLOW_T_MAP_in_complexType469); 
+                    	// ooa.g:225:12: ( T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN )?
+                    	int alt9 = 2;
+                    	int LA9_0 = input.LA(1);
+
+                    	if ( (LA9_0 == T_LSQPAREN) )
+                    	{
+                    	    alt9 = 1;
+                    	}
+                    	switch (alt9) 
+                    	{
+                    	    case 1 :
+                    	        // ooa.g:225:13: T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN
+                    	        {
+                    	        	Match(input,T_LSQPAREN,FOLLOW_T_LSQPAREN_in_complexType474); 
+                    	        	numOfElements = (IToken)input.LT(1);
+                    	        	if ( input.LA(1) == T_IDENTIFIER || input.LA(1) == T_INTNUMBER ) 
+                    	        	{
+                    	        	    input.Consume();
+                    	        	    state.errorRecovery = false;
+                    	        	}
+                    	        	else 
+                    	        	{
+                    	        	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	        	    throw mse;
+                    	        	}
+
+                    	        	Match(input,T_RSQPAREN,FOLLOW_T_RSQPAREN_in_complexType484); 
+
+                    	        }
+                    	        break;
+
+                    	}
+
+                    	PushFollow(FOLLOW_simpleType_in_complexType490);
+                    	mapfromtype = simpleType();
+                    	state.followingStackPointer--;
+
+                    	Match(input,T_TO,FOLLOW_T_TO_in_complexType492); 
+                    	PushFollow(FOLLOW_complexType_in_complexType496);
+                    	maptotype = complexType();
+                    	state.followingStackPointer--;
+
+                    	aTypeSymbol = createMapType(numOfElements,mapfromtype,maptotype);
+
+                    }
+                    break;
+                case 4 :
+                    // ooa.g:228:4: T_QUANTITY T_OF T_LSQPAREN (alandmark= T_IDENTIFIER | alandmark= T_MINUS T_INFTY ) ( T_COMMA (otherlandmark= T_IDENTIFIER | otherlandmark= T_INFTY ) )* T_RSQPAREN
+                    {
+                    	Match(input,T_QUANTITY,FOLLOW_T_QUANTITY_in_complexType510); 
+                    	Match(input,T_OF,FOLLOW_T_OF_in_complexType512); 
+                    	Match(input,T_LSQPAREN,FOLLOW_T_LSQPAREN_in_complexType514); 
+                    	// ooa.g:228:31: (alandmark= T_IDENTIFIER | alandmark= T_MINUS T_INFTY )
+                    	int alt10 = 2;
+                    	int LA10_0 = input.LA(1);
+
+                    	if ( (LA10_0 == T_IDENTIFIER) )
+                    	{
+                    	    alt10 = 1;
+                    	}
+                    	else if ( (LA10_0 == T_MINUS) )
+                    	{
+                    	    alt10 = 2;
+                    	}
+                    	else 
+                    	{
+                    	    NoViableAltException nvae_d10s0 =
+                    	        new NoViableAltException("", 10, 0, input);
+
+                    	    throw nvae_d10s0;
+                    	}
+                    	switch (alt10) 
+                    	{
+                    	    case 1 :
+                    	        // ooa.g:228:32: alandmark= T_IDENTIFIER
+                    	        {
+                    	        	alandmark=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_complexType519); 
+
+                    	        }
+                    	        break;
+                    	    case 2 :
+                    	        // ooa.g:228:56: alandmark= T_MINUS T_INFTY
+                    	        {
+                    	        	alandmark=(IToken)Match(input,T_MINUS,FOLLOW_T_MINUS_in_complexType524); 
+                    	        	Match(input,T_INFTY,FOLLOW_T_INFTY_in_complexType526); 
+
+                    	        }
+                    	        break;
+
+                    	}
+
+                    	aTypeSymbol = createQrType(alandmark);
+                    	// ooa.g:229:4: ( T_COMMA (otherlandmark= T_IDENTIFIER | otherlandmark= T_INFTY ) )*
+                    	do 
+                    	{
+                    	    int alt12 = 2;
+                    	    int LA12_0 = input.LA(1);
+
+                    	    if ( (LA12_0 == T_COMMA) )
+                    	    {
+                    	        alt12 = 1;
+                    	    }
+
+
+                    	    switch (alt12) 
+                    		{
+                    			case 1 :
+                    			    // ooa.g:229:5: T_COMMA (otherlandmark= T_IDENTIFIER | otherlandmark= T_INFTY )
+                    			    {
+                    			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_complexType536); 
+                    			    	// ooa.g:229:13: (otherlandmark= T_IDENTIFIER | otherlandmark= T_INFTY )
+                    			    	int alt11 = 2;
+                    			    	int LA11_0 = input.LA(1);
+
+                    			    	if ( (LA11_0 == T_IDENTIFIER) )
+                    			    	{
+                    			    	    alt11 = 1;
+                    			    	}
+                    			    	else if ( (LA11_0 == T_INFTY) )
+                    			    	{
+                    			    	    alt11 = 2;
+                    			    	}
+                    			    	else 
+                    			    	{
+                    			    	    NoViableAltException nvae_d11s0 =
+                    			    	        new NoViableAltException("", 11, 0, input);
+
+                    			    	    throw nvae_d11s0;
+                    			    	}
+                    			    	switch (alt11) 
+                    			    	{
+                    			    	    case 1 :
+                    			    	        // ooa.g:229:14: otherlandmark= T_IDENTIFIER
+                    			    	        {
+                    			    	        	otherlandmark=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_complexType541); 
+
+                    			    	        }
+                    			    	        break;
+                    			    	    case 2 :
+                    			    	        // ooa.g:229:41: otherlandmark= T_INFTY
+                    			    	        {
+                    			    	        	otherlandmark=(IToken)Match(input,T_INFTY,FOLLOW_T_INFTY_in_complexType545); 
+
+                    			    	        }
+                    			    	        break;
+
+                    			    	}
+
+                    			    	addToQrType(aTypeSymbol,otherlandmark);
+
+                    			    }
+                    			    break;
+
+                    			default:
+                    			    goto loop12;
+                    	    }
+                    	} while (true);
+
+                    	loop12:
+                    		;	// Stops C# compiler whining that label 'loop12' has no statements
+
+                    	Match(input,T_RSQPAREN,FOLLOW_T_RSQPAREN_in_complexType552); 
+
+                    }
+                    break;
+                case 5 :
+                    // ooa.g:231:5: T_LPAREN aType= complexType ( T_COMMA anotherType= complexType )* T_RPAREN
+                    {
+                    	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_complexType562); 
+                    	PushFollow(FOLLOW_complexType_in_complexType566);
+                    	aType = complexType();
+                    	state.followingStackPointer--;
+
+                    	aTypeSymbol = createTupleType(aType);
+                    	// ooa.g:232:4: ( T_COMMA anotherType= complexType )*
+                    	do 
+                    	{
+                    	    int alt13 = 2;
+                    	    int LA13_0 = input.LA(1);
+
+                    	    if ( (LA13_0 == T_COMMA) )
+                    	    {
+                    	        alt13 = 1;
+                    	    }
+
+
+                    	    switch (alt13) 
+                    		{
+                    			case 1 :
+                    			    // ooa.g:232:5: T_COMMA anotherType= complexType
+                    			    {
+                    			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_complexType575); 
+                    			    	PushFollow(FOLLOW_complexType_in_complexType579);
+                    			    	anotherType = complexType();
+                    			    	state.followingStackPointer--;
+
+                    			    	addToTupleType(aTypeSymbol,anotherType);
+
+                    			    }
+                    			    break;
+
+                    			default:
+                    			    goto loop13;
+                    	    }
+                    	} while (true);
+
+                    	loop13:
+                    		;	// Stops C# compiler whining that label 'loop13' has no statements
+
+                    	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_complexType586); 
+
+                    }
+                    break;
+                case 6 :
+                    // ooa.g:235:4: r= simpleType
+                    {
+                    	PushFollow(FOLLOW_simpleType_in_complexType599);
+                    	r = simpleType();
+                    	state.followingStackPointer--;
+
+                    	aTypeSymbol = r;
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            fixupComplexType(aTypeSymbol);
+        }
+        return aTypeSymbol;
+    }
+    // $ANTLR end "complexType"
+
+
+    // $ANTLR start "simpleType"
+    // ooa.g:241:1: simpleType returns [UlyssesType aTypeSymbol] : ( T_BOOL | T_INT T_LSQPAREN rangeLow= ( T_INTNUMBER | T_INFTY | T_IDENTIFIER ) T_RANGETO rangeHigh= ( T_INTNUMBER | T_INFTY | T_IDENTIFIER ) T_RSQPAREN | T_FLOAT T_LSQPAREN rangeLow= ( T_FLOATNUMBER | T_INFTY | T_IDENTIFIER ) T_RANGETO rangeHigh= ( T_FLOATNUMBER | T_INFTY | T_IDENTIFIER ) T_RSQPAREN | T_CHAR | T_CBRL aRangeValue= T_IDENTIFIER ( T_EQUAL optVal= T_INTNUMBER )? ( T_COMMA otherRangeValue= T_IDENTIFIER ( T_EQUAL otherOptVal= T_INTNUMBER )? )* T_CBRR | aType= T_IDENTIFIER );
+    public UlyssesType simpleType() // throws RecognitionException [1]
+    {   
+        UlyssesType aTypeSymbol = default(UlyssesType);
+
+        IToken rangeLow = null;
+        IToken rangeHigh = null;
+        IToken aRangeValue = null;
+        IToken optVal = null;
+        IToken otherRangeValue = null;
+        IToken otherOptVal = null;
+        IToken aType = null;
+
+         
+        		aTypeSymbol = null;
+        	
+        try 
+    	{
+            // ooa.g:246:2: ( T_BOOL | T_INT T_LSQPAREN rangeLow= ( T_INTNUMBER | T_INFTY | T_IDENTIFIER ) T_RANGETO rangeHigh= ( T_INTNUMBER | T_INFTY | T_IDENTIFIER ) T_RSQPAREN | T_FLOAT T_LSQPAREN rangeLow= ( T_FLOATNUMBER | T_INFTY | T_IDENTIFIER ) T_RANGETO rangeHigh= ( T_FLOATNUMBER | T_INFTY | T_IDENTIFIER ) T_RSQPAREN | T_CHAR | T_CBRL aRangeValue= T_IDENTIFIER ( T_EQUAL optVal= T_INTNUMBER )? ( T_COMMA otherRangeValue= T_IDENTIFIER ( T_EQUAL otherOptVal= T_INTNUMBER )? )* T_CBRR | aType= T_IDENTIFIER )
+            int alt18 = 6;
+            switch ( input.LA(1) ) 
+            {
+            case T_BOOL:
+            	{
+                alt18 = 1;
+                }
+                break;
+            case T_INT:
+            	{
+                alt18 = 2;
+                }
+                break;
+            case T_FLOAT:
+            	{
+                alt18 = 3;
+                }
+                break;
+            case T_CHAR:
+            	{
+                alt18 = 4;
+                }
+                break;
+            case T_CBRL:
+            	{
+                alt18 = 5;
+                }
+                break;
+            case T_IDENTIFIER:
+            	{
+                alt18 = 6;
+                }
+                break;
+            	default:
+            	    NoViableAltException nvae_d18s0 =
+            	        new NoViableAltException("", 18, 0, input);
+
+            	    throw nvae_d18s0;
+            }
+
+            switch (alt18) 
+            {
+                case 1 :
+                    // ooa.g:246:4: T_BOOL
+                    {
+                    	Match(input,T_BOOL,FOLLOW_T_BOOL_in_simpleType632); 
+                    	aTypeSymbol = createBoolType();
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:249:4: T_INT T_LSQPAREN rangeLow= ( T_INTNUMBER | T_INFTY | T_IDENTIFIER ) T_RANGETO rangeHigh= ( T_INTNUMBER | T_INFTY | T_IDENTIFIER ) T_RSQPAREN
+                    {
+                    	Match(input,T_INT,FOLLOW_T_INT_in_simpleType645); 
+                    	Match(input,T_LSQPAREN,FOLLOW_T_LSQPAREN_in_simpleType647); 
+                    	rangeLow = (IToken)input.LT(1);
+                    	if ( input.LA(1) == T_IDENTIFIER || input.LA(1) == T_INTNUMBER || input.LA(1) == T_INFTY ) 
+                    	{
+                    	    input.Consume();
+                    	    state.errorRecovery = false;
+                    	}
+                    	else 
+                    	{
+                    	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	    throw mse;
+                    	}
+
+                    	Match(input,T_RANGETO,FOLLOW_T_RANGETO_in_simpleType659); 
+                    	rangeHigh = (IToken)input.LT(1);
+                    	if ( input.LA(1) == T_IDENTIFIER || input.LA(1) == T_INTNUMBER || input.LA(1) == T_INFTY ) 
+                    	{
+                    	    input.Consume();
+                    	    state.errorRecovery = false;
+                    	}
+                    	else 
+                    	{
+                    	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	    throw mse;
+                    	}
+
+                    	Match(input,T_RSQPAREN,FOLLOW_T_RSQPAREN_in_simpleType671); 
+                    	aTypeSymbol = createIntType(rangeLow,rangeHigh);
+
+                    }
+                    break;
+                case 3 :
+                    // ooa.g:253:4: T_FLOAT T_LSQPAREN rangeLow= ( T_FLOATNUMBER | T_INFTY | T_IDENTIFIER ) T_RANGETO rangeHigh= ( T_FLOATNUMBER | T_INFTY | T_IDENTIFIER ) T_RSQPAREN
+                    {
+                    	Match(input,T_FLOAT,FOLLOW_T_FLOAT_in_simpleType690); 
+                    	Match(input,T_LSQPAREN,FOLLOW_T_LSQPAREN_in_simpleType693); 
+                    	rangeLow = (IToken)input.LT(1);
+                    	if ( input.LA(1) == T_IDENTIFIER || input.LA(1) == T_INFTY || input.LA(1) == T_FLOATNUMBER ) 
+                    	{
+                    	    input.Consume();
+                    	    state.errorRecovery = false;
+                    	}
+                    	else 
+                    	{
+                    	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	    throw mse;
+                    	}
+
+                    	Match(input,T_RANGETO,FOLLOW_T_RANGETO_in_simpleType705); 
+                    	rangeHigh = (IToken)input.LT(1);
+                    	if ( input.LA(1) == T_IDENTIFIER || input.LA(1) == T_INFTY || input.LA(1) == T_FLOATNUMBER ) 
+                    	{
+                    	    input.Consume();
+                    	    state.errorRecovery = false;
+                    	}
+                    	else 
+                    	{
+                    	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	    throw mse;
+                    	}
+
+                    	Match(input,T_RSQPAREN,FOLLOW_T_RSQPAREN_in_simpleType717); 
+                    	aTypeSymbol = createFloatType(rangeLow,rangeHigh);
+
+                    }
+                    break;
+                case 4 :
+                    // ooa.g:257:4: T_CHAR
+                    {
+                    	Match(input,T_CHAR,FOLLOW_T_CHAR_in_simpleType735); 
+                    	aTypeSymbol = createCharType();
+
+                    }
+                    break;
+                case 5 :
+                    // ooa.g:261:4: T_CBRL aRangeValue= T_IDENTIFIER ( T_EQUAL optVal= T_INTNUMBER )? ( T_COMMA otherRangeValue= T_IDENTIFIER ( T_EQUAL otherOptVal= T_INTNUMBER )? )* T_CBRR
+                    {
+                    	Match(input,T_CBRL,FOLLOW_T_CBRL_in_simpleType751); 
+                    	aRangeValue=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_simpleType755); 
+                    	// ooa.g:261:36: ( T_EQUAL optVal= T_INTNUMBER )?
+                    	int alt15 = 2;
+                    	int LA15_0 = input.LA(1);
+
+                    	if ( (LA15_0 == T_EQUAL) )
+                    	{
+                    	    alt15 = 1;
+                    	}
+                    	switch (alt15) 
+                    	{
+                    	    case 1 :
+                    	        // ooa.g:261:37: T_EQUAL optVal= T_INTNUMBER
+                    	        {
+                    	        	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_simpleType758); 
+                    	        	optVal=(IToken)Match(input,T_INTNUMBER,FOLLOW_T_INTNUMBER_in_simpleType762); 
+
+                    	        }
+                    	        break;
+
+                    	}
+
+                    	aTypeSymbol = createEnumType(aRangeValue, optVal);
+                    	// ooa.g:262:4: ( T_COMMA otherRangeValue= T_IDENTIFIER ( T_EQUAL otherOptVal= T_INTNUMBER )? )*
+                    	do 
+                    	{
+                    	    int alt17 = 2;
+                    	    int LA17_0 = input.LA(1);
+
+                    	    if ( (LA17_0 == T_COMMA) )
+                    	    {
+                    	        alt17 = 1;
+                    	    }
+
+
+                    	    switch (alt17) 
+                    		{
+                    			case 1 :
+                    			    // ooa.g:262:5: T_COMMA otherRangeValue= T_IDENTIFIER ( T_EQUAL otherOptVal= T_INTNUMBER )?
+                    			    {
+                    			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_simpleType773); 
+                    			    	otherRangeValue=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_simpleType777); 
+                    			    	// ooa.g:262:42: ( T_EQUAL otherOptVal= T_INTNUMBER )?
+                    			    	int alt16 = 2;
+                    			    	int LA16_0 = input.LA(1);
+
+                    			    	if ( (LA16_0 == T_EQUAL) )
+                    			    	{
+                    			    	    alt16 = 1;
+                    			    	}
+                    			    	switch (alt16) 
+                    			    	{
+                    			    	    case 1 :
+                    			    	        // ooa.g:262:43: T_EQUAL otherOptVal= T_INTNUMBER
+                    			    	        {
+                    			    	        	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_simpleType780); 
+                    			    	        	otherOptVal=(IToken)Match(input,T_INTNUMBER,FOLLOW_T_INTNUMBER_in_simpleType784); 
+
+                    			    	        }
+                    			    	        break;
+
+                    			    	}
+
+                    			    	addToEnumType(aTypeSymbol,otherRangeValue,otherOptVal); otherOptVal=null;
+
+                    			    }
+                    			    break;
+
+                    			default:
+                    			    goto loop17;
+                    	    }
+                    	} while (true);
+
+                    	loop17:
+                    		;	// Stops C# compiler whining that label 'loop17' has no statements
+
+                    	Match(input,T_CBRR,FOLLOW_T_CBRR_in_simpleType792); 
+
+                    }
+                    break;
+                case 6 :
+                    // ooa.g:264:4: aType= T_IDENTIFIER
+                    {
+                    	aType=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_simpleType803); 
+                    	aTypeSymbol = getNamedType(aType);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            fixupSimpleType(aTypeSymbol);
+        }
+        return aTypeSymbol;
+    }
+    // $ANTLR end "simpleType"
+
+
+    // $ANTLR start "ooActionSystem"
+    // ooa.g:274:1: ooActionSystem returns [OoActionSystemType aTypeSymbol] : ( T_AUTOCONS )? T_SYSTEM ( T_LPAREN refinesSystemName= T_IDENTIFIER T_RPAREN )? '|[' ( T_VAR attrList )? ( T_METHODS methodList )? ( T_ACTIONS namedActionList )? ( T_DO (bl= actionBlock[null] )? T_OD )? ']|' ;
+    public OoActionSystemType ooActionSystem() // throws RecognitionException [1]
+    {   
+        OoActionSystemType aTypeSymbol = default(OoActionSystemType);
+
+        IToken refinesSystemName = null;
+        Block bl = default(Block);
+
+
+         
+        		bool autoCons = false; 
+        		aTypeSymbol = null;
+        		refinesSystemName = null;
+        	
+        try 
+    	{
+            // ooa.g:281:2: ( ( T_AUTOCONS )? T_SYSTEM ( T_LPAREN refinesSystemName= T_IDENTIFIER T_RPAREN )? '|[' ( T_VAR attrList )? ( T_METHODS methodList )? ( T_ACTIONS namedActionList )? ( T_DO (bl= actionBlock[null] )? T_OD )? ']|' )
+            // ooa.g:281:9: ( T_AUTOCONS )? T_SYSTEM ( T_LPAREN refinesSystemName= T_IDENTIFIER T_RPAREN )? '|[' ( T_VAR attrList )? ( T_METHODS methodList )? ( T_ACTIONS namedActionList )? ( T_DO (bl= actionBlock[null] )? T_OD )? ']|'
+            {
+            	// ooa.g:281:9: ( T_AUTOCONS )?
+            	int alt19 = 2;
+            	int LA19_0 = input.LA(1);
+
+            	if ( (LA19_0 == T_AUTOCONS) )
+            	{
+            	    alt19 = 1;
+            	}
+            	switch (alt19) 
+            	{
+            	    case 1 :
+            	        // ooa.g:281:10: T_AUTOCONS
+            	        {
+            	        	Match(input,T_AUTOCONS,FOLLOW_T_AUTOCONS_in_ooActionSystem846); 
+            	        	autoCons = true;
+
+            	        }
+            	        break;
+
+            	}
+
+            	Match(input,T_SYSTEM,FOLLOW_T_SYSTEM_in_ooActionSystem855); 
+            	// ooa.g:282:12: ( T_LPAREN refinesSystemName= T_IDENTIFIER T_RPAREN )?
+            	int alt20 = 2;
+            	int LA20_0 = input.LA(1);
+
+            	if ( (LA20_0 == T_LPAREN) )
+            	{
+            	    alt20 = 1;
+            	}
+            	switch (alt20) 
+            	{
+            	    case 1 :
+            	        // ooa.g:282:13: T_LPAREN refinesSystemName= T_IDENTIFIER T_RPAREN
+            	        {
+            	        	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_ooActionSystem858); 
+            	        	refinesSystemName=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_ooActionSystem862); 
+            	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_ooActionSystem864); 
+
+            	        }
+            	        break;
+
+            	}
+
+            	aTypeSymbol = createOoaType(refinesSystemName,autoCons);
+            	Match(input,117,FOLLOW_117_in_ooActionSystem877); 
+            	// ooa.g:285:4: ( T_VAR attrList )?
+            	int alt21 = 2;
+            	int LA21_0 = input.LA(1);
+
+            	if ( (LA21_0 == T_VAR) )
+            	{
+            	    alt21 = 1;
+            	}
+            	switch (alt21) 
+            	{
+            	    case 1 :
+            	        // ooa.g:285:5: T_VAR attrList
+            	        {
+            	        	Match(input,T_VAR,FOLLOW_T_VAR_in_ooActionSystem883); 
+            	        	PushFollow(FOLLOW_attrList_in_ooActionSystem885);
+            	        	attrList();
+            	        	state.followingStackPointer--;
+
+
+            	        }
+            	        break;
+
+            	}
+
+            	// ooa.g:286:4: ( T_METHODS methodList )?
+            	int alt22 = 2;
+            	int LA22_0 = input.LA(1);
+
+            	if ( (LA22_0 == T_METHODS) )
+            	{
+            	    alt22 = 1;
+            	}
+            	switch (alt22) 
+            	{
+            	    case 1 :
+            	        // ooa.g:286:5: T_METHODS methodList
+            	        {
+            	        	Match(input,T_METHODS,FOLLOW_T_METHODS_in_ooActionSystem893); 
+            	        	PushFollow(FOLLOW_methodList_in_ooActionSystem895);
+            	        	methodList();
+            	        	state.followingStackPointer--;
+
+
+            	        }
+            	        break;
+
+            	}
+
+            	// ooa.g:287:4: ( T_ACTIONS namedActionList )?
+            	int alt23 = 2;
+            	int LA23_0 = input.LA(1);
+
+            	if ( (LA23_0 == T_ACTIONS) )
+            	{
+            	    alt23 = 1;
+            	}
+            	switch (alt23) 
+            	{
+            	    case 1 :
+            	        // ooa.g:287:5: T_ACTIONS namedActionList
+            	        {
+            	        	Match(input,T_ACTIONS,FOLLOW_T_ACTIONS_in_ooActionSystem903); 
+            	        	PushFollow(FOLLOW_namedActionList_in_ooActionSystem905);
+            	        	namedActionList();
+            	        	state.followingStackPointer--;
+
+
+            	        }
+            	        break;
+
+            	}
+
+            	// ooa.g:288:4: ( T_DO (bl= actionBlock[null] )? T_OD )?
+            	int alt25 = 2;
+            	int LA25_0 = input.LA(1);
+
+            	if ( (LA25_0 == T_DO) )
+            	{
+            	    alt25 = 1;
+            	}
+            	switch (alt25) 
+            	{
+            	    case 1 :
+            	        // ooa.g:288:5: T_DO (bl= actionBlock[null] )? T_OD
+            	        {
+            	        	Match(input,T_DO,FOLLOW_T_DO_in_ooActionSystem913); 
+            	        	// ooa.g:288:10: (bl= actionBlock[null] )?
+            	        	int alt24 = 2;
+            	        	int LA24_0 = input.LA(1);
+
+            	        	if ( (LA24_0 == T_IDENTIFIER || LA24_0 == T_LPAREN || LA24_0 == T_VAR || (LA24_0 >= T_CONT && LA24_0 <= T_REQUIRES) || LA24_0 == T_SKIP) )
+            	        	{
+            	        	    alt24 = 1;
+            	        	}
+            	        	switch (alt24) 
+            	        	{
+            	        	    case 1 :
+            	        	        // ooa.g:288:11: bl= actionBlock[null]
+            	        	        {
+            	        	        	PushFollow(FOLLOW_actionBlock_in_ooActionSystem918);
+            	        	        	bl = actionBlock(null);
+            	        	        	state.followingStackPointer--;
+
+            	        	        	addActionBlock(aTypeSymbol,bl);
+
+            	        	        }
+            	        	        break;
+
+            	        	}
+
+            	        	Match(input,T_OD,FOLLOW_T_OD_in_ooActionSystem925); 
+
+            	        }
+            	        break;
+
+            	}
+
+            	Match(input,118,FOLLOW_118_in_ooActionSystem931); 
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            fixupOoaType(aTypeSymbol);
+        }
+        return aTypeSymbol;
+    }
+    // $ANTLR end "ooActionSystem"
+
+
+    // $ANTLR start "attrList"
+    // ooa.g:300:1: attrList : attr ( T_SEMICOLON attr )* ;
+    public void attrList() // throws RecognitionException [1]
+    {   
+        try 
+    	{
+            // ooa.g:301:2: ( attr ( T_SEMICOLON attr )* )
+            // ooa.g:301:4: attr ( T_SEMICOLON attr )*
+            {
+            	BeginParsingAttributes();
+            	PushFollow(FOLLOW_attr_in_attrList962);
+            	attr();
+            	state.followingStackPointer--;
+
+            	// ooa.g:302:9: ( T_SEMICOLON attr )*
+            	do 
+            	{
+            	    int alt26 = 2;
+            	    int LA26_0 = input.LA(1);
+
+            	    if ( (LA26_0 == T_SEMICOLON) )
+            	    {
+            	        alt26 = 1;
+            	    }
+
+
+            	    switch (alt26) 
+            		{
+            			case 1 :
+            			    // ooa.g:302:10: T_SEMICOLON attr
+            			    {
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_attrList965); 
+            			    	PushFollow(FOLLOW_attr_in_attrList967);
+            			    	attr();
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop26;
+            	    }
+            	} while (true);
+
+            	loop26:
+            		;	// Stops C# compiler whining that label 'loop26' has no statements
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+
+            		EndParsingAttributes();
+            	
+        }
+        return ;
+    }
+    // $ANTLR end "attrList"
+
+
+    // $ANTLR start "attr"
+    // ooa.g:308:1: attr : ( T_STATIC )? ( T_OBS | T_CTRL )? varname= T_IDENTIFIER T_COLON aType= complexType ( T_EQUAL anExpr= expression )? ;
+    public void attr() // throws RecognitionException [1]
+    {   
+        IToken varname = null;
+        UlyssesType aType = default(UlyssesType);
+
+        Expression anExpr = default(Expression);
+
+
+         
+        		bool isStatic = false; 
+        		bool isCtr = false;
+        		bool isObs = false;				
+        		
+        	
+        try 
+    	{
+            // ooa.g:315:2: ( ( T_STATIC )? ( T_OBS | T_CTRL )? varname= T_IDENTIFIER T_COLON aType= complexType ( T_EQUAL anExpr= expression )? )
+            // ooa.g:315:5: ( T_STATIC )? ( T_OBS | T_CTRL )? varname= T_IDENTIFIER T_COLON aType= complexType ( T_EQUAL anExpr= expression )?
+            {
+            	// ooa.g:315:5: ( T_STATIC )?
+            	int alt27 = 2;
+            	int LA27_0 = input.LA(1);
+
+            	if ( (LA27_0 == T_STATIC) )
+            	{
+            	    alt27 = 1;
+            	}
+            	switch (alt27) 
+            	{
+            	    case 1 :
+            	        // ooa.g:315:6: T_STATIC
+            	        {
+            	        	Match(input,T_STATIC,FOLLOW_T_STATIC_in_attr992); 
+            	        	isStatic = true;
+
+            	        }
+            	        break;
+
+            	}
+
+            	// ooa.g:315:36: ( T_OBS | T_CTRL )?
+            	int alt28 = 3;
+            	int LA28_0 = input.LA(1);
+
+            	if ( (LA28_0 == T_OBS) )
+            	{
+            	    alt28 = 1;
+            	}
+            	else if ( (LA28_0 == T_CTRL) )
+            	{
+            	    alt28 = 2;
+            	}
+            	switch (alt28) 
+            	{
+            	    case 1 :
+            	        // ooa.g:315:37: T_OBS
+            	        {
+            	        	Match(input,T_OBS,FOLLOW_T_OBS_in_attr999); 
+            	        	isObs = true;
+
+            	        }
+            	        break;
+            	    case 2 :
+            	        // ooa.g:315:61: T_CTRL
+            	        {
+            	        	Match(input,T_CTRL,FOLLOW_T_CTRL_in_attr1005); 
+            	        	isCtr = true;
+
+            	        }
+            	        break;
+
+            	}
+
+            	varname=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_attr1016); 
+            	Match(input,T_COLON,FOLLOW_T_COLON_in_attr1019); 
+            	PushFollow(FOLLOW_complexType_in_attr1023);
+            	aType = complexType();
+            	state.followingStackPointer--;
+
+            	// ooa.g:316:51: ( T_EQUAL anExpr= expression )?
+            	int alt29 = 2;
+            	int LA29_0 = input.LA(1);
+
+            	if ( (LA29_0 == T_EQUAL) )
+            	{
+            	    alt29 = 1;
+            	}
+            	switch (alt29) 
+            	{
+            	    case 1 :
+            	        // ooa.g:316:52: T_EQUAL anExpr= expression
+            	        {
+            	        	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_attr1026); 
+            	        	PushFollow(FOLLOW_expression_in_attr1030);
+            	        	anExpr = expression();
+            	        	state.followingStackPointer--;
+
+
+            	        }
+            	        break;
+
+            	}
+
+            	createAttribute(varname, isStatic, isObs, isCtr, aType, anExpr);
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "attr"
+
+
+    // $ANTLR start "methodList"
+    // ooa.g:323:1: methodList : method ( T_SEMICOLON method )* ;
+    public void methodList() // throws RecognitionException [1]
+    {   
+        try 
+    	{
+            // ooa.g:324:2: ( method ( T_SEMICOLON method )* )
+            // ooa.g:324:5: method ( T_SEMICOLON method )*
+            {
+            	PushFollow(FOLLOW_method_in_methodList1052);
+            	method();
+            	state.followingStackPointer--;
+
+            	// ooa.g:324:12: ( T_SEMICOLON method )*
+            	do 
+            	{
+            	    int alt30 = 2;
+            	    int LA30_0 = input.LA(1);
+
+            	    if ( (LA30_0 == T_SEMICOLON) )
+            	    {
+            	        alt30 = 1;
+            	    }
+
+
+            	    switch (alt30) 
+            		{
+            			case 1 :
+            			    // ooa.g:324:13: T_SEMICOLON method
+            			    {
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_methodList1055); 
+            			    	PushFollow(FOLLOW_method_in_methodList1057);
+            			    	method();
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop30;
+            	    }
+            	} while (true);
+
+            	loop30:
+            		;	// Stops C# compiler whining that label 'loop30' has no statements
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "methodList"
+
+
+    // $ANTLR start "method"
+    // ooa.g:327:1: method : mname= T_IDENTIFIER ( T_LPAREN methodParameterList[newMethod] T_RPAREN )? ( T_COLON rt= complexType )? T_EQUAL ( T_VAR localActionVars[newMethod] 'begin' )? statements= actionBody[null] T_END ;
+    public void method() // throws RecognitionException [1]
+    {   
+        IToken mname = null;
+        UlyssesType rt = default(UlyssesType);
+
+        Block statements = default(Block);
+
+
+        	
+        		FunctionIdentifier newMethod = null;
+        	
+        try 
+    	{
+            // ooa.g:331:2: (mname= T_IDENTIFIER ( T_LPAREN methodParameterList[newMethod] T_RPAREN )? ( T_COLON rt= complexType )? T_EQUAL ( T_VAR localActionVars[newMethod] 'begin' )? statements= actionBody[null] T_END )
+            // ooa.g:331:4: mname= T_IDENTIFIER ( T_LPAREN methodParameterList[newMethod] T_RPAREN )? ( T_COLON rt= complexType )? T_EQUAL ( T_VAR localActionVars[newMethod] 'begin' )? statements= actionBody[null] T_END
+            {
+            	mname=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_method1079); 
+            	newMethod = createMethodSymbol(mname);
+            	// ooa.g:332:3: ( T_LPAREN methodParameterList[newMethod] T_RPAREN )?
+            	int alt31 = 2;
+            	int LA31_0 = input.LA(1);
+
+            	if ( (LA31_0 == T_LPAREN) )
+            	{
+            	    alt31 = 1;
+            	}
+            	switch (alt31) 
+            	{
+            	    case 1 :
+            	        // ooa.g:332:4: T_LPAREN methodParameterList[newMethod] T_RPAREN
+            	        {
+            	        	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_method1087); 
+            	        	PushFollow(FOLLOW_methodParameterList_in_method1089);
+            	        	methodParameterList(newMethod);
+            	        	state.followingStackPointer--;
+
+            	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_method1093); 
+
+            	        }
+            	        break;
+
+            	}
+
+            	// ooa.g:333:3: ( T_COLON rt= complexType )?
+            	int alt32 = 2;
+            	int LA32_0 = input.LA(1);
+
+            	if ( (LA32_0 == T_COLON) )
+            	{
+            	    alt32 = 1;
+            	}
+            	switch (alt32) 
+            	{
+            	    case 1 :
+            	        // ooa.g:333:4: T_COLON rt= complexType
+            	        {
+            	        	Match(input,T_COLON,FOLLOW_T_COLON_in_method1101); 
+            	        	PushFollow(FOLLOW_complexType_in_method1105);
+            	        	rt = complexType();
+            	        	state.followingStackPointer--;
+
+            	        	setMethodReturnType(newMethod,rt);
+
+            	        }
+            	        break;
+
+            	}
+
+            	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_method1115); 
+            	// ooa.g:335:4: ( T_VAR localActionVars[newMethod] 'begin' )?
+            	int alt33 = 2;
+            	int LA33_0 = input.LA(1);
+
+            	if ( (LA33_0 == T_VAR) )
+            	{
+            	    alt33 = 1;
+            	}
+            	switch (alt33) 
+            	{
+            	    case 1 :
+            	        // ooa.g:335:5: T_VAR localActionVars[newMethod] 'begin'
+            	        {
+            	        	Match(input,T_VAR,FOLLOW_T_VAR_in_method1122); 
+            	        	PushFollow(FOLLOW_localActionVars_in_method1124);
+            	        	localActionVars(newMethod);
+            	        	state.followingStackPointer--;
+
+            	        	Match(input,119,FOLLOW_119_in_method1127); 
+
+            	        }
+            	        break;
+
+            	}
+
+            	PushFollow(FOLLOW_actionBody_in_method1136);
+            	statements = actionBody(null);
+            	state.followingStackPointer--;
+
+            	addMethodBody(newMethod,statements);
+            	Match(input,T_END,FOLLOW_T_END_in_method1144); 
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            popResolveStack(newMethod);
+        }
+        return ;
+    }
+    // $ANTLR end "method"
+
+
+    // $ANTLR start "methodParameterList"
+    // ooa.g:342:1: methodParameterList[FunctionIdentifier newMethod] : paramName= T_IDENTIFIER T_COLON atype= complexType ( T_COMMA otherparam= T_IDENTIFIER T_COLON othertype= complexType )* ;
+    public void methodParameterList(FunctionIdentifier newMethod) // throws RecognitionException [1]
+    {   
+        IToken paramName = null;
+        IToken otherparam = null;
+        UlyssesType atype = default(UlyssesType);
+
+        UlyssesType othertype = default(UlyssesType);
+
+
+        try 
+    	{
+            // ooa.g:343:2: (paramName= T_IDENTIFIER T_COLON atype= complexType ( T_COMMA otherparam= T_IDENTIFIER T_COLON othertype= complexType )* )
+            // ooa.g:343:5: paramName= T_IDENTIFIER T_COLON atype= complexType ( T_COMMA otherparam= T_IDENTIFIER T_COLON othertype= complexType )*
+            {
+            	paramName=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_methodParameterList1168); 
+            	Match(input,T_COLON,FOLLOW_T_COLON_in_methodParameterList1170); 
+            	PushFollow(FOLLOW_complexType_in_methodParameterList1174);
+            	atype = complexType();
+            	state.followingStackPointer--;
+
+            	addMethodParameter(newMethod,paramName,atype);
+            	// ooa.g:344:4: ( T_COMMA otherparam= T_IDENTIFIER T_COLON othertype= complexType )*
+            	do 
+            	{
+            	    int alt34 = 2;
+            	    int LA34_0 = input.LA(1);
+
+            	    if ( (LA34_0 == T_COMMA) )
+            	    {
+            	        alt34 = 1;
+            	    }
+
+
+            	    switch (alt34) 
+            		{
+            			case 1 :
+            			    // ooa.g:344:5: T_COMMA otherparam= T_IDENTIFIER T_COLON othertype= complexType
+            			    {
+            			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_methodParameterList1182); 
+            			    	otherparam=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_methodParameterList1186); 
+            			    	Match(input,T_COLON,FOLLOW_T_COLON_in_methodParameterList1188); 
+            			    	PushFollow(FOLLOW_complexType_in_methodParameterList1192);
+            			    	othertype = complexType();
+            			    	state.followingStackPointer--;
+
+            			    	addMethodParameter(newMethod,otherparam,othertype);
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop34;
+            	    }
+            	} while (true);
+
+            	loop34:
+            		;	// Stops C# compiler whining that label 'loop34' has no statements
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "methodParameterList"
+
+
+    // $ANTLR start "namedActionList"
+    // ooa.g:353:1: namedActionList : namedAction ( T_SEMICOLON namedAction )* ;
+    public void namedActionList() // throws RecognitionException [1]
+    {   
+        try 
+    	{
+            // ooa.g:354:2: ( namedAction ( T_SEMICOLON namedAction )* )
+            // ooa.g:354:4: namedAction ( T_SEMICOLON namedAction )*
+            {
+            	PushFollow(FOLLOW_namedAction_in_namedActionList1219);
+            	namedAction();
+            	state.followingStackPointer--;
+
+            	// ooa.g:354:16: ( T_SEMICOLON namedAction )*
+            	do 
+            	{
+            	    int alt35 = 2;
+            	    int LA35_0 = input.LA(1);
+
+            	    if ( (LA35_0 == T_SEMICOLON) )
+            	    {
+            	        alt35 = 1;
+            	    }
+
+
+            	    switch (alt35) 
+            		{
+            			case 1 :
+            			    // ooa.g:354:17: T_SEMICOLON namedAction
+            			    {
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_namedActionList1222); 
+            			    	PushFollow(FOLLOW_namedAction_in_namedActionList1224);
+            			    	namedAction();
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop35;
+            	    }
+            	} while (true);
+
+            	loop35:
+            		;	// Stops C# compiler whining that label 'loop35' has no statements
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "namedActionList"
+
+
+    // $ANTLR start "namedAction"
+    // ooa.g:357:1: namedAction : ( T_CONT cactionname= T_IDENTIFIER ( T_LPAREN methodParameterList[newAction] T_RPAREN )? T_EQUAL constraints= continuousActionBody | ( T_CTRL | T_OBS | ) actionname= T_IDENTIFIER ( T_LPAREN methodParameterList[newAction] T_RPAREN )? T_EQUAL ( T_VAR localActionVars[newAction] )? body= discreteActionBody );
+    public void namedAction() // throws RecognitionException [1]
+    {   
+        IToken cactionname = null;
+        IToken actionname = null;
+        GuardedCommand constraints = default(GuardedCommand);
+
+        GuardedCommand body = default(GuardedCommand);
+
+
+
+        		FunctionTypeEnum actionType;
+        		FunctionIdentifier newAction = null;
+        	
+        try 
+    	{
+            // ooa.g:362:2: ( T_CONT cactionname= T_IDENTIFIER ( T_LPAREN methodParameterList[newAction] T_RPAREN )? T_EQUAL constraints= continuousActionBody | ( T_CTRL | T_OBS | ) actionname= T_IDENTIFIER ( T_LPAREN methodParameterList[newAction] T_RPAREN )? T_EQUAL ( T_VAR localActionVars[newAction] )? body= discreteActionBody )
+            int alt40 = 2;
+            int LA40_0 = input.LA(1);
+
+            if ( (LA40_0 == T_CONT) )
+            {
+                alt40 = 1;
+            }
+            else if ( (LA40_0 == T_IDENTIFIER || (LA40_0 >= T_OBS && LA40_0 <= T_CTRL)) )
+            {
+                alt40 = 2;
+            }
+            else 
+            {
+                NoViableAltException nvae_d40s0 =
+                    new NoViableAltException("", 40, 0, input);
+
+                throw nvae_d40s0;
+            }
+            switch (alt40) 
+            {
+                case 1 :
+                    // ooa.g:362:4: T_CONT cactionname= T_IDENTIFIER ( T_LPAREN methodParameterList[newAction] T_RPAREN )? T_EQUAL constraints= continuousActionBody
+                    {
+                    	Match(input,T_CONT,FOLLOW_T_CONT_in_namedAction1244); 
+                    	cactionname=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_namedAction1248); 
+                    	newAction = createNamedContinuousAction(cactionname, FunctionTypeEnum.Continuous);
+                    	// ooa.g:363:3: ( T_LPAREN methodParameterList[newAction] T_RPAREN )?
+                    	int alt36 = 2;
+                    	int LA36_0 = input.LA(1);
+
+                    	if ( (LA36_0 == T_LPAREN) )
+                    	{
+                    	    alt36 = 1;
+                    	}
+                    	switch (alt36) 
+                    	{
+                    	    case 1 :
+                    	        // ooa.g:363:4: T_LPAREN methodParameterList[newAction] T_RPAREN
+                    	        {
+                    	        	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_namedAction1256); 
+                    	        	PushFollow(FOLLOW_methodParameterList_in_namedAction1258);
+                    	        	methodParameterList(newAction);
+                    	        	state.followingStackPointer--;
+
+                    	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_namedAction1262); 
+
+                    	        }
+                    	        break;
+
+                    	}
+
+                    	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_namedAction1269); 
+                    	PushFollow(FOLLOW_continuousActionBody_in_namedAction1273);
+                    	constraints = continuousActionBody();
+                    	state.followingStackPointer--;
+
+                    	addContinuousActionBody(newAction,constraints);
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:366:4: ( T_CTRL | T_OBS | ) actionname= T_IDENTIFIER ( T_LPAREN methodParameterList[newAction] T_RPAREN )? T_EQUAL ( T_VAR localActionVars[newAction] )? body= discreteActionBody
+                    {
+                    	actionType = FunctionTypeEnum.Internal;
+                    	// ooa.g:367:3: ( T_CTRL | T_OBS | )
+                    	int alt37 = 3;
+                    	switch ( input.LA(1) ) 
+                    	{
+                    	case T_CTRL:
+                    		{
+                    	    alt37 = 1;
+                    	    }
+                    	    break;
+                    	case T_OBS:
+                    		{
+                    	    alt37 = 2;
+                    	    }
+                    	    break;
+                    	case T_IDENTIFIER:
+                    		{
+                    	    alt37 = 3;
+                    	    }
+                    	    break;
+                    		default:
+                    		    NoViableAltException nvae_d37s0 =
+                    		        new NoViableAltException("", 37, 0, input);
+
+                    		    throw nvae_d37s0;
+                    	}
+
+                    	switch (alt37) 
+                    	{
+                    	    case 1 :
+                    	        // ooa.g:367:4: T_CTRL
+                    	        {
+                    	        	Match(input,T_CTRL,FOLLOW_T_CTRL_in_namedAction1288); 
+                    	        	actionType = FunctionTypeEnum.Controllable;
+
+                    	        }
+                    	        break;
+                    	    case 2 :
+                    	        // ooa.g:367:58: T_OBS
+                    	        {
+                    	        	Match(input,T_OBS,FOLLOW_T_OBS_in_namedAction1293); 
+                    	        	actionType = FunctionTypeEnum.Observable;
+
+                    	        }
+                    	        break;
+                    	    case 3 :
+                    	        // ooa.g:367:109: 
+                    	        {
+                    	        }
+                    	        break;
+
+                    	}
+
+                    	actionname=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_namedAction1305); 
+                    	newAction = createNamedAction(actionname,actionType);
+                    	// ooa.g:369:3: ( T_LPAREN methodParameterList[newAction] T_RPAREN )?
+                    	int alt38 = 2;
+                    	int LA38_0 = input.LA(1);
+
+                    	if ( (LA38_0 == T_LPAREN) )
+                    	{
+                    	    alt38 = 1;
+                    	}
+                    	switch (alt38) 
+                    	{
+                    	    case 1 :
+                    	        // ooa.g:369:4: T_LPAREN methodParameterList[newAction] T_RPAREN
+                    	        {
+                    	        	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_namedAction1313); 
+                    	        	PushFollow(FOLLOW_methodParameterList_in_namedAction1315);
+                    	        	methodParameterList(newAction);
+                    	        	state.followingStackPointer--;
+
+                    	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_namedAction1319); 
+
+                    	        }
+                    	        break;
+
+                    	}
+
+                    	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_namedAction1326); 
+                    	// ooa.g:371:3: ( T_VAR localActionVars[newAction] )?
+                    	int alt39 = 2;
+                    	int LA39_0 = input.LA(1);
+
+                    	if ( (LA39_0 == T_VAR) )
+                    	{
+                    	    alt39 = 1;
+                    	}
+                    	switch (alt39) 
+                    	{
+                    	    case 1 :
+                    	        // ooa.g:371:4: T_VAR localActionVars[newAction]
+                    	        {
+                    	        	Match(input,T_VAR,FOLLOW_T_VAR_in_namedAction1332); 
+                    	        	PushFollow(FOLLOW_localActionVars_in_namedAction1334);
+                    	        	localActionVars(newAction);
+                    	        	state.followingStackPointer--;
+
+
+                    	        }
+                    	        break;
+
+                    	}
+
+                    	PushFollow(FOLLOW_discreteActionBody_in_namedAction1345);
+                    	body = discreteActionBody();
+                    	state.followingStackPointer--;
+
+                    	addActionBody(newAction,body);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            popResolveStack(newAction);
+        }
+        return ;
+    }
+    // $ANTLR end "namedAction"
+
+
+    // $ANTLR start "localActionVars"
+    // ooa.g:379:1: localActionVars[FunctionIdentifier newMethod] : id1= T_IDENTIFIER T_COLON t1= complexType ( T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType )* ;
+    public void localActionVars(FunctionIdentifier newMethod) // throws RecognitionException [1]
+    {   
+        IToken id1 = null;
+        IToken id2 = null;
+        UlyssesType t1 = default(UlyssesType);
+
+        UlyssesType t2 = default(UlyssesType);
+
+
+        try 
+    	{
+            // ooa.g:380:2: (id1= T_IDENTIFIER T_COLON t1= complexType ( T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType )* )
+            // ooa.g:381:3: id1= T_IDENTIFIER T_COLON t1= complexType ( T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType )*
+            {
+            	id1=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_localActionVars1377); 
+            	Match(input,T_COLON,FOLLOW_T_COLON_in_localActionVars1379); 
+            	PushFollow(FOLLOW_complexType_in_localActionVars1383);
+            	t1 = complexType();
+            	state.followingStackPointer--;
+
+            	addLocalVariableToNamedAction(newMethod,id1,t1);
+            	// ooa.g:382:4: ( T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType )*
+            	do 
+            	{
+            	    int alt41 = 2;
+            	    int LA41_0 = input.LA(1);
+
+            	    if ( (LA41_0 == T_SEMICOLON) )
+            	    {
+            	        alt41 = 1;
+            	    }
+
+
+            	    switch (alt41) 
+            		{
+            			case 1 :
+            			    // ooa.g:382:5: T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType
+            			    {
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_localActionVars1392); 
+            			    	id2=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_localActionVars1396); 
+            			    	Match(input,T_COLON,FOLLOW_T_COLON_in_localActionVars1398); 
+            			    	PushFollow(FOLLOW_complexType_in_localActionVars1402);
+            			    	t2 = complexType();
+            			    	state.followingStackPointer--;
+
+            			    	addLocalVariableToNamedAction(newMethod,id2,t2);
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop41;
+            	    }
+            	} while (true);
+
+            	loop41:
+            		;	// Stops C# compiler whining that label 'loop41' has no statements
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "localActionVars"
+
+
+    // $ANTLR start "anonymousAction"
+    // ooa.g:388:1: anonymousAction returns [GuardedCommand result] : (a= continuousActionBody | b= discreteActionBody );
+    public GuardedCommand anonymousAction() // throws RecognitionException [1]
+    {   
+        GuardedCommand result = default(GuardedCommand);
+
+        GuardedCommand a = default(GuardedCommand);
+
+        GuardedCommand b = default(GuardedCommand);
+
+
+        try 
+    	{
+            // ooa.g:390:2: (a= continuousActionBody | b= discreteActionBody )
+            int alt42 = 2;
+            int LA42_0 = input.LA(1);
+
+            if ( (LA42_0 == T_CONT) )
+            {
+                alt42 = 1;
+            }
+            else if ( (LA42_0 == T_REQUIRES) )
+            {
+                alt42 = 2;
+            }
+            else 
+            {
+                NoViableAltException nvae_d42s0 =
+                    new NoViableAltException("", 42, 0, input);
+
+                throw nvae_d42s0;
+            }
+            switch (alt42) 
+            {
+                case 1 :
+                    // ooa.g:390:4: a= continuousActionBody
+                    {
+                    	PushFollow(FOLLOW_continuousActionBody_in_anonymousAction1432);
+                    	a = continuousActionBody();
+                    	state.followingStackPointer--;
+
+                    	result = a;
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:391:4: b= discreteActionBody
+                    {
+                    	PushFollow(FOLLOW_discreteActionBody_in_anonymousAction1441);
+                    	b = discreteActionBody();
+                    	state.followingStackPointer--;
+
+                    	result = b;
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return result;
+    }
+    // $ANTLR end "anonymousAction"
+
+
+    // $ANTLR start "continuousActionBody"
+    // ooa.g:394:1: continuousActionBody returns [GuardedCommand result] : T_CONT T_REQUIRES expr= expression T_COLON bdy= qualConstraintList T_END ;
+    public GuardedCommand continuousActionBody() // throws RecognitionException [1]
+    {   
+        GuardedCommand result = default(GuardedCommand);
+
+        Expression expr = default(Expression);
+
+        Block bdy = default(Block);
+
+
+
+        		result = null;
+        	
+        try 
+    	{
+            // ooa.g:399:2: ( T_CONT T_REQUIRES expr= expression T_COLON bdy= qualConstraintList T_END )
+            // ooa.g:399:4: T_CONT T_REQUIRES expr= expression T_COLON bdy= qualConstraintList T_END
+            {
+            	Match(input,T_CONT,FOLLOW_T_CONT_in_continuousActionBody1466); 
+            	Match(input,T_REQUIRES,FOLLOW_T_REQUIRES_in_continuousActionBody1468); 
+            	PushFollow(FOLLOW_expression_in_continuousActionBody1472);
+            	expr = expression();
+            	state.followingStackPointer--;
+
+            	Match(input,T_COLON,FOLLOW_T_COLON_in_continuousActionBody1474); 
+            	PushFollow(FOLLOW_qualConstraintList_in_continuousActionBody1481);
+            	bdy = qualConstraintList();
+            	state.followingStackPointer--;
+
+            	Match(input,T_END,FOLLOW_T_END_in_continuousActionBody1486); 
+            	result = createGuardedCommandStatement(expr,bdy,true);
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return result;
+    }
+    // $ANTLR end "continuousActionBody"
+
+
+    // $ANTLR start "qualConstraintList"
+    // ooa.g:405:1: qualConstraintList returns [Block result] : stmt= qualConstraint ( T_COMMA ostmt= qualConstraint )* ;
+    public Block qualConstraintList() // throws RecognitionException [1]
+    {   
+        Block result = default(Block);
+
+        QualitativeConstraintStatement stmt = default(QualitativeConstraintStatement);
+
+        QualitativeConstraintStatement ostmt = default(QualitativeConstraintStatement);
+
+
+
+        		result = createSeqBlock(null);
+        		pushBlockToResolveStack(result);
+        	
+        try 
+    	{
+            // ooa.g:411:2: (stmt= qualConstraint ( T_COMMA ostmt= qualConstraint )* )
+            // ooa.g:411:4: stmt= qualConstraint ( T_COMMA ostmt= qualConstraint )*
+            {
+            	PushFollow(FOLLOW_qualConstraint_in_qualConstraintList1514);
+            	stmt = qualConstraint();
+            	state.followingStackPointer--;
+
+            	addToBlockList(result,stmt);
+            	// ooa.g:412:3: ( T_COMMA ostmt= qualConstraint )*
+            	do 
+            	{
+            	    int alt43 = 2;
+            	    int LA43_0 = input.LA(1);
+
+            	    if ( (LA43_0 == T_COMMA) )
+            	    {
+            	        alt43 = 1;
+            	    }
+
+
+            	    switch (alt43) 
+            		{
+            			case 1 :
+            			    // ooa.g:412:4: T_COMMA ostmt= qualConstraint
+            			    {
+            			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_qualConstraintList1521); 
+            			    	PushFollow(FOLLOW_qualConstraint_in_qualConstraintList1525);
+            			    	ostmt = qualConstraint();
+            			    	state.followingStackPointer--;
+
+            			    	addToBlockList(result,ostmt);
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop43;
+            	    }
+            	} while (true);
+
+            	loop43:
+            		;	// Stops C# compiler whining that label 'loop43' has no statements
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            popBlockFromResolveStack(result);
+        }
+        return result;
+    }
+    // $ANTLR end "qualConstraintList"
+
+
+    // $ANTLR start "qualConstraint"
+    // ooa.g:419:1: qualConstraint returns [QualitativeConstraintStatement result] : id1= T_IDENTIFIER T_EQUAL ( T_DERIV derivid= T_IDENTIFIER | id2= T_IDENTIFIER ( (op= T_SUM | op= T_DIFF | op= T_PROD ) id3= T_IDENTIFIER | ) ) ;
+    public QualitativeConstraintStatement qualConstraint() // throws RecognitionException [1]
+    {   
+        QualitativeConstraintStatement result = default(QualitativeConstraintStatement);
+
+        IToken id1 = null;
+        IToken derivid = null;
+        IToken id2 = null;
+        IToken op = null;
+        IToken id3 = null;
+
+        try 
+    	{
+            // ooa.g:421:2: (id1= T_IDENTIFIER T_EQUAL ( T_DERIV derivid= T_IDENTIFIER | id2= T_IDENTIFIER ( (op= T_SUM | op= T_DIFF | op= T_PROD ) id3= T_IDENTIFIER | ) ) )
+            // ooa.g:421:4: id1= T_IDENTIFIER T_EQUAL ( T_DERIV derivid= T_IDENTIFIER | id2= T_IDENTIFIER ( (op= T_SUM | op= T_DIFF | op= T_PROD ) id3= T_IDENTIFIER | ) )
+            {
+            	id1=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_qualConstraint1556); 
+            	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_qualConstraint1558); 
+            	// ooa.g:422:3: ( T_DERIV derivid= T_IDENTIFIER | id2= T_IDENTIFIER ( (op= T_SUM | op= T_DIFF | op= T_PROD ) id3= T_IDENTIFIER | ) )
+            	int alt46 = 2;
+            	int LA46_0 = input.LA(1);
+
+            	if ( (LA46_0 == T_DERIV) )
+            	{
+            	    alt46 = 1;
+            	}
+            	else if ( (LA46_0 == T_IDENTIFIER) )
+            	{
+            	    alt46 = 2;
+            	}
+            	else 
+            	{
+            	    NoViableAltException nvae_d46s0 =
+            	        new NoViableAltException("", 46, 0, input);
+
+            	    throw nvae_d46s0;
+            	}
+            	switch (alt46) 
+            	{
+            	    case 1 :
+            	        // ooa.g:422:5: T_DERIV derivid= T_IDENTIFIER
+            	        {
+            	        	Match(input,T_DERIV,FOLLOW_T_DERIV_in_qualConstraint1565); 
+            	        	derivid=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_qualConstraint1569); 
+            	        	result = createQualDerivConstraintStatement(id1,derivid);
+
+            	        }
+            	        break;
+            	    case 2 :
+            	        // ooa.g:426:11: id2= T_IDENTIFIER ( (op= T_SUM | op= T_DIFF | op= T_PROD ) id3= T_IDENTIFIER | )
+            	        {
+            	        	id2=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_qualConstraint1604); 
+            	        	// ooa.g:427:11: ( (op= T_SUM | op= T_DIFF | op= T_PROD ) id3= T_IDENTIFIER | )
+            	        	int alt45 = 2;
+            	        	int LA45_0 = input.LA(1);
+
+            	        	if ( ((LA45_0 >= T_SUM && LA45_0 <= T_PROD)) )
+            	        	{
+            	        	    alt45 = 1;
+            	        	}
+            	        	else if ( (LA45_0 == T_COMMA || LA45_0 == T_END) )
+            	        	{
+            	        	    alt45 = 2;
+            	        	}
+            	        	else 
+            	        	{
+            	        	    NoViableAltException nvae_d45s0 =
+            	        	        new NoViableAltException("", 45, 0, input);
+
+            	        	    throw nvae_d45s0;
+            	        	}
+            	        	switch (alt45) 
+            	        	{
+            	        	    case 1 :
+            	        	        // ooa.g:428:12: (op= T_SUM | op= T_DIFF | op= T_PROD ) id3= T_IDENTIFIER
+            	        	        {
+            	        	        	// ooa.g:428:12: (op= T_SUM | op= T_DIFF | op= T_PROD )
+            	        	        	int alt44 = 3;
+            	        	        	switch ( input.LA(1) ) 
+            	        	        	{
+            	        	        	case T_SUM:
+            	        	        		{
+            	        	        	    alt44 = 1;
+            	        	        	    }
+            	        	        	    break;
+            	        	        	case T_DIFF:
+            	        	        		{
+            	        	        	    alt44 = 2;
+            	        	        	    }
+            	        	        	    break;
+            	        	        	case T_PROD:
+            	        	        		{
+            	        	        	    alt44 = 3;
+            	        	        	    }
+            	        	        	    break;
+            	        	        		default:
+            	        	        		    NoViableAltException nvae_d44s0 =
+            	        	        		        new NoViableAltException("", 44, 0, input);
+
+            	        	        		    throw nvae_d44s0;
+            	        	        	}
+
+            	        	        	switch (alt44) 
+            	        	        	{
+            	        	        	    case 1 :
+            	        	        	        // ooa.g:428:14: op= T_SUM
+            	        	        	        {
+            	        	        	        	op=(IToken)Match(input,T_SUM,FOLLOW_T_SUM_in_qualConstraint1635); 
+
+            	        	        	        }
+            	        	        	        break;
+            	        	        	    case 2 :
+            	        	        	        // ooa.g:429:14: op= T_DIFF
+            	        	        	        {
+            	        	        	        	op=(IToken)Match(input,T_DIFF,FOLLOW_T_DIFF_in_qualConstraint1652); 
+
+            	        	        	        }
+            	        	        	        break;
+            	        	        	    case 3 :
+            	        	        	        // ooa.g:430:14: op= T_PROD
+            	        	        	        {
+            	        	        	        	op=(IToken)Match(input,T_PROD,FOLLOW_T_PROD_in_qualConstraint1669); 
+
+            	        	        	        }
+            	        	        	        break;
+
+            	        	        	}
+
+            	        	        	id3=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_qualConstraint1698); 
+            	        	        	result = createQualArithConstraintStatement(id1,id2,id3,op);
+
+            	        	        }
+            	        	        break;
+            	        	    case 2 :
+            	        	        // ooa.g:435:12: 
+            	        	        {
+            	        	        	result = createQualEqualConstraintStatement(id1,id2);
+
+            	        	        }
+            	        	        break;
+
+            	        	}
+
+
+            	        }
+            	        break;
+
+            	}
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return result;
+    }
+    // $ANTLR end "qualConstraint"
+
+
+    // $ANTLR start "discreteActionBody"
+    // ooa.g:443:1: discreteActionBody returns [GuardedCommand result] : T_REQUIRES expr= expression T_COLON bdy= actionBody[null] T_END ;
+    public GuardedCommand discreteActionBody() // throws RecognitionException [1]
+    {   
+        GuardedCommand result = default(GuardedCommand);
+
+        Expression expr = default(Expression);
+
+        Block bdy = default(Block);
+
+
+
+        		result = null;
+        	
+        try 
+    	{
+            // ooa.g:448:2: ( T_REQUIRES expr= expression T_COLON bdy= actionBody[null] T_END )
+            // ooa.g:449:3: T_REQUIRES expr= expression T_COLON bdy= actionBody[null] T_END
+            {
+            	Match(input,T_REQUIRES,FOLLOW_T_REQUIRES_in_discreteActionBody1788); 
+            	PushFollow(FOLLOW_expression_in_discreteActionBody1792);
+            	expr = expression();
+            	state.followingStackPointer--;
+
+            	Match(input,T_COLON,FOLLOW_T_COLON_in_discreteActionBody1794); 
+            	PushFollow(FOLLOW_actionBody_in_discreteActionBody1801);
+            	bdy = actionBody(null);
+            	state.followingStackPointer--;
+
+            	Match(input,T_END,FOLLOW_T_END_in_discreteActionBody1806); 
+            	result = createGuardedCommandStatement(expr,bdy);
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return result;
+    }
+    // $ANTLR end "discreteActionBody"
+
+
+    // $ANTLR start "actionBlock"
+    // ooa.g:460:1: actionBlock[Block top] returns [Block prioList] : actionBlockParallel[prioList] ( T_PRIO actionBlockParallel[prioList] )* ;
+    public Block actionBlock(Block top) // throws RecognitionException [1]
+    {   
+        Block prioList = default(Block);
+
+        try 
+    	{
+            // ooa.g:462:2: ( actionBlockParallel[prioList] ( T_PRIO actionBlockParallel[prioList] )* )
+            // ooa.g:462:6: actionBlockParallel[prioList] ( T_PRIO actionBlockParallel[prioList] )*
+            {
+            	prioList = createPrioBlock(top);
+            	PushFollow(FOLLOW_actionBlockParallel_in_actionBlock1842);
+            	actionBlockParallel(prioList);
+            	state.followingStackPointer--;
+
+            	// ooa.g:463:34: ( T_PRIO actionBlockParallel[prioList] )*
+            	do 
+            	{
+            	    int alt47 = 2;
+            	    int LA47_0 = input.LA(1);
+
+            	    if ( (LA47_0 == T_PRIO) )
+            	    {
+            	        alt47 = 1;
+            	    }
+
+
+            	    switch (alt47) 
+            		{
+            			case 1 :
+            			    // ooa.g:463:35: T_PRIO actionBlockParallel[prioList]
+            			    {
+            			    	Match(input,T_PRIO,FOLLOW_T_PRIO_in_actionBlock1846); 
+            			    	PushFollow(FOLLOW_actionBlockParallel_in_actionBlock1848);
+            			    	actionBlockParallel(prioList);
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop47;
+            	    }
+            	} while (true);
+
+            	loop47:
+            		;	// Stops C# compiler whining that label 'loop47' has no statements
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return prioList;
+    }
+    // $ANTLR end "actionBlock"
+
+
+    // $ANTLR start "actionBlockParallel"
+    // ooa.g:466:1: actionBlockParallel[Block top] : actionBlockSequential[parList] ( T_NONDET actionBlockSequential[parList] )* ;
+    public void actionBlockParallel(Block top) // throws RecognitionException [1]
+    {   
+        try 
+    	{
+            // ooa.g:467:2: ( actionBlockSequential[parList] ( T_NONDET actionBlockSequential[parList] )* )
+            // ooa.g:467:6: actionBlockSequential[parList] ( T_NONDET actionBlockSequential[parList] )*
+            {
+            	Block parList = createNondetBlock(top);
+            	PushFollow(FOLLOW_actionBlockSequential_in_actionBlockParallel1873);
+            	actionBlockSequential(parList);
+            	state.followingStackPointer--;
+
+            	// ooa.g:468:34: ( T_NONDET actionBlockSequential[parList] )*
+            	do 
+            	{
+            	    int alt48 = 2;
+            	    int LA48_0 = input.LA(1);
+
+            	    if ( (LA48_0 == T_NONDET) )
+            	    {
+            	        alt48 = 1;
+            	    }
+
+
+            	    switch (alt48) 
+            		{
+            			case 1 :
+            			    // ooa.g:468:35: T_NONDET actionBlockSequential[parList]
+            			    {
+            			    	Match(input,T_NONDET,FOLLOW_T_NONDET_in_actionBlockParallel1877); 
+            			    	PushFollow(FOLLOW_actionBlockSequential_in_actionBlockParallel1879);
+            			    	actionBlockSequential(parList);
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop48;
+            	    }
+            	} while (true);
+
+            	loop48:
+            		;	// Stops C# compiler whining that label 'loop48' has no statements
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "actionBlockParallel"
+
+
+    // $ANTLR start "actionBlockSequential"
+    // ooa.g:472:1: actionBlockSequential[Block top] : ( T_VAR syms= blockvarlist[seqList] ( '&' sexpr= expression )? T_COLON )? actionBlockParen[seqList] ( T_SEMICOLON actionBlockParen[seqList] )* ;
+    public void actionBlockSequential(Block top) // throws RecognitionException [1]
+    {   
+        Expression sexpr = default(Expression);
+
+
+
+        			Block seqList = createSeqBlock(top);
+        			pushBlockToResolveStack(seqList);
+        		
+        try 
+    	{
+            // ooa.g:477:2: ( ( T_VAR syms= blockvarlist[seqList] ( '&' sexpr= expression )? T_COLON )? actionBlockParen[seqList] ( T_SEMICOLON actionBlockParen[seqList] )* )
+            // ooa.g:477:5: ( T_VAR syms= blockvarlist[seqList] ( '&' sexpr= expression )? T_COLON )? actionBlockParen[seqList] ( T_SEMICOLON actionBlockParen[seqList] )*
+            {
+            	// ooa.g:477:5: ( T_VAR syms= blockvarlist[seqList] ( '&' sexpr= expression )? T_COLON )?
+            	int alt50 = 2;
+            	int LA50_0 = input.LA(1);
+
+            	if ( (LA50_0 == T_VAR) )
+            	{
+            	    alt50 = 1;
+            	}
+            	switch (alt50) 
+            	{
+            	    case 1 :
+            	        // ooa.g:477:6: T_VAR syms= blockvarlist[seqList] ( '&' sexpr= expression )? T_COLON
+            	        {
+            	        	Match(input,T_VAR,FOLLOW_T_VAR_in_actionBlockSequential1908); 
+            	        	PushFollow(FOLLOW_blockvarlist_in_actionBlockSequential1912);
+            	        	blockvarlist(seqList);
+            	        	state.followingStackPointer--;
+
+            	        	// ooa.g:477:39: ( '&' sexpr= expression )?
+            	        	int alt49 = 2;
+            	        	int LA49_0 = input.LA(1);
+
+            	        	if ( (LA49_0 == 120) )
+            	        	{
+            	        	    alt49 = 1;
+            	        	}
+            	        	switch (alt49) 
+            	        	{
+            	        	    case 1 :
+            	        	        // ooa.g:477:40: '&' sexpr= expression
+            	        	        {
+            	        	        	Match(input,120,FOLLOW_120_in_actionBlockSequential1916); 
+            	        	        	PushFollow(FOLLOW_expression_in_actionBlockSequential1920);
+            	        	        	sexpr = expression();
+            	        	        	state.followingStackPointer--;
+
+            	        	        	addSeqBlockExpression(seqList,sexpr);
+
+            	        	        }
+            	        	        break;
+
+            	        	}
+
+            	        	Match(input,T_COLON,FOLLOW_T_COLON_in_actionBlockSequential1927); 
+
+            	        }
+            	        break;
+
+            	}
+
+            	PushFollow(FOLLOW_actionBlockParen_in_actionBlockSequential1936);
+            	actionBlockParen(seqList);
+            	state.followingStackPointer--;
+
+            	// ooa.g:478:30: ( T_SEMICOLON actionBlockParen[seqList] )*
+            	do 
+            	{
+            	    int alt51 = 2;
+            	    int LA51_0 = input.LA(1);
+
+            	    if ( (LA51_0 == T_SEMICOLON) )
+            	    {
+            	        alt51 = 1;
+            	    }
+
+
+            	    switch (alt51) 
+            		{
+            			case 1 :
+            			    // ooa.g:478:31: T_SEMICOLON actionBlockParen[seqList]
+            			    {
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_actionBlockSequential1940); 
+            			    	PushFollow(FOLLOW_actionBlockParen_in_actionBlockSequential1942);
+            			    	actionBlockParen(seqList);
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop51;
+            	    }
+            	} while (true);
+
+            	loop51:
+            		;	// Stops C# compiler whining that label 'loop51' has no statements
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            popBlockFromResolveStack(seqList);
+        }
+        return ;
+    }
+    // $ANTLR end "actionBlockSequential"
+
+
+    // $ANTLR start "actionBlockParen"
+    // ooa.g:483:1: actionBlockParen[Block top] : ( T_LPAREN actionBlock[top] T_RPAREN | anonymousOrNamedAction[top] );
+    public void actionBlockParen(Block top) // throws RecognitionException [1]
+    {   
+        try 
+    	{
+            // ooa.g:484:2: ( T_LPAREN actionBlock[top] T_RPAREN | anonymousOrNamedAction[top] )
+            int alt52 = 2;
+            int LA52_0 = input.LA(1);
+
+            if ( (LA52_0 == T_LPAREN) )
+            {
+                alt52 = 1;
+            }
+            else if ( (LA52_0 == T_IDENTIFIER || (LA52_0 >= T_CONT && LA52_0 <= T_REQUIRES) || LA52_0 == T_SKIP) )
+            {
+                alt52 = 2;
+            }
+            else 
+            {
+                NoViableAltException nvae_d52s0 =
+                    new NoViableAltException("", 52, 0, input);
+
+                throw nvae_d52s0;
+            }
+            switch (alt52) 
+            {
+                case 1 :
+                    // ooa.g:484:4: T_LPAREN actionBlock[top] T_RPAREN
+                    {
+                    	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_actionBlockParen1966); 
+                    	PushFollow(FOLLOW_actionBlock_in_actionBlockParen1968);
+                    	actionBlock(top);
+                    	state.followingStackPointer--;
+
+                    	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_actionBlockParen1971); 
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:485:4: anonymousOrNamedAction[top]
+                    {
+                    	PushFollow(FOLLOW_anonymousOrNamedAction_in_actionBlockParen1976);
+                    	anonymousOrNamedAction(top);
+                    	state.followingStackPointer--;
+
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "actionBlockParen"
+
+
+    // $ANTLR start "anonymousOrNamedAction"
+    // ooa.g:488:1: anonymousOrNamedAction[Block top] : (gcmd= anonymousAction | aname= T_IDENTIFIER ( T_LPAREN m_params= methodCallParams T_RPAREN )? (amap= ( T_FOLDLR | T_FOLDRL ) '(' amapexpr= expression ')' )? | T_SKIP );
+    public void anonymousOrNamedAction(Block top) // throws RecognitionException [1]
+    {   
+        IToken aname = null;
+        IToken amap = null;
+        GuardedCommand gcmd = default(GuardedCommand);
+
+        System.Collections.Generic.List<Expression> m_params = default(System.Collections.Generic.List<Expression>);
+
+        Expression amapexpr = default(Expression);
+
+
+        try 
+    	{
+            // ooa.g:489:2: (gcmd= anonymousAction | aname= T_IDENTIFIER ( T_LPAREN m_params= methodCallParams T_RPAREN )? (amap= ( T_FOLDLR | T_FOLDRL ) '(' amapexpr= expression ')' )? | T_SKIP )
+            int alt55 = 3;
+            switch ( input.LA(1) ) 
+            {
+            case T_CONT:
+            case T_REQUIRES:
+            	{
+                alt55 = 1;
+                }
+                break;
+            case T_IDENTIFIER:
+            	{
+                alt55 = 2;
+                }
+                break;
+            case T_SKIP:
+            	{
+                alt55 = 3;
+                }
+                break;
+            	default:
+            	    NoViableAltException nvae_d55s0 =
+            	        new NoViableAltException("", 55, 0, input);
+
+            	    throw nvae_d55s0;
+            }
+
+            switch (alt55) 
+            {
+                case 1 :
+                    // ooa.g:489:4: gcmd= anonymousAction
+                    {
+                    	PushFollow(FOLLOW_anonymousAction_in_anonymousOrNamedAction1993);
+                    	gcmd = anonymousAction();
+                    	state.followingStackPointer--;
+
+                    	addToBlockList(top,gcmd);
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:490:4: aname= T_IDENTIFIER ( T_LPAREN m_params= methodCallParams T_RPAREN )? (amap= ( T_FOLDLR | T_FOLDRL ) '(' amapexpr= expression ')' )?
+                    {
+                    	aname=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_anonymousOrNamedAction2002); 
+                    	// ooa.g:491:11: ( T_LPAREN m_params= methodCallParams T_RPAREN )?
+                    	int alt53 = 2;
+                    	int LA53_0 = input.LA(1);
+
+                    	if ( (LA53_0 == T_LPAREN) )
+                    	{
+                    	    alt53 = 1;
+                    	}
+                    	switch (alt53) 
+                    	{
+                    	    case 1 :
+                    	        // ooa.g:491:12: T_LPAREN m_params= methodCallParams T_RPAREN
+                    	        {
+                    	        	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_anonymousOrNamedAction2016); 
+                    	        	PushFollow(FOLLOW_methodCallParams_in_anonymousOrNamedAction2021);
+                    	        	m_params = methodCallParams();
+                    	        	state.followingStackPointer--;
+
+                    	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_anonymousOrNamedAction2023); 
+
+                    	        }
+                    	        break;
+
+                    	}
+
+                    	// ooa.g:492:11: (amap= ( T_FOLDLR | T_FOLDRL ) '(' amapexpr= expression ')' )?
+                    	int alt54 = 2;
+                    	int LA54_0 = input.LA(1);
+
+                    	if ( ((LA54_0 >= T_FOLDLR && LA54_0 <= T_FOLDRL)) )
+                    	{
+                    	    alt54 = 1;
+                    	}
+                    	switch (alt54) 
+                    	{
+                    	    case 1 :
+                    	        // ooa.g:492:12: amap= ( T_FOLDLR | T_FOLDRL ) '(' amapexpr= expression ')'
+                    	        {
+                    	        	amap = (IToken)input.LT(1);
+                    	        	if ( (input.LA(1) >= T_FOLDLR && input.LA(1) <= T_FOLDRL) ) 
+                    	        	{
+                    	        	    input.Consume();
+                    	        	    state.errorRecovery = false;
+                    	        	}
+                    	        	else 
+                    	        	{
+                    	        	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	        	    throw mse;
+                    	        	}
+
+                    	        	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_anonymousOrNamedAction2047); 
+                    	        	PushFollow(FOLLOW_expression_in_anonymousOrNamedAction2051);
+                    	        	amapexpr = expression();
+                    	        	state.followingStackPointer--;
+
+                    	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_anonymousOrNamedAction2053); 
+
+                    	        }
+                    	        break;
+
+                    	}
+
+                    	addNamedActionCallToBlockList(top,aname,m_params,amap,amapexpr);
+
+                    }
+                    break;
+                case 3 :
+                    // ooa.g:494:4: T_SKIP
+                    {
+                    	Match(input,T_SKIP,FOLLOW_T_SKIP_in_anonymousOrNamedAction2064); 
+                    	addSkipStatementToBlockList(top);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "anonymousOrNamedAction"
+
+
+    // $ANTLR start "blockvarlist"
+    // ooa.g:498:1: blockvarlist[Block seqList] : blockvar[seqList] ( T_SEMICOLON blockvar[seqList] )* ;
+    public void blockvarlist(Block seqList) // throws RecognitionException [1]
+    {   
+        try 
+    	{
+            // ooa.g:499:2: ( blockvar[seqList] ( T_SEMICOLON blockvar[seqList] )* )
+            // ooa.g:499:4: blockvar[seqList] ( T_SEMICOLON blockvar[seqList] )*
+            {
+            	PushFollow(FOLLOW_blockvar_in_blockvarlist2080);
+            	blockvar(seqList);
+            	state.followingStackPointer--;
+
+            	// ooa.g:499:23: ( T_SEMICOLON blockvar[seqList] )*
+            	do 
+            	{
+            	    int alt56 = 2;
+            	    int LA56_0 = input.LA(1);
+
+            	    if ( (LA56_0 == T_SEMICOLON) )
+            	    {
+            	        alt56 = 1;
+            	    }
+
+
+            	    switch (alt56) 
+            		{
+            			case 1 :
+            			    // ooa.g:499:24: T_SEMICOLON blockvar[seqList]
+            			    {
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_blockvarlist2085); 
+            			    	PushFollow(FOLLOW_blockvar_in_blockvarlist2087);
+            			    	blockvar(seqList);
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop56;
+            	    }
+            	} while (true);
+
+            	loop56:
+            		;	// Stops C# compiler whining that label 'loop56' has no statements
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "blockvarlist"
+
+
+    // $ANTLR start "blockvar"
+    // ooa.g:502:1: blockvar[Block seqList] : varname= T_IDENTIFIER T_COLON aType= complexType ;
+    public void blockvar(Block seqList) // throws RecognitionException [1]
+    {   
+        IToken varname = null;
+        UlyssesType aType = default(UlyssesType);
+
+
+        try 
+    	{
+            // ooa.g:503:2: (varname= T_IDENTIFIER T_COLON aType= complexType )
+            // ooa.g:503:5: varname= T_IDENTIFIER T_COLON aType= complexType
+            {
+            	varname=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_blockvar2107); 
+            	Match(input,T_COLON,FOLLOW_T_COLON_in_blockvar2110); 
+            	PushFollow(FOLLOW_complexType_in_blockvar2114);
+            	aType = complexType();
+            	state.followingStackPointer--;
+
+            	addBlockVariable(seqList,varname,aType);
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "blockvar"
+
+
+    // $ANTLR start "actionBody"
+    // ooa.g:513:1: actionBody[Block top] returns [Block result] : actionBodyParallel[result] ( T_PRIO actionBodyParallel[result] )? ;
+    public Block actionBody(Block top) // throws RecognitionException [1]
+    {   
+        Block result = default(Block);
+
+        try 
+    	{
+            // ooa.g:515:2: ( actionBodyParallel[result] ( T_PRIO actionBodyParallel[result] )? )
+            // ooa.g:515:4: actionBodyParallel[result] ( T_PRIO actionBodyParallel[result] )?
+            {
+            	result = createPrioBlock(top);
+            	PushFollow(FOLLOW_actionBodyParallel_in_actionBody2149);
+            	actionBodyParallel(result);
+            	state.followingStackPointer--;
+
+            	// ooa.g:516:30: ( T_PRIO actionBodyParallel[result] )?
+            	int alt57 = 2;
+            	int LA57_0 = input.LA(1);
+
+            	if ( (LA57_0 == T_PRIO) )
+            	{
+            	    alt57 = 1;
+            	}
+            	switch (alt57) 
+            	{
+            	    case 1 :
+            	        // ooa.g:516:31: T_PRIO actionBodyParallel[result]
+            	        {
+            	        	Match(input,T_PRIO,FOLLOW_T_PRIO_in_actionBody2153); 
+            	        	PushFollow(FOLLOW_actionBodyParallel_in_actionBody2155);
+            	        	actionBodyParallel(result);
+            	        	state.followingStackPointer--;
+
+
+            	        }
+            	        break;
+
+            	}
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return result;
+    }
+    // $ANTLR end "actionBody"
+
+
+    // $ANTLR start "actionBodyParallel"
+    // ooa.g:519:1: actionBodyParallel[Block top] returns [Block result] : actionBodySequential[result] ( T_NONDET olst= actionBodySequential[result] )* ;
+    public Block actionBodyParallel(Block top) // throws RecognitionException [1]
+    {   
+        Block result = default(Block);
+
+        Block olst = default(Block);
+
+
+        try 
+    	{
+            // ooa.g:521:2: ( actionBodySequential[result] ( T_NONDET olst= actionBodySequential[result] )* )
+            // ooa.g:521:4: actionBodySequential[result] ( T_NONDET olst= actionBodySequential[result] )*
+            {
+            	result = createNondetBlock(top);
+            	PushFollow(FOLLOW_actionBodySequential_in_actionBodyParallel2183);
+            	actionBodySequential(result);
+            	state.followingStackPointer--;
+
+            	// ooa.g:523:3: ( T_NONDET olst= actionBodySequential[result] )*
+            	do 
+            	{
+            	    int alt58 = 2;
+            	    int LA58_0 = input.LA(1);
+
+            	    if ( (LA58_0 == T_NONDET) )
+            	    {
+            	        alt58 = 1;
+            	    }
+
+
+            	    switch (alt58) 
+            		{
+            			case 1 :
+            			    // ooa.g:523:4: T_NONDET olst= actionBodySequential[result]
+            			    {
+            			    	Match(input,T_NONDET,FOLLOW_T_NONDET_in_actionBodyParallel2189); 
+            			    	PushFollow(FOLLOW_actionBodySequential_in_actionBodyParallel2193);
+            			    	olst = actionBodySequential(result);
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop58;
+            	    }
+            	} while (true);
+
+            	loop58:
+            		;	// Stops C# compiler whining that label 'loop58' has no statements
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return result;
+    }
+    // $ANTLR end "actionBodyParallel"
+
+
+    // $ANTLR start "actionBodySequential"
+    // ooa.g:527:1: actionBodySequential[Block top] returns [Block result] : actionBodyParen[result] ( T_SEMICOLON actionBodyParen[result] )* ;
+    public Block actionBodySequential(Block top) // throws RecognitionException [1]
+    {   
+        Block result = default(Block);
+
+        try 
+    	{
+            // ooa.g:529:2: ( actionBodyParen[result] ( T_SEMICOLON actionBodyParen[result] )* )
+            // ooa.g:529:4: actionBodyParen[result] ( T_SEMICOLON actionBodyParen[result] )*
+            {
+            	result = createSeqBlock(top);
+            	PushFollow(FOLLOW_actionBodyParen_in_actionBodySequential2220);
+            	actionBodyParen(result);
+            	state.followingStackPointer--;
+
+            	// ooa.g:530:27: ( T_SEMICOLON actionBodyParen[result] )*
+            	do 
+            	{
+            	    int alt59 = 2;
+            	    int LA59_0 = input.LA(1);
+
+            	    if ( (LA59_0 == T_SEMICOLON) )
+            	    {
+            	        alt59 = 1;
+            	    }
+
+
+            	    switch (alt59) 
+            		{
+            			case 1 :
+            			    // ooa.g:530:28: T_SEMICOLON actionBodyParen[result]
+            			    {
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_actionBodySequential2224); 
+            			    	PushFollow(FOLLOW_actionBodyParen_in_actionBodySequential2226);
+            			    	actionBodyParen(result);
+            			    	state.followingStackPointer--;
+
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop59;
+            	    }
+            	} while (true);
+
+            	loop59:
+            		;	// Stops C# compiler whining that label 'loop59' has no statements
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return result;
+    }
+    // $ANTLR end "actionBodySequential"
+
+
+    // $ANTLR start "actionBodyParen"
+    // ooa.g:533:1: actionBodyParen[Block top] : ( T_LPAREN actionBody[top] T_RPAREN | stmt= statement );
+    public void actionBodyParen(Block top) // throws RecognitionException [1]
+    {   
+        Statement stmt = default(Statement);
+
+
+        try 
+    	{
+            // ooa.g:534:2: ( T_LPAREN actionBody[top] T_RPAREN | stmt= statement )
+            int alt60 = 2;
+            int LA60_0 = input.LA(1);
+
+            if ( (LA60_0 == T_LPAREN) )
+            {
+                alt60 = 1;
+            }
+            else if ( (LA60_0 == T_IDENTIFIER || LA60_0 == T_REQUIRES || (LA60_0 >= T_SKIP && LA60_0 <= T_SELF)) )
+            {
+                alt60 = 2;
+            }
+            else 
+            {
+                NoViableAltException nvae_d60s0 =
+                    new NoViableAltException("", 60, 0, input);
+
+                throw nvae_d60s0;
+            }
+            switch (alt60) 
+            {
+                case 1 :
+                    // ooa.g:534:4: T_LPAREN actionBody[top] T_RPAREN
+                    {
+                    	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_actionBodyParen2244); 
+                    	PushFollow(FOLLOW_actionBody_in_actionBodyParen2246);
+                    	actionBody(top);
+                    	state.followingStackPointer--;
+
+                    	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_actionBodyParen2249); 
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:535:4: stmt= statement
+                    {
+                    	PushFollow(FOLLOW_statement_in_actionBodyParen2256);
+                    	stmt = statement();
+                    	state.followingStackPointer--;
+
+                    	addToStatementList(top,stmt);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "actionBodyParen"
+
+
+    // $ANTLR start "statement"
+    // ooa.g:540:1: statement returns [Statement result] : ( T_ABORT | T_SKIP | T_KILL T_LPAREN aname= ( T_IDENTIFIER | T_SELF ) T_RPAREN | gc= discreteActionBody | aqname= reference ( T_ASSIGNMENT aexp= expression ( T_WITH ndexp= expression )? | ( T_COMMA malhs= reference )+ T_ASSIGNMENT mexp= expression ( T_COMMA mexp2= expression )+ ( T_WITH ndex2= expression )? | ) );
+    public Statement statement() // throws RecognitionException [1]
+    {   
+        Statement result = default(Statement);
+
+        IToken aname = null;
+        GuardedCommand gc = default(GuardedCommand);
+
+        Expression aqname = default(Expression);
+
+        Expression aexp = default(Expression);
+
+        Expression ndexp = default(Expression);
+
+        Expression malhs = default(Expression);
+
+        Expression mexp = default(Expression);
+
+        Expression mexp2 = default(Expression);
+
+        Expression ndex2 = default(Expression);
+
+
+
+        		bool popFromResolveStack = false;
+        		result = null;
+        	
+        try 
+    	{
+            // ooa.g:546:2: ( T_ABORT | T_SKIP | T_KILL T_LPAREN aname= ( T_IDENTIFIER | T_SELF ) T_RPAREN | gc= discreteActionBody | aqname= reference ( T_ASSIGNMENT aexp= expression ( T_WITH ndexp= expression )? | ( T_COMMA malhs= reference )+ T_ASSIGNMENT mexp= expression ( T_COMMA mexp2= expression )+ ( T_WITH ndex2= expression )? | ) )
+            int alt66 = 5;
+            switch ( input.LA(1) ) 
+            {
+            case T_ABORT:
+            	{
+                alt66 = 1;
+                }
+                break;
+            case T_SKIP:
+            	{
+                alt66 = 2;
+                }
+                break;
+            case T_KILL:
+            	{
+                alt66 = 3;
+                }
+                break;
+            case T_REQUIRES:
+            	{
+                alt66 = 4;
+                }
+                break;
+            case T_IDENTIFIER:
+            case T_SELF:
+            	{
+                alt66 = 5;
+                }
+                break;
+            	default:
+            	    NoViableAltException nvae_d66s0 =
+            	        new NoViableAltException("", 66, 0, input);
+
+            	    throw nvae_d66s0;
+            }
+
+            switch (alt66) 
+            {
+                case 1 :
+                    // ooa.g:546:4: T_ABORT
+                    {
+                    	Match(input,T_ABORT,FOLLOW_T_ABORT_in_statement2284); 
+                    	result = createAbortStatement();
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:547:4: T_SKIP
+                    {
+                    	Match(input,T_SKIP,FOLLOW_T_SKIP_in_statement2291); 
+                    	result = createSkipStatement();
+
+                    }
+                    break;
+                case 3 :
+                    // ooa.g:548:4: T_KILL T_LPAREN aname= ( T_IDENTIFIER | T_SELF ) T_RPAREN
+                    {
+                    	Match(input,T_KILL,FOLLOW_T_KILL_in_statement2298); 
+                    	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_statement2300); 
+                    	aname = (IToken)input.LT(1);
+                    	if ( input.LA(1) == T_IDENTIFIER || input.LA(1) == T_SELF ) 
+                    	{
+                    	    input.Consume();
+                    	    state.errorRecovery = false;
+                    	}
+                    	else 
+                    	{
+                    	    MismatchedSetException mse = new MismatchedSetException(null,input);
+                    	    throw mse;
+                    	}
+
+                    	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_statement2312); 
+                    	result = createKillStatement(aname);
+
+                    }
+                    break;
+                case 4 :
+                    // ooa.g:549:5: gc= discreteActionBody
+                    {
+                    	PushFollow(FOLLOW_discreteActionBody_in_statement2322);
+                    	gc = discreteActionBody();
+                    	state.followingStackPointer--;
+
+                    	result = gc;
+
+                    }
+                    break;
+                case 5 :
+                    // ooa.g:550:4: aqname= reference ( T_ASSIGNMENT aexp= expression ( T_WITH ndexp= expression )? | ( T_COMMA malhs= reference )+ T_ASSIGNMENT mexp= expression ( T_COMMA mexp2= expression )+ ( T_WITH ndex2= expression )? | )
+                    {
+                    	PushFollow(FOLLOW_reference_in_statement2331);
+                    	aqname = reference();
+                    	state.followingStackPointer--;
+
+                    	// ooa.g:551:7: ( T_ASSIGNMENT aexp= expression ( T_WITH ndexp= expression )? | ( T_COMMA malhs= reference )+ T_ASSIGNMENT mexp= expression ( T_COMMA mexp2= expression )+ ( T_WITH ndex2= expression )? | )
+                    	int alt65 = 3;
+                    	switch ( input.LA(1) ) 
+                    	{
+                    	case T_ASSIGNMENT:
+                    		{
+                    	    alt65 = 1;
+                    	    }
+                    	    break;
+                    	case T_COMMA:
+                    		{
+                    	    alt65 = 2;
+                    	    }
+                    	    break;
+                    	case T_SEMICOLON:
+                    	case T_PRIO:
+                    	case T_NONDET:
+                    	case T_RPAREN:
+                    	case T_END:
+                    		{
+                    	    alt65 = 3;
+                    	    }
+                    	    break;
+                    		default:
+                    		    NoViableAltException nvae_d65s0 =
+                    		        new NoViableAltException("", 65, 0, input);
+
+                    		    throw nvae_d65s0;
+                    	}
+
+                    	switch (alt65) 
+                    	{
+                    	    case 1 :
+                    	        // ooa.g:552:12: T_ASSIGNMENT aexp= expression ( T_WITH ndexp= expression )?
+                    	        {
+                    	        	Match(input,T_ASSIGNMENT,FOLLOW_T_ASSIGNMENT_in_statement2359); 
+                    	        	PushFollow(FOLLOW_expression_in_statement2364);
+                    	        	aexp = expression();
+                    	        	state.followingStackPointer--;
+
+                    	        	result = createSingleAssignmentStatement(aqname,aexp);
+                    	        	// ooa.g:553:15: ( T_WITH ndexp= expression )?
+                    	        	int alt61 = 2;
+                    	        	int LA61_0 = input.LA(1);
+
+                    	        	if ( (LA61_0 == T_WITH) )
+                    	        	{
+                    	        	    alt61 = 1;
+                    	        	}
+                    	        	switch (alt61) 
+                    	        	{
+                    	        	    case 1 :
+                    	        	        // ooa.g:553:16: T_WITH ndexp= expression
+                    	        	        {
+                    	        	        	Match(input,T_WITH,FOLLOW_T_WITH_in_statement2384); 
+                    	        	        	PushFollow(FOLLOW_expression_in_statement2388);
+                    	        	        	ndexp = expression();
+                    	        	        	state.followingStackPointer--;
+
+                    	        	        	addConstraintToAssignment(result,ndexp);
+
+                    	        	        }
+                    	        	        break;
+
+                    	        	}
+
+
+                    	        }
+                    	        break;
+                    	    case 2 :
+                    	        // ooa.g:556:8: ( T_COMMA malhs= reference )+ T_ASSIGNMENT mexp= expression ( T_COMMA mexp2= expression )+ ( T_WITH ndex2= expression )?
+                    	        {
+                    	        	result = createMultipleAssignmentStatementLHS(aqname);
+                    	        	// ooa.g:557:7: ( T_COMMA malhs= reference )+
+                    	        	int cnt62 = 0;
+                    	        	do 
+                    	        	{
+                    	        	    int alt62 = 2;
+                    	        	    int LA62_0 = input.LA(1);
+
+                    	        	    if ( (LA62_0 == T_COMMA) )
+                    	        	    {
+                    	        	        alt62 = 1;
+                    	        	    }
+
+
+                    	        	    switch (alt62) 
+                    	        		{
+                    	        			case 1 :
+                    	        			    // ooa.g:557:8: T_COMMA malhs= reference
+                    	        			    {
+                    	        			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_statement2441); 
+                    	        			    	PushFollow(FOLLOW_reference_in_statement2445);
+                    	        			    	malhs = reference();
+                    	        			    	state.followingStackPointer--;
+
+                    	        			    	addMultipleAssignmentStatementLHS(result,malhs);
+
+                    	        			    }
+                    	        			    break;
+
+                    	        			default:
+                    	        			    if ( cnt62 >= 1 ) goto loop62;
+                    	        		            EarlyExitException eee62 =
+                    	        		                new EarlyExitException(62, input);
+                    	        		            throw eee62;
+                    	        	    }
+                    	        	    cnt62++;
+                    	        	} while (true);
+
+                    	        	loop62:
+                    	        		;	// Stops C# compiler whining that label 'loop62' has no statements
+
+                    	        	Match(input,T_ASSIGNMENT,FOLLOW_T_ASSIGNMENT_in_statement2460); 
+                    	        	pushAssignmentOnResolveStack(result); popFromResolveStack = true;
+                    	        	PushFollow(FOLLOW_expression_in_statement2482);
+                    	        	mexp = expression();
+                    	        	state.followingStackPointer--;
+
+                    	        	addMutlipleAssignmentStatementRHS(result,mexp);
+                    	        	// ooa.g:562:8: ( T_COMMA mexp2= expression )+
+                    	        	int cnt63 = 0;
+                    	        	do 
+                    	        	{
+                    	        	    int alt63 = 2;
+                    	        	    int LA63_0 = input.LA(1);
+
+                    	        	    if ( (LA63_0 == T_COMMA) )
+                    	        	    {
+                    	        	        alt63 = 1;
+                    	        	    }
+
+
+                    	        	    switch (alt63) 
+                    	        		{
+                    	        			case 1 :
+                    	        			    // ooa.g:562:9: T_COMMA mexp2= expression
+                    	        			    {
+                    	        			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_statement2501); 
+                    	        			    	PushFollow(FOLLOW_expression_in_statement2505);
+                    	        			    	mexp2 = expression();
+                    	        			    	state.followingStackPointer--;
+
+                    	        			    	addMutlipleAssignmentStatementRHS(result,mexp2);
+
+                    	        			    }
+                    	        			    break;
+
+                    	        			default:
+                    	        			    if ( cnt63 >= 1 ) goto loop63;
+                    	        		            EarlyExitException eee63 =
+                    	        		                new EarlyExitException(63, input);
+                    	        		            throw eee63;
+                    	        	    }
+                    	        	    cnt63++;
+                    	        	} while (true);
+
+                    	        	loop63:
+                    	        		;	// Stops C# compiler whining that label 'loop63' has no statements
+
+                    	        	// ooa.g:563:8: ( T_WITH ndex2= expression )?
+                    	        	int alt64 = 2;
+                    	        	int LA64_0 = input.LA(1);
+
+                    	        	if ( (LA64_0 == T_WITH) )
+                    	        	{
+                    	        	    alt64 = 1;
+                    	        	}
+                    	        	switch (alt64) 
+                    	        	{
+                    	        	    case 1 :
+                    	        	        // ooa.g:563:9: T_WITH ndex2= expression
+                    	        	        {
+                    	        	        	Match(input,T_WITH,FOLLOW_T_WITH_in_statement2519); 
+                    	        	        	PushFollow(FOLLOW_expression_in_statement2523);
+                    	        	        	ndex2 = expression();
+                    	        	        	state.followingStackPointer--;
+
+                    	        	        	addConstraintToAssignment(result,ndex2);
+
+                    	        	        }
+                    	        	        break;
+
+                    	        	}
+
+
+                    	        }
+                    	        break;
+                    	    case 3 :
+                    	        // ooa.g:566:7: 
+                    	        {
+                    	        	result = createCallStatement(aqname);
+
+                    	        }
+                    	        break;
+
+                    	}
+
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+
+            	       if (popFromResolveStack == true)
+            	            popAssignmentOffResolveStack(result);
+            	
+        }
+        return result;
+    }
+    // $ANTLR end "statement"
+
+
+    // $ANTLR start "expression"
+    // ooa.g:577:1: expression returns [Expression expr] : left= atomExpression (op= binoperator right= atomExpression )* ;
+    public Expression expression() // throws RecognitionException [1]
+    {   
+        Expression expr = default(Expression);
+
+        Expression left = default(Expression);
+
+        BinaryOperator op = default(BinaryOperator);
+
+        Expression right = default(Expression);
+
+
+
+        		System.Collections.Generic.List<BinaryOperator> operators = new System.Collections.Generic.List<BinaryOperator>();
+        		System.Collections.Generic.List<Expression> expressions = new System.Collections.Generic.List<Expression>();		
+        	
+        try 
+    	{
+            // ooa.g:583:2: (left= atomExpression (op= binoperator right= atomExpression )* )
+            // ooa.g:583:4: left= atomExpression (op= binoperator right= atomExpression )*
+            {
+            	PushFollow(FOLLOW_atomExpression_in_expression2598);
+            	left = atomExpression();
+            	state.followingStackPointer--;
+
+            	expressions.Add(left);
+            	// ooa.g:585:3: (op= binoperator right= atomExpression )*
+            	do 
+            	{
+            	    int alt67 = 2;
+            	    alt67 = dfa67.Predict(input);
+            	    switch (alt67) 
+            		{
+            			case 1 :
+            			    // ooa.g:585:5: op= binoperator right= atomExpression
+            			    {
+            			    	PushFollow(FOLLOW_binoperator_in_expression2611);
+            			    	op = binoperator();
+            			    	state.followingStackPointer--;
+
+            			    	PushFollow(FOLLOW_atomExpression_in_expression2619);
+            			    	right = atomExpression();
+            			    	state.followingStackPointer--;
+
+
+            			    			  	operators.Add(op);
+            			    			  	expressions.Add(right);
+            			    			  
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop67;
+            	    }
+            	} while (true);
+
+            	loop67:
+            		;	// Stops C# compiler whining that label 'loop67' has no statements
+
+            	expr = createPrecedenceTree(expressions,operators);
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return expr;
+    }
+    // $ANTLR end "expression"
+
+
+    // $ANTLR start "binoperator"
+    // ooa.g:596:1: binoperator returns [BinaryOperator binop] : ( T_BIIMPLIES | T_GREATER | T_GREATEREQUAL | T_LESS | T_LESSEQUAL | T_EQUAL | T_NOTEQUAL | T_IMPLIES | T_MINUS | T_SUM | T_IN ( T_SET )? | T_NOT T_IN ( T_SET )? | T_SUBSET | T_OR | T_DIV | T_PROD | T_IDIV | T_MOD | T_UNION | T_DIFF | T_INTER | T_AND | T_POW | T_CONC | T_DOMRESBY | T_DOMRESTO | T_RNGRESBY | T_RNGRESTO | T_MUNION | T_SEQMOD_MAPOVERRIDE );
+    public BinaryOperator binoperator() // throws RecognitionException [1]
+    {   
+        BinaryOperator binop = default(BinaryOperator);
+
+        try 
+    	{
+            // ooa.g:598:2: ( T_BIIMPLIES | T_GREATER | T_GREATEREQUAL | T_LESS | T_LESSEQUAL | T_EQUAL | T_NOTEQUAL | T_IMPLIES | T_MINUS | T_SUM | T_IN ( T_SET )? | T_NOT T_IN ( T_SET )? | T_SUBSET | T_OR | T_DIV | T_PROD | T_IDIV | T_MOD | T_UNION | T_DIFF | T_INTER | T_AND | T_POW | T_CONC | T_DOMRESBY | T_DOMRESTO | T_RNGRESBY | T_RNGRESTO | T_MUNION | T_SEQMOD_MAPOVERRIDE )
+            int alt70 = 30;
+            alt70 = dfa70.Predict(input);
+            switch (alt70) 
+            {
+                case 1 :
+                    // ooa.g:598:4: T_BIIMPLIES
+                    {
+                    	Match(input,T_BIIMPLIES,FOLLOW_T_BIIMPLIES_in_binoperator2652); 
+                    	binop = createBinaryOperator(ExpressionKind.biimplies);
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:600:4: T_GREATER
+                    {
+                    	Match(input,T_GREATER,FOLLOW_T_GREATER_in_binoperator2661); 
+                    	binop = createBinaryOperator(ExpressionKind.greater);
+
+                    }
+                    break;
+                case 3 :
+                    // ooa.g:602:4: T_GREATEREQUAL
+                    {
+                    	Match(input,T_GREATEREQUAL,FOLLOW_T_GREATEREQUAL_in_binoperator2671); 
+                    	binop = createBinaryOperator(ExpressionKind.greaterequal);
+
+                    }
+                    break;
+                case 4 :
+                    // ooa.g:604:4: T_LESS
+                    {
+                    	Match(input,T_LESS,FOLLOW_T_LESS_in_binoperator2680); 
+                    	binop = createBinaryOperator(ExpressionKind.less);
+
+                    }
+                    break;
+                case 5 :
+                    // ooa.g:606:4: T_LESSEQUAL
+                    {
+                    	Match(input,T_LESSEQUAL,FOLLOW_T_LESSEQUAL_in_binoperator2690); 
+                    	binop = createBinaryOperator(ExpressionKind.lessequal);
+
+                    }
+                    break;
+                case 6 :
+                    // ooa.g:608:4: T_EQUAL
+                    {
+                    	Match(input,T_EQUAL,FOLLOW_T_EQUAL_in_binoperator2699); 
+                    	binop = createBinaryOperator(ExpressionKind.equal);
+
+                    }
+                    break;
+                case 7 :
+                    // ooa.g:610:4: T_NOTEQUAL
+                    {
+                    	Match(input,T_NOTEQUAL,FOLLOW_T_NOTEQUAL_in_binoperator2711); 
+                    	binop = createBinaryOperator(ExpressionKind.notequal);
+
+                    }
+                    break;
+                case 8 :
+                    // ooa.g:612:4: T_IMPLIES
+                    {
+                    	Match(input,T_IMPLIES,FOLLOW_T_IMPLIES_in_binoperator2722); 
+                    	binop = createBinaryOperator(ExpressionKind.implies);
+
+                    }
+                    break;
+                case 9 :
+                    // ooa.g:614:4: T_MINUS
+                    {
+                    	Match(input,T_MINUS,FOLLOW_T_MINUS_in_binoperator2731); 
+                    	binop = createBinaryOperator(ExpressionKind.minus);
+
+                    }
+                    break;
+                case 10 :
+                    // ooa.g:616:4: T_SUM
+                    {
+                    	Match(input,T_SUM,FOLLOW_T_SUM_in_binoperator2741); 
+                    	binop = createBinaryOperator(ExpressionKind.sum);
+
+                    }
+                    break;
+                case 11 :
+                    // ooa.g:618:4: T_IN ( T_SET )?
+                    {
+                    	Match(input,T_IN,FOLLOW_T_IN_in_binoperator2751); 
+                    	// ooa.g:618:9: ( T_SET )?
+                    	int alt68 = 2;
+                    	alt68 = dfa68.Predict(input);
+                    	switch (alt68) 
+                    	{
+                    	    case 1 :
+                    	        // ooa.g:618:9: T_SET
+                    	        {
+                    	        	Match(input,T_SET,FOLLOW_T_SET_in_binoperator2753); 
+
+                    	        }
+                    	        break;
+
+                    	}
+
+                    	binop = createBinaryOperator(ExpressionKind.elemin);
+
+                    }
+                    break;
+                case 12 :
+                    // ooa.g:620:4: T_NOT T_IN ( T_SET )?
+                    {
+                    	Match(input,T_NOT,FOLLOW_T_NOT_in_binoperator2764); 
+                    	Match(input,T_IN,FOLLOW_T_IN_in_binoperator2766); 
+                    	// ooa.g:620:15: ( T_SET )?
+                    	int alt69 = 2;
+                    	alt69 = dfa69.Predict(input);
+                    	switch (alt69) 
+                    	{
+                    	    case 1 :
+                    	        // ooa.g:620:15: T_SET
+                    	        {
+                    	        	Match(input,T_SET,FOLLOW_T_SET_in_binoperator2768); 
+
+                    	        }
+                    	        break;
+
+                    	}
+
+                    	binop = createBinaryOperator(ExpressionKind.notelemin);
+
+                    }
+                    break;
+                case 13 :
+                    // ooa.g:622:4: T_SUBSET
+                    {
+                    	Match(input,T_SUBSET,FOLLOW_T_SUBSET_in_binoperator2779); 
+                    	binop = createBinaryOperator(ExpressionKind.subset);
+
+                    }
+                    break;
+                case 14 :
+                    // ooa.g:624:4: T_OR
+                    {
+                    	Match(input,T_OR,FOLLOW_T_OR_in_binoperator2789); 
+                    	binop = createBinaryOperator(ExpressionKind.or);
+
+                    }
+                    break;
+                case 15 :
+                    // ooa.g:626:4: T_DIV
+                    {
+                    	Match(input,T_DIV,FOLLOW_T_DIV_in_binoperator2798); 
+                    	binop = createBinaryOperator(ExpressionKind.div);
+
+                    }
+                    break;
+                case 16 :
+                    // ooa.g:628:4: T_PROD
+                    {
+                    	Match(input,T_PROD,FOLLOW_T_PROD_in_binoperator2807); 
+                    	binop = createBinaryOperator(ExpressionKind.prod);
+
+                    }
+                    break;
+                case 17 :
+                    // ooa.g:630:4: T_IDIV
+                    {
+                    	Match(input,T_IDIV,FOLLOW_T_IDIV_in_binoperator2817); 
+                    	binop = createBinaryOperator(ExpressionKind.idiv);
+
+                    }
+                    break;
+                case 18 :
+                    // ooa.g:632:4: T_MOD
+                    {
+                    	Match(input,T_MOD,FOLLOW_T_MOD_in_binoperator2827); 
+                    	binop = createBinaryOperator(ExpressionKind.mod);
+
+                    }
+                    break;
+                case 19 :
+                    // ooa.g:634:4: T_UNION
+                    {
+                    	Match(input,T_UNION,FOLLOW_T_UNION_in_binoperator2837); 
+                    	binop = createBinaryOperator(ExpressionKind.union);
+
+                    }
+                    break;
+                case 20 :
+                    // ooa.g:636:4: T_DIFF
+                    {
+                    	Match(input,T_DIFF,FOLLOW_T_DIFF_in_binoperator2848); 
+                    	binop = createBinaryOperator(ExpressionKind.diff);
+
+                    }
+                    break;
+                case 21 :
+                    // ooa.g:638:4: T_INTER
+                    {
+                    	Match(input,T_INTER,FOLLOW_T_INTER_in_binoperator2859); 
+                    	binop = createBinaryOperator(ExpressionKind.inter);
+
+                    }
+                    break;
+                case 22 :
+                    // ooa.g:640:4: T_AND
+                    {
+                    	Match(input,T_AND,FOLLOW_T_AND_in_binoperator2870); 
+                    	binop = createBinaryOperator(ExpressionKind.and);
+
+                    }
+                    break;
+                case 23 :
+                    // ooa.g:642:4: T_POW
+                    {
+                    	Match(input,T_POW,FOLLOW_T_POW_in_binoperator2885); 
+                    	binop = createBinaryOperator(ExpressionKind.pow);
+
+                    }
+                    break;
+                case 24 :
+                    // ooa.g:644:4: T_CONC
+                    {
+                    	Match(input,T_CONC,FOLLOW_T_CONC_in_binoperator2900); 
+                    	binop = createBinaryOperator(ExpressionKind.conc);
+
+                    }
+                    break;
+                case 25 :
+                    // ooa.g:646:4: T_DOMRESBY
+                    {
+                    	Match(input,T_DOMRESBY,FOLLOW_T_DOMRESBY_in_binoperator2913); 
+                    	binop = createBinaryOperator(ExpressionKind.domresby);
+
+                    }
+                    break;
+                case 26 :
+                    // ooa.g:648:4: T_DOMRESTO
+                    {
+                    	Match(input,T_DOMRESTO,FOLLOW_T_DOMRESTO_in_binoperator2923); 
+                    	binop = createBinaryOperator(ExpressionKind.domresto);
+
+                    }
+                    break;
+                case 27 :
+                    // ooa.g:650:4: T_RNGRESBY
+                    {
+                    	Match(input,T_RNGRESBY,FOLLOW_T_RNGRESBY_in_binoperator2933); 
+                    	binop = createBinaryOperator(ExpressionKind.rngresby);
+
+                    }
+                    break;
+                case 28 :
+                    // ooa.g:652:4: T_RNGRESTO
+                    {
+                    	Match(input,T_RNGRESTO,FOLLOW_T_RNGRESTO_in_binoperator2943); 
+                    	binop = createBinaryOperator(ExpressionKind.rngresto);
+
+                    }
+                    break;
+                case 29 :
+                    // ooa.g:654:4: T_MUNION
+                    {
+                    	Match(input,T_MUNION,FOLLOW_T_MUNION_in_binoperator2953); 
+                    	binop = createBinaryOperator(ExpressionKind.munion);
+
+                    }
+                    break;
+                case 30 :
+                    // ooa.g:656:4: T_SEQMOD_MAPOVERRIDE
+                    {
+                    	Match(input,T_SEQMOD_MAPOVERRIDE,FOLLOW_T_SEQMOD_MAPOVERRIDE_in_binoperator2963); 
+                    	binop = createBinaryOperator(ExpressionKind.seqmod_mapoverride);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return binop;
+    }
+    // $ANTLR end "binoperator"
+
+
+    // $ANTLR start "atomExpression"
+    // ooa.g:662:1: atomExpression returns [Expression expr] : ( ( (unexpr= op_un )? (e= identifierExpression | e= qvalExpression | e= constant | e= initializedComplexType | e= quantifierExpression | T_LPAREN e= expression T_RPAREN ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )? ) ( 'as' cid= T_IDENTIFIER )? ) | ie= T_IF ce= expression T_THEN te= expression T_ELSE ee= expression T_END );
+    public Expression atomExpression() // throws RecognitionException [1]
+    {   
+        Expression expr = default(Expression);
+
+        IToken idn = null;
+        IToken cid = null;
+        IToken ie = null;
+        UnaryOperator unexpr = default(UnaryOperator);
+
+        Expression e = default(Expression);
+
+        Expression res = default(Expression);
+
+        Expression ce = default(Expression);
+
+        Expression te = default(Expression);
+
+        Expression ee = default(Expression);
+
+
+
+        		expr = null;
+        	
+        try 
+    	{
+            // ooa.g:667:2: ( ( (unexpr= op_un )? (e= identifierExpression | e= qvalExpression | e= constant | e= initializedComplexType | e= quantifierExpression | T_LPAREN e= expression T_RPAREN ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )? ) ( 'as' cid= T_IDENTIFIER )? ) | ie= T_IF ce= expression T_THEN te= expression T_ELSE ee= expression T_END )
+            int alt77 = 2;
+            alt77 = dfa77.Predict(input);
+            switch (alt77) 
+            {
+                case 1 :
+                    // ooa.g:667:4: ( (unexpr= op_un )? (e= identifierExpression | e= qvalExpression | e= constant | e= initializedComplexType | e= quantifierExpression | T_LPAREN e= expression T_RPAREN ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )? ) ( 'as' cid= T_IDENTIFIER )? )
+                    {
+                    	// ooa.g:667:4: ( (unexpr= op_un )? (e= identifierExpression | e= qvalExpression | e= constant | e= initializedComplexType | e= quantifierExpression | T_LPAREN e= expression T_RPAREN ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )? ) ( 'as' cid= T_IDENTIFIER )? )
+                    	// ooa.g:667:5: (unexpr= op_un )? (e= identifierExpression | e= qvalExpression | e= constant | e= initializedComplexType | e= quantifierExpression | T_LPAREN e= expression T_RPAREN ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )? ) ( 'as' cid= T_IDENTIFIER )?
+                    	{
+                    		// ooa.g:667:11: (unexpr= op_un )?
+                    		int alt71 = 2;
+                    		alt71 = dfa71.Predict(input);
+                    		switch (alt71) 
+                    		{
+                    		    case 1 :
+                    		        // ooa.g:667:11: unexpr= op_un
+                    		        {
+                    		        	PushFollow(FOLLOW_op_un_in_atomExpression3001);
+                    		        	unexpr = op_un();
+                    		        	state.followingStackPointer--;
+
+
+                    		        }
+                    		        break;
+
+                    		}
+
+                    		// ooa.g:667:19: (e= identifierExpression | e= qvalExpression | e= constant | e= initializedComplexType | e= quantifierExpression | T_LPAREN e= expression T_RPAREN ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )? )
+                    		int alt75 = 6;
+                    		alt75 = dfa75.Predict(input);
+                    		switch (alt75) 
+                    		{
+                    		    case 1 :
+                    		        // ooa.g:668:8: e= identifierExpression
+                    		        {
+                    		        	PushFollow(FOLLOW_identifierExpression_in_atomExpression3018);
+                    		        	e = identifierExpression();
+                    		        	state.followingStackPointer--;
+
+
+                    		        }
+                    		        break;
+                    		    case 2 :
+                    		        // ooa.g:669:8: e= qvalExpression
+                    		        {
+                    		        	PushFollow(FOLLOW_qvalExpression_in_atomExpression3029);
+                    		        	e = qvalExpression();
+                    		        	state.followingStackPointer--;
+
+
+                    		        }
+                    		        break;
+                    		    case 3 :
+                    		        // ooa.g:670:8: e= constant
+                    		        {
+                    		        	PushFollow(FOLLOW_constant_in_atomExpression3040);
+                    		        	e = constant();
+                    		        	state.followingStackPointer--;
+
+
+                    		        }
+                    		        break;
+                    		    case 4 :
+                    		        // ooa.g:671:8: e= initializedComplexType
+                    		        {
+                    		        	PushFollow(FOLLOW_initializedComplexType_in_atomExpression3051);
+                    		        	e = initializedComplexType();
+                    		        	state.followingStackPointer--;
+
+
+                    		        }
+                    		        break;
+                    		    case 5 :
+                    		        // ooa.g:672:8: e= quantifierExpression
+                    		        {
+                    		        	PushFollow(FOLLOW_quantifierExpression_in_atomExpression3063);
+                    		        	e = quantifierExpression();
+                    		        	state.followingStackPointer--;
+
+
+                    		        }
+                    		        break;
+                    		    case 6 :
+                    		        // ooa.g:673:8: T_LPAREN e= expression T_RPAREN ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )?
+                    		        {
+                    		        	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_atomExpression3072); 
+                    		        	PushFollow(FOLLOW_expression_in_atomExpression3076);
+                    		        	e = expression();
+                    		        	state.followingStackPointer--;
+
+                    		        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_atomExpression3078); 
+                    		        	// ooa.g:674:8: ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )?
+                    		        	int alt74 = 3;
+                    		        	alt74 = dfa74.Predict(input);
+                    		        	switch (alt74) 
+                    		        	{
+                    		        	    case 1 :
+                    		        	        // ooa.g:675:6: ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )?
+                    		        	        {
+                    		        	        	// ooa.g:675:6: ( T_POINT idn= T_IDENTIFIER )+
+                    		        	        	int cnt72 = 0;
+                    		        	        	do 
+                    		        	        	{
+                    		        	        	    int alt72 = 2;
+                    		        	        	    alt72 = dfa72.Predict(input);
+                    		        	        	    switch (alt72) 
+                    		        	        		{
+                    		        	        			case 1 :
+                    		        	        			    // ooa.g:675:7: T_POINT idn= T_IDENTIFIER
+                    		        	        			    {
+                    		        	        			    	Match(input,T_POINT,FOLLOW_T_POINT_in_atomExpression3101); 
+                    		        	        			    	idn=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_atomExpression3113); 
+                    		        	        			    	e = addIdentifierAccessExpression(e,idn);
+
+                    		        	        			    }
+                    		        	        			    break;
+
+                    		        	        			default:
+                    		        	        			    if ( cnt72 >= 1 ) goto loop72;
+                    		        	        		            EarlyExitException eee72 =
+                    		        	        		                new EarlyExitException(72, input);
+                    		        	        		            throw eee72;
+                    		        	        	    }
+                    		        	        	    cnt72++;
+                    		        	        	} while (true);
+
+                    		        	        	loop72:
+                    		        	        		;	// Stops C# compiler whining that label 'loop72' has no statements
+
+                    		        	        	// ooa.g:678:8: (res= accessExpression[e] )?
+                    		        	        	int alt73 = 2;
+                    		        	        	alt73 = dfa73.Predict(input);
+                    		        	        	switch (alt73) 
+                    		        	        	{
+                    		        	        	    case 1 :
+                    		        	        	        // ooa.g:678:9: res= accessExpression[e]
+                    		        	        	        {
+                    		        	        	        	PushFollow(FOLLOW_accessExpression_in_atomExpression3137);
+                    		        	        	        	res = accessExpression(e);
+                    		        	        	        	state.followingStackPointer--;
+
+                    		        	        	        	e=res;
+
+                    		        	        	        }
+                    		        	        	        break;
+
+                    		        	        	}
+
+
+                    		        	        }
+                    		        	        break;
+                    		        	    case 2 :
+                    		        	        // ooa.g:680:6: e= accessExpression[e]
+                    		        	        {
+                    		        	        	PushFollow(FOLLOW_accessExpression_in_atomExpression3157);
+                    		        	        	e = accessExpression(e);
+                    		        	        	state.followingStackPointer--;
+
+
+                    		        	        }
+                    		        	        break;
+
+                    		        	}
+
+
+                    		        }
+                    		        break;
+
+                    		}
+
+                    		// ooa.g:682:5: ( 'as' cid= T_IDENTIFIER )?
+                    		int alt76 = 2;
+                    		alt76 = dfa76.Predict(input);
+                    		switch (alt76) 
+                    		{
+                    		    case 1 :
+                    		        // ooa.g:682:6: 'as' cid= T_IDENTIFIER
+                    		        {
+                    		        	Match(input,121,FOLLOW_121_in_atomExpression3176); 
+                    		        	cid=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_atomExpression3180); 
+                    		        	e=addCastExpression(e,cid);
+
+                    		        }
+                    		        break;
+
+                    		}
+
+                    		expr = addUnaryExpression(unexpr,e);
+
+                    	}
+
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:685:6: ie= T_IF ce= expression T_THEN te= expression T_ELSE ee= expression T_END
+                    {
+                    	ie=(IToken)Match(input,T_IF,FOLLOW_T_IF_in_atomExpression3201); 
+                    	PushFollow(FOLLOW_expression_in_atomExpression3205);
+                    	ce = expression();
+                    	state.followingStackPointer--;
+
+                    	Match(input,T_THEN,FOLLOW_T_THEN_in_atomExpression3207); 
+                    	PushFollow(FOLLOW_expression_in_atomExpression3211);
+                    	te = expression();
+                    	state.followingStackPointer--;
+
+                    	Match(input,T_ELSE,FOLLOW_T_ELSE_in_atomExpression3213); 
+                    	PushFollow(FOLLOW_expression_in_atomExpression3217);
+                    	ee = expression();
+                    	state.followingStackPointer--;
+
+                    	Match(input,T_END,FOLLOW_T_END_in_atomExpression3219); 
+                    	expr = createConditionalExpression(ce,te,ee,ie);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return expr;
+    }
+    // $ANTLR end "atomExpression"
+
+
+    // $ANTLR start "quantifierExpression"
+    // ooa.g:690:1: quantifierExpression returns [Quantifier result] : t= ( T_FORALL | T_EXISTS ) (id= T_IDENTIFIER ( T_COLON id_type= simpleType ) ( T_COMMA id2= T_IDENTIFIER ( T_COLON id_type2= simpleType ) )* ) T_COLON T_LPAREN e= expression T_RPAREN ;
+    public Quantifier quantifierExpression() // throws RecognitionException [1]
+    {   
+        Quantifier result = default(Quantifier);
+
+        IToken t = null;
+        IToken id = null;
+        IToken id2 = null;
+        UlyssesType id_type = default(UlyssesType);
+
+        UlyssesType id_type2 = default(UlyssesType);
+
+        Expression e = default(Expression);
+
+
+
+        		result = null;
+        	
+        try 
+    	{
+            // ooa.g:695:2: (t= ( T_FORALL | T_EXISTS ) (id= T_IDENTIFIER ( T_COLON id_type= simpleType ) ( T_COMMA id2= T_IDENTIFIER ( T_COLON id_type2= simpleType ) )* ) T_COLON T_LPAREN e= expression T_RPAREN )
+            // ooa.g:695:5: t= ( T_FORALL | T_EXISTS ) (id= T_IDENTIFIER ( T_COLON id_type= simpleType ) ( T_COMMA id2= T_IDENTIFIER ( T_COLON id_type2= simpleType ) )* ) T_COLON T_LPAREN e= expression T_RPAREN
+            {
+            	t = (IToken)input.LT(1);
+            	if ( (input.LA(1) >= T_FORALL && input.LA(1) <= T_EXISTS) ) 
+            	{
+            	    input.Consume();
+            	    state.errorRecovery = false;
+            	}
+            	else 
+            	{
+            	    MismatchedSetException mse = new MismatchedSetException(null,input);
+            	    throw mse;
+            	}
+
+            	result = createQuantifierExpression(t);
+            	// ooa.g:697:3: (id= T_IDENTIFIER ( T_COLON id_type= simpleType ) ( T_COMMA id2= T_IDENTIFIER ( T_COLON id_type2= simpleType ) )* )
+            	// ooa.g:697:4: id= T_IDENTIFIER ( T_COLON id_type= simpleType ) ( T_COMMA id2= T_IDENTIFIER ( T_COLON id_type2= simpleType ) )*
+            	{
+            		id=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_quantifierExpression3268); 
+            		// ooa.g:697:20: ( T_COLON id_type= simpleType )
+            		// ooa.g:697:21: T_COLON id_type= simpleType
+            		{
+            			Match(input,T_COLON,FOLLOW_T_COLON_in_quantifierExpression3271); 
+            			PushFollow(FOLLOW_simpleType_in_quantifierExpression3275);
+            			id_type = simpleType();
+            			state.followingStackPointer--;
+
+            			addBoundVarToQuantifierExpression(result,id,id_type);
+
+            		}
+
+            		// ooa.g:698:5: ( T_COMMA id2= T_IDENTIFIER ( T_COLON id_type2= simpleType ) )*
+            		do 
+            		{
+            		    int alt78 = 2;
+            		    int LA78_0 = input.LA(1);
+
+            		    if ( (LA78_0 == T_COMMA) )
+            		    {
+            		        alt78 = 1;
+            		    }
+
+
+            		    switch (alt78) 
+            			{
+            				case 1 :
+            				    // ooa.g:698:6: T_COMMA id2= T_IDENTIFIER ( T_COLON id_type2= simpleType )
+            				    {
+            				    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_quantifierExpression3286); 
+            				    	id2=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_quantifierExpression3290); 
+            				    	// ooa.g:698:31: ( T_COLON id_type2= simpleType )
+            				    	// ooa.g:698:32: T_COLON id_type2= simpleType
+            				    	{
+            				    		Match(input,T_COLON,FOLLOW_T_COLON_in_quantifierExpression3293); 
+            				    		PushFollow(FOLLOW_simpleType_in_quantifierExpression3297);
+            				    		id_type2 = simpleType();
+            				    		state.followingStackPointer--;
+
+
+            				    	}
+
+            				    	addBoundVarToQuantifierExpression(result,id2,id_type2);
+
+            				    }
+            				    break;
+
+            				default:
+            				    goto loop78;
+            		    }
+            		} while (true);
+
+            		loop78:
+            			;	// Stops C# compiler whining that label 'loop78' has no statements
+
+
+            	}
+
+            	Match(input,T_COLON,FOLLOW_T_COLON_in_quantifierExpression3307); 
+            	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_quantifierExpression3309); 
+            	PushFollow(FOLLOW_expression_in_quantifierExpression3313);
+            	e = expression();
+            	state.followingStackPointer--;
+
+            	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_quantifierExpression3315); 
+            	addExpressionToQuantifier(result,e);
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            removeBoundVarsFromResolveStack(result);
+        }
+        return result;
+    }
+    // $ANTLR end "quantifierExpression"
+
+
+    // $ANTLR start "constant"
+    // ooa.g:705:1: constant returns [LeafExpression result] : ( T_TRUE | T_FALSE | T_NIL | T_SELF | t_fl= T_FLOATNUMBER | t_in= T_INTNUMBER | t_l= T_STRINGLITERAL );
+    public LeafExpression constant() // throws RecognitionException [1]
+    {   
+        LeafExpression result = default(LeafExpression);
+
+        IToken t_fl = null;
+        IToken t_in = null;
+        IToken t_l = null;
+
+
+        		result = null;
+        	
+        try 
+    	{
+            // ooa.g:710:2: ( T_TRUE | T_FALSE | T_NIL | T_SELF | t_fl= T_FLOATNUMBER | t_in= T_INTNUMBER | t_l= T_STRINGLITERAL )
+            int alt79 = 7;
+            switch ( input.LA(1) ) 
+            {
+            case T_TRUE:
+            	{
+                alt79 = 1;
+                }
+                break;
+            case T_FALSE:
+            	{
+                alt79 = 2;
+                }
+                break;
+            case T_NIL:
+            	{
+                alt79 = 3;
+                }
+                break;
+            case T_SELF:
+            	{
+                alt79 = 4;
+                }
+                break;
+            case T_FLOATNUMBER:
+            	{
+                alt79 = 5;
+                }
+                break;
+            case T_INTNUMBER:
+            	{
+                alt79 = 6;
+                }
+                break;
+            case T_STRINGLITERAL:
+            	{
+                alt79 = 7;
+                }
+                break;
+            	default:
+            	    NoViableAltException nvae_d79s0 =
+            	        new NoViableAltException("", 79, 0, input);
+
+            	    throw nvae_d79s0;
+            }
+
+            switch (alt79) 
+            {
+                case 1 :
+                    // ooa.g:710:5: T_TRUE
+                    {
+                    	Match(input,T_TRUE,FOLLOW_T_TRUE_in_constant3349); 
+                    	result = createBoolConstant(true);
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:711:4: T_FALSE
+                    {
+                    	Match(input,T_FALSE,FOLLOW_T_FALSE_in_constant3357); 
+                    	result = createBoolConstant(false);
+
+                    }
+                    break;
+                case 3 :
+                    // ooa.g:712:4: T_NIL
+                    {
+                    	Match(input,T_NIL,FOLLOW_T_NIL_in_constant3364); 
+                    	result = createNullPointerConstant();
+
+                    }
+                    break;
+                case 4 :
+                    // ooa.g:713:4: T_SELF
+                    {
+                    	Match(input,T_SELF,FOLLOW_T_SELF_in_constant3372); 
+                    	result = createSelfPointer();
+
+                    }
+                    break;
+                case 5 :
+                    // ooa.g:714:5: t_fl= T_FLOATNUMBER
+                    {
+                    	t_fl=(IToken)Match(input,T_FLOATNUMBER,FOLLOW_T_FLOATNUMBER_in_constant3383); 
+                    	result = createFloatConstant(t_fl);
+
+                    }
+                    break;
+                case 6 :
+                    // ooa.g:715:4: t_in= T_INTNUMBER
+                    {
+                    	t_in=(IToken)Match(input,T_INTNUMBER,FOLLOW_T_INTNUMBER_in_constant3392); 
+                    	result = createIntConstant(t_in);
+
+                    }
+                    break;
+                case 7 :
+                    // ooa.g:716:4: t_l= T_STRINGLITERAL
+                    {
+                    	t_l=(IToken)Match(input,T_STRINGLITERAL,FOLLOW_T_STRINGLITERAL_in_constant3401); 
+                    	result = createStringConstant(t_l);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return result;
+    }
+    // $ANTLR end "constant"
+
+
+    // $ANTLR start "initializedComplexType"
+    // ooa.g:719:1: initializedComplexType returns [Expression result] : (res= initializedListType | res= initializedSetType | T_NEW T_LPAREN anid= T_IDENTIFIER ( T_COMMA aname= T_STRINGLITERAL T_RPAREN | T_RPAREN ) );
+    public Expression initializedComplexType() // throws RecognitionException [1]
+    {   
+        Expression result = default(Expression);
+
+        IToken anid = null;
+        IToken aname = null;
+        Expression res = default(Expression);
+
+
+
+        		result = null;
+        	
+        try 
+    	{
+            // ooa.g:724:2: (res= initializedListType | res= initializedSetType | T_NEW T_LPAREN anid= T_IDENTIFIER ( T_COMMA aname= T_STRINGLITERAL T_RPAREN | T_RPAREN ) )
+            int alt81 = 3;
+            switch ( input.LA(1) ) 
+            {
+            case T_LSQPAREN:
+            	{
+                alt81 = 1;
+                }
+                break;
+            case T_CBRL:
+            	{
+                alt81 = 2;
+                }
+                break;
+            case T_NEW:
+            	{
+                alt81 = 3;
+                }
+                break;
+            	default:
+            	    NoViableAltException nvae_d81s0 =
+            	        new NoViableAltException("", 81, 0, input);
+
+            	    throw nvae_d81s0;
+            }
+
+            switch (alt81) 
+            {
+                case 1 :
+                    // ooa.g:724:4: res= initializedListType
+                    {
+                    	PushFollow(FOLLOW_initializedListType_in_initializedComplexType3428);
+                    	res = initializedListType();
+                    	state.followingStackPointer--;
+
+                    	result = res;
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:725:4: res= initializedSetType
+                    {
+                    	PushFollow(FOLLOW_initializedSetType_in_initializedComplexType3437);
+                    	res = initializedSetType();
+                    	state.followingStackPointer--;
+
+                    	result = res;
+
+                    }
+                    break;
+                case 3 :
+                    // ooa.g:726:5: T_NEW T_LPAREN anid= T_IDENTIFIER ( T_COMMA aname= T_STRINGLITERAL T_RPAREN | T_RPAREN )
+                    {
+                    	Match(input,T_NEW,FOLLOW_T_NEW_in_initializedComplexType3445); 
+                    	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_initializedComplexType3447); 
+                    	anid=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_initializedComplexType3451); 
+                    	// ooa.g:727:4: ( T_COMMA aname= T_STRINGLITERAL T_RPAREN | T_RPAREN )
+                    	int alt80 = 2;
+                    	int LA80_0 = input.LA(1);
+
+                    	if ( (LA80_0 == T_COMMA) )
+                    	{
+                    	    alt80 = 1;
+                    	}
+                    	else if ( (LA80_0 == T_RPAREN) )
+                    	{
+                    	    alt80 = 2;
+                    	}
+                    	else 
+                    	{
+                    	    NoViableAltException nvae_d80s0 =
+                    	        new NoViableAltException("", 80, 0, input);
+
+                    	    throw nvae_d80s0;
+                    	}
+                    	switch (alt80) 
+                    	{
+                    	    case 1 :
+                    	        // ooa.g:728:5: T_COMMA aname= T_STRINGLITERAL T_RPAREN
+                    	        {
+                    	        	Match(input,T_COMMA,FOLLOW_T_COMMA_in_initializedComplexType3463); 
+                    	        	aname=(IToken)Match(input,T_STRINGLITERAL,FOLLOW_T_STRINGLITERAL_in_initializedComplexType3468); 
+                    	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_initializedComplexType3470); 
+                    	        	result = createNamedObject(anid, aname);
+
+                    	        }
+                    	        break;
+                    	    case 2 :
+                    	        // ooa.g:729:6: T_RPAREN
+                    	        {
+                    	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_initializedComplexType3479); 
+                    	        	result = createObject(anid);
+
+                    	        }
+                    	        break;
+
+                    	}
+
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return result;
+    }
+    // $ANTLR end "initializedComplexType"
+
+
+    // $ANTLR start "initializedListType"
+    // ooa.g:733:1: initializedListType returns [ListConstructor result] : T_LSQPAREN e= expression ( ( T_COMMA e2= expression )+ | listComprehension[result] )? T_RSQPAREN ;
+    public ListConstructor initializedListType() // throws RecognitionException [1]
+    {   
+        ListConstructor result = default(ListConstructor);
+
+        Expression e = default(Expression);
+
+        Expression e2 = default(Expression);
+
+
+
+        		result = createInitializedList();
+        		pushListVarsOnResolveStack(result); // need this here for list comprehension
+        	
+        try 
+    	{
+            // ooa.g:739:2: ( T_LSQPAREN e= expression ( ( T_COMMA e2= expression )+ | listComprehension[result] )? T_RSQPAREN )
+            // ooa.g:739:4: T_LSQPAREN e= expression ( ( T_COMMA e2= expression )+ | listComprehension[result] )? T_RSQPAREN
+            {
+            	Match(input,T_LSQPAREN,FOLLOW_T_LSQPAREN_in_initializedListType3510); 
+            	PushFollow(FOLLOW_expression_in_initializedListType3514);
+            	e = expression();
+            	state.followingStackPointer--;
+
+            	addListElement(result,e);
+            	// ooa.g:739:56: ( ( T_COMMA e2= expression )+ | listComprehension[result] )?
+            	int alt83 = 3;
+            	int LA83_0 = input.LA(1);
+
+            	if ( (LA83_0 == T_COMMA) )
+            	{
+            	    alt83 = 1;
+            	}
+            	else if ( (LA83_0 == T_BAR) )
+            	{
+            	    alt83 = 2;
+            	}
+            	switch (alt83) 
+            	{
+            	    case 1 :
+            	        // ooa.g:740:4: ( T_COMMA e2= expression )+
+            	        {
+            	        	// ooa.g:740:4: ( T_COMMA e2= expression )+
+            	        	int cnt82 = 0;
+            	        	do 
+            	        	{
+            	        	    int alt82 = 2;
+            	        	    int LA82_0 = input.LA(1);
+
+            	        	    if ( (LA82_0 == T_COMMA) )
+            	        	    {
+            	        	        alt82 = 1;
+            	        	    }
+
+
+            	        	    switch (alt82) 
+            	        		{
+            	        			case 1 :
+            	        			    // ooa.g:740:5: T_COMMA e2= expression
+            	        			    {
+            	        			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_initializedListType3525); 
+            	        			    	PushFollow(FOLLOW_expression_in_initializedListType3529);
+            	        			    	e2 = expression();
+            	        			    	state.followingStackPointer--;
+
+            	        			    	addListElement(result,e2);
+
+            	        			    }
+            	        			    break;
+
+            	        			default:
+            	        			    if ( cnt82 >= 1 ) goto loop82;
+            	        		            EarlyExitException eee82 =
+            	        		                new EarlyExitException(82, input);
+            	        		            throw eee82;
+            	        	    }
+            	        	    cnt82++;
+            	        	} while (true);
+
+            	        	loop82:
+            	        		;	// Stops C# compiler whining that label 'loop82' has no statements
+
+
+            	        }
+            	        break;
+            	    case 2 :
+            	        // ooa.g:741:6: listComprehension[result]
+            	        {
+            	        	PushFollow(FOLLOW_listComprehension_in_initializedListType3541);
+            	        	listComprehension(result);
+            	        	state.followingStackPointer--;
+
+
+            	        }
+            	        break;
+
+            	}
+
+            	Match(input,T_RSQPAREN,FOLLOW_T_RSQPAREN_in_initializedListType3549); 
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            popListVarsFromResolveStack(result);
+        }
+        return result;
+    }
+    // $ANTLR end "initializedListType"
+
+
+    // $ANTLR start "listComprehension"
+    // ooa.g:747:1: listComprehension[ListConstructor result] : T_BAR T_VAR id= T_IDENTIFIER T_COLON t1= complexType ( T_SEMICOLON id2= T_IDENTIFIER t2= complexType )* ( '&' e= expression )? ;
+    public void listComprehension(ListConstructor result) // throws RecognitionException [1]
+    {   
+        IToken id = null;
+        IToken id2 = null;
+        UlyssesType t1 = default(UlyssesType);
+
+        UlyssesType t2 = default(UlyssesType);
+
+        Expression e = default(Expression);
+
+
+        	
+        		result.SetHasComprehension(true);
+        	
+        try 
+    	{
+            // ooa.g:751:2: ( T_BAR T_VAR id= T_IDENTIFIER T_COLON t1= complexType ( T_SEMICOLON id2= T_IDENTIFIER t2= complexType )* ( '&' e= expression )? )
+            // ooa.g:752:3: T_BAR T_VAR id= T_IDENTIFIER T_COLON t1= complexType ( T_SEMICOLON id2= T_IDENTIFIER t2= complexType )* ( '&' e= expression )?
+            {
+            	Match(input,T_BAR,FOLLOW_T_BAR_in_listComprehension3580); 
+            	Match(input,T_VAR,FOLLOW_T_VAR_in_listComprehension3582); 
+            	id=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_listComprehension3588); 
+            	Match(input,T_COLON,FOLLOW_T_COLON_in_listComprehension3591); 
+            	PushFollow(FOLLOW_complexType_in_listComprehension3595);
+            	t1 = complexType();
+            	state.followingStackPointer--;
+
+            	addListComprVar(result,id,t1);
+            	// ooa.g:754:4: ( T_SEMICOLON id2= T_IDENTIFIER t2= complexType )*
+            	do 
+            	{
+            	    int alt84 = 2;
+            	    int LA84_0 = input.LA(1);
+
+            	    if ( (LA84_0 == T_SEMICOLON) )
+            	    {
+            	        alt84 = 1;
+            	    }
+
+
+            	    switch (alt84) 
+            		{
+            			case 1 :
+            			    // ooa.g:754:5: T_SEMICOLON id2= T_IDENTIFIER t2= complexType
+            			    {
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_listComprehension3604); 
+            			    	id2=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_listComprehension3608); 
+            			    	PushFollow(FOLLOW_complexType_in_listComprehension3613);
+            			    	t2 = complexType();
+            			    	state.followingStackPointer--;
+
+            			    	addListComprVar(result,id2,t2);
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop84;
+            	    }
+            	} while (true);
+
+            	loop84:
+            		;	// Stops C# compiler whining that label 'loop84' has no statements
+
+            	// ooa.g:755:3: ( '&' e= expression )?
+            	int alt85 = 2;
+            	int LA85_0 = input.LA(1);
+
+            	if ( (LA85_0 == 120) )
+            	{
+            	    alt85 = 1;
+            	}
+            	switch (alt85) 
+            	{
+            	    case 1 :
+            	        // ooa.g:755:4: '&' e= expression
+            	        {
+            	        	Match(input,120,FOLLOW_120_in_listComprehension3623); 
+            	        	PushFollow(FOLLOW_expression_in_listComprehension3629);
+            	        	e = expression();
+            	        	state.followingStackPointer--;
+
+            	        	addListComprExpr(result,e);
+
+            	        }
+            	        break;
+
+            	}
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "listComprehension"
+
+
+    // $ANTLR start "initializedSetType"
+    // ooa.g:759:1: initializedSetType returns [Expression result] : ( T_CBRL T_MAPS T_CBRR | res= initializedSet );
+    public Expression initializedSetType() // throws RecognitionException [1]
+    {   
+        Expression result = default(Expression);
+
+        Expression res = default(Expression);
+
+
+
+        		result = null;
+        	
+        try 
+    	{
+            // ooa.g:764:2: ( T_CBRL T_MAPS T_CBRR | res= initializedSet )
+            int alt86 = 2;
+            alt86 = dfa86.Predict(input);
+            switch (alt86) 
+            {
+                case 1 :
+                    // ooa.g:764:4: T_CBRL T_MAPS T_CBRR
+                    {
+                    	Match(input,T_CBRL,FOLLOW_T_CBRL_in_initializedSetType3655); 
+                    	Match(input,T_MAPS,FOLLOW_T_MAPS_in_initializedSetType3657); 
+                    	Match(input,T_CBRR,FOLLOW_T_CBRR_in_initializedSetType3659); 
+                    	result = createEmptyMap();
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:765:4: res= initializedSet
+                    {
+                    	PushFollow(FOLLOW_initializedSet_in_initializedSetType3670);
+                    	res = initializedSet();
+                    	state.followingStackPointer--;
+
+                    	result = res;
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return result;
+    }
+    // $ANTLR end "initializedSetType"
+
+
+    // $ANTLR start "initializedSet"
+    // ooa.g:768:1: initializedSet returns [Expression result] : T_CBRL e1= expression ( ( T_COMMA e2= expression )* | m= map[result, e1] | setComprehension[(SetConstructor)result] ) T_CBRR ;
+    public Expression initializedSet() // throws RecognitionException [1]
+    {   
+        Expression result = default(Expression);
+
+        Expression e1 = default(Expression);
+
+        Expression e2 = default(Expression);
+
+        Expression m = default(Expression);
+
+
+
+        		SetConstructor theset = createSet(); 
+        		pushSetVarsOnResolveStack(theset); // need this here for set comprehension
+        		result = theset;
+        	
+        try 
+    	{
+            // ooa.g:775:2: ( T_CBRL e1= expression ( ( T_COMMA e2= expression )* | m= map[result, e1] | setComprehension[(SetConstructor)result] ) T_CBRR )
+            // ooa.g:775:4: T_CBRL e1= expression ( ( T_COMMA e2= expression )* | m= map[result, e1] | setComprehension[(SetConstructor)result] ) T_CBRR
+            {
+            	Match(input,T_CBRL,FOLLOW_T_CBRL_in_initializedSet3696); 
+            	PushFollow(FOLLOW_expression_in_initializedSet3700);
+            	e1 = expression();
+            	state.followingStackPointer--;
+
+            	// ooa.g:776:10: ( ( T_COMMA e2= expression )* | m= map[result, e1] | setComprehension[(SetConstructor)result] )
+            	int alt88 = 3;
+            	switch ( input.LA(1) ) 
+            	{
+            	case T_COMMA:
+            	case T_CBRR:
+            		{
+            	    alt88 = 1;
+            	    }
+            	    break;
+            	case T_MAPS:
+            		{
+            	    alt88 = 2;
+            	    }
+            	    break;
+            	case T_BAR:
+            		{
+            	    alt88 = 3;
+            	    }
+            	    break;
+            		default:
+            		    NoViableAltException nvae_d88s0 =
+            		        new NoViableAltException("", 88, 0, input);
+
+            		    throw nvae_d88s0;
+            	}
+
+            	switch (alt88) 
+            	{
+            	    case 1 :
+            	        // ooa.g:777:4: ( T_COMMA e2= expression )*
+            	        {
+            	        	addToSet(result,e1);
+            	        	// ooa.g:778:4: ( T_COMMA e2= expression )*
+            	        	do 
+            	        	{
+            	        	    int alt87 = 2;
+            	        	    int LA87_0 = input.LA(1);
+
+            	        	    if ( (LA87_0 == T_COMMA) )
+            	        	    {
+            	        	        alt87 = 1;
+            	        	    }
+
+
+            	        	    switch (alt87) 
+            	        		{
+            	        			case 1 :
+            	        			    // ooa.g:778:5: T_COMMA e2= expression
+            	        			    {
+            	        			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_initializedSet3730); 
+            	        			    	PushFollow(FOLLOW_expression_in_initializedSet3734);
+            	        			    	e2 = expression();
+            	        			    	state.followingStackPointer--;
+
+            	        			    	addToSet(result,e2);
+
+            	        			    }
+            	        			    break;
+
+            	        			default:
+            	        			    goto loop87;
+            	        	    }
+            	        	} while (true);
+
+            	        	loop87:
+            	        		;	// Stops C# compiler whining that label 'loop87' has no statements
+
+
+            	        }
+            	        break;
+            	    case 2 :
+            	        // ooa.g:779:6: m= map[result, e1]
+            	        {
+            	        	PushFollow(FOLLOW_map_in_initializedSet3752);
+            	        	m = map(result, e1);
+            	        	state.followingStackPointer--;
+
+            	        	result = m;
+
+            	        }
+            	        break;
+            	    case 3 :
+            	        // ooa.g:780:5: setComprehension[(SetConstructor)result]
+            	        {
+            	        	addToSet(result,e1);
+            	        	PushFollow(FOLLOW_setComprehension_in_initializedSet3765);
+            	        	setComprehension((SetConstructor)result);
+            	        	state.followingStackPointer--;
+
+
+            	        }
+            	        break;
+
+            	}
+
+            	Match(input,T_CBRR,FOLLOW_T_CBRR_in_initializedSet3775); 
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+            popSetVarsFromResolveStack(theset);
+        }
+        return result;
+    }
+    // $ANTLR end "initializedSet"
+
+
+    // $ANTLR start "map"
+    // ooa.g:787:1: map[Expression _map, Expression e1] returns [Expression result] : am= T_MAPS e2= expression ( T_COMMA e3= expression T_MAPS e4= expression )* ;
+    public Expression map(Expression _map, Expression e1) // throws RecognitionException [1]
+    {   
+        Expression result = default(Expression);
+
+        IToken am = null;
+        Expression e2 = default(Expression);
+
+        Expression e3 = default(Expression);
+
+        Expression e4 = default(Expression);
+
+
+
+        		result = null;
+        	
+        try 
+    	{
+            // ooa.g:792:2: (am= T_MAPS e2= expression ( T_COMMA e3= expression T_MAPS e4= expression )* )
+            // ooa.g:792:4: am= T_MAPS e2= expression ( T_COMMA e3= expression T_MAPS e4= expression )*
+            {
+            	am=(IToken)Match(input,T_MAPS,FOLLOW_T_MAPS_in_map3813); 
+            	PushFollow(FOLLOW_expression_in_map3817);
+            	e2 = expression();
+            	state.followingStackPointer--;
+
+            	result = createMap(e1,e2,am);
+            	// ooa.g:792:63: ( T_COMMA e3= expression T_MAPS e4= expression )*
+            	do 
+            	{
+            	    int alt89 = 2;
+            	    int LA89_0 = input.LA(1);
+
+            	    if ( (LA89_0 == T_COMMA) )
+            	    {
+            	        alt89 = 1;
+            	    }
+
+
+            	    switch (alt89) 
+            		{
+            			case 1 :
+            			    // ooa.g:792:64: T_COMMA e3= expression T_MAPS e4= expression
+            			    {
+            			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_map3825); 
+            			    	PushFollow(FOLLOW_expression_in_map3829);
+            			    	e3 = expression();
+            			    	state.followingStackPointer--;
+
+            			    	Match(input,T_MAPS,FOLLOW_T_MAPS_in_map3831); 
+            			    	PushFollow(FOLLOW_expression_in_map3835);
+            			    	e4 = expression();
+            			    	state.followingStackPointer--;
+
+            			    	addToMap(result,e3,e4);
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop89;
+            	    }
+            	} while (true);
+
+            	loop89:
+            		;	// Stops C# compiler whining that label 'loop89' has no statements
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return result;
+    }
+    // $ANTLR end "map"
+
+
+    // $ANTLR start "setComprehension"
+    // ooa.g:795:1: setComprehension[SetConstructor _set] : T_BAR T_VAR (id1= T_IDENTIFIER T_COLON t1= complexType T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType )* ( '&' epx= expression )? ;
+    public void setComprehension(SetConstructor _set) // throws RecognitionException [1]
+    {   
+        IToken id1 = null;
+        IToken id2 = null;
+        UlyssesType t1 = default(UlyssesType);
+
+        UlyssesType t2 = default(UlyssesType);
+
+        Expression epx = default(Expression);
+
+
+
+        		_set.SetHasComprehension(true);
+        	
+        try 
+    	{
+            // ooa.g:799:2: ( T_BAR T_VAR (id1= T_IDENTIFIER T_COLON t1= complexType T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType )* ( '&' epx= expression )? )
+            // ooa.g:799:4: T_BAR T_VAR (id1= T_IDENTIFIER T_COLON t1= complexType T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType )* ( '&' epx= expression )?
+            {
+            	Match(input,T_BAR,FOLLOW_T_BAR_in_setComprehension3857); 
+            	Match(input,T_VAR,FOLLOW_T_VAR_in_setComprehension3859); 
+            	// ooa.g:799:16: (id1= T_IDENTIFIER T_COLON t1= complexType T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType )*
+            	do 
+            	{
+            	    int alt90 = 2;
+            	    int LA90_0 = input.LA(1);
+
+            	    if ( (LA90_0 == T_IDENTIFIER) )
+            	    {
+            	        alt90 = 1;
+            	    }
+
+
+            	    switch (alt90) 
+            		{
+            			case 1 :
+            			    // ooa.g:799:17: id1= T_IDENTIFIER T_COLON t1= complexType T_SEMICOLON id2= T_IDENTIFIER T_COLON t2= complexType
+            			    {
+            			    	id1=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_setComprehension3864); 
+            			    	Match(input,T_COLON,FOLLOW_T_COLON_in_setComprehension3867); 
+            			    	PushFollow(FOLLOW_complexType_in_setComprehension3871);
+            			    	t1 = complexType();
+            			    	state.followingStackPointer--;
+
+            			    	 addSetComprVar(_set, id1, t1); 
+            			    	Match(input,T_SEMICOLON,FOLLOW_T_SEMICOLON_in_setComprehension3880); 
+            			    	id2=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_setComprehension3884); 
+            			    	Match(input,T_COLON,FOLLOW_T_COLON_in_setComprehension3886); 
+            			    	PushFollow(FOLLOW_complexType_in_setComprehension3890);
+            			    	t2 = complexType();
+            			    	state.followingStackPointer--;
+
+            			    	 addSetComprVar(_set, id2, t2); 
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop90;
+            	    }
+            	} while (true);
+
+            	loop90:
+            		;	// Stops C# compiler whining that label 'loop90' has no statements
+
+            	// ooa.g:803:3: ( '&' epx= expression )?
+            	int alt91 = 2;
+            	int LA91_0 = input.LA(1);
+
+            	if ( (LA91_0 == 120) )
+            	{
+            	    alt91 = 1;
+            	}
+            	switch (alt91) 
+            	{
+            	    case 1 :
+            	        // ooa.g:803:4: '&' epx= expression
+            	        {
+            	        	Match(input,120,FOLLOW_120_in_setComprehension3904); 
+            	        	PushFollow(FOLLOW_expression_in_setComprehension3910);
+            	        	epx = expression();
+            	        	state.followingStackPointer--;
+
+            	        	 addSetComprExpr(_set,epx); 
+
+            	        }
+            	        break;
+
+            	}
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return ;
+    }
+    // $ANTLR end "setComprehension"
+
+
+    // $ANTLR start "qvalExpression"
+    // ooa.g:809:1: qvalExpression returns [QValConstructor result] : aval= 'qval' T_LPAREN ( T_NIL | (expr= qualifiedIdentifier | ( '-' )? T_INFTY ) ( T_RANGETO (expr2= qualifiedIdentifier | T_INFTY ) )? ) T_COMMA ( T_NIL | ( 'steady' | 'inc' | 'dec' ) ) T_RPAREN ;
+    public QValConstructor qvalExpression() // throws RecognitionException [1]
+    {   
+        QValConstructor result = default(QValConstructor);
+
+        IToken aval = null;
+        Expression expr = default(Expression);
+
+        Expression expr2 = default(Expression);
+
+
+
+        		bool minus = false;
+        		result = null;		
+        	
+        try 
+    	{
+            // ooa.g:815:2: (aval= 'qval' T_LPAREN ( T_NIL | (expr= qualifiedIdentifier | ( '-' )? T_INFTY ) ( T_RANGETO (expr2= qualifiedIdentifier | T_INFTY ) )? ) T_COMMA ( T_NIL | ( 'steady' | 'inc' | 'dec' ) ) T_RPAREN )
+            // ooa.g:816:3: aval= 'qval' T_LPAREN ( T_NIL | (expr= qualifiedIdentifier | ( '-' )? T_INFTY ) ( T_RANGETO (expr2= qualifiedIdentifier | T_INFTY ) )? ) T_COMMA ( T_NIL | ( 'steady' | 'inc' | 'dec' ) ) T_RPAREN
+            {
+            	aval=(IToken)Match(input,122,FOLLOW_122_in_qvalExpression3945); 
+            	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_qvalExpression3947); 
+            	result = createQualitativeValue(aval);
+            	// ooa.g:818:3: ( T_NIL | (expr= qualifiedIdentifier | ( '-' )? T_INFTY ) ( T_RANGETO (expr2= qualifiedIdentifier | T_INFTY ) )? )
+            	int alt96 = 2;
+            	int LA96_0 = input.LA(1);
+
+            	if ( (LA96_0 == T_NIL) )
+            	{
+            	    alt96 = 1;
+            	}
+            	else if ( (LA96_0 == T_IDENTIFIER || (LA96_0 >= T_MINUS && LA96_0 <= T_INFTY) || LA96_0 == T_SELF) )
+            	{
+            	    alt96 = 2;
+            	}
+            	else 
+            	{
+            	    NoViableAltException nvae_d96s0 =
+            	        new NoViableAltException("", 96, 0, input);
+
+            	    throw nvae_d96s0;
+            	}
+            	switch (alt96) 
+            	{
+            	    case 1 :
+            	        // ooa.g:819:4: T_NIL
+            	        {
+            	        	Match(input,T_NIL,FOLLOW_T_NIL_in_qvalExpression3961); 
+            	        	setQualitativeValueDontCare(result);
+
+            	        }
+            	        break;
+            	    case 2 :
+            	        // ooa.g:822:4: (expr= qualifiedIdentifier | ( '-' )? T_INFTY ) ( T_RANGETO (expr2= qualifiedIdentifier | T_INFTY ) )?
+            	        {
+            	        	// ooa.g:822:4: (expr= qualifiedIdentifier | ( '-' )? T_INFTY )
+            	        	int alt93 = 2;
+            	        	int LA93_0 = input.LA(1);
+
+            	        	if ( (LA93_0 == T_IDENTIFIER || LA93_0 == T_SELF) )
+            	        	{
+            	        	    alt93 = 1;
+            	        	}
+            	        	else if ( ((LA93_0 >= T_MINUS && LA93_0 <= T_INFTY)) )
+            	        	{
+            	        	    alt93 = 2;
+            	        	}
+            	        	else 
+            	        	{
+            	        	    NoViableAltException nvae_d93s0 =
+            	        	        new NoViableAltException("", 93, 0, input);
+
+            	        	    throw nvae_d93s0;
+            	        	}
+            	        	switch (alt93) 
+            	        	{
+            	        	    case 1 :
+            	        	        // ooa.g:822:6: expr= qualifiedIdentifier
+            	        	        {
+            	        	        	PushFollow(FOLLOW_qualifiedIdentifier_in_qvalExpression3982);
+            	        	        	expr = qualifiedIdentifier();
+            	        	        	state.followingStackPointer--;
+
+            	        	        	setQualitativeValueLandmark(result,expr);
+
+            	        	        }
+            	        	        break;
+            	        	    case 2 :
+            	        	        // ooa.g:825:5: ( '-' )? T_INFTY
+            	        	        {
+            	        	        	// ooa.g:825:5: ( '-' )?
+            	        	        	int alt92 = 2;
+            	        	        	int LA92_0 = input.LA(1);
+
+            	        	        	if ( (LA92_0 == T_MINUS) )
+            	        	        	{
+            	        	        	    alt92 = 1;
+            	        	        	}
+            	        	        	switch (alt92) 
+            	        	        	{
+            	        	        	    case 1 :
+            	        	        	        // ooa.g:825:6: '-'
+            	        	        	        {
+            	        	        	        	Match(input,T_MINUS,FOLLOW_T_MINUS_in_qvalExpression4001); 
+            	        	        	        	minus = true;
+
+            	        	        	        }
+            	        	        	        break;
+
+            	        	        	}
+
+            	        	        	Match(input,T_INFTY,FOLLOW_T_INFTY_in_qvalExpression4007); 
+            	        	        	setQualitativeValueInfinity(result,minus);
+
+            	        	        }
+            	        	        break;
+
+            	        	}
+
+            	        	// ooa.g:828:4: ( T_RANGETO (expr2= qualifiedIdentifier | T_INFTY ) )?
+            	        	int alt95 = 2;
+            	        	int LA95_0 = input.LA(1);
+
+            	        	if ( (LA95_0 == T_RANGETO) )
+            	        	{
+            	        	    alt95 = 1;
+            	        	}
+            	        	switch (alt95) 
+            	        	{
+            	        	    case 1 :
+            	        	        // ooa.g:828:5: T_RANGETO (expr2= qualifiedIdentifier | T_INFTY )
+            	        	        {
+            	        	        	Match(input,T_RANGETO,FOLLOW_T_RANGETO_in_qvalExpression4025); 
+            	        	        	// ooa.g:829:4: (expr2= qualifiedIdentifier | T_INFTY )
+            	        	        	int alt94 = 2;
+            	        	        	int LA94_0 = input.LA(1);
+
+            	        	        	if ( (LA94_0 == T_IDENTIFIER || LA94_0 == T_SELF) )
+            	        	        	{
+            	        	        	    alt94 = 1;
+            	        	        	}
+            	        	        	else if ( (LA94_0 == T_INFTY) )
+            	        	        	{
+            	        	        	    alt94 = 2;
+            	        	        	}
+            	        	        	else 
+            	        	        	{
+            	        	        	    NoViableAltException nvae_d94s0 =
+            	        	        	        new NoViableAltException("", 94, 0, input);
+
+            	        	        	    throw nvae_d94s0;
+            	        	        	}
+            	        	        	switch (alt94) 
+            	        	        	{
+            	        	        	    case 1 :
+            	        	        	        // ooa.g:829:6: expr2= qualifiedIdentifier
+            	        	        	        {
+            	        	        	        	PushFollow(FOLLOW_qualifiedIdentifier_in_qvalExpression4035);
+            	        	        	        	expr2 = qualifiedIdentifier();
+            	        	        	        	state.followingStackPointer--;
+
+            	        	        	        	setQualitativeValueRange(result,expr2);
+
+            	        	        	        }
+            	        	        	        break;
+            	        	        	    case 2 :
+            	        	        	        // ooa.g:832:5: T_INFTY
+            	        	        	        {
+            	        	        	        	Match(input,T_INFTY,FOLLOW_T_INFTY_in_qvalExpression4053); 
+            	        	        	        	setQualitativeValueRangeInfinity(result,false);
+
+            	        	        	        }
+            	        	        	        break;
+
+            	        	        	}
+
+
+            	        	        }
+            	        	        break;
+
+            	        	}
+
+
+            	        }
+            	        break;
+
+            	}
+
+            	Match(input,T_COMMA,FOLLOW_T_COMMA_in_qvalExpression4077); 
+            	// ooa.g:837:3: ( T_NIL | ( 'steady' | 'inc' | 'dec' ) )
+            	int alt98 = 2;
+            	int LA98_0 = input.LA(1);
+
+            	if ( (LA98_0 == T_NIL) )
+            	{
+            	    alt98 = 1;
+            	}
+            	else if ( ((LA98_0 >= 123 && LA98_0 <= 125)) )
+            	{
+            	    alt98 = 2;
+            	}
+            	else 
+            	{
+            	    NoViableAltException nvae_d98s0 =
+            	        new NoViableAltException("", 98, 0, input);
+
+            	    throw nvae_d98s0;
+            	}
+            	switch (alt98) 
+            	{
+            	    case 1 :
+            	        // ooa.g:838:4: T_NIL
+            	        {
+            	        	Match(input,T_NIL,FOLLOW_T_NIL_in_qvalExpression4087); 
+            	        	setQualitativeDerivDontCare(result);
+
+            	        }
+            	        break;
+            	    case 2 :
+            	        // ooa.g:841:4: ( 'steady' | 'inc' | 'dec' )
+            	        {
+            	        	// ooa.g:841:4: ( 'steady' | 'inc' | 'dec' )
+            	        	int alt97 = 3;
+            	        	switch ( input.LA(1) ) 
+            	        	{
+            	        	case 123:
+            	        		{
+            	        	    alt97 = 1;
+            	        	    }
+            	        	    break;
+            	        	case 124:
+            	        		{
+            	        	    alt97 = 2;
+            	        	    }
+            	        	    break;
+            	        	case 125:
+            	        		{
+            	        	    alt97 = 3;
+            	        	    }
+            	        	    break;
+            	        		default:
+            	        		    NoViableAltException nvae_d97s0 =
+            	        		        new NoViableAltException("", 97, 0, input);
+
+            	        		    throw nvae_d97s0;
+            	        	}
+
+            	        	switch (alt97) 
+            	        	{
+            	        	    case 1 :
+            	        	        // ooa.g:841:6: 'steady'
+            	        	        {
+            	        	        	Match(input,123,FOLLOW_123_in_qvalExpression4103); 
+            	        	        	setQualitativeDerivSteady(result);
+
+            	        	        }
+            	        	        break;
+            	        	    case 2 :
+            	        	        // ooa.g:843:6: 'inc'
+            	        	        {
+            	        	        	Match(input,124,FOLLOW_124_in_qvalExpression4116); 
+            	        	        	setQualitativeDerivInc(result);
+
+            	        	        }
+            	        	        break;
+            	        	    case 3 :
+            	        	        // ooa.g:845:6: 'dec'
+            	        	        {
+            	        	        	Match(input,125,FOLLOW_125_in_qvalExpression4129); 
+            	        	        	setQualitativeDerivDec(result);
+
+            	        	        }
+            	        	        break;
+
+            	        	}
+
+
+            	        }
+            	        break;
+
+            	}
+
+            	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_qvalExpression4151); 
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return result;
+    }
+    // $ANTLR end "qvalExpression"
+
+
+    // $ANTLR start "identifierExpression"
+    // ooa.g:853:1: identifierExpression returns [Expression result] : ({...}?aName= T_IDENTIFIER T_LPAREN m_params= methodCallParams T_RPAREN | res= reference );
+    public Expression identifierExpression() // throws RecognitionException [1]
+    {   
+        Expression result = default(Expression);
+
+        IToken aName = null;
+        System.Collections.Generic.List<Expression> m_params = default(System.Collections.Generic.List<Expression>);
+
+        Expression res = default(Expression);
+
+
+        try 
+    	{
+            // ooa.g:855:2: ({...}?aName= T_IDENTIFIER T_LPAREN m_params= methodCallParams T_RPAREN | res= reference )
+            int alt99 = 2;
+            alt99 = dfa99.Predict(input);
+            switch (alt99) 
+            {
+                case 1 :
+                    // ooa.g:856:3: {...}?aName= T_IDENTIFIER T_LPAREN m_params= methodCallParams T_RPAREN
+                    {
+                    	if ( !((isTuple(input.LT(1).Text))) ) 
+                    	{
+                    	    throw new FailedPredicateException(input, "identifierExpression", "isTuple(input.LT(1).Text)");
+                    	}
+                    	aName=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_identifierExpression4184); 
+                    	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_identifierExpression4186); 
+                    	PushFollow(FOLLOW_methodCallParams_in_identifierExpression4190);
+                    	m_params = methodCallParams();
+                    	state.followingStackPointer--;
+
+                    	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_identifierExpression4192); 
+                    	result = createInitializedTuple(aName,m_params);
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:860:3: res= reference
+                    {
+                    	PushFollow(FOLLOW_reference_in_identifierExpression4207);
+                    	res = reference();
+                    	state.followingStackPointer--;
+
+                    	result = res;
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return result;
+    }
+    // $ANTLR end "identifierExpression"
+
+
+    // $ANTLR start "reference"
+    // ooa.g:865:1: reference returns [Expression result] : {...}?aName= qualifiedIdentifier (output= accessExpression[result] | ) (pr= T_PRIMED | ( '::' T_LPAREN init= expression T_RPAREN )? afold= ( T_FOLDLR | T_FOLDRL ) T_LPAREN anexpr= expression T_RPAREN )? ;
+    public Expression reference() // throws RecognitionException [1]
+    {   
+        Expression result = default(Expression);
+
+        IToken pr = null;
+        IToken afold = null;
+        Expression aName = default(Expression);
+
+        Expression output = default(Expression);
+
+        Expression init = default(Expression);
+
+        Expression anexpr = default(Expression);
+
+
+
+        		result = null;
+        		init = null;
+        	
+        try 
+    	{
+            // ooa.g:871:2: ({...}?aName= qualifiedIdentifier (output= accessExpression[result] | ) (pr= T_PRIMED | ( '::' T_LPAREN init= expression T_RPAREN )? afold= ( T_FOLDLR | T_FOLDRL ) T_LPAREN anexpr= expression T_RPAREN )? )
+            // ooa.g:871:4: {...}?aName= qualifiedIdentifier (output= accessExpression[result] | ) (pr= T_PRIMED | ( '::' T_LPAREN init= expression T_RPAREN )? afold= ( T_FOLDLR | T_FOLDRL ) T_LPAREN anexpr= expression T_RPAREN )?
+            {
+            	if ( !((!isTuple(input.LT(1).Text))) ) 
+            	{
+            	    throw new FailedPredicateException(input, "reference", "!isTuple(input.LT(1).Text)");
+            	}
+            	PushFollow(FOLLOW_qualifiedIdentifier_in_reference4245);
+            	aName = qualifiedIdentifier();
+            	state.followingStackPointer--;
+
+            	result = aName;
+            	// ooa.g:873:3: (output= accessExpression[result] | )
+            	int alt100 = 2;
+            	alt100 = dfa100.Predict(input);
+            	switch (alt100) 
+            	{
+            	    case 1 :
+            	        // ooa.g:873:5: output= accessExpression[result]
+            	        {
+            	        	PushFollow(FOLLOW_accessExpression_in_reference4257);
+            	        	output = accessExpression(result);
+            	        	state.followingStackPointer--;
+
+            	        	result = output;
+
+            	        }
+            	        break;
+            	    case 2 :
+            	        // ooa.g:876:3: 
+            	        {
+            	        }
+            	        break;
+
+            	}
+
+            	// ooa.g:877:3: (pr= T_PRIMED | ( '::' T_LPAREN init= expression T_RPAREN )? afold= ( T_FOLDLR | T_FOLDRL ) T_LPAREN anexpr= expression T_RPAREN )?
+            	int alt102 = 3;
+            	alt102 = dfa102.Predict(input);
+            	switch (alt102) 
+            	{
+            	    case 1 :
+            	        // ooa.g:877:6: pr= T_PRIMED
+            	        {
+            	        	pr=(IToken)Match(input,T_PRIMED,FOLLOW_T_PRIMED_in_reference4282); 
+            	        	setIdentifierExpressionPrimed(ref result,pr);
+
+            	        }
+            	        break;
+            	    case 2 :
+            	        // ooa.g:879:5: ( '::' T_LPAREN init= expression T_RPAREN )? afold= ( T_FOLDLR | T_FOLDRL ) T_LPAREN anexpr= expression T_RPAREN
+            	        {
+            	        	// ooa.g:879:5: ( '::' T_LPAREN init= expression T_RPAREN )?
+            	        	int alt101 = 2;
+            	        	int LA101_0 = input.LA(1);
+
+            	        	if ( (LA101_0 == 126) )
+            	        	{
+            	        	    alt101 = 1;
+            	        	}
+            	        	switch (alt101) 
+            	        	{
+            	        	    case 1 :
+            	        	        // ooa.g:879:6: '::' T_LPAREN init= expression T_RPAREN
+            	        	        {
+            	        	        	Match(input,126,FOLLOW_126_in_reference4298); 
+            	        	        	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_reference4300); 
+            	        	        	PushFollow(FOLLOW_expression_in_reference4304);
+            	        	        	init = expression();
+            	        	        	state.followingStackPointer--;
+
+            	        	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_reference4306); 
+
+            	        	        }
+            	        	        break;
+
+            	        	}
+
+            	        	afold = (IToken)input.LT(1);
+            	        	if ( (input.LA(1) >= T_FOLDLR && input.LA(1) <= T_FOLDRL) ) 
+            	        	{
+            	        	    input.Consume();
+            	        	    state.errorRecovery = false;
+            	        	}
+            	        	else 
+            	        	{
+            	        	    MismatchedSetException mse = new MismatchedSetException(null,input);
+            	        	    throw mse;
+            	        	}
+
+            	        	Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_reference4318); 
+            	        	PushFollow(FOLLOW_expression_in_reference4322);
+            	        	anexpr = expression();
+            	        	state.followingStackPointer--;
+
+            	        	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_reference4324); 
+            	        	result = createFoldExpression(result,afold,init,anexpr);
+
+            	        }
+            	        break;
+
+            	}
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return result;
+    }
+    // $ANTLR end "reference"
+
+
+    // $ANTLR start "accessExpression"
+    // ooa.g:884:1: accessExpression[Expression subexpr] returns [Expression result] : (tcall= T_LSQPAREN ac= expression T_RSQPAREN | bcall= T_LPAREN m_params= methodCallParams T_RPAREN )+ ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[result] )? )? ;
+    public Expression accessExpression(Expression subexpr) // throws RecognitionException [1]
+    {   
+        Expression result = default(Expression);
+
+        IToken tcall = null;
+        IToken bcall = null;
+        IToken idn = null;
+        Expression ac = default(Expression);
+
+        System.Collections.Generic.List<Expression> m_params = default(System.Collections.Generic.List<Expression>);
+
+        Expression res = default(Expression);
+
+
+
+        		UnaryOperator newExpr = null;
+        		result = subexpr;
+        	
+        try 
+    	{
+            // ooa.g:890:2: ( (tcall= T_LSQPAREN ac= expression T_RSQPAREN | bcall= T_LPAREN m_params= methodCallParams T_RPAREN )+ ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[result] )? )? )
+            // ooa.g:891:7: (tcall= T_LSQPAREN ac= expression T_RSQPAREN | bcall= T_LPAREN m_params= methodCallParams T_RPAREN )+ ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[result] )? )?
+            {
+            	// ooa.g:891:7: (tcall= T_LSQPAREN ac= expression T_RSQPAREN | bcall= T_LPAREN m_params= methodCallParams T_RPAREN )+
+            	int cnt103 = 0;
+            	do 
+            	{
+            	    int alt103 = 3;
+            	    alt103 = dfa103.Predict(input);
+            	    switch (alt103) 
+            		{
+            			case 1 :
+            			    // ooa.g:891:9: tcall= T_LSQPAREN ac= expression T_RSQPAREN
+            			    {
+            			    	tcall=(IToken)Match(input,T_LSQPAREN,FOLLOW_T_LSQPAREN_in_accessExpression4369); 
+            			    	PushFollow(FOLLOW_expression_in_accessExpression4373);
+            			    	ac = expression();
+            			    	state.followingStackPointer--;
+
+            			    	Match(input,T_RSQPAREN,FOLLOW_T_RSQPAREN_in_accessExpression4375); 
+            			    	 result = createTupleMapAccessExpression(result,ac,tcall); 
+
+            			    }
+            			    break;
+            			case 2 :
+            			    // ooa.g:893:10: bcall= T_LPAREN m_params= methodCallParams T_RPAREN
+            			    {
+            			    	bcall=(IToken)Match(input,T_LPAREN,FOLLOW_T_LPAREN_in_accessExpression4402); 
+            			    	PushFollow(FOLLOW_methodCallParams_in_accessExpression4406);
+            			    	m_params = methodCallParams();
+            			    	state.followingStackPointer--;
+
+            			    	Match(input,T_RPAREN,FOLLOW_T_RPAREN_in_accessExpression4408); 
+            			    	 result = createMethodAccessExpression(result,m_params,bcall); 
+
+            			    }
+            			    break;
+
+            			default:
+            			    if ( cnt103 >= 1 ) goto loop103;
+            		            EarlyExitException eee103 =
+            		                new EarlyExitException(103, input);
+            		            throw eee103;
+            	    }
+            	    cnt103++;
+            	} while (true);
+
+            	loop103:
+            		;	// Stops C# compiler whining that label 'loop103' has no statements
+
+            	// ooa.g:896:3: ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[result] )? )?
+            	int alt106 = 2;
+            	alt106 = dfa106.Predict(input);
+            	switch (alt106) 
+            	{
+            	    case 1 :
+            	        // ooa.g:897:4: ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[result] )?
+            	        {
+            	        	// ooa.g:897:4: ( T_POINT idn= T_IDENTIFIER )+
+            	        	int cnt104 = 0;
+            	        	do 
+            	        	{
+            	        	    int alt104 = 2;
+            	        	    alt104 = dfa104.Predict(input);
+            	        	    switch (alt104) 
+            	        		{
+            	        			case 1 :
+            	        			    // ooa.g:897:5: T_POINT idn= T_IDENTIFIER
+            	        			    {
+            	        			    	Match(input,T_POINT,FOLLOW_T_POINT_in_accessExpression4430); 
+            	        			    	idn=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_accessExpression4438); 
+            	        			    	result = addIdentifierAccessExpression(result,idn);
+
+            	        			    }
+            	        			    break;
+
+            	        			default:
+            	        			    if ( cnt104 >= 1 ) goto loop104;
+            	        		            EarlyExitException eee104 =
+            	        		                new EarlyExitException(104, input);
+            	        		            throw eee104;
+            	        	    }
+            	        	    cnt104++;
+            	        	} while (true);
+
+            	        	loop104:
+            	        		;	// Stops C# compiler whining that label 'loop104' has no statements
+
+            	        	// ooa.g:900:4: (res= accessExpression[result] )?
+            	        	int alt105 = 2;
+            	        	alt105 = dfa105.Predict(input);
+            	        	switch (alt105) 
+            	        	{
+            	        	    case 1 :
+            	        	        // ooa.g:900:5: res= accessExpression[result]
+            	        	        {
+            	        	        	PushFollow(FOLLOW_accessExpression_in_accessExpression4454);
+            	        	        	res = accessExpression(result);
+            	        	        	state.followingStackPointer--;
+
+            	        	        	result=res;
+
+            	        	        }
+            	        	        break;
+
+            	        	}
+
+
+            	        }
+            	        break;
+
+            	}
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return result;
+    }
+    // $ANTLR end "accessExpression"
+
+
+    // $ANTLR start "qualifiedIdentifier"
+    // ooa.g:904:1: qualifiedIdentifier returns [Expression top] : (self= T_SELF T_POINT )? idb= T_IDENTIFIER ( T_POINT idd= T_IDENTIFIER )* ;
+    public Expression qualifiedIdentifier() // throws RecognitionException [1]
+    {   
+        Expression top = default(Expression);
+
+        IToken self = null;
+        IToken idb = null;
+        IToken idd = null;
+
+
+        		IdentifierExpression selfexpr = null;
+        		top = null;
+        	
+        try 
+    	{
+            // ooa.g:910:2: ( (self= T_SELF T_POINT )? idb= T_IDENTIFIER ( T_POINT idd= T_IDENTIFIER )* )
+            // ooa.g:911:3: (self= T_SELF T_POINT )? idb= T_IDENTIFIER ( T_POINT idd= T_IDENTIFIER )*
+            {
+            	// ooa.g:911:3: (self= T_SELF T_POINT )?
+            	int alt107 = 2;
+            	int LA107_0 = input.LA(1);
+
+            	if ( (LA107_0 == T_SELF) )
+            	{
+            	    alt107 = 1;
+            	}
+            	switch (alt107) 
+            	{
+            	    case 1 :
+            	        // ooa.g:911:4: self= T_SELF T_POINT
+            	        {
+            	        	self=(IToken)Match(input,T_SELF,FOLLOW_T_SELF_in_qualifiedIdentifier4493); 
+            	        	Match(input,T_POINT,FOLLOW_T_POINT_in_qualifiedIdentifier4495); 
+            	        	selfexpr = createSelfIdentifierExpression(self);
+
+            	        }
+            	        break;
+
+            	}
+
+            	idb=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_qualifiedIdentifier4507); 
+            	top = createIdentifierAccessExpression(selfexpr,idb);
+            	// ooa.g:913:3: ( T_POINT idd= T_IDENTIFIER )*
+            	do 
+            	{
+            	    int alt108 = 2;
+            	    alt108 = dfa108.Predict(input);
+            	    switch (alt108) 
+            		{
+            			case 1 :
+            			    // ooa.g:913:4: T_POINT idd= T_IDENTIFIER
+            			    {
+            			    	Match(input,T_POINT,FOLLOW_T_POINT_in_qualifiedIdentifier4516); 
+            			    	idd=(IToken)Match(input,T_IDENTIFIER,FOLLOW_T_IDENTIFIER_in_qualifiedIdentifier4520); 
+            			    	top = addIdentifierAccessExpression(top,idd);
+
+            			    }
+            			    break;
+
+            			default:
+            			    goto loop108;
+            	    }
+            	} while (true);
+
+            	loop108:
+            		;	// Stops C# compiler whining that label 'loop108' has no statements
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return top;
+    }
+    // $ANTLR end "qualifiedIdentifier"
+
+
+    // $ANTLR start "methodCallParams"
+    // ooa.g:917:1: methodCallParams returns [System.Collections.Generic.List<Expression> result] : (expa= expression ( T_COMMA expb= expression )* )? ;
+    public System.Collections.Generic.List<Expression> methodCallParams() // throws RecognitionException [1]
+    {   
+        System.Collections.Generic.List<Expression> result = default(System.Collections.Generic.List<Expression>);
+
+        Expression expa = default(Expression);
+
+        Expression expb = default(Expression);
+
+
+
+        		result = new System.Collections.Generic.List<Expression>();
+        	
+        try 
+    	{
+            // ooa.g:922:2: ( (expa= expression ( T_COMMA expb= expression )* )? )
+            // ooa.g:922:4: (expa= expression ( T_COMMA expb= expression )* )?
+            {
+            	// ooa.g:922:4: (expa= expression ( T_COMMA expb= expression )* )?
+            	int alt110 = 2;
+            	alt110 = dfa110.Predict(input);
+            	switch (alt110) 
+            	{
+            	    case 1 :
+            	        // ooa.g:922:5: expa= expression ( T_COMMA expb= expression )*
+            	        {
+            	        	PushFollow(FOLLOW_expression_in_methodCallParams4553);
+            	        	expa = expression();
+            	        	state.followingStackPointer--;
+
+            	        	result.Add(expa);
+            	        	// ooa.g:922:41: ( T_COMMA expb= expression )*
+            	        	do 
+            	        	{
+            	        	    int alt109 = 2;
+            	        	    int LA109_0 = input.LA(1);
+
+            	        	    if ( (LA109_0 == T_COMMA) )
+            	        	    {
+            	        	        alt109 = 1;
+            	        	    }
+
+
+            	        	    switch (alt109) 
+            	        		{
+            	        			case 1 :
+            	        			    // ooa.g:922:42: T_COMMA expb= expression
+            	        			    {
+            	        			    	Match(input,T_COMMA,FOLLOW_T_COMMA_in_methodCallParams4558); 
+            	        			    	PushFollow(FOLLOW_expression_in_methodCallParams4562);
+            	        			    	expb = expression();
+            	        			    	state.followingStackPointer--;
+
+            	        			    	result.Add(expb);
+
+            	        			    }
+            	        			    break;
+
+            	        			default:
+            	        			    goto loop109;
+            	        	    }
+            	        	} while (true);
+
+            	        	loop109:
+            	        		;	// Stops C# compiler whining that label 'loop109' has no statements
+
+
+            	        }
+            	        break;
+
+            	}
+
+
+            }
+
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return result;
+    }
+    // $ANTLR end "methodCallParams"
+
+
+    // $ANTLR start "op_un"
+    // ooa.g:932:1: op_un returns [UnaryOperator expr] : (r= op_un_set_list | r2= op_un_map | T_MINUS | T_NOT | T_ABS );
+    public UnaryOperator op_un() // throws RecognitionException [1]
+    {   
+        UnaryOperator expr = default(UnaryOperator);
+
+        UnaryOperator r = default(UnaryOperator);
+
+        UnaryOperator r2 = default(UnaryOperator);
+
+
+
+        		expr = null;
+        	
+        try 
+    	{
+            // ooa.g:937:2: (r= op_un_set_list | r2= op_un_map | T_MINUS | T_NOT | T_ABS )
+            int alt111 = 5;
+            alt111 = dfa111.Predict(input);
+            switch (alt111) 
+            {
+                case 1 :
+                    // ooa.g:937:4: r= op_un_set_list
+                    {
+                    	PushFollow(FOLLOW_op_un_set_list_in_op_un4601);
+                    	r = op_un_set_list();
+                    	state.followingStackPointer--;
+
+                    	expr = r;
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:938:4: r2= op_un_map
+                    {
+                    	PushFollow(FOLLOW_op_un_map_in_op_un4610);
+                    	r2 = op_un_map();
+                    	state.followingStackPointer--;
+
+                    	expr = r2;
+
+                    }
+                    break;
+                case 3 :
+                    // ooa.g:939:4: T_MINUS
+                    {
+                    	Match(input,T_MINUS,FOLLOW_T_MINUS_in_op_un4618); 
+                    	expr = createUnaryOperator(ExpressionKind.unminus);
+
+                    }
+                    break;
+                case 4 :
+                    // ooa.g:940:4: T_NOT
+                    {
+                    	Match(input,T_NOT,FOLLOW_T_NOT_in_op_un4626); 
+                    	expr = createUnaryOperator(ExpressionKind.not);
+
+                    }
+                    break;
+                case 5 :
+                    // ooa.g:941:4: T_ABS
+                    {
+                    	Match(input,T_ABS,FOLLOW_T_ABS_in_op_un4634); 
+                    	expr = createUnaryOperator(ExpressionKind.abs);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return expr;
+    }
+    // $ANTLR end "op_un"
+
+
+    // $ANTLR start "op_un_set_list"
+    // ooa.g:945:1: op_un_set_list returns [UnaryOperator expr] : ( T_CARD | T_DCONC | T_DINTER | T_DUNION | T_ELEMS | T_HEAD | T_INDS | T_LEN | T_TAIL );
+    public UnaryOperator op_un_set_list() // throws RecognitionException [1]
+    {   
+        UnaryOperator expr = default(UnaryOperator);
+
+
+        		expr = null;
+        	
+        try 
+    	{
+            // ooa.g:950:2: ( T_CARD | T_DCONC | T_DINTER | T_DUNION | T_ELEMS | T_HEAD | T_INDS | T_LEN | T_TAIL )
+            int alt112 = 9;
+            alt112 = dfa112.Predict(input);
+            switch (alt112) 
+            {
+                case 1 :
+                    // ooa.g:950:4: T_CARD
+                    {
+                    	Match(input,T_CARD,FOLLOW_T_CARD_in_op_un_set_list4661); 
+                    	expr = createUnaryOperator(ExpressionKind.card);
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:952:4: T_DCONC
+                    {
+                    	Match(input,T_DCONC,FOLLOW_T_DCONC_in_op_un_set_list4672); 
+                    	expr = createUnaryOperator(ExpressionKind.dconc);
+
+                    }
+                    break;
+                case 3 :
+                    // ooa.g:954:4: T_DINTER
+                    {
+                    	Match(input,T_DINTER,FOLLOW_T_DINTER_in_op_un_set_list4683); 
+                    	expr = createUnaryOperator(ExpressionKind.dinter);
+
+                    }
+                    break;
+                case 4 :
+                    // ooa.g:956:4: T_DUNION
+                    {
+                    	Match(input,T_DUNION,FOLLOW_T_DUNION_in_op_un_set_list4693); 
+                    	expr = createUnaryOperator(ExpressionKind.dunion);
+
+                    }
+                    break;
+                case 5 :
+                    // ooa.g:958:4: T_ELEMS
+                    {
+                    	Match(input,T_ELEMS,FOLLOW_T_ELEMS_in_op_un_set_list4703); 
+                    	expr = createUnaryOperator(ExpressionKind.elems);
+
+                    }
+                    break;
+                case 6 :
+                    // ooa.g:960:4: T_HEAD
+                    {
+                    	Match(input,T_HEAD,FOLLOW_T_HEAD_in_op_un_set_list4714); 
+                    	expr = createUnaryOperator(ExpressionKind.head);
+
+                    }
+                    break;
+                case 7 :
+                    // ooa.g:962:4: T_INDS
+                    {
+                    	Match(input,T_INDS,FOLLOW_T_INDS_in_op_un_set_list4725); 
+                    	expr = createUnaryOperator(ExpressionKind.inds);
+
+                    }
+                    break;
+                case 8 :
+                    // ooa.g:964:4: T_LEN
+                    {
+                    	Match(input,T_LEN,FOLLOW_T_LEN_in_op_un_set_list4736); 
+                    	expr = createUnaryOperator(ExpressionKind.len);
+
+                    }
+                    break;
+                case 9 :
+                    // ooa.g:966:4: T_TAIL
+                    {
+                    	Match(input,T_TAIL,FOLLOW_T_TAIL_in_op_un_set_list4747); 
+                    	expr = createUnaryOperator(ExpressionKind.tail);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return expr;
+    }
+    // $ANTLR end "op_un_set_list"
+
+
+    // $ANTLR start "op_un_map"
+    // ooa.g:971:1: op_un_map returns [UnaryOperator expr] : ( T_DOM | T_RNG | T_MERGE );
+    public UnaryOperator op_un_map() // throws RecognitionException [1]
+    {   
+        UnaryOperator expr = default(UnaryOperator);
+
+
+        		expr = null;
+        	
+        try 
+    	{
+            // ooa.g:976:2: ( T_DOM | T_RNG | T_MERGE )
+            int alt113 = 3;
+            switch ( input.LA(1) ) 
+            {
+            case T_DOM:
+            	{
+                alt113 = 1;
+                }
+                break;
+            case T_RNG:
+            	{
+                alt113 = 2;
+                }
+                break;
+            case T_MERGE:
+            	{
+                alt113 = 3;
+                }
+                break;
+            	default:
+            	    NoViableAltException nvae_d113s0 =
+            	        new NoViableAltException("", 113, 0, input);
+
+            	    throw nvae_d113s0;
+            }
+
+            switch (alt113) 
+            {
+                case 1 :
+                    // ooa.g:976:4: T_DOM
+                    {
+                    	Match(input,T_DOM,FOLLOW_T_DOM_in_op_un_map4776); 
+                    	expr = createUnaryOperator(ExpressionKind.dom);
+
+                    }
+                    break;
+                case 2 :
+                    // ooa.g:978:4: T_RNG
+                    {
+                    	Match(input,T_RNG,FOLLOW_T_RNG_in_op_un_map4787); 
+                    	expr = createUnaryOperator(ExpressionKind.range);
+
+                    }
+                    break;
+                case 3 :
+                    // ooa.g:980:4: T_MERGE
+                    {
+                    	Match(input,T_MERGE,FOLLOW_T_MERGE_in_op_un_map4798); 
+                    	expr = createUnaryOperator(ExpressionKind.merge);
+
+                    }
+                    break;
+
+            }
+        }
+        catch (RecognitionException re) 
+    	{
+            ReportError(re);
+            Recover(input,re);
+        }
+        finally 
+    	{
+        }
+        return expr;
+    }
+    // $ANTLR end "op_un_map"
+
+    // Delegated rules
+
+
+   	protected DFA4 dfa4;
+   	protected DFA14 dfa14;
+   	protected DFA67 dfa67;
+   	protected DFA70 dfa70;
+   	protected DFA68 dfa68;
+   	protected DFA69 dfa69;
+   	protected DFA77 dfa77;
+   	protected DFA71 dfa71;
+   	protected DFA75 dfa75;
+   	protected DFA74 dfa74;
+   	protected DFA72 dfa72;
+   	protected DFA73 dfa73;
+   	protected DFA76 dfa76;
+   	protected DFA86 dfa86;
+   	protected DFA99 dfa99;
+   	protected DFA100 dfa100;
+   	protected DFA102 dfa102;
+   	protected DFA103 dfa103;
+   	protected DFA106 dfa106;
+   	protected DFA104 dfa104;
+   	protected DFA105 dfa105;
+   	protected DFA108 dfa108;
+   	protected DFA110 dfa110;
+   	protected DFA111 dfa111;
+   	protected DFA112 dfa112;
+	private void InitializeCyclicDFAs()
+	{
+    	this.dfa4 = new DFA4(this);
+    	this.dfa14 = new DFA14(this);
+    	this.dfa67 = new DFA67(this);
+    	this.dfa70 = new DFA70(this);
+    	this.dfa68 = new DFA68(this);
+    	this.dfa69 = new DFA69(this);
+    	this.dfa77 = new DFA77(this);
+    	this.dfa71 = new DFA71(this);
+    	this.dfa75 = new DFA75(this);
+    	this.dfa74 = new DFA74(this);
+    	this.dfa72 = new DFA72(this);
+    	this.dfa73 = new DFA73(this);
+    	this.dfa76 = new DFA76(this);
+    	this.dfa86 = new DFA86(this);
+    	this.dfa99 = new DFA99(this);
+    	this.dfa100 = new DFA100(this);
+    	this.dfa102 = new DFA102(this);
+    	this.dfa103 = new DFA103(this);
+    	this.dfa106 = new DFA106(this);
+    	this.dfa104 = new DFA104(this);
+    	this.dfa105 = new DFA105(this);
+    	this.dfa108 = new DFA108(this);
+    	this.dfa110 = new DFA110(this);
+    	this.dfa111 = new DFA111(this);
+    	this.dfa112 = new DFA112(this);
+	    this.dfa99.specialStateTransitionHandler = new DFA.SpecialStateTransitionHandler(DFA99_SpecialStateTransition);
+	}
+
+    const string DFA4_eotS =
+        "\x0e\uffff";
+    const string DFA4_eofS =
+        "\x0e\uffff";
+    const string DFA4_minS =
+        "\x01\x06\x0d\uffff";
+    const string DFA4_maxS =
+        "\x01\x21\x0d\uffff";
+    const string DFA4_acceptS =
+        "\x01\uffff\x01\x01\x0a\uffff\x01\x02\x01\uffff";
+    const string DFA4_specialS =
+        "\x0e\uffff}>";
+    static readonly string[] DFA4_transitionS = {
+            "\x01\x0c\x01\uffff\x01\x01\x03\uffff\x01\x01\x01\uffff\x02"+
+            "\x01\x04\uffff\x01\x01\x01\uffff\x01\x01\x02\uffff\x02\x01\x01"+
+            "\uffff\x01\x01\x01\uffff\x02\x01\x01\uffff\x01\x0c",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA4_eot = DFA.UnpackEncodedString(DFA4_eotS);
+    static readonly short[] DFA4_eof = DFA.UnpackEncodedString(DFA4_eofS);
+    static readonly char[] DFA4_min = DFA.UnpackEncodedStringToUnsignedChars(DFA4_minS);
+    static readonly char[] DFA4_max = DFA.UnpackEncodedStringToUnsignedChars(DFA4_maxS);
+    static readonly short[] DFA4_accept = DFA.UnpackEncodedString(DFA4_acceptS);
+    static readonly short[] DFA4_special = DFA.UnpackEncodedString(DFA4_specialS);
+    static readonly short[][] DFA4_transition = DFA.UnpackEncodedStringArray(DFA4_transitionS);
+
+    protected class DFA4 : DFA
+    {
+        public DFA4(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 4;
+            this.eot = DFA4_eot;
+            this.eof = DFA4_eof;
+            this.min = DFA4_min;
+            this.max = DFA4_max;
+            this.accept = DFA4_accept;
+            this.special = DFA4_special;
+            this.transition = DFA4_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "177:3: (aType= complexType | anOoaType= ooActionSystem )"; }
+        }
+
+    }
+
+    const string DFA14_eotS =
+        "\x0c\uffff";
+    const string DFA14_eofS =
+        "\x0c\uffff";
+    const string DFA14_minS =
+        "\x01\x08\x0b\uffff";
+    const string DFA14_maxS =
+        "\x01\x1f\x0b\uffff";
+    const string DFA14_acceptS =
+        "\x01\uffff\x01\x01\x01\x02\x01\x03\x01\x04\x01\x05\x01\x06\x05"+
+        "\uffff";
+    const string DFA14_specialS =
+        "\x0c\uffff}>";
+    static readonly string[] DFA14_transitionS = {
+            "\x01\x06\x03\uffff\x01\x05\x01\uffff\x01\x01\x01\x02\x04\uffff"+
+            "\x01\x03\x01\uffff\x01\x04\x02\uffff\x02\x06\x01\uffff\x01\x06"+
+            "\x01\uffff\x02\x06",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA14_eot = DFA.UnpackEncodedString(DFA14_eotS);
+    static readonly short[] DFA14_eof = DFA.UnpackEncodedString(DFA14_eofS);
+    static readonly char[] DFA14_min = DFA.UnpackEncodedStringToUnsignedChars(DFA14_minS);
+    static readonly char[] DFA14_max = DFA.UnpackEncodedStringToUnsignedChars(DFA14_maxS);
+    static readonly short[] DFA14_accept = DFA.UnpackEncodedString(DFA14_acceptS);
+    static readonly short[] DFA14_special = DFA.UnpackEncodedString(DFA14_specialS);
+    static readonly short[][] DFA14_transition = DFA.UnpackEncodedStringArray(DFA14_transitionS);
+
+    protected class DFA14 : DFA
+    {
+        public DFA14(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 14;
+            this.eot = DFA14_eot;
+            this.eof = DFA14_eof;
+            this.min = DFA14_min;
+            this.max = DFA14_max;
+            this.accept = DFA14_accept;
+            this.special = DFA14_special;
+            this.transition = DFA14_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "211:1: complexType returns [UlyssesType aTypeSymbol] : ( T_LIST T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN T_OF innertype= complexType | T_LSQPAREN alistelem= T_IDENTIFIER ( T_COMMA otherlistelem= T_IDENTIFIER )* T_RSQPAREN | T_MAP ( T_LSQPAREN numOfElements= ( T_INTNUMBER | T_IDENTIFIER ) T_RSQPAREN )? mapfromtype= simpleType T_TO maptotype= complexType | T_QUANTITY T_OF T_LSQPAREN (alandmark= T_IDENTIFIER | alandmark= T_MINUS T_INFTY ) ( T_COMMA (otherlandmark= T_IDENTIFIER | otherlandmark= T_INFTY ) )* T_RSQPAREN | T_LPAREN aType= complexType ( T_COMMA anotherType= complexType )* T_RPAREN | r= simpleType );"; }
+        }
+
+    }
+
+    const string DFA67_eotS =
+        "\x32\uffff";
+    const string DFA67_eofS =
+        "\x32\uffff";
+    const string DFA67_minS =
+        "\x01\x05\x31\uffff";
+    const string DFA67_maxS =
+        "\x01\x76\x31\uffff";
+    const string DFA67_acceptS =
+        "\x01\uffff\x01\x02\x12\uffff\x01\x01\x1d\uffff";
+    const string DFA67_specialS =
+        "\x32\uffff}>";
+    static readonly string[] DFA67_transitionS = {
+            "\x01\x01\x01\uffff\x01\x01\x01\uffff\x01\x14\x02\x01\x01\uffff"+
+            "\x01\x01\x03\uffff\x01\x01\x01\uffff\x01\x01\x03\uffff\x01\x14"+
+            "\x08\uffff\x01\x01\x02\uffff\x03\x01\x04\uffff\x02\x01\x03\uffff"+
+            "\x03\x14\x07\uffff\x01\x01\x08\x14\x01\uffff\x11\x14\x02\uffff"+
+            "\x02\x01\x07\uffff\x02\x01\x15\uffff\x01\x01",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA67_eot = DFA.UnpackEncodedString(DFA67_eotS);
+    static readonly short[] DFA67_eof = DFA.UnpackEncodedString(DFA67_eofS);
+    static readonly char[] DFA67_min = DFA.UnpackEncodedStringToUnsignedChars(DFA67_minS);
+    static readonly char[] DFA67_max = DFA.UnpackEncodedStringToUnsignedChars(DFA67_maxS);
+    static readonly short[] DFA67_accept = DFA.UnpackEncodedString(DFA67_acceptS);
+    static readonly short[] DFA67_special = DFA.UnpackEncodedString(DFA67_specialS);
+    static readonly short[][] DFA67_transition = DFA.UnpackEncodedStringArray(DFA67_transitionS);
+
+    protected class DFA67 : DFA
+    {
+        public DFA67(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 67;
+            this.eot = DFA67_eot;
+            this.eof = DFA67_eof;
+            this.min = DFA67_min;
+            this.max = DFA67_max;
+            this.accept = DFA67_accept;
+            this.special = DFA67_special;
+            this.transition = DFA67_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "()* loopback of 585:3: (op= binoperator right= atomExpression )*"; }
+        }
+
+    }
+
+    const string DFA70_eotS =
+        "\x1f\uffff";
+    const string DFA70_eofS =
+        "\x1f\uffff";
+    const string DFA70_minS =
+        "\x01\x09\x1e\uffff";
+    const string DFA70_maxS =
+        "\x01\x53\x1e\uffff";
+    const string DFA70_acceptS =
+        "\x01\uffff\x01\x01\x01\x02\x01\x03\x01\x04\x01\x05\x01\x06\x01"+
+        "\x07\x01\x08\x01\x09\x01\x0a\x01\x0b\x01\x0c\x01\x0d\x01\x0e\x01"+
+        "\x0f\x01\x10\x01\x11\x01\x12\x01\x13\x01\x14\x01\x15\x01\x16\x01"+
+        "\x17\x01\x18\x01\x19\x01\x1a\x01\x1b\x01\x1c\x01\x1d\x01\x1e";
+    const string DFA70_specialS =
+        "\x1f\uffff}>";
+    static readonly string[] DFA70_transitionS = {
+            "\x01\x06\x0d\uffff\x01\x09\x17\uffff\x01\x0a\x01\x14\x01\x10"+
+            "\x08\uffff\x01\x01\x01\x02\x01\x03\x01\x04\x01\x05\x01\x07\x01"+
+            "\x08\x01\x0b\x01\uffff\x01\x0c\x01\x0d\x01\x0e\x01\x0f\x01\x11"+
+            "\x01\x12\x01\x13\x01\x15\x01\x16\x01\x17\x01\x18\x01\x19\x01"+
+            "\x1a\x01\x1b\x01\x1c\x01\x1d\x01\x1e",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA70_eot = DFA.UnpackEncodedString(DFA70_eotS);
+    static readonly short[] DFA70_eof = DFA.UnpackEncodedString(DFA70_eofS);
+    static readonly char[] DFA70_min = DFA.UnpackEncodedStringToUnsignedChars(DFA70_minS);
+    static readonly char[] DFA70_max = DFA.UnpackEncodedStringToUnsignedChars(DFA70_maxS);
+    static readonly short[] DFA70_accept = DFA.UnpackEncodedString(DFA70_acceptS);
+    static readonly short[] DFA70_special = DFA.UnpackEncodedString(DFA70_specialS);
+    static readonly short[][] DFA70_transition = DFA.UnpackEncodedStringArray(DFA70_transitionS);
+
+    protected class DFA70 : DFA
+    {
+        public DFA70(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 70;
+            this.eot = DFA70_eot;
+            this.eof = DFA70_eof;
+            this.min = DFA70_min;
+            this.max = DFA70_max;
+            this.accept = DFA70_accept;
+            this.special = DFA70_special;
+            this.transition = DFA70_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "596:1: binoperator returns [BinaryOperator binop] : ( T_BIIMPLIES | T_GREATER | T_GREATEREQUAL | T_LESS | T_LESSEQUAL | T_EQUAL | T_NOTEQUAL | T_IMPLIES | T_MINUS | T_SUM | T_IN ( T_SET )? | T_NOT T_IN ( T_SET )? | T_SUBSET | T_OR | T_DIV | T_PROD | T_IDIV | T_MOD | T_UNION | T_DIFF | T_INTER | T_AND | T_POW | T_CONC | T_DOMRESBY | T_DOMRESTO | T_RNGRESBY | T_RNGRESTO | T_MUNION | T_SEQMOD_MAPOVERRIDE );"; }
+        }
+
+    }
+
+    const string DFA68_eotS =
+        "\x20\uffff";
+    const string DFA68_eofS =
+        "\x20\uffff";
+    const string DFA68_minS =
+        "\x01\x08\x1f\uffff";
+    const string DFA68_maxS =
+        "\x01\x7a\x1f\uffff";
+    const string DFA68_acceptS =
+        "\x01\uffff\x01\x01\x01\x02\x1d\uffff";
+    const string DFA68_specialS =
+        "\x20\uffff}>";
+    static readonly string[] DFA68_transitionS = {
+            "\x01\x02\x03\uffff\x01\x02\x02\uffff\x02\x02\x06\uffff\x01"+
+            "\x02\x05\uffff\x01\x02\x01\uffff\x01\x02\x17\uffff\x01\x02\x0a"+
+            "\uffff\x01\x01\x01\x02\x11\uffff\x01\x02\x02\uffff\x07\x02\x03"+
+            "\uffff\x0d\x02\x0b\uffff\x01\x02",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA68_eot = DFA.UnpackEncodedString(DFA68_eotS);
+    static readonly short[] DFA68_eof = DFA.UnpackEncodedString(DFA68_eofS);
+    static readonly char[] DFA68_min = DFA.UnpackEncodedStringToUnsignedChars(DFA68_minS);
+    static readonly char[] DFA68_max = DFA.UnpackEncodedStringToUnsignedChars(DFA68_maxS);
+    static readonly short[] DFA68_accept = DFA.UnpackEncodedString(DFA68_acceptS);
+    static readonly short[] DFA68_special = DFA.UnpackEncodedString(DFA68_specialS);
+    static readonly short[][] DFA68_transition = DFA.UnpackEncodedStringArray(DFA68_transitionS);
+
+    protected class DFA68 : DFA
+    {
+        public DFA68(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 68;
+            this.eot = DFA68_eot;
+            this.eof = DFA68_eof;
+            this.min = DFA68_min;
+            this.max = DFA68_max;
+            this.accept = DFA68_accept;
+            this.special = DFA68_special;
+            this.transition = DFA68_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "618:9: ( T_SET )?"; }
+        }
+
+    }
+
+    const string DFA69_eotS =
+        "\x20\uffff";
+    const string DFA69_eofS =
+        "\x20\uffff";
+    const string DFA69_minS =
+        "\x01\x08\x1f\uffff";
+    const string DFA69_maxS =
+        "\x01\x7a\x1f\uffff";
+    const string DFA69_acceptS =
+        "\x01\uffff\x01\x01\x01\x02\x1d\uffff";
+    const string DFA69_specialS =
+        "\x20\uffff}>";
+    static readonly string[] DFA69_transitionS = {
+            "\x01\x02\x03\uffff\x01\x02\x02\uffff\x02\x02\x06\uffff\x01"+
+            "\x02\x05\uffff\x01\x02\x01\uffff\x01\x02\x17\uffff\x01\x02\x0a"+
+            "\uffff\x01\x01\x01\x02\x11\uffff\x01\x02\x02\uffff\x07\x02\x03"+
+            "\uffff\x0d\x02\x0b\uffff\x01\x02",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA69_eot = DFA.UnpackEncodedString(DFA69_eotS);
+    static readonly short[] DFA69_eof = DFA.UnpackEncodedString(DFA69_eofS);
+    static readonly char[] DFA69_min = DFA.UnpackEncodedStringToUnsignedChars(DFA69_minS);
+    static readonly char[] DFA69_max = DFA.UnpackEncodedStringToUnsignedChars(DFA69_maxS);
+    static readonly short[] DFA69_accept = DFA.UnpackEncodedString(DFA69_acceptS);
+    static readonly short[] DFA69_special = DFA.UnpackEncodedString(DFA69_specialS);
+    static readonly short[][] DFA69_transition = DFA.UnpackEncodedStringArray(DFA69_transitionS);
+
+    protected class DFA69 : DFA
+    {
+        public DFA69(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 69;
+            this.eot = DFA69_eot;
+            this.eof = DFA69_eof;
+            this.min = DFA69_min;
+            this.max = DFA69_max;
+            this.accept = DFA69_accept;
+            this.special = DFA69_special;
+            this.transition = DFA69_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "620:15: ( T_SET )?"; }
+        }
+
+    }
+
+    const string DFA77_eotS =
+        "\x1f\uffff";
+    const string DFA77_eofS =
+        "\x1f\uffff";
+    const string DFA77_minS =
+        "\x01\x08\x1e\uffff";
+    const string DFA77_maxS =
+        "\x01\x7a\x1e\uffff";
+    const string DFA77_acceptS =
+        "\x01\uffff\x01\x01\x1c\uffff\x01\x02";
+    const string DFA77_specialS =
+        "\x1f\uffff}>";
+    static readonly string[] DFA77_transitionS = {
+            "\x01\x01\x03\uffff\x01\x01\x02\uffff\x02\x01\x06\uffff\x01"+
+            "\x01\x05\uffff\x01\x01\x01\uffff\x01\x01\x17\uffff\x01\x01\x0b"+
+            "\uffff\x01\x01\x11\uffff\x01\x1e\x02\uffff\x07\x01\x03\uffff"+
+            "\x0d\x01\x0b\uffff\x01\x01",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA77_eot = DFA.UnpackEncodedString(DFA77_eotS);
+    static readonly short[] DFA77_eof = DFA.UnpackEncodedString(DFA77_eofS);
+    static readonly char[] DFA77_min = DFA.UnpackEncodedStringToUnsignedChars(DFA77_minS);
+    static readonly char[] DFA77_max = DFA.UnpackEncodedStringToUnsignedChars(DFA77_maxS);
+    static readonly short[] DFA77_accept = DFA.UnpackEncodedString(DFA77_acceptS);
+    static readonly short[] DFA77_special = DFA.UnpackEncodedString(DFA77_specialS);
+    static readonly short[][] DFA77_transition = DFA.UnpackEncodedStringArray(DFA77_transitionS);
+
+    protected class DFA77 : DFA
+    {
+        public DFA77(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 77;
+            this.eot = DFA77_eot;
+            this.eof = DFA77_eof;
+            this.min = DFA77_min;
+            this.max = DFA77_max;
+            this.accept = DFA77_accept;
+            this.special = DFA77_special;
+            this.transition = DFA77_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "662:1: atomExpression returns [Expression expr] : ( ( (unexpr= op_un )? (e= identifierExpression | e= qvalExpression | e= constant | e= initializedComplexType | e= quantifierExpression | T_LPAREN e= expression T_RPAREN ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )? ) ( 'as' cid= T_IDENTIFIER )? ) | ie= T_IF ce= expression T_THEN te= expression T_ELSE ee= expression T_END );"; }
+        }
+
+    }
+
+    const string DFA71_eotS =
+        "\x1e\uffff";
+    const string DFA71_eofS =
+        "\x1e\uffff";
+    const string DFA71_minS =
+        "\x01\x08\x1d\uffff";
+    const string DFA71_maxS =
+        "\x01\x7a\x1d\uffff";
+    const string DFA71_acceptS =
+        "\x01\uffff\x01\x01\x0e\uffff\x01\x02\x0d\uffff";
+    const string DFA71_specialS =
+        "\x1e\uffff}>";
+    static readonly string[] DFA71_transitionS = {
+            "\x01\x10\x03\uffff\x01\x10\x02\uffff\x02\x10\x06\uffff\x01"+
+            "\x01\x05\uffff\x01\x10\x01\uffff\x01\x10\x17\uffff\x01\x10\x0b"+
+            "\uffff\x01\x01\x14\uffff\x07\x10\x03\uffff\x0d\x01\x0b\uffff"+
+            "\x01\x10",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA71_eot = DFA.UnpackEncodedString(DFA71_eotS);
+    static readonly short[] DFA71_eof = DFA.UnpackEncodedString(DFA71_eofS);
+    static readonly char[] DFA71_min = DFA.UnpackEncodedStringToUnsignedChars(DFA71_minS);
+    static readonly char[] DFA71_max = DFA.UnpackEncodedStringToUnsignedChars(DFA71_maxS);
+    static readonly short[] DFA71_accept = DFA.UnpackEncodedString(DFA71_acceptS);
+    static readonly short[] DFA71_special = DFA.UnpackEncodedString(DFA71_specialS);
+    static readonly short[][] DFA71_transition = DFA.UnpackEncodedStringArray(DFA71_transitionS);
+
+    protected class DFA71 : DFA
+    {
+        public DFA71(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 71;
+            this.eot = DFA71_eot;
+            this.eof = DFA71_eof;
+            this.min = DFA71_min;
+            this.max = DFA71_max;
+            this.accept = DFA71_accept;
+            this.special = DFA71_special;
+            this.transition = DFA71_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "667:11: (unexpr= op_un )?"; }
+        }
+
+    }
+
+    const string DFA75_eotS =
+        "\x42\uffff";
+    const string DFA75_eofS =
+        "\x42\uffff";
+    const string DFA75_minS =
+        "\x01\x08\x01\uffff\x01\x05\x3f\uffff";
+    const string DFA75_maxS =
+        "\x01\x7a\x01\uffff\x01\x79\x3f\uffff";
+    const string DFA75_acceptS =
+        "\x01\uffff\x01\x01\x01\uffff\x01\x02\x01\x03\x05\uffff\x01\x04"+
+        "\x02\uffff\x01\x05\x01\x06\x33\uffff";
+    const string DFA75_specialS =
+        "\x42\uffff}>";
+    static readonly string[] DFA75_transitionS = {
+            "\x01\x01\x03\uffff\x01\x0e\x02\uffff\x01\x0a\x01\x04\x0c\uffff"+
+            "\x01\x04\x01\uffff\x01\x0a\x17\uffff\x01\x02\x20\uffff\x02\x0d"+
+            "\x04\x04\x01\x0a\x1b\uffff\x01\x03",
+            "",
+            "\x01\x04\x01\uffff\x01\x04\x01\uffff\x03\x04\x01\uffff\x01"+
+            "\x04\x03\uffff\x01\x04\x01\uffff\x01\x04\x03\uffff\x01\x04\x08"+
+            "\uffff\x01\x04\x02\uffff\x03\x04\x04\uffff\x02\x04\x03\uffff"+
+            "\x03\x04\x07\uffff\x09\x04\x01\uffff\x11\x04\x01\x01\x01\uffff"+
+            "\x02\x04\x07\uffff\x02\x04\x15\uffff\x01\x04\x02\uffff\x01\x04",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA75_eot = DFA.UnpackEncodedString(DFA75_eotS);
+    static readonly short[] DFA75_eof = DFA.UnpackEncodedString(DFA75_eofS);
+    static readonly char[] DFA75_min = DFA.UnpackEncodedStringToUnsignedChars(DFA75_minS);
+    static readonly char[] DFA75_max = DFA.UnpackEncodedStringToUnsignedChars(DFA75_maxS);
+    static readonly short[] DFA75_accept = DFA.UnpackEncodedString(DFA75_acceptS);
+    static readonly short[] DFA75_special = DFA.UnpackEncodedString(DFA75_specialS);
+    static readonly short[][] DFA75_transition = DFA.UnpackEncodedStringArray(DFA75_transitionS);
+
+    protected class DFA75 : DFA
+    {
+        public DFA75(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 75;
+            this.eot = DFA75_eot;
+            this.eof = DFA75_eof;
+            this.min = DFA75_min;
+            this.max = DFA75_max;
+            this.accept = DFA75_accept;
+            this.special = DFA75_special;
+            this.transition = DFA75_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "667:19: (e= identifierExpression | e= qvalExpression | e= constant | e= initializedComplexType | e= quantifierExpression | T_LPAREN e= expression T_RPAREN ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )? )"; }
+        }
+
+    }
+
+    const string DFA74_eotS =
+        "\x36\uffff";
+    const string DFA74_eofS =
+        "\x36\uffff";
+    const string DFA74_minS =
+        "\x01\x05\x35\uffff";
+    const string DFA74_maxS =
+        "\x01\x79\x35\uffff";
+    const string DFA74_acceptS =
+        "\x01\uffff\x01\x01\x01\x02\x01\uffff\x01\x03\x31\uffff";
+    const string DFA74_specialS =
+        "\x36\uffff}>";
+    static readonly string[] DFA74_transitionS = {
+            "\x01\x04\x01\uffff\x01\x04\x01\uffff\x03\x04\x01\x02\x01\x04"+
+            "\x01\uffff\x01\x02\x01\uffff\x01\x04\x01\uffff\x01\x04\x03\uffff"+
+            "\x01\x04\x08\uffff\x01\x04\x02\uffff\x03\x04\x04\uffff\x02\x04"+
+            "\x03\uffff\x03\x04\x07\uffff\x09\x04\x01\uffff\x11\x04\x01\x01"+
+            "\x01\uffff\x02\x04\x07\uffff\x02\x04\x15\uffff\x01\x04\x02\uffff"+
+            "\x01\x04",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA74_eot = DFA.UnpackEncodedString(DFA74_eotS);
+    static readonly short[] DFA74_eof = DFA.UnpackEncodedString(DFA74_eofS);
+    static readonly char[] DFA74_min = DFA.UnpackEncodedStringToUnsignedChars(DFA74_minS);
+    static readonly char[] DFA74_max = DFA.UnpackEncodedStringToUnsignedChars(DFA74_maxS);
+    static readonly short[] DFA74_accept = DFA.UnpackEncodedString(DFA74_acceptS);
+    static readonly short[] DFA74_special = DFA.UnpackEncodedString(DFA74_specialS);
+    static readonly short[][] DFA74_transition = DFA.UnpackEncodedStringArray(DFA74_transitionS);
+
+    protected class DFA74 : DFA
+    {
+        public DFA74(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 74;
+            this.eot = DFA74_eot;
+            this.eof = DFA74_eof;
+            this.min = DFA74_min;
+            this.max = DFA74_max;
+            this.accept = DFA74_accept;
+            this.special = DFA74_special;
+            this.transition = DFA74_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "674:8: ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[e] )? | e= accessExpression[e] )?"; }
+        }
+
+    }
+
+    const string DFA72_eotS =
+        "\x36\uffff";
+    const string DFA72_eofS =
+        "\x36\uffff";
+    const string DFA72_minS =
+        "\x01\x05\x35\uffff";
+    const string DFA72_maxS =
+        "\x01\x79\x35\uffff";
+    const string DFA72_acceptS =
+        "\x01\uffff\x01\x02\x33\uffff\x01\x01";
+    const string DFA72_specialS =
+        "\x36\uffff}>";
+    static readonly string[] DFA72_transitionS = {
+            "\x01\x01\x01\uffff\x01\x01\x01\uffff\x05\x01\x01\uffff\x01"+
+            "\x01\x01\uffff\x01\x01\x01\uffff\x01\x01\x03\uffff\x01\x01\x08"+
+            "\uffff\x01\x01\x02\uffff\x03\x01\x04\uffff\x02\x01\x03\uffff"+
+            "\x03\x01\x07\uffff\x09\x01\x01\uffff\x11\x01\x01\x35\x01\uffff"+
+            "\x02\x01\x07\uffff\x02\x01\x15\uffff\x01\x01\x02\uffff\x01\x01",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA72_eot = DFA.UnpackEncodedString(DFA72_eotS);
+    static readonly short[] DFA72_eof = DFA.UnpackEncodedString(DFA72_eofS);
+    static readonly char[] DFA72_min = DFA.UnpackEncodedStringToUnsignedChars(DFA72_minS);
+    static readonly char[] DFA72_max = DFA.UnpackEncodedStringToUnsignedChars(DFA72_maxS);
+    static readonly short[] DFA72_accept = DFA.UnpackEncodedString(DFA72_acceptS);
+    static readonly short[] DFA72_special = DFA.UnpackEncodedString(DFA72_specialS);
+    static readonly short[][] DFA72_transition = DFA.UnpackEncodedStringArray(DFA72_transitionS);
+
+    protected class DFA72 : DFA
+    {
+        public DFA72(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 72;
+            this.eot = DFA72_eot;
+            this.eof = DFA72_eof;
+            this.min = DFA72_min;
+            this.max = DFA72_max;
+            this.accept = DFA72_accept;
+            this.special = DFA72_special;
+            this.transition = DFA72_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "()+ loopback of 675:6: ( T_POINT idn= T_IDENTIFIER )+"; }
+        }
+
+    }
+
+    const string DFA73_eotS =
+        "\x35\uffff";
+    const string DFA73_eofS =
+        "\x35\uffff";
+    const string DFA73_minS =
+        "\x01\x05\x34\uffff";
+    const string DFA73_maxS =
+        "\x01\x79\x34\uffff";
+    const string DFA73_acceptS =
+        "\x01\uffff\x01\x01\x01\uffff\x01\x02\x31\uffff";
+    const string DFA73_specialS =
+        "\x35\uffff}>";
+    static readonly string[] DFA73_transitionS = {
+            "\x01\x03\x01\uffff\x01\x03\x01\uffff\x03\x03\x01\x01\x01\x03"+
+            "\x01\uffff\x01\x01\x01\uffff\x01\x03\x01\uffff\x01\x03\x03\uffff"+
+            "\x01\x03\x08\uffff\x01\x03\x02\uffff\x03\x03\x04\uffff\x02\x03"+
+            "\x03\uffff\x03\x03\x07\uffff\x09\x03\x01\uffff\x11\x03\x02\uffff"+
+            "\x02\x03\x07\uffff\x02\x03\x15\uffff\x01\x03\x02\uffff\x01\x03",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA73_eot = DFA.UnpackEncodedString(DFA73_eotS);
+    static readonly short[] DFA73_eof = DFA.UnpackEncodedString(DFA73_eofS);
+    static readonly char[] DFA73_min = DFA.UnpackEncodedStringToUnsignedChars(DFA73_minS);
+    static readonly char[] DFA73_max = DFA.UnpackEncodedStringToUnsignedChars(DFA73_maxS);
+    static readonly short[] DFA73_accept = DFA.UnpackEncodedString(DFA73_acceptS);
+    static readonly short[] DFA73_special = DFA.UnpackEncodedString(DFA73_specialS);
+    static readonly short[][] DFA73_transition = DFA.UnpackEncodedStringArray(DFA73_transitionS);
+
+    protected class DFA73 : DFA
+    {
+        public DFA73(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 73;
+            this.eot = DFA73_eot;
+            this.eof = DFA73_eof;
+            this.min = DFA73_min;
+            this.max = DFA73_max;
+            this.accept = DFA73_accept;
+            this.special = DFA73_special;
+            this.transition = DFA73_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "678:8: (res= accessExpression[e] )?"; }
+        }
+
+    }
+
+    const string DFA76_eotS =
+        "\x33\uffff";
+    const string DFA76_eofS =
+        "\x33\uffff";
+    const string DFA76_minS =
+        "\x01\x05\x32\uffff";
+    const string DFA76_maxS =
+        "\x01\x79\x32\uffff";
+    const string DFA76_acceptS =
+        "\x01\uffff\x01\x01\x01\x02\x30\uffff";
+    const string DFA76_specialS =
+        "\x33\uffff}>";
+    static readonly string[] DFA76_transitionS = {
+            "\x01\x02\x01\uffff\x01\x02\x01\uffff\x03\x02\x01\uffff\x01"+
+            "\x02\x03\uffff\x01\x02\x01\uffff\x01\x02\x03\uffff\x01\x02\x08"+
+            "\uffff\x01\x02\x02\uffff\x03\x02\x04\uffff\x02\x02\x03\uffff"+
+            "\x03\x02\x07\uffff\x09\x02\x01\uffff\x11\x02\x02\uffff\x02\x02"+
+            "\x07\uffff\x02\x02\x15\uffff\x01\x02\x02\uffff\x01\x01",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA76_eot = DFA.UnpackEncodedString(DFA76_eotS);
+    static readonly short[] DFA76_eof = DFA.UnpackEncodedString(DFA76_eofS);
+    static readonly char[] DFA76_min = DFA.UnpackEncodedStringToUnsignedChars(DFA76_minS);
+    static readonly char[] DFA76_max = DFA.UnpackEncodedStringToUnsignedChars(DFA76_maxS);
+    static readonly short[] DFA76_accept = DFA.UnpackEncodedString(DFA76_acceptS);
+    static readonly short[] DFA76_special = DFA.UnpackEncodedString(DFA76_specialS);
+    static readonly short[][] DFA76_transition = DFA.UnpackEncodedStringArray(DFA76_transitionS);
+
+    protected class DFA76 : DFA
+    {
+        public DFA76(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 76;
+            this.eot = DFA76_eot;
+            this.eof = DFA76_eof;
+            this.min = DFA76_min;
+            this.max = DFA76_max;
+            this.accept = DFA76_accept;
+            this.special = DFA76_special;
+            this.transition = DFA76_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "682:5: ( 'as' cid= T_IDENTIFIER )?"; }
+        }
+
+    }
+
+    const string DFA86_eotS =
+        "\x21\uffff";
+    const string DFA86_eofS =
+        "\x21\uffff";
+    const string DFA86_minS =
+        "\x01\x1f\x01\x08\x1f\uffff";
+    const string DFA86_maxS =
+        "\x01\x1f\x01\x7a\x1f\uffff";
+    const string DFA86_acceptS =
+        "\x02\uffff\x01\x01\x01\x02\x1d\uffff";
+    const string DFA86_specialS =
+        "\x21\uffff}>";
+    static readonly string[] DFA86_transitionS = {
+            "\x01\x01",
+            "\x01\x03\x03\uffff\x01\x03\x02\uffff\x02\x03\x06\uffff\x01"+
+            "\x03\x05\uffff\x01\x03\x01\uffff\x01\x03\x17\uffff\x01\x03\x0b"+
+            "\uffff\x01\x03\x11\uffff\x01\x03\x02\uffff\x07\x03\x01\uffff"+
+            "\x01\x02\x01\uffff\x0d\x03\x0b\uffff\x01\x03",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA86_eot = DFA.UnpackEncodedString(DFA86_eotS);
+    static readonly short[] DFA86_eof = DFA.UnpackEncodedString(DFA86_eofS);
+    static readonly char[] DFA86_min = DFA.UnpackEncodedStringToUnsignedChars(DFA86_minS);
+    static readonly char[] DFA86_max = DFA.UnpackEncodedStringToUnsignedChars(DFA86_maxS);
+    static readonly short[] DFA86_accept = DFA.UnpackEncodedString(DFA86_acceptS);
+    static readonly short[] DFA86_special = DFA.UnpackEncodedString(DFA86_specialS);
+    static readonly short[][] DFA86_transition = DFA.UnpackEncodedStringArray(DFA86_transitionS);
+
+    protected class DFA86 : DFA
+    {
+        public DFA86(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 86;
+            this.eot = DFA86_eot;
+            this.eof = DFA86_eof;
+            this.min = DFA86_min;
+            this.max = DFA86_max;
+            this.accept = DFA86_accept;
+            this.special = DFA86_special;
+            this.transition = DFA86_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "759:1: initializedSetType returns [Expression result] : ( T_CBRL T_MAPS T_CBRR | res= initializedSet );"; }
+        }
+
+    }
+
+    const string DFA99_eotS =
+        "\x3c\uffff";
+    const string DFA99_eofS =
+        "\x3c\uffff";
+    const string DFA99_minS =
+        "\x01\x08\x01\x05\x01\uffff\x01\x00\x38\uffff";
+    const string DFA99_maxS =
+        "\x01\x37\x01\x7e\x01\uffff\x01\x00\x38\uffff";
+    const string DFA99_acceptS =
+        "\x02\uffff\x01\x02\x38\uffff\x01\x01";
+    const string DFA99_specialS =
+        "\x03\uffff\x01\x00\x38\uffff}>";
+    static readonly string[] DFA99_transitionS = {
+            "\x01\x01\x2e\uffff\x01\x02",
+            "\x01\x02\x01\uffff\x01\x02\x01\uffff\x03\x02\x01\x03\x01\x02"+
+            "\x01\uffff\x01\x02\x01\uffff\x01\x02\x01\uffff\x01\x02\x03\uffff"+
+            "\x01\x02\x08\uffff\x01\x02\x02\uffff\x03\x02\x04\uffff\x02\x02"+
+            "\x03\uffff\x05\x02\x05\uffff\x09\x02\x01\uffff\x12\x02\x01\uffff"+
+            "\x02\x02\x07\uffff\x03\x02\x14\uffff\x01\x02\x02\uffff\x01\x02"+
+            "\x04\uffff\x01\x02",
+            "",
+            "\x01\uffff",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA99_eot = DFA.UnpackEncodedString(DFA99_eotS);
+    static readonly short[] DFA99_eof = DFA.UnpackEncodedString(DFA99_eofS);
+    static readonly char[] DFA99_min = DFA.UnpackEncodedStringToUnsignedChars(DFA99_minS);
+    static readonly char[] DFA99_max = DFA.UnpackEncodedStringToUnsignedChars(DFA99_maxS);
+    static readonly short[] DFA99_accept = DFA.UnpackEncodedString(DFA99_acceptS);
+    static readonly short[] DFA99_special = DFA.UnpackEncodedString(DFA99_specialS);
+    static readonly short[][] DFA99_transition = DFA.UnpackEncodedStringArray(DFA99_transitionS);
+
+    protected class DFA99 : DFA
+    {
+        public DFA99(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 99;
+            this.eot = DFA99_eot;
+            this.eof = DFA99_eof;
+            this.min = DFA99_min;
+            this.max = DFA99_max;
+            this.accept = DFA99_accept;
+            this.special = DFA99_special;
+            this.transition = DFA99_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "853:1: identifierExpression returns [Expression result] : ({...}?aName= T_IDENTIFIER T_LPAREN m_params= methodCallParams T_RPAREN | res= reference );"; }
+        }
+
+    }
+
+
+    protected internal int DFA99_SpecialStateTransition(DFA dfa, int s, IIntStream _input) //throws NoViableAltException
+    {
+            ITokenStream input = (ITokenStream)_input;
+    	int _s = s;
+        switch ( s )
+        {
+               	case 0 : 
+                   	int LA99_3 = input.LA(1);
+
+                   	 
+                   	int index99_3 = input.Index();
+                   	input.Rewind();
+                   	s = -1;
+                   	if ( ((isTuple(input.LT(1).Text))) ) { s = 59; }
+
+                   	else if ( ((!isTuple(input.LT(1).Text))) ) { s = 2; }
+
+                   	 
+                   	input.Seek(index99_3);
+                   	if ( s >= 0 ) return s;
+                   	break;
+        }
+        NoViableAltException nvae99 =
+            new NoViableAltException(dfa.Description, 99, _s, input);
+        dfa.Error(nvae99);
+        throw nvae99;
+    }
+    const string DFA100_eotS =
+        "\x39\uffff";
+    const string DFA100_eofS =
+        "\x39\uffff";
+    const string DFA100_minS =
+        "\x01\x05\x38\uffff";
+    const string DFA100_maxS =
+        "\x01\x7e\x38\uffff";
+    const string DFA100_acceptS =
+        "\x01\uffff\x01\x01\x01\uffff\x01\x02\x35\uffff";
+    const string DFA100_specialS =
+        "\x39\uffff}>";
+    static readonly string[] DFA100_transitionS = {
+            "\x01\x03\x01\uffff\x01\x03\x01\uffff\x03\x03\x01\x01\x01\x03"+
+            "\x01\uffff\x01\x01\x01\uffff\x01\x03\x01\uffff\x01\x03\x03\uffff"+
+            "\x01\x03\x08\uffff\x01\x03\x02\uffff\x03\x03\x04\uffff\x02\x03"+
+            "\x03\uffff\x05\x03\x04\uffff\x0a\x03\x01\uffff\x11\x03\x02\uffff"+
+            "\x02\x03\x07\uffff\x03\x03\x14\uffff\x01\x03\x02\uffff\x01\x03"+
+            "\x04\uffff\x01\x03",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA100_eot = DFA.UnpackEncodedString(DFA100_eotS);
+    static readonly short[] DFA100_eof = DFA.UnpackEncodedString(DFA100_eofS);
+    static readonly char[] DFA100_min = DFA.UnpackEncodedStringToUnsignedChars(DFA100_minS);
+    static readonly char[] DFA100_max = DFA.UnpackEncodedStringToUnsignedChars(DFA100_maxS);
+    static readonly short[] DFA100_accept = DFA.UnpackEncodedString(DFA100_acceptS);
+    static readonly short[] DFA100_special = DFA.UnpackEncodedString(DFA100_specialS);
+    static readonly short[][] DFA100_transition = DFA.UnpackEncodedStringArray(DFA100_transitionS);
+
+    protected class DFA100 : DFA
+    {
+        public DFA100(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 100;
+            this.eot = DFA100_eot;
+            this.eof = DFA100_eof;
+            this.min = DFA100_min;
+            this.max = DFA100_max;
+            this.accept = DFA100_accept;
+            this.special = DFA100_special;
+            this.transition = DFA100_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "873:3: (output= accessExpression[result] | )"; }
+        }
+
+    }
+
+    const string DFA102_eotS =
+        "\x37\uffff";
+    const string DFA102_eofS =
+        "\x37\uffff";
+    const string DFA102_minS =
+        "\x01\x05\x36\uffff";
+    const string DFA102_maxS =
+        "\x01\x7e\x36\uffff";
+    const string DFA102_acceptS =
+        "\x01\uffff\x01\x01\x01\x02\x01\uffff\x01\x03\x32\uffff";
+    const string DFA102_specialS =
+        "\x37\uffff}>";
+    static readonly string[] DFA102_transitionS = {
+            "\x01\x04\x01\uffff\x01\x04\x01\uffff\x03\x04\x01\uffff\x01"+
+            "\x04\x03\uffff\x01\x04\x01\uffff\x01\x04\x03\uffff\x01\x04\x08"+
+            "\uffff\x01\x04\x02\uffff\x03\x04\x04\uffff\x02\x04\x03\uffff"+
+            "\x03\x04\x02\x02\x04\uffff\x0a\x04\x01\uffff\x11\x04\x02\uffff"+
+            "\x02\x04\x07\uffff\x02\x04\x01\x01\x14\uffff\x01\x04\x02\uffff"+
+            "\x01\x04\x04\uffff\x01\x02",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA102_eot = DFA.UnpackEncodedString(DFA102_eotS);
+    static readonly short[] DFA102_eof = DFA.UnpackEncodedString(DFA102_eofS);
+    static readonly char[] DFA102_min = DFA.UnpackEncodedStringToUnsignedChars(DFA102_minS);
+    static readonly char[] DFA102_max = DFA.UnpackEncodedStringToUnsignedChars(DFA102_maxS);
+    static readonly short[] DFA102_accept = DFA.UnpackEncodedString(DFA102_acceptS);
+    static readonly short[] DFA102_special = DFA.UnpackEncodedString(DFA102_specialS);
+    static readonly short[][] DFA102_transition = DFA.UnpackEncodedStringArray(DFA102_transitionS);
+
+    protected class DFA102 : DFA
+    {
+        public DFA102(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 102;
+            this.eot = DFA102_eot;
+            this.eof = DFA102_eof;
+            this.min = DFA102_min;
+            this.max = DFA102_max;
+            this.accept = DFA102_accept;
+            this.special = DFA102_special;
+            this.transition = DFA102_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "877:3: (pr= T_PRIMED | ( '::' T_LPAREN init= expression T_RPAREN )? afold= ( T_FOLDLR | T_FOLDRL ) T_LPAREN anexpr= expression T_RPAREN )?"; }
+        }
+
+    }
+
+    const string DFA103_eotS =
+        "\x3a\uffff";
+    const string DFA103_eofS =
+        "\x3a\uffff";
+    const string DFA103_minS =
+        "\x01\x05\x39\uffff";
+    const string DFA103_maxS =
+        "\x01\x7e\x39\uffff";
+    const string DFA103_acceptS =
+        "\x01\uffff\x01\x03\x36\uffff\x01\x01\x01\x02";
+    const string DFA103_specialS =
+        "\x3a\uffff}>";
+    static readonly string[] DFA103_transitionS = {
+            "\x01\x01\x01\uffff\x01\x01\x01\uffff\x03\x01\x01\x39\x01\x01"+
+            "\x01\uffff\x01\x38\x01\uffff\x01\x01\x01\uffff\x01\x01\x03\uffff"+
+            "\x01\x01\x08\uffff\x01\x01\x02\uffff\x03\x01\x04\uffff\x02\x01"+
+            "\x03\uffff\x05\x01\x04\uffff\x0a\x01\x01\uffff\x12\x01\x01\uffff"+
+            "\x02\x01\x07\uffff\x03\x01\x14\uffff\x01\x01\x02\uffff\x01\x01"+
+            "\x04\uffff\x01\x01",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA103_eot = DFA.UnpackEncodedString(DFA103_eotS);
+    static readonly short[] DFA103_eof = DFA.UnpackEncodedString(DFA103_eofS);
+    static readonly char[] DFA103_min = DFA.UnpackEncodedStringToUnsignedChars(DFA103_minS);
+    static readonly char[] DFA103_max = DFA.UnpackEncodedStringToUnsignedChars(DFA103_maxS);
+    static readonly short[] DFA103_accept = DFA.UnpackEncodedString(DFA103_acceptS);
+    static readonly short[] DFA103_special = DFA.UnpackEncodedString(DFA103_specialS);
+    static readonly short[][] DFA103_transition = DFA.UnpackEncodedStringArray(DFA103_transitionS);
+
+    protected class DFA103 : DFA
+    {
+        public DFA103(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 103;
+            this.eot = DFA103_eot;
+            this.eof = DFA103_eof;
+            this.min = DFA103_min;
+            this.max = DFA103_max;
+            this.accept = DFA103_accept;
+            this.special = DFA103_special;
+            this.transition = DFA103_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "()+ loopback of 891:7: (tcall= T_LSQPAREN ac= expression T_RSQPAREN | bcall= T_LPAREN m_params= methodCallParams T_RPAREN )+"; }
+        }
+
+    }
+
+    const string DFA106_eotS =
+        "\x38\uffff";
+    const string DFA106_eofS =
+        "\x38\uffff";
+    const string DFA106_minS =
+        "\x01\x05\x37\uffff";
+    const string DFA106_maxS =
+        "\x01\x7e\x37\uffff";
+    const string DFA106_acceptS =
+        "\x01\uffff\x01\x01\x01\x02\x35\uffff";
+    const string DFA106_specialS =
+        "\x38\uffff}>";
+    static readonly string[] DFA106_transitionS = {
+            "\x01\x02\x01\uffff\x01\x02\x01\uffff\x03\x02\x01\uffff\x01"+
+            "\x02\x03\uffff\x01\x02\x01\uffff\x01\x02\x03\uffff\x01\x02\x08"+
+            "\uffff\x01\x02\x02\uffff\x03\x02\x04\uffff\x02\x02\x03\uffff"+
+            "\x05\x02\x04\uffff\x0a\x02\x01\uffff\x11\x02\x01\x01\x01\uffff"+
+            "\x02\x02\x07\uffff\x03\x02\x14\uffff\x01\x02\x02\uffff\x01\x02"+
+            "\x04\uffff\x01\x02",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA106_eot = DFA.UnpackEncodedString(DFA106_eotS);
+    static readonly short[] DFA106_eof = DFA.UnpackEncodedString(DFA106_eofS);
+    static readonly char[] DFA106_min = DFA.UnpackEncodedStringToUnsignedChars(DFA106_minS);
+    static readonly char[] DFA106_max = DFA.UnpackEncodedStringToUnsignedChars(DFA106_maxS);
+    static readonly short[] DFA106_accept = DFA.UnpackEncodedString(DFA106_acceptS);
+    static readonly short[] DFA106_special = DFA.UnpackEncodedString(DFA106_specialS);
+    static readonly short[][] DFA106_transition = DFA.UnpackEncodedStringArray(DFA106_transitionS);
+
+    protected class DFA106 : DFA
+    {
+        public DFA106(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 106;
+            this.eot = DFA106_eot;
+            this.eof = DFA106_eof;
+            this.min = DFA106_min;
+            this.max = DFA106_max;
+            this.accept = DFA106_accept;
+            this.special = DFA106_special;
+            this.transition = DFA106_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "896:3: ( ( T_POINT idn= T_IDENTIFIER )+ (res= accessExpression[result] )? )?"; }
+        }
+
+    }
+
+    const string DFA104_eotS =
+        "\x3a\uffff";
+    const string DFA104_eofS =
+        "\x3a\uffff";
+    const string DFA104_minS =
+        "\x01\x05\x39\uffff";
+    const string DFA104_maxS =
+        "\x01\x7e\x39\uffff";
+    const string DFA104_acceptS =
+        "\x01\uffff\x01\x02\x37\uffff\x01\x01";
+    const string DFA104_specialS =
+        "\x3a\uffff}>";
+    static readonly string[] DFA104_transitionS = {
+            "\x01\x01\x01\uffff\x01\x01\x01\uffff\x05\x01\x01\uffff\x01"+
+            "\x01\x01\uffff\x01\x01\x01\uffff\x01\x01\x03\uffff\x01\x01\x08"+
+            "\uffff\x01\x01\x02\uffff\x03\x01\x04\uffff\x02\x01\x03\uffff"+
+            "\x05\x01\x04\uffff\x0a\x01\x01\uffff\x11\x01\x01\x39\x01\uffff"+
+            "\x02\x01\x07\uffff\x03\x01\x14\uffff\x01\x01\x02\uffff\x01\x01"+
+            "\x04\uffff\x01\x01",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA104_eot = DFA.UnpackEncodedString(DFA104_eotS);
+    static readonly short[] DFA104_eof = DFA.UnpackEncodedString(DFA104_eofS);
+    static readonly char[] DFA104_min = DFA.UnpackEncodedStringToUnsignedChars(DFA104_minS);
+    static readonly char[] DFA104_max = DFA.UnpackEncodedStringToUnsignedChars(DFA104_maxS);
+    static readonly short[] DFA104_accept = DFA.UnpackEncodedString(DFA104_acceptS);
+    static readonly short[] DFA104_special = DFA.UnpackEncodedString(DFA104_specialS);
+    static readonly short[][] DFA104_transition = DFA.UnpackEncodedStringArray(DFA104_transitionS);
+
+    protected class DFA104 : DFA
+    {
+        public DFA104(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 104;
+            this.eot = DFA104_eot;
+            this.eof = DFA104_eof;
+            this.min = DFA104_min;
+            this.max = DFA104_max;
+            this.accept = DFA104_accept;
+            this.special = DFA104_special;
+            this.transition = DFA104_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "()+ loopback of 897:4: ( T_POINT idn= T_IDENTIFIER )+"; }
+        }
+
+    }
+
+    const string DFA105_eotS =
+        "\x39\uffff";
+    const string DFA105_eofS =
+        "\x39\uffff";
+    const string DFA105_minS =
+        "\x01\x05\x38\uffff";
+    const string DFA105_maxS =
+        "\x01\x7e\x38\uffff";
+    const string DFA105_acceptS =
+        "\x01\uffff\x01\x01\x01\uffff\x01\x02\x35\uffff";
+    const string DFA105_specialS =
+        "\x39\uffff}>";
+    static readonly string[] DFA105_transitionS = {
+            "\x01\x03\x01\uffff\x01\x03\x01\uffff\x03\x03\x01\x01\x01\x03"+
+            "\x01\uffff\x01\x01\x01\uffff\x01\x03\x01\uffff\x01\x03\x03\uffff"+
+            "\x01\x03\x08\uffff\x01\x03\x02\uffff\x03\x03\x04\uffff\x02\x03"+
+            "\x03\uffff\x05\x03\x04\uffff\x0a\x03\x01\uffff\x11\x03\x02\uffff"+
+            "\x02\x03\x07\uffff\x03\x03\x14\uffff\x01\x03\x02\uffff\x01\x03"+
+            "\x04\uffff\x01\x03",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA105_eot = DFA.UnpackEncodedString(DFA105_eotS);
+    static readonly short[] DFA105_eof = DFA.UnpackEncodedString(DFA105_eofS);
+    static readonly char[] DFA105_min = DFA.UnpackEncodedStringToUnsignedChars(DFA105_minS);
+    static readonly char[] DFA105_max = DFA.UnpackEncodedStringToUnsignedChars(DFA105_maxS);
+    static readonly short[] DFA105_accept = DFA.UnpackEncodedString(DFA105_acceptS);
+    static readonly short[] DFA105_special = DFA.UnpackEncodedString(DFA105_specialS);
+    static readonly short[][] DFA105_transition = DFA.UnpackEncodedStringArray(DFA105_transitionS);
+
+    protected class DFA105 : DFA
+    {
+        public DFA105(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 105;
+            this.eot = DFA105_eot;
+            this.eof = DFA105_eof;
+            this.min = DFA105_min;
+            this.max = DFA105_max;
+            this.accept = DFA105_accept;
+            this.special = DFA105_special;
+            this.transition = DFA105_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "900:4: (res= accessExpression[result] )?"; }
+        }
+
+    }
+
+    const string DFA108_eotS =
+        "\x3b\uffff";
+    const string DFA108_eofS =
+        "\x3b\uffff";
+    const string DFA108_minS =
+        "\x01\x05\x3a\uffff";
+    const string DFA108_maxS =
+        "\x01\x7e\x3a\uffff";
+    const string DFA108_acceptS =
+        "\x01\uffff\x01\x02\x38\uffff\x01\x01";
+    const string DFA108_specialS =
+        "\x3b\uffff}>";
+    static readonly string[] DFA108_transitionS = {
+            "\x01\x01\x01\uffff\x01\x01\x01\uffff\x05\x01\x01\uffff\x01"+
+            "\x01\x01\uffff\x01\x01\x01\uffff\x01\x01\x03\uffff\x01\x01\x03"+
+            "\uffff\x01\x01\x04\uffff\x01\x01\x02\uffff\x03\x01\x04\uffff"+
+            "\x02\x01\x03\uffff\x05\x01\x04\uffff\x0a\x01\x01\uffff\x11\x01"+
+            "\x01\x3a\x01\uffff\x02\x01\x07\uffff\x03\x01\x14\uffff\x01\x01"+
+            "\x02\uffff\x01\x01\x04\uffff\x01\x01",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA108_eot = DFA.UnpackEncodedString(DFA108_eotS);
+    static readonly short[] DFA108_eof = DFA.UnpackEncodedString(DFA108_eofS);
+    static readonly char[] DFA108_min = DFA.UnpackEncodedStringToUnsignedChars(DFA108_minS);
+    static readonly char[] DFA108_max = DFA.UnpackEncodedStringToUnsignedChars(DFA108_maxS);
+    static readonly short[] DFA108_accept = DFA.UnpackEncodedString(DFA108_acceptS);
+    static readonly short[] DFA108_special = DFA.UnpackEncodedString(DFA108_specialS);
+    static readonly short[][] DFA108_transition = DFA.UnpackEncodedStringArray(DFA108_transitionS);
+
+    protected class DFA108 : DFA
+    {
+        public DFA108(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 108;
+            this.eot = DFA108_eot;
+            this.eof = DFA108_eof;
+            this.min = DFA108_min;
+            this.max = DFA108_max;
+            this.accept = DFA108_accept;
+            this.special = DFA108_special;
+            this.transition = DFA108_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "()* loopback of 913:3: ( T_POINT idd= T_IDENTIFIER )*"; }
+        }
+
+    }
+
+    const string DFA110_eotS =
+        "\x20\uffff";
+    const string DFA110_eofS =
+        "\x20\uffff";
+    const string DFA110_minS =
+        "\x01\x08\x1f\uffff";
+    const string DFA110_maxS =
+        "\x01\x7a\x1f\uffff";
+    const string DFA110_acceptS =
+        "\x01\uffff\x01\x01\x1d\uffff\x01\x02";
+    const string DFA110_specialS =
+        "\x20\uffff}>";
+    static readonly string[] DFA110_transitionS = {
+            "\x01\x01\x03\uffff\x01\x01\x01\x1f\x01\uffff\x02\x01\x06\uffff"+
+            "\x01\x01\x05\uffff\x01\x01\x01\uffff\x01\x01\x17\uffff\x01\x01"+
+            "\x0b\uffff\x01\x01\x11\uffff\x01\x01\x02\uffff\x07\x01\x03\uffff"+
+            "\x0d\x01\x0b\uffff\x01\x01",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA110_eot = DFA.UnpackEncodedString(DFA110_eotS);
+    static readonly short[] DFA110_eof = DFA.UnpackEncodedString(DFA110_eofS);
+    static readonly char[] DFA110_min = DFA.UnpackEncodedStringToUnsignedChars(DFA110_minS);
+    static readonly char[] DFA110_max = DFA.UnpackEncodedStringToUnsignedChars(DFA110_maxS);
+    static readonly short[] DFA110_accept = DFA.UnpackEncodedString(DFA110_acceptS);
+    static readonly short[] DFA110_special = DFA.UnpackEncodedString(DFA110_specialS);
+    static readonly short[][] DFA110_transition = DFA.UnpackEncodedStringArray(DFA110_transitionS);
+
+    protected class DFA110 : DFA
+    {
+        public DFA110(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 110;
+            this.eot = DFA110_eot;
+            this.eof = DFA110_eof;
+            this.min = DFA110_min;
+            this.max = DFA110_max;
+            this.accept = DFA110_accept;
+            this.special = DFA110_special;
+            this.transition = DFA110_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "922:4: (expa= expression ( T_COMMA expb= expression )* )?"; }
+        }
+
+    }
+
+    const string DFA111_eotS =
+        "\x10\uffff";
+    const string DFA111_eofS =
+        "\x10\uffff";
+    const string DFA111_minS =
+        "\x01\x17\x0f\uffff";
+    const string DFA111_maxS =
+        "\x01\x6e\x0f\uffff";
+    const string DFA111_acceptS =
+        "\x01\uffff\x01\x01\x08\uffff\x01\x02\x02\uffff\x01\x03\x01\x04"+
+        "\x01\x05";
+    const string DFA111_specialS =
+        "\x10\uffff}>";
+    static readonly string[] DFA111_transitionS = {
+            "\x01\x0d\x2b\uffff\x01\x0e\x1e\uffff\x01\x0f\x09\x01\x03\x0a",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA111_eot = DFA.UnpackEncodedString(DFA111_eotS);
+    static readonly short[] DFA111_eof = DFA.UnpackEncodedString(DFA111_eofS);
+    static readonly char[] DFA111_min = DFA.UnpackEncodedStringToUnsignedChars(DFA111_minS);
+    static readonly char[] DFA111_max = DFA.UnpackEncodedStringToUnsignedChars(DFA111_maxS);
+    static readonly short[] DFA111_accept = DFA.UnpackEncodedString(DFA111_acceptS);
+    static readonly short[] DFA111_special = DFA.UnpackEncodedString(DFA111_specialS);
+    static readonly short[][] DFA111_transition = DFA.UnpackEncodedStringArray(DFA111_transitionS);
+
+    protected class DFA111 : DFA
+    {
+        public DFA111(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 111;
+            this.eot = DFA111_eot;
+            this.eof = DFA111_eof;
+            this.min = DFA111_min;
+            this.max = DFA111_max;
+            this.accept = DFA111_accept;
+            this.special = DFA111_special;
+            this.transition = DFA111_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "932:1: op_un returns [UnaryOperator expr] : (r= op_un_set_list | r2= op_un_map | T_MINUS | T_NOT | T_ABS );"; }
+        }
+
+    }
+
+    const string DFA112_eotS =
+        "\x0a\uffff";
+    const string DFA112_eofS =
+        "\x0a\uffff";
+    const string DFA112_minS =
+        "\x01\x63\x09\uffff";
+    const string DFA112_maxS =
+        "\x01\x6b\x09\uffff";
+    const string DFA112_acceptS =
+        "\x01\uffff\x01\x01\x01\x02\x01\x03\x01\x04\x01\x05\x01\x06\x01"+
+        "\x07\x01\x08\x01\x09";
+    const string DFA112_specialS =
+        "\x0a\uffff}>";
+    static readonly string[] DFA112_transitionS = {
+            "\x01\x01\x01\x02\x01\x03\x01\x04\x01\x05\x01\x06\x01\x07\x01"+
+            "\x08\x01\x09",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            "",
+            ""
+    };
+
+    static readonly short[] DFA112_eot = DFA.UnpackEncodedString(DFA112_eotS);
+    static readonly short[] DFA112_eof = DFA.UnpackEncodedString(DFA112_eofS);
+    static readonly char[] DFA112_min = DFA.UnpackEncodedStringToUnsignedChars(DFA112_minS);
+    static readonly char[] DFA112_max = DFA.UnpackEncodedStringToUnsignedChars(DFA112_maxS);
+    static readonly short[] DFA112_accept = DFA.UnpackEncodedString(DFA112_acceptS);
+    static readonly short[] DFA112_special = DFA.UnpackEncodedString(DFA112_specialS);
+    static readonly short[][] DFA112_transition = DFA.UnpackEncodedStringArray(DFA112_transitionS);
+
+    protected class DFA112 : DFA
+    {
+        public DFA112(BaseRecognizer recognizer)
+        {
+            this.recognizer = recognizer;
+            this.decisionNumber = 112;
+            this.eot = DFA112_eot;
+            this.eof = DFA112_eof;
+            this.min = DFA112_min;
+            this.max = DFA112_max;
+            this.accept = DFA112_accept;
+            this.special = DFA112_special;
+            this.transition = DFA112_transition;
+
+        }
+
+        override public string Description
+        {
+            get { return "945:1: op_un_set_list returns [UnaryOperator expr] : ( T_CARD | T_DCONC | T_DINTER | T_DUNION | T_ELEMS | T_HEAD | T_INDS | T_LEN | T_TAIL );"; }
+        }
+
+    }
+
+ 
+
+    public static readonly BitSet FOLLOW_T_CONSTS_in_ooActionSystems93 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_namedConstList_in_ooActionSystems95 = new BitSet(new ulong[]{0x0000000000000020UL});
+    public static readonly BitSet FOLLOW_T_TYPES_in_ooActionSystems105 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_namedTypeList_in_ooActionSystems113 = new BitSet(new ulong[]{0x0000000000000040UL});
+    public static readonly BitSet FOLLOW_T_SYSTEM_in_ooActionSystems118 = new BitSet(new ulong[]{0x0000000000001100UL});
+    public static readonly BitSet FOLLOW_asTypeComposition_in_ooActionSystems125 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_namedConst_in_namedConstList148 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_namedConstList151 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_namedConst_in_namedConstList153 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_namedConst169 = new BitSet(new ulong[]{0x0000000000000200UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_namedConst173 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_namedConst179 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_namedType_in_namedTypeList199 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_namedTypeList202 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_namedType_in_namedTypeList204 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_namedType220 = new BitSet(new ulong[]{0x0000000000000200UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_namedType225 = new BitSet(new ulong[]{0x00000002D650D140UL});
+    public static readonly BitSet FOLLOW_complexType_in_namedType237 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_ooActionSystem_in_namedType249 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_asTypeCompositionParallel_in_asTypeComposition285 = new BitSet(new ulong[]{0x0000000000000402UL});
+    public static readonly BitSet FOLLOW_T_PRIO_in_asTypeComposition290 = new BitSet(new ulong[]{0x0000000000001100UL});
+    public static readonly BitSet FOLLOW_asTypeCompositionParallel_in_asTypeComposition292 = new BitSet(new ulong[]{0x0000000000000402UL});
+    public static readonly BitSet FOLLOW_asTypeCompositionSequential_in_asTypeCompositionParallel315 = new BitSet(new ulong[]{0x0000000000000802UL});
+    public static readonly BitSet FOLLOW_T_NONDET_in_asTypeCompositionParallel319 = new BitSet(new ulong[]{0x0000000000001100UL});
+    public static readonly BitSet FOLLOW_asTypeCompositionSequential_in_asTypeCompositionParallel321 = new BitSet(new ulong[]{0x0000000000000802UL});
+    public static readonly BitSet FOLLOW_asTypeCompositionBlockParen_in_asTypeCompositionSequential343 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_asTypeCompositionBlockParen358 = new BitSet(new ulong[]{0x0000000000001100UL});
+    public static readonly BitSet FOLLOW_asTypeComposition_in_asTypeCompositionBlockParen360 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_asTypeCompositionBlockParen363 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_asTypeCompositionBlockParen370 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_LIST_in_complexType401 = new BitSet(new ulong[]{0x0000000000008000UL});
+    public static readonly BitSet FOLLOW_T_LSQPAREN_in_complexType404 = new BitSet(new ulong[]{0x0000000000010100UL});
+    public static readonly BitSet FOLLOW_set_in_complexType408 = new BitSet(new ulong[]{0x0000000000020000UL});
+    public static readonly BitSet FOLLOW_T_RSQPAREN_in_complexType414 = new BitSet(new ulong[]{0x0000000000040000UL});
+    public static readonly BitSet FOLLOW_T_OF_in_complexType416 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_complexType421 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_LSQPAREN_in_complexType436 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_complexType440 = new BitSet(new ulong[]{0x00000000000A0000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_complexType449 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_complexType453 = new BitSet(new ulong[]{0x00000000000A0000UL});
+    public static readonly BitSet FOLLOW_T_RSQPAREN_in_complexType459 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_MAP_in_complexType469 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_T_LSQPAREN_in_complexType474 = new BitSet(new ulong[]{0x0000000000010100UL});
+    public static readonly BitSet FOLLOW_set_in_complexType478 = new BitSet(new ulong[]{0x0000000000020000UL});
+    public static readonly BitSet FOLLOW_T_RSQPAREN_in_complexType484 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_simpleType_in_complexType490 = new BitSet(new ulong[]{0x0000000000200000UL});
+    public static readonly BitSet FOLLOW_T_TO_in_complexType492 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_complexType496 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_QUANTITY_in_complexType510 = new BitSet(new ulong[]{0x0000000000040000UL});
+    public static readonly BitSet FOLLOW_T_OF_in_complexType512 = new BitSet(new ulong[]{0x0000000000008000UL});
+    public static readonly BitSet FOLLOW_T_LSQPAREN_in_complexType514 = new BitSet(new ulong[]{0x0000000000800100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_complexType519 = new BitSet(new ulong[]{0x00000000000A0000UL});
+    public static readonly BitSet FOLLOW_T_MINUS_in_complexType524 = new BitSet(new ulong[]{0x0000000001000000UL});
+    public static readonly BitSet FOLLOW_T_INFTY_in_complexType526 = new BitSet(new ulong[]{0x00000000000A0000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_complexType536 = new BitSet(new ulong[]{0x0000000001000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_complexType541 = new BitSet(new ulong[]{0x00000000000A0000UL});
+    public static readonly BitSet FOLLOW_T_INFTY_in_complexType545 = new BitSet(new ulong[]{0x00000000000A0000UL});
+    public static readonly BitSet FOLLOW_T_RSQPAREN_in_complexType552 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_complexType562 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_complexType566 = new BitSet(new ulong[]{0x0000000000082000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_complexType575 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_complexType579 = new BitSet(new ulong[]{0x0000000000082000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_complexType586 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_simpleType_in_complexType599 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_BOOL_in_simpleType632 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_INT_in_simpleType645 = new BitSet(new ulong[]{0x0000000000008000UL});
+    public static readonly BitSet FOLLOW_T_LSQPAREN_in_simpleType647 = new BitSet(new ulong[]{0x0000000001010100UL});
+    public static readonly BitSet FOLLOW_set_in_simpleType651 = new BitSet(new ulong[]{0x0000000008000000UL});
+    public static readonly BitSet FOLLOW_T_RANGETO_in_simpleType659 = new BitSet(new ulong[]{0x0000000001010100UL});
+    public static readonly BitSet FOLLOW_set_in_simpleType663 = new BitSet(new ulong[]{0x0000000000020000UL});
+    public static readonly BitSet FOLLOW_T_RSQPAREN_in_simpleType671 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_FLOAT_in_simpleType690 = new BitSet(new ulong[]{0x0000000000008000UL});
+    public static readonly BitSet FOLLOW_T_LSQPAREN_in_simpleType693 = new BitSet(new ulong[]{0x0000000021000100UL});
+    public static readonly BitSet FOLLOW_set_in_simpleType697 = new BitSet(new ulong[]{0x0000000008000000UL});
+    public static readonly BitSet FOLLOW_T_RANGETO_in_simpleType705 = new BitSet(new ulong[]{0x0000000021000100UL});
+    public static readonly BitSet FOLLOW_set_in_simpleType709 = new BitSet(new ulong[]{0x0000000000020000UL});
+    public static readonly BitSet FOLLOW_T_RSQPAREN_in_simpleType717 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_CHAR_in_simpleType735 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_CBRL_in_simpleType751 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_simpleType755 = new BitSet(new ulong[]{0x0000000100080200UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_simpleType758 = new BitSet(new ulong[]{0x0000000000010000UL});
+    public static readonly BitSet FOLLOW_T_INTNUMBER_in_simpleType762 = new BitSet(new ulong[]{0x0000000100080000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_simpleType773 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_simpleType777 = new BitSet(new ulong[]{0x0000000100080200UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_simpleType780 = new BitSet(new ulong[]{0x0000000000010000UL});
+    public static readonly BitSet FOLLOW_T_INTNUMBER_in_simpleType784 = new BitSet(new ulong[]{0x0000000100080000UL});
+    public static readonly BitSet FOLLOW_T_CBRR_in_simpleType792 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_simpleType803 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_AUTOCONS_in_ooActionSystem846 = new BitSet(new ulong[]{0x0000000000000040UL});
+    public static readonly BitSet FOLLOW_T_SYSTEM_in_ooActionSystem855 = new BitSet(new ulong[]{0x0000000000001000UL,0x0020000000000000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_ooActionSystem858 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_ooActionSystem862 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_ooActionSystem864 = new BitSet(new ulong[]{0x0000000000000000UL,0x0020000000000000UL});
+    public static readonly BitSet FOLLOW_117_in_ooActionSystem877 = new BitSet(new ulong[]{0x0000003C00000000UL,0x0040000000000000UL});
+    public static readonly BitSet FOLLOW_T_VAR_in_ooActionSystem883 = new BitSet(new ulong[]{0x0000038000000100UL});
+    public static readonly BitSet FOLLOW_attrList_in_ooActionSystem885 = new BitSet(new ulong[]{0x0000003800000000UL,0x0040000000000000UL});
+    public static readonly BitSet FOLLOW_T_METHODS_in_ooActionSystem893 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_methodList_in_ooActionSystem895 = new BitSet(new ulong[]{0x0000003000000000UL,0x0040000000000000UL});
+    public static readonly BitSet FOLLOW_T_ACTIONS_in_ooActionSystem903 = new BitSet(new ulong[]{0x0000130000000100UL});
+    public static readonly BitSet FOLLOW_namedActionList_in_ooActionSystem905 = new BitSet(new ulong[]{0x0000002000000000UL,0x0040000000000000UL});
+    public static readonly BitSet FOLLOW_T_DO_in_ooActionSystem913 = new BitSet(new ulong[]{0x0010304400001100UL});
+    public static readonly BitSet FOLLOW_actionBlock_in_ooActionSystem918 = new BitSet(new ulong[]{0x0000004000000000UL});
+    public static readonly BitSet FOLLOW_T_OD_in_ooActionSystem925 = new BitSet(new ulong[]{0x0000000000000000UL,0x0040000000000000UL});
+    public static readonly BitSet FOLLOW_118_in_ooActionSystem931 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_attr_in_attrList962 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_attrList965 = new BitSet(new ulong[]{0x0000038000000100UL});
+    public static readonly BitSet FOLLOW_attr_in_attrList967 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_STATIC_in_attr992 = new BitSet(new ulong[]{0x0000030000000100UL});
+    public static readonly BitSet FOLLOW_T_OBS_in_attr999 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_CTRL_in_attr1005 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_attr1016 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_attr1019 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_attr1023 = new BitSet(new ulong[]{0x0000000000000202UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_attr1026 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_attr1030 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_method_in_methodList1052 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_methodList1055 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_method_in_methodList1057 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_method1079 = new BitSet(new ulong[]{0x0000040000001200UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_method1087 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_methodParameterList_in_method1089 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_method1093 = new BitSet(new ulong[]{0x0000040000000200UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_method1101 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_method1105 = new BitSet(new ulong[]{0x0000000000000200UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_method1115 = new BitSet(new ulong[]{0x00F0300400001100UL});
+    public static readonly BitSet FOLLOW_T_VAR_in_method1122 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_localActionVars_in_method1124 = new BitSet(new ulong[]{0x0000000000000000UL,0x0080000000000000UL});
+    public static readonly BitSet FOLLOW_119_in_method1127 = new BitSet(new ulong[]{0x00F0300400001100UL});
+    public static readonly BitSet FOLLOW_actionBody_in_method1136 = new BitSet(new ulong[]{0x0000080000000000UL});
+    public static readonly BitSet FOLLOW_T_END_in_method1144 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_methodParameterList1168 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_methodParameterList1170 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_methodParameterList1174 = new BitSet(new ulong[]{0x0000000000080002UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_methodParameterList1182 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_methodParameterList1186 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_methodParameterList1188 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_methodParameterList1192 = new BitSet(new ulong[]{0x0000000000080002UL});
+    public static readonly BitSet FOLLOW_namedAction_in_namedActionList1219 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_namedActionList1222 = new BitSet(new ulong[]{0x0000130000000100UL});
+    public static readonly BitSet FOLLOW_namedAction_in_namedActionList1224 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_CONT_in_namedAction1244 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_namedAction1248 = new BitSet(new ulong[]{0x0000000000001200UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_namedAction1256 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_methodParameterList_in_namedAction1258 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_namedAction1262 = new BitSet(new ulong[]{0x0000000000000200UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_namedAction1269 = new BitSet(new ulong[]{0x0000100000000000UL});
+    public static readonly BitSet FOLLOW_continuousActionBody_in_namedAction1273 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_CTRL_in_namedAction1288 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_OBS_in_namedAction1293 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_namedAction1305 = new BitSet(new ulong[]{0x0000000000001200UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_namedAction1313 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_methodParameterList_in_namedAction1315 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_namedAction1319 = new BitSet(new ulong[]{0x0000000000000200UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_namedAction1326 = new BitSet(new ulong[]{0x0000300400000000UL});
+    public static readonly BitSet FOLLOW_T_VAR_in_namedAction1332 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_localActionVars_in_namedAction1334 = new BitSet(new ulong[]{0x0000300000000000UL});
+    public static readonly BitSet FOLLOW_discreteActionBody_in_namedAction1345 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_localActionVars1377 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_localActionVars1379 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_localActionVars1383 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_localActionVars1392 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_localActionVars1396 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_localActionVars1398 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_localActionVars1402 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_continuousActionBody_in_anonymousAction1432 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_discreteActionBody_in_anonymousAction1441 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_CONT_in_continuousActionBody1466 = new BitSet(new ulong[]{0x0000200000000000UL});
+    public static readonly BitSet FOLLOW_T_REQUIRES_in_continuousActionBody1468 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_continuousActionBody1472 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_continuousActionBody1474 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_qualConstraintList_in_continuousActionBody1481 = new BitSet(new ulong[]{0x0000080000000000UL});
+    public static readonly BitSet FOLLOW_T_END_in_continuousActionBody1486 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_qualConstraint_in_qualConstraintList1514 = new BitSet(new ulong[]{0x0000000000080002UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_qualConstraintList1521 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_qualConstraint_in_qualConstraintList1525 = new BitSet(new ulong[]{0x0000000000080002UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_qualConstraint1556 = new BitSet(new ulong[]{0x0000000000000200UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_qualConstraint1558 = new BitSet(new ulong[]{0x0000400000000100UL});
+    public static readonly BitSet FOLLOW_T_DERIV_in_qualConstraint1565 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_qualConstraint1569 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_qualConstraint1604 = new BitSet(new ulong[]{0x0003800000000002UL});
+    public static readonly BitSet FOLLOW_T_SUM_in_qualConstraint1635 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_DIFF_in_qualConstraint1652 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_PROD_in_qualConstraint1669 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_qualConstraint1698 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_REQUIRES_in_discreteActionBody1788 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_discreteActionBody1792 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_discreteActionBody1794 = new BitSet(new ulong[]{0x00F0300400001100UL});
+    public static readonly BitSet FOLLOW_actionBody_in_discreteActionBody1801 = new BitSet(new ulong[]{0x0000080000000000UL});
+    public static readonly BitSet FOLLOW_T_END_in_discreteActionBody1806 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_actionBlockParallel_in_actionBlock1842 = new BitSet(new ulong[]{0x0000000000000402UL});
+    public static readonly BitSet FOLLOW_T_PRIO_in_actionBlock1846 = new BitSet(new ulong[]{0x0010300400001100UL});
+    public static readonly BitSet FOLLOW_actionBlockParallel_in_actionBlock1848 = new BitSet(new ulong[]{0x0000000000000402UL});
+    public static readonly BitSet FOLLOW_actionBlockSequential_in_actionBlockParallel1873 = new BitSet(new ulong[]{0x0000000000000802UL});
+    public static readonly BitSet FOLLOW_T_NONDET_in_actionBlockParallel1877 = new BitSet(new ulong[]{0x0010300400001100UL});
+    public static readonly BitSet FOLLOW_actionBlockSequential_in_actionBlockParallel1879 = new BitSet(new ulong[]{0x0000000000000802UL});
+    public static readonly BitSet FOLLOW_T_VAR_in_actionBlockSequential1908 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_blockvarlist_in_actionBlockSequential1912 = new BitSet(new ulong[]{0x0000040000000000UL,0x0100000000000000UL});
+    public static readonly BitSet FOLLOW_120_in_actionBlockSequential1916 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_actionBlockSequential1920 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_actionBlockSequential1927 = new BitSet(new ulong[]{0x0010300400001100UL});
+    public static readonly BitSet FOLLOW_actionBlockParen_in_actionBlockSequential1936 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_actionBlockSequential1940 = new BitSet(new ulong[]{0x0010300400001100UL});
+    public static readonly BitSet FOLLOW_actionBlockParen_in_actionBlockSequential1942 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_actionBlockParen1966 = new BitSet(new ulong[]{0x0010300400001100UL});
+    public static readonly BitSet FOLLOW_actionBlock_in_actionBlockParen1968 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_actionBlockParen1971 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_anonymousOrNamedAction_in_actionBlockParen1976 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_anonymousAction_in_anonymousOrNamedAction1993 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_anonymousOrNamedAction2002 = new BitSet(new ulong[]{0x000C000000001002UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_anonymousOrNamedAction2016 = new BitSet(new ulong[]{0x00800000A081B100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_methodCallParams_in_anonymousOrNamedAction2021 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_anonymousOrNamedAction2023 = new BitSet(new ulong[]{0x000C000000000002UL});
+    public static readonly BitSet FOLLOW_set_in_anonymousOrNamedAction2041 = new BitSet(new ulong[]{0x0000000000001000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_anonymousOrNamedAction2047 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_anonymousOrNamedAction2051 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_anonymousOrNamedAction2053 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_SKIP_in_anonymousOrNamedAction2064 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_blockvar_in_blockvarlist2080 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_blockvarlist2085 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_blockvar_in_blockvarlist2087 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_blockvar2107 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_blockvar2110 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_blockvar2114 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_actionBodyParallel_in_actionBody2149 = new BitSet(new ulong[]{0x0000000000000402UL});
+    public static readonly BitSet FOLLOW_T_PRIO_in_actionBody2153 = new BitSet(new ulong[]{0x00F0300400001100UL});
+    public static readonly BitSet FOLLOW_actionBodyParallel_in_actionBody2155 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_actionBodySequential_in_actionBodyParallel2183 = new BitSet(new ulong[]{0x0000000000000802UL});
+    public static readonly BitSet FOLLOW_T_NONDET_in_actionBodyParallel2189 = new BitSet(new ulong[]{0x00F0300400001100UL});
+    public static readonly BitSet FOLLOW_actionBodySequential_in_actionBodyParallel2193 = new BitSet(new ulong[]{0x0000000000000802UL});
+    public static readonly BitSet FOLLOW_actionBodyParen_in_actionBodySequential2220 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_actionBodySequential2224 = new BitSet(new ulong[]{0x00F0300400001100UL});
+    public static readonly BitSet FOLLOW_actionBodyParen_in_actionBodySequential2226 = new BitSet(new ulong[]{0x0000000000000082UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_actionBodyParen2244 = new BitSet(new ulong[]{0x00F0300400001100UL});
+    public static readonly BitSet FOLLOW_actionBody_in_actionBodyParen2246 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_actionBodyParen2249 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_statement_in_actionBodyParen2256 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_ABORT_in_statement2284 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_SKIP_in_statement2291 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_KILL_in_statement2298 = new BitSet(new ulong[]{0x0000000000001000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_statement2300 = new BitSet(new ulong[]{0x0080000000000100UL});
+    public static readonly BitSet FOLLOW_set_in_statement2304 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_statement2312 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_discreteActionBody_in_statement2322 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_reference_in_statement2331 = new BitSet(new ulong[]{0x0100000000080002UL});
+    public static readonly BitSet FOLLOW_T_ASSIGNMENT_in_statement2359 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_statement2364 = new BitSet(new ulong[]{0x0200000000000002UL});
+    public static readonly BitSet FOLLOW_T_WITH_in_statement2384 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_statement2388 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_statement2441 = new BitSet(new ulong[]{0x0080000000000100UL});
+    public static readonly BitSet FOLLOW_reference_in_statement2445 = new BitSet(new ulong[]{0x0100000000080000UL});
+    public static readonly BitSet FOLLOW_T_ASSIGNMENT_in_statement2460 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_statement2482 = new BitSet(new ulong[]{0x0000000000080000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_statement2501 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_statement2505 = new BitSet(new ulong[]{0x0200000000080002UL});
+    public static readonly BitSet FOLLOW_T_WITH_in_statement2519 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_statement2523 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_atomExpression_in_expression2598 = new BitSet(new ulong[]{0xFC03800000800202UL,0x00000000000FFFFBUL});
+    public static readonly BitSet FOLLOW_binoperator_in_expression2611 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_atomExpression_in_expression2619 = new BitSet(new ulong[]{0xFC03800000800202UL,0x00000000000FFFFBUL});
+    public static readonly BitSet FOLLOW_T_BIIMPLIES_in_binoperator2652 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_GREATER_in_binoperator2661 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_GREATEREQUAL_in_binoperator2671 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_LESS_in_binoperator2680 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_LESSEQUAL_in_binoperator2690 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_EQUAL_in_binoperator2699 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_NOTEQUAL_in_binoperator2711 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IMPLIES_in_binoperator2722 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_MINUS_in_binoperator2731 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_SUM_in_binoperator2741 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IN_in_binoperator2751 = new BitSet(new ulong[]{0x0000000000000002UL,0x0000000000000004UL});
+    public static readonly BitSet FOLLOW_T_SET_in_binoperator2753 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_NOT_in_binoperator2764 = new BitSet(new ulong[]{0x0000000000000000UL,0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IN_in_binoperator2766 = new BitSet(new ulong[]{0x0000000000000002UL,0x0000000000000004UL});
+    public static readonly BitSet FOLLOW_T_SET_in_binoperator2768 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_SUBSET_in_binoperator2779 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_OR_in_binoperator2789 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_DIV_in_binoperator2798 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_PROD_in_binoperator2807 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IDIV_in_binoperator2817 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_MOD_in_binoperator2827 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_UNION_in_binoperator2837 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_DIFF_in_binoperator2848 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_INTER_in_binoperator2859 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_AND_in_binoperator2870 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_POW_in_binoperator2885 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_CONC_in_binoperator2900 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_DOMRESBY_in_binoperator2913 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_DOMRESTO_in_binoperator2923 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_RNGRESBY_in_binoperator2933 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_RNGRESTO_in_binoperator2943 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_MUNION_in_binoperator2953 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_SEQMOD_MAPOVERRIDE_in_binoperator2963 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_op_un_in_atomExpression3001 = new BitSet(new ulong[]{0x00800000A0019100UL,0x040000007F000000UL});
+    public static readonly BitSet FOLLOW_identifierExpression_in_atomExpression3018 = new BitSet(new ulong[]{0x0000000000000002UL,0x0200000000000000UL});
+    public static readonly BitSet FOLLOW_qvalExpression_in_atomExpression3029 = new BitSet(new ulong[]{0x0000000000000002UL,0x0200000000000000UL});
+    public static readonly BitSet FOLLOW_constant_in_atomExpression3040 = new BitSet(new ulong[]{0x0000000000000002UL,0x0200000000000000UL});
+    public static readonly BitSet FOLLOW_initializedComplexType_in_atomExpression3051 = new BitSet(new ulong[]{0x0000000000000002UL,0x0200000000000000UL});
+    public static readonly BitSet FOLLOW_quantifierExpression_in_atomExpression3063 = new BitSet(new ulong[]{0x0000000000000002UL,0x0200000000000000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_atomExpression3072 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_atomExpression3076 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_atomExpression3078 = new BitSet(new ulong[]{0x0000000000009002UL,0x0200000000100000UL});
+    public static readonly BitSet FOLLOW_T_POINT_in_atomExpression3101 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_atomExpression3113 = new BitSet(new ulong[]{0x0000000000009002UL,0x0200000000100000UL});
+    public static readonly BitSet FOLLOW_accessExpression_in_atomExpression3137 = new BitSet(new ulong[]{0x0000000000000002UL,0x0200000000000000UL});
+    public static readonly BitSet FOLLOW_accessExpression_in_atomExpression3157 = new BitSet(new ulong[]{0x0000000000000002UL,0x0200000000000000UL});
+    public static readonly BitSet FOLLOW_121_in_atomExpression3176 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_atomExpression3180 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IF_in_atomExpression3201 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_atomExpression3205 = new BitSet(new ulong[]{0x0000000000000000UL,0x0000000000400000UL});
+    public static readonly BitSet FOLLOW_T_THEN_in_atomExpression3207 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_atomExpression3211 = new BitSet(new ulong[]{0x0000000000000000UL,0x0000000000800000UL});
+    public static readonly BitSet FOLLOW_T_ELSE_in_atomExpression3213 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_atomExpression3217 = new BitSet(new ulong[]{0x0000080000000000UL});
+    public static readonly BitSet FOLLOW_T_END_in_atomExpression3219 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_set_in_quantifierExpression3251 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_quantifierExpression3268 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_quantifierExpression3271 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_simpleType_in_quantifierExpression3275 = new BitSet(new ulong[]{0x0000040000080000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_quantifierExpression3286 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_quantifierExpression3290 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_quantifierExpression3293 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_simpleType_in_quantifierExpression3297 = new BitSet(new ulong[]{0x0000040000080000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_quantifierExpression3307 = new BitSet(new ulong[]{0x0000000000001000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_quantifierExpression3309 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_quantifierExpression3313 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_quantifierExpression3315 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_TRUE_in_constant3349 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_FALSE_in_constant3357 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_NIL_in_constant3364 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_SELF_in_constant3372 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_FLOATNUMBER_in_constant3383 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_INTNUMBER_in_constant3392 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_STRINGLITERAL_in_constant3401 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_initializedListType_in_initializedComplexType3428 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_initializedSetType_in_initializedComplexType3437 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_NEW_in_initializedComplexType3445 = new BitSet(new ulong[]{0x0000000000001000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_initializedComplexType3447 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_initializedComplexType3451 = new BitSet(new ulong[]{0x0000000000082000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_initializedComplexType3463 = new BitSet(new ulong[]{0x0000000000000000UL,0x0000000020000000UL});
+    public static readonly BitSet FOLLOW_T_STRINGLITERAL_in_initializedComplexType3468 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_initializedComplexType3470 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_initializedComplexType3479 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_LSQPAREN_in_initializedListType3510 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_initializedListType3514 = new BitSet(new ulong[]{0x00000000000A0000UL,0x0000000080000000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_initializedListType3525 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_initializedListType3529 = new BitSet(new ulong[]{0x00000000000A0000UL});
+    public static readonly BitSet FOLLOW_listComprehension_in_initializedListType3541 = new BitSet(new ulong[]{0x0000000000020000UL});
+    public static readonly BitSet FOLLOW_T_RSQPAREN_in_initializedListType3549 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_BAR_in_listComprehension3580 = new BitSet(new ulong[]{0x0000000400000000UL});
+    public static readonly BitSet FOLLOW_T_VAR_in_listComprehension3582 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_listComprehension3588 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_listComprehension3591 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_listComprehension3595 = new BitSet(new ulong[]{0x0000000000000082UL,0x0100000000000000UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_listComprehension3604 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_listComprehension3608 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_listComprehension3613 = new BitSet(new ulong[]{0x0000000000000082UL,0x0100000000000000UL});
+    public static readonly BitSet FOLLOW_120_in_listComprehension3623 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_listComprehension3629 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_CBRL_in_initializedSetType3655 = new BitSet(new ulong[]{0x0000000000000000UL,0x0000000100000000UL});
+    public static readonly BitSet FOLLOW_T_MAPS_in_initializedSetType3657 = new BitSet(new ulong[]{0x0000000100000000UL});
+    public static readonly BitSet FOLLOW_T_CBRR_in_initializedSetType3659 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_initializedSet_in_initializedSetType3670 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_CBRL_in_initializedSet3696 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_initializedSet3700 = new BitSet(new ulong[]{0x0000000100080000UL,0x0000000180000000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_initializedSet3730 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_initializedSet3734 = new BitSet(new ulong[]{0x0000000100080000UL});
+    public static readonly BitSet FOLLOW_map_in_initializedSet3752 = new BitSet(new ulong[]{0x0000000100000000UL});
+    public static readonly BitSet FOLLOW_setComprehension_in_initializedSet3765 = new BitSet(new ulong[]{0x0000000100000000UL});
+    public static readonly BitSet FOLLOW_T_CBRR_in_initializedSet3775 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_MAPS_in_map3813 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_map3817 = new BitSet(new ulong[]{0x0000000000080002UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_map3825 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_map3829 = new BitSet(new ulong[]{0x0000000000000000UL,0x0000000100000000UL});
+    public static readonly BitSet FOLLOW_T_MAPS_in_map3831 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_map3835 = new BitSet(new ulong[]{0x0000000000080002UL});
+    public static readonly BitSet FOLLOW_T_BAR_in_setComprehension3857 = new BitSet(new ulong[]{0x0000000400000000UL});
+    public static readonly BitSet FOLLOW_T_VAR_in_setComprehension3859 = new BitSet(new ulong[]{0x0000000000000102UL,0x0100000000000000UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_setComprehension3864 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_setComprehension3867 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_setComprehension3871 = new BitSet(new ulong[]{0x0000000000000080UL});
+    public static readonly BitSet FOLLOW_T_SEMICOLON_in_setComprehension3880 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_setComprehension3884 = new BitSet(new ulong[]{0x0000040000000000UL});
+    public static readonly BitSet FOLLOW_T_COLON_in_setComprehension3886 = new BitSet(new ulong[]{0x00000000D650D100UL});
+    public static readonly BitSet FOLLOW_complexType_in_setComprehension3890 = new BitSet(new ulong[]{0x0000000000000102UL,0x0100000000000000UL});
+    public static readonly BitSet FOLLOW_120_in_setComprehension3904 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_setComprehension3910 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_122_in_qvalExpression3945 = new BitSet(new ulong[]{0x0000000000001000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_qvalExpression3947 = new BitSet(new ulong[]{0x0080000001800100UL,0x0000000010000000UL});
+    public static readonly BitSet FOLLOW_T_NIL_in_qvalExpression3961 = new BitSet(new ulong[]{0x0000000000080000UL});
+    public static readonly BitSet FOLLOW_qualifiedIdentifier_in_qvalExpression3982 = new BitSet(new ulong[]{0x0000000008080000UL});
+    public static readonly BitSet FOLLOW_T_MINUS_in_qvalExpression4001 = new BitSet(new ulong[]{0x0000000001000000UL});
+    public static readonly BitSet FOLLOW_T_INFTY_in_qvalExpression4007 = new BitSet(new ulong[]{0x0000000008080000UL});
+    public static readonly BitSet FOLLOW_T_RANGETO_in_qvalExpression4025 = new BitSet(new ulong[]{0x0080000001000100UL});
+    public static readonly BitSet FOLLOW_qualifiedIdentifier_in_qvalExpression4035 = new BitSet(new ulong[]{0x0000000000080000UL});
+    public static readonly BitSet FOLLOW_T_INFTY_in_qvalExpression4053 = new BitSet(new ulong[]{0x0000000000080000UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_qvalExpression4077 = new BitSet(new ulong[]{0x0000000000000000UL,0x3800000010000000UL});
+    public static readonly BitSet FOLLOW_T_NIL_in_qvalExpression4087 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_123_in_qvalExpression4103 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_124_in_qvalExpression4116 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_125_in_qvalExpression4129 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_qvalExpression4151 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_identifierExpression4184 = new BitSet(new ulong[]{0x0000000000001000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_identifierExpression4186 = new BitSet(new ulong[]{0x00800000A081B100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_methodCallParams_in_identifierExpression4190 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_identifierExpression4192 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_reference_in_identifierExpression4207 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_qualifiedIdentifier_in_reference4245 = new BitSet(new ulong[]{0x000C000000009002UL,0x4000000200000000UL});
+    public static readonly BitSet FOLLOW_accessExpression_in_reference4257 = new BitSet(new ulong[]{0x000C000000000002UL,0x4000000200000000UL});
+    public static readonly BitSet FOLLOW_T_PRIMED_in_reference4282 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_126_in_reference4298 = new BitSet(new ulong[]{0x0000000000001000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_reference4300 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_reference4304 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_reference4306 = new BitSet(new ulong[]{0x000C000000000000UL});
+    public static readonly BitSet FOLLOW_set_in_reference4312 = new BitSet(new ulong[]{0x0000000000001000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_reference4318 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_reference4322 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_reference4324 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_LSQPAREN_in_accessExpression4369 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_accessExpression4373 = new BitSet(new ulong[]{0x0000000000020000UL});
+    public static readonly BitSet FOLLOW_T_RSQPAREN_in_accessExpression4375 = new BitSet(new ulong[]{0x0000000000009002UL,0x0000000000100000UL});
+    public static readonly BitSet FOLLOW_T_LPAREN_in_accessExpression4402 = new BitSet(new ulong[]{0x00800000A081B100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_methodCallParams_in_accessExpression4406 = new BitSet(new ulong[]{0x0000000000002000UL});
+    public static readonly BitSet FOLLOW_T_RPAREN_in_accessExpression4408 = new BitSet(new ulong[]{0x0000000000009002UL,0x0000000000100000UL});
+    public static readonly BitSet FOLLOW_T_POINT_in_accessExpression4430 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_accessExpression4438 = new BitSet(new ulong[]{0x0000000000009002UL,0x0000000000100000UL});
+    public static readonly BitSet FOLLOW_accessExpression_in_accessExpression4454 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_SELF_in_qualifiedIdentifier4493 = new BitSet(new ulong[]{0x0000000000000000UL,0x0000000000100000UL});
+    public static readonly BitSet FOLLOW_T_POINT_in_qualifiedIdentifier4495 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_qualifiedIdentifier4507 = new BitSet(new ulong[]{0x0000000000000002UL,0x0000000000100000UL});
+    public static readonly BitSet FOLLOW_T_POINT_in_qualifiedIdentifier4516 = new BitSet(new ulong[]{0x0000000000000100UL});
+    public static readonly BitSet FOLLOW_T_IDENTIFIER_in_qualifiedIdentifier4520 = new BitSet(new ulong[]{0x0000000000000002UL,0x0000000000100000UL});
+    public static readonly BitSet FOLLOW_expression_in_methodCallParams4553 = new BitSet(new ulong[]{0x0000000000080002UL});
+    public static readonly BitSet FOLLOW_T_COMMA_in_methodCallParams4558 = new BitSet(new ulong[]{0x00800000A0819100UL,0x04007FFC7F200008UL});
+    public static readonly BitSet FOLLOW_expression_in_methodCallParams4562 = new BitSet(new ulong[]{0x0000000000080002UL});
+    public static readonly BitSet FOLLOW_op_un_set_list_in_op_un4601 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_op_un_map_in_op_un4610 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_MINUS_in_op_un4618 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_NOT_in_op_un4626 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_ABS_in_op_un4634 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_CARD_in_op_un_set_list4661 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_DCONC_in_op_un_set_list4672 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_DINTER_in_op_un_set_list4683 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_DUNION_in_op_un_set_list4693 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_ELEMS_in_op_un_set_list4703 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_HEAD_in_op_un_set_list4714 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_INDS_in_op_un_set_list4725 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_LEN_in_op_un_set_list4736 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_TAIL_in_op_un_set_list4747 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_DOM_in_op_un_map4776 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_RNG_in_op_un_map4787 = new BitSet(new ulong[]{0x0000000000000002UL});
+    public static readonly BitSet FOLLOW_T_MERGE_in_op_un_map4798 = new BitSet(new ulong[]{0x0000000000000002UL});
+
+}
+}
\ No newline at end of file
Index: branches/compiler/cSharp/LICENSE
===================================================================
--- branches/compiler/cSharp/LICENSE	(nonexistent)
+++ branches/compiler/cSharp/LICENSE	(revision 3)
@@ -0,0 +1,14 @@
+This is the BSD 3-Clause License.
+
+Copyright (c) 2015, AIT Austrian Institute of Technology, and Graz University of Technology
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the names of the copyright holders nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Index: branches/compiler/cSharp/README
===================================================================
--- branches/compiler/cSharp/README	(nonexistent)
+++ branches/compiler/cSharp/README	(revision 3)
@@ -0,0 +1,13 @@
+
+              Object-Oriented Action System (OOAS) Compiler
+              =============================================
+
+This folder contains the original C# version of the compiler backed by a
+Technical Report that introduces the main language features and also dis-
+cusses some of the shortcomings of the C# implementation.
+Note that the C# version of the CADP Backend is not included in this 
+release.
+
+
+Vienna, Graz, 30th March 2015
+
