Click here to Skip to main content
15,885,366 members
Articles / Programming Languages / C#

GOF's Adapters and Some Magic

Rate me:
Please Sign up or sign in to vote.
3.80/5 (3 votes)
21 Apr 2009CPOL14 min read 25K   85   32  
How to create automated Adapters and extend/modify the original functionality with default member’s implementation for interfaces, Eiffel-like Separates, Code Injection, and Design by Contract.
using System;
using System.Xml ;
using System.Xml.Xsl ;
using System.Xml.XPath ;
using System.Collections ;
using System.Reflection ;
using System.Reflection.Emit ;
using Compiling ;
using Compiling.DataStructures ;
using Compiling.StringTreatment ;
using System.Resources ;
using System.IO ;

namespace Scaredfingers.Assertions
{
	using Assertions.Exceptions ;
	using Assertions.Runtime ;
	using Documentation ;

	public interface IAssertion
	{
		string BoolExpression
		{
			get ;
		}
		string Label
		{
			get ;
			set ;
		}
		Type AssertionViolation
		{
			get ;
			set ;
		}
	}

	public abstract class Assertion : IAssertion
	{
		IDictionary scope ;
		Type violation ;
		string label ;
		MemberInfo target ;

		XmlDocument document = new XmlDocument() ;

		public static string CompilingOKMessage = "OK" ;
		protected string boolExpression ;

		public Assertion(string boolExpression, string label, IDictionary scope)
		{
			this.boolExpression = boolExpression == null ? "" : boolExpression ;
			this.label = label == null ? "" : label ;
			AssertionScope = scope ;
		}
		public Assertion() : this("","",new Hashtable())
		{
		}
		public Assertion(string boolExpression) : this(boolExpression, "", new Hashtable())
		{
		}
		public Assertion(string boolExpression, string label) : this(boolExpression, label, new Hashtable())
		{
		}
		public Assertion(string boolExpression, IDictionary scope) : this(boolExpression, "", scope)
		{
		}

		
		public abstract bool Check() ;
		public abstract bool EmitAssertion(ILGenerator generator) ;
		public abstract bool EmitInicializations(ILGenerator generator) ;
		public abstract string CompilingMessage
		{
			get ;
		}

		
		public virtual string BoolExpression
		{
			get
			{
				return boolExpression ;
			}
		}
		internal bool IsBlank
		{
			get
			{
				return BoolExpression == null || BoolExpression == "" ;
			}
		}
		public string Label 
		{
			get
			{
				if (label == null)
					return "" ;
				return label ;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException() ;
				label = value ;
			}
		}
		public virtual Type AssertionViolation
		{
			get
			{
				return violation ;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException() ;
				if (!value.IsSubclassOf(typeof(Exception)) ||
					value.GetConstructor(new Type[0]) == null)
					throw new ArgumentException() ;
				violation = value ;
			}
		}
		public IDictionary AssertionScope
		{
			get
			{
				return scope ;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException() ;
				scope = value ;
			}
		}
		public virtual MemberInfo Target
		{
			get
			{
				return target ;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException() ;
				target = value ;
			}
		}

        Type typ_ForcedTargetType;
        public virtual Type ForcedTargetsType
        {
            get
            {
                return typ_ForcedTargetType;
            }
            set
            {
                typ_ForcedTargetType = value;
            }
        }

        MemberInfo inf_ForcedTarget;
        public virtual MemberInfo ForcedTarget
        {
            get
            {
                return inf_ForcedTarget;
            }
            set
            {
                inf_ForcedTarget = value;
            }
        }

        FieldInfo inf_ForcedReference;
        public virtual FieldInfo ForcedReference
        {
            get
            {
                return inf_ForcedReference;
            }
            set
            {
                inf_ForcedReference = value;
            }
        }

		public override string ToString()
		{
			return BoolExpression ;
		}

		public virtual XmlNode XmlView
		{
			get
			{
				return document.CreateElement("assertion") ;
			}
		}
	}
	
	public abstract class AssertionGroup : Assertion, IEnumerable
	{
		#region Protected fields
		protected ArrayList assertionList ;
		protected string compilingMessage ;
		protected bool childrenThrowOnFail = true ;
		protected bool localThrowOnFail = true ;
		#endregion
		#region Constructors
		public AssertionGroup(Assertion[] list)
		{
			if (list == null)
				throw new ArgumentNullException() ;
			assertionList = new ArrayList() ;
			foreach(Assertion assertion in list)
			{
				this.Add(assertion) ;
				assertion.AssertionScope = AssertionScope ;
			}
		}
		public AssertionGroup() : this(new Assertion[0])
		{
		}
		#endregion
		public void Add(Assertion assertion)
		{
			if (assertion == null)
				throw new ArgumentNullException() ;
			assertionList.Add(assertion) ;
		}
		public int Length
		{
			get
			{
				return assertionList.Count ;
			}
		}
		public IEnumerator GetEnumerator()
		{
			return assertionList.GetEnumerator() ;
		}
		public IEnumerator GetEnumerator(int index, int count)
		{
			return assertionList.GetEnumerator(index, count) ;
		}

		internal bool LocalThrowOnFail
		{
			get
			{
				return localThrowOnFail ;
			}
			set
			{
				localThrowOnFail = value ;
				if (! value)
					ChildrenThrowOnFail = false ;
			}
		}
		internal bool ChildrenThrowOnFail
		{
			get
			{
				return childrenThrowOnFail ;
			}
			set
			{
				childrenThrowOnFail = value ;
				foreach(Assertion assertion in assertionList)
				{
					if (assertion is AssertionGroup)
					{
						((AssertionGroup)assertion).LocalThrowOnFail = value ;
					}
				}
			}
		}
		
		public override bool Check()
		{
			bool result = true ;
			compilingMessage = "" ;
			foreach(Assertion assertion in assertionList)
				if (!assertion.Check())
				{
					compilingMessage += "Assertion Parse Error in \"" + assertion.BoolExpression + "\"\r\n " 
						+ "from: " + Target.MemberType + ":" + Target.Name + "\r\n" 
						+ assertion.CompilingMessage + "\r\n" ;
					result = false ;
				}
			if (compilingMessage == "")
				compilingMessage = "OK" ;
			return result ;
		}
		
		public override bool EmitInicializations(ILGenerator generator)
		{
			foreach(Assertion assertion in assertionList)
			{
				if (!assertion.EmitInicializations(generator))
					return false ;
			}
			return true ;
		}
		public override string CompilingMessage
		{
			get
			{
				return compilingMessage ;
			}
		}


		public override Type AssertionViolation
		{
			set
			{
				base.AssertionViolation = value ;
				foreach(Assertion assertion in assertionList)
					if (assertion is AssertionGroup)
						assertion.AssertionViolation = value ;
			}
			get
			{
				return base.AssertionViolation ;
			}
		}
		public virtual Assertion[] ToArray()
		{
			return assertionList.ToArray(typeof(Assertion)) as Assertion[] ;
			}
		public override MemberInfo Target
		{
			set
			{
				base.Target = value ;
				foreach(Assertion assertion in assertionList)
					assertion.Target = value ;
			}
			get
			{
				return base.Target ;
			}
        }

        #region Forced Members
        public override FieldInfo ForcedReference
        {
            get
            {
                return base.ForcedReference;
            }
            set
            {
                base.ForcedReference = value;
                foreach (Assertion child in assertionList)
                    child.ForcedReference = value;
            }
        }

        public override MemberInfo ForcedTarget
        {
            get
            {
                return base.ForcedTarget;
            }
            set
            {
                base.ForcedTarget = value;
                foreach (Assertion child in assertionList)
                    child.ForcedTarget = value;
            }
        }

        public override Type ForcedTargetsType
        {
            get
            {
                return base.ForcedTargetsType;
            }
            set
            {
                base.ForcedTargetsType = value;
                foreach (Assertion child in assertionList)
                    child.ForcedTargetsType = value;
            }
        }
        #endregion
    }
	public class AssertionANDGroup : AssertionGroup
	{
		#region Constructors
		public AssertionANDGroup(Assertion[] list) : base(list)
		{
		}
		public AssertionANDGroup() : base(new Assertion[0])
		{
		}
		#endregion
		public override string BoolExpression
		{
			get
			{
				if (assertionList.Count == 0)
					return "" ;
				if (assertionList.Count == 1)
					return ((Assertion)assertionList[0]).BoolExpression ;
				string result = "(" ;
				foreach(Assertion assertion in assertionList)
				{
					if (!assertion.IsBlank)
						result += assertion.BoolExpression + ") && (" ;
				}
				return result != "(" ? result.Substring(0, result.Length - 5) : "" ;
			}
		}
		public override bool EmitAssertion(ILGenerator generator)
		{
			if (IsBlank)
				return true ;
			bool isTheFirst = true ;
			#region
			foreach(Assertion assertion in assertionList)
			{
				if (assertion.IsBlank) continue ;
				Label fullFill = generator.DefineLabel() ;
				if (assertion is AssertionGroup)
				{
					if (!assertion.EmitAssertion(generator))
					{
						compilingMessage = assertion.CompilingMessage ;
						return false ;
					}
					if (!isTheFirst && !((AssertionGroup)assertion).LocalThrowOnFail)
						generator.Emit(OpCodes.And) ;
				}
				else
				{
					if (!this.localThrowOnFail)
					{
						if (!assertion.EmitAssertion(generator))
						{
							compilingMessage = assertion.CompilingMessage ;
							return false ;
						}
						if (!isTheFirst)
							generator.Emit(OpCodes.And) ;
					}
					else
					{
						generator.BeginExceptionBlock() ;
						if (!assertion.EmitAssertion(generator))
						{
							compilingMessage = assertion.CompilingMessage ;
							return false ;
						}
						generator.Emit(OpCodes.Brtrue, fullFill) ;
						if (assertion.AssertionViolation != null)
							generator.ThrowException(assertion.AssertionViolation) ;
						else
						{
							generator.Emit(OpCodes.Ldstr, assertion.Label) ;
							generator.Emit(OpCodes.Newobj, AssertionViolation.GetConstructor(
								new Type[] {typeof(string)})) ;
							generator.Emit(OpCodes.Throw) ;
						}
						generator.MarkLabel(fullFill) ;
						generator.BeginCatchBlock(typeof(AssertionException)) ;
						generator.Emit(OpCodes.Throw) ;
						generator.BeginCatchBlock(typeof(Exception)) ;
						LocalBuilder exc = generator.DeclareLocal(typeof(Exception)) ;
						generator.Emit(OpCodes.Stloc, exc) ;
						generator.Emit(OpCodes.Ldstr, assertion.Label) ;
						generator.Emit(OpCodes.Ldloc, exc) ;
						generator.Emit(OpCodes.Newobj, AssertionViolation.GetConstructor(
							new Type[] {typeof(string), typeof(Exception)})) ;
						generator.Emit(OpCodes.Throw) ;
						generator.EndExceptionBlock() ;

					}
				}
				isTheFirst = false ;
			}
			#endregion
			compilingMessage = CompilingOKMessage ;
			return true ;
		}
	}
	public class AssertionORGroup : AssertionGroup
	{
		#region Constructors
		public AssertionORGroup(Assertion[] list) : base(list)
		{
		}
		public AssertionORGroup() : base(new Assertion[0])
		{
		}
		#endregion
		public override string BoolExpression
		{
			get
			{
				if (assertionList.Count == 0)
					return "" ;
				if (assertionList.Count == 1)
					return ((Assertion)assertionList[0]).BoolExpression ;
				string result = "(" ;
				foreach(Assertion assertion in assertionList)
				{
					if (!assertion.IsBlank)
						result += assertion.BoolExpression + ") || (" ;
				}
				return result != "(" ? result.Substring(0, result.Length - 5) : "" ;
			}
		}
		public override bool EmitAssertion(ILGenerator generator)
		{
			if (IsBlank)
				return true ;
			ChildrenThrowOnFail = false ;
			bool isTheFirst = true ;
			Label fullFill = generator.DefineLabel()  ;
			generator.BeginExceptionBlock() ;
			foreach(Assertion assertion in assertionList)
			{
				if (assertion.IsBlank)
					continue ;
				if (!assertion.EmitAssertion(generator))
				{
					compilingMessage = assertion.CompilingMessage ;
					return false ;
				}
				if (! isTheFirst)
					generator.Emit(OpCodes.Or) ;
				isTheFirst = false ;
			}
			generator.Emit(OpCodes.Brtrue, fullFill) ;
			generator.ThrowException(typeof(PreconditionException)) ;
			generator.MarkLabel(fullFill) ;
			generator.BeginCatchBlock(typeof(AssertionException)) ;
			generator.Emit(OpCodes.Throw) ;
			generator.BeginCatchBlock(typeof(Exception)) ;
			generator.Emit(OpCodes.Newobj, typeof(PreconditionException).GetConstructor(new Type[] 
				{typeof(Exception)})) ;
			generator.Emit(OpCodes.Throw) ;
			generator.EndExceptionBlock() ;
			compilingMessage = CompilingOKMessage ;
			return true ;
		}
	}
	
	public abstract class AssertionManager
	{

		public static bool EnablePreconditions = true ;
		public static bool EnablePostconditions = true ;
		public static bool EnableInvariants = true ;
		internal static FieldInfo ckPre = typeof(AssertionManager).GetField("EnablePreconditions"),
			ckPos = typeof(AssertionManager).GetField("EnablePostconditions"),
			ckInv = typeof(AssertionManager).GetField("EnableInvariants") ;

		#region Scope creation methods (public)
		public IDictionary GetParamScope(MemberInfo target) 
		{
			return GetParamScope(target, new Hashtable()) ;
		}
		virtual protected IDictionary GetParamScope(MemberInfo target, IDictionary result)
		{
			ParameterInfo[] paramList = (target is MethodBase)? ((MethodBase)target).GetParameters() :
				(target is PropertyInfo)? ((PropertyInfo)target).GetIndexParameters() : new ParameterInfo[0] ;
			foreach(ParameterInfo param in paramList)
				result[param.Name] = param ;
			return result ;
		}
		public IDictionary GetInvScope(Type type)
		{
			return GetInvScope(type, new Hashtable()) ;
		}
		virtual protected IDictionary GetInvScope(Type type, IDictionary result)
		{
			result["this"] = result["@@this@@"] = type ;
			if (type.IsInterface)
				foreach(Type interfaceImpl in type.GetInterfaces())
					GetInvScope(interfaceImpl, result) ;
			foreach(MemberInfo member in type.GetMembers())
				result[CreateMemberEntry(member)] = member ;
			return result ;
		}
		public IDictionary GetPreScope(MemberInfo target)
		{
			return GetPreScope(target, new Hashtable()) ;
		}
		virtual protected IDictionary GetPreScope(MemberInfo target, IDictionary result)
		{
			result = GetParamScope(target, result) ;
			result = GetStaticScope(target.ReflectedType, result) ;
			if (target is MethodInfo && ((MethodInfo)target).IsStatic)
				return result ;
			if (target is MethodInfo || target is PropertyInfo)
				return GetInvScope(target.ReflectedType, result) ;
			return result ;
		}
		public IDictionary GetPosScope(MemberInfo target)
		{
			return GetPosScope(target, new Hashtable()) ;
		}
		virtual protected IDictionary GetPosScope(MemberInfo target, IDictionary result)
		{
			result = GetPreScope(target, result) ;
			IDictionary fullTable = new Hashtable(result) ;

			result = fullTable ;
			result["result"] = new object []{
				target is MethodInfo? ((MethodInfo)target).ReturnType : typeof(void), 0} ;
			return result ;
		}
		public IDictionary GetStaticScope(Type target) 
		{
			return GetStaticScope(target, new Hashtable()) ;
		}
		virtual protected IDictionary GetStaticScope(Type target, IDictionary result) 
		{
			foreach(MemberInfo member in target.GetMembers(BindingFlags.Static | BindingFlags.Public))
				result[CreateMemberEntry(member)] = member ;
			return result ;
		}

		#endregion

		#region Inheritance resolve methods (public and protected)
		protected MemberInfo[] GetBaseDefinition(MemberInfo target, MemberBasesPolicy policy)
		{
			return policy.GetBases(target) ;
		}
		public virtual Type[] GetBases(Type target)
		{
			return (Type[])GetBaseDefinition(target, new TypeBasesPolicy()) ;
		}
		public virtual PropertyInfo[] GetBaseProperty(PropertyInfo target)
		{
			return (PropertyInfo[])GetBaseDefinition(target, new PropertyBasesPolicy()) ;
		}
		public virtual MethodInfo[] GetBaseMethods(MethodInfo target)
		{
			return (MethodInfo[])GetBaseDefinition(target, new MethodBasesPolicy()) ;
		}
		#endregion

		#region Local and recursive attributes extraction (private region)
		private class InheritanceNode
		{
			public InheritanceNode(MemberInfo target, bool isFirst)
			{
				Target = target ;
				IsFirst = isFirst ;
			}
			public MemberInfo Target ;
			public bool IsFirst ;
		}
		private AssertionANDGroup GetLocalAssertionAttributes(MemberInfo target, Type attributeType)
		{
			return CreateAssertions((AssertionAttribute[])target.GetCustomAttributes(attributeType, false), target) ;
		}
		private AssertionANDGroup[] GetFullAssertionAttributes(MemberInfo target, Type attributeType, 
			MemberBasesPolicy policy)
		{
			Queue queue = new Queue() ;
			queue.Enqueue(new InheritanceNode(target, true)) ;
			ArrayList result = new ArrayList() ;
			AssertionANDGroup bornGroup = null ;
			bool firstNotFound = false ;
			while(queue.Count > 0)
			{
				InheritanceNode current = (InheritanceNode)queue.Dequeue() ;
				MemberInfo[] bases = GetBaseDefinition(current.Target, policy) ;
				InheritanceNode[] newNodes = new InheritanceNode[bases.Length] ;
				for(int i = 0; i < bases.Length; i++) 
					newNodes[i] = new InheritanceNode(bases[i], false) ;
				if (current.IsFirst)
				{
					if (bornGroup != null)
						result.Add(bornGroup) ;
					bornGroup = new AssertionANDGroup() ;
					if (bases.Length == 0)
						firstNotFound = true ;
					else
					{
						newNodes[0].IsFirst = true ;
						firstNotFound = false ;
					}
				}
				bornGroup.Add(GetLocalAssertionAttributes(current.Target, attributeType)) ;
				if (firstNotFound && bases.Length > 0)
				{
					newNodes[0].IsFirst = true ;
					firstNotFound = false ;
				}
				foreach(InheritanceNode node in newNodes)
					queue.Enqueue(node) ;
			}
			if (bornGroup != null)
			result.Add(bornGroup) ;
			return result.ToArray(typeof(AssertionANDGroup)) as AssertionANDGroup[] ;
			}
		#endregion

		#region Extraction methods (public region)
		public AssertionORGroup GetPreconditions(PropertyInfo property)
		{
			AssertionORGroup group = new AssertionORGroup(GetFullAssertionAttributes(property, 
				typeof(RequireAttribute), new PropertyBasesPolicy())) ;
			group.AssertionViolation = typeof(PreconditionException) ;
			group.Target = property ;
			return group ;
		}
		public AssertionORGroup GetPreconditions(MethodInfo method)
		{
			AssertionORGroup group = new AssertionORGroup(GetFullAssertionAttributes(method, 
				typeof(RequireAttribute), new MethodBasesPolicy())) ;
			group.AssertionViolation = typeof(PreconditionException) ;
			group.Target = method ;
			return group ;
		}
		public AssertionORGroup GetPreconditions(ConstructorInfo ctor)
		{
			AssertionORGroup group = new AssertionORGroup(GetFullAssertionAttributes(ctor,
				typeof(RequireAttribute), new ConstructorPolicy())) ;
			group.AssertionViolation = typeof(PreconditionException) ;
			group.Target = ctor;
			return group ;
		}
		public AssertionANDGroup GetPostconditions(PropertyInfo property)
		{
			AssertionANDGroup group = new AssertionANDGroup(GetFullAssertionAttributes(property, 
				typeof(EnsureAttribute), new PropertyBasesPolicy())) ;
			group.LocalThrowOnFail = true ;
			group.AssertionViolation = typeof(PostconditionException) ;
			group.Target = property ;
			return group ;
		}
		public AssertionANDGroup GetPostconditions(MethodInfo method)
		{
			AssertionANDGroup group = new AssertionANDGroup(GetFullAssertionAttributes(method, 
				typeof(EnsureAttribute), new MethodBasesPolicy())) ;
			group.LocalThrowOnFail = true ;
			group.AssertionViolation = typeof(PostconditionException) ;
			group.Target = method ;
			return group ;
		}
		public AssertionANDGroup GetPostconditions(ConstructorInfo ctor)
		{
			AssertionANDGroup group = new AssertionANDGroup(GetFullAssertionAttributes(ctor,
				typeof(EnsureAttribute), new ConstructorPolicy())) ;
			group.LocalThrowOnFail = true ;
			group.AssertionViolation = typeof(PostconditionException) ;
			group.Target = ctor;
			return group ;
		}
		public AssertionANDGroup GetInvariants(Type type)
		{
			AssertionANDGroup group = new AssertionANDGroup(GetFullAssertionAttributes(type, 
				typeof(InvariantAttribute), new TypeBasesPolicy())) ;
			group.LocalThrowOnFail = true ;
			group.AssertionViolation = typeof(InvariantException) ;
			group.Target = type ;
			return group ;
		}
		#endregion

		#region Overrideable method (protected)
		protected abstract Assertion CreatePrecondition(RequireAttribute attribute, MemberInfo target) ;
		protected abstract Assertion CreatePostcondition(EnsureAttribute attribute, MemberInfo target) ;
		protected abstract Assertion CreateInvariant(InvariantAttribute attribute, Type target) ;
		protected AssertionANDGroup CreatePreconditions(RequireAttribute[] attributes, MemberInfo target)
		{
			AssertionANDGroup andGroup = new AssertionANDGroup() ;
			foreach(RequireAttribute attribute in attributes)
			{
				andGroup.Add(CreatePrecondition(attribute, target)) ;
			}
			return andGroup ;
		}
		protected AssertionANDGroup CreatePostconditions(EnsureAttribute[] attributes, MemberInfo target)
		{
			AssertionANDGroup andGroup = new AssertionANDGroup() ;
			foreach(EnsureAttribute attribute in attributes)
			{
				andGroup.Add(CreatePostcondition(attribute, target)) ;
			}
			return andGroup ;
		}
		protected AssertionANDGroup CreateInvariants(InvariantAttribute[] attributes, Type target)
		{
			AssertionANDGroup andGroup = new AssertionANDGroup() ;
			foreach(InvariantAttribute attribute in attributes)
			{
				andGroup.Add(CreateInvariant(attribute, target)) ;
			}
			return andGroup ;
		}

		protected virtual AssertionANDGroup CreateAssertions(AssertionAttribute[] attributes, MemberInfo target)
		{
			AssertionANDGroup result = null ;
			if (attributes.Length == 0)
				result = new AssertionANDGroup() ;
			else if (attributes[0] is RequireAttribute)
				result = CreatePreconditions((RequireAttribute[])attributes, target) ;
			else if (attributes[0] is EnsureAttribute)
				result = CreatePostconditions((EnsureAttribute[])attributes, target) ;
			else if (attributes[0] is InvariantAttribute)
				result = CreateInvariants((InvariantAttribute[])attributes, (Type)target) ;
			else throw new Exception("Unknow attribute type") ;
			result.Target = target ;
			return result ;
		}
		#endregion

		#region Assertion explicit checking methods 
		public virtual bool CheckPreconditions(MethodInfo target)
		{
			return GetPreconditions(target).Check() ;
		}
		public virtual bool CheckPreconditions(PropertyInfo target)
		{
			return GetPreconditions(target).Check() ;
		}
		public virtual bool CheckPreconditions(ConstructorInfo target)
		{
			return GetPreconditions(target).Check() ;
		}
		public virtual bool CheckPostconditions(MethodInfo target)
		{
			return GetPostconditions(target).Check() ;
		}
		public virtual bool CheckPostconditions(PropertyInfo target)
		{
			return GetPostconditions(target).Check() ;
		}
		public virtual bool CheckPostconditions(ConstructorInfo target)
		{
			return GetPostconditions(target).Check() ;
		}
		public virtual bool CheckInvariants(Type target)
		{
			Assertion invariants = GetInvariants(target) ;
			bool result = invariants.Check() ;
			return result ;
		}
		#endregion

		#region Messages and strings formating tools
		virtual public string GetMemberString(object reference, MemberInfo member, object[] param)
		{
			if (member is MethodBase)
				return GetMethodString(reference, member.Name, param) ;
			if (member is PropertyInfo)
				return GetMethodString(reference, member.Name, param) ;
			return "" ;
		}
		public string GetMethodString(object reference, string methodName, 
			object[] param) 
		{
			string result = methodName + "(" ;
			foreach(object t in param)
				result += "," + (t == null? "null" : t.ToString()) ;
			result += ")" ;
			int index = result.IndexOf(",") ;
			if (index > -1)
				result = result.Remove(index,1) ;
			return string.Format("object: {0}, method: {1}", reference, result) ;
		}
		public string GetPropertyString(object reference, string propertyName, 
			object[] param) 
		{
			string result = propertyName ;
			if (param.Length == 0)
			{
				result += "[" ;
				foreach(object t in param)
					result += "," + (t == null? "null" : t.ToString()) ;
				result += "]" ;
				int index = result.IndexOf(",") ;
				if (index > -1)
					result = result.Remove(index,1) ;
			}
			return string.Format("object: {0}, property: {1}", reference, result) ;
		}
		public static Type[] GetTypes(object[] array)
		{
			Type[] result = new Type[array.Length] ;
			for(int i = 0; i < result.Length; i++)
				result[i] = (array[i] == null) ? typeof(void) : array[i].GetType() ;
			return result ;
		}

		static string CreateMemberEntry(MemberInfo member)
		{
			string result = member.ToString() ;
			return result.Substring(result.IndexOf(" ") + 1) ;
		}
		#endregion
	}

    public static class EmitHelper
    {
        public static void LdArg(ILGenerator _this, ParameterInfo param)
        { 
			int paramIndex = 0 ;
			if (
                    // Parameter 0 is this on instance methods, but it is the first parameter for static methods.
					(
						(param.Member is MethodBase) && (! ((MethodBase)param.Member).IsStatic)
					) || 
					(
						(param.Member is PropertyInfo) && (! ((PropertyInfo)param.Member).GetGetMethod().IsStatic)
					)
				)
				paramIndex = 1 ;
			unchecked{paramIndex += param.Position ;} // Just in case it's a very large parameter list
            // There is an opcode foreach parameters in [0,3]
			if (paramIndex < 4)
			{
				OpCode ldarg_i = new OpCode() ;
				switch(paramIndex)
				{
					case 0:
						ldarg_i = OpCodes.Ldarg_0 ;
						break ;
					case 1:
						ldarg_i = OpCodes.Ldarg_1 ;
						break ;
					case 2:
						ldarg_i = OpCodes.Ldarg_2 ;
						break ;
					case 3:
						ldarg_i = OpCodes.Ldarg_3 ;
						break ;
				}
                _this.Emit(ldarg_i);
				return ;
			}
            // Parameter with positions in [0, 255] can be manipulated with short form
            if (paramIndex < 256)
                _this.Emit(OpCodes.Ldarg_S, paramIndex);
            else
                _this.Emit(OpCodes.Ldarg, paramIndex);
		}
    }	

	#region Inheritance resolvers policies
	public abstract class MemberBasesPolicy
	{
		public abstract MemberInfo[] GetBases(MemberInfo target) ;
	}
	public class TypeBasesPolicy : MemberBasesPolicy
	{
		public override MemberInfo[] GetBases(MemberInfo targetType)
		{
			if (targetType == null || !(targetType is Type))
				throw new ArgumentException() ;
			Type type = (Type)targetType ;
			Type[] interfaces = type.GetInterfaces() ;
			Type[] result ;
			int currentIndex = 0, offset = 0 ;
			if (type != typeof(object) && ! type.IsInterface)
			{
				result = new Type[interfaces.Length + 1] ;
				result[currentIndex] = type.BaseType ;
				currentIndex ++ ;
				offset = 1 ;
			}
			else
				result = new Type[interfaces.Length] ;
			for(;currentIndex < result.Length; currentIndex++)
			{
				result[currentIndex] = interfaces[currentIndex - offset] ;
			}
			return result ;
		}
	}
	public class MethodBasesPolicy : MemberBasesPolicy
	{
		public override MemberInfo[] GetBases(MemberInfo targetMethod)
		{
			if (targetMethod == null || !(targetMethod is MethodInfo))
				throw new ArgumentException() ;
			MethodInfo target = (MethodInfo)targetMethod ;
			ParameterInfo[] parameters = target.GetParameters() ;
			Type[] parameterTypes = new Type[parameters.Length] ;
			for(int i = 0; i < parameters.Length; i++)
				parameterTypes[i] = parameters[i].ParameterType ;
			ArrayList result = new ArrayList() ;
			Type baseType = target.ReflectedType.BaseType ;
			if (baseType != null && (target.Attributes & MethodAttributes.NewSlot) != MethodAttributes.NewSlot)
			{
				MethodInfo method = baseType.GetMethod(target.Name, parameterTypes) ;
				if (method != null)
					result.Add(method) ;
			}
			foreach(Type intf in target.ReflectedType.GetInterfaces())
			{
				if (target.ReflectedType.GetMethod(intf.FullName + "." + target.Name, BindingFlags.NonPublic |
					BindingFlags.Instance, null, parameterTypes, null) != null)
					break ;
				MethodInfo method = intf.GetMethod(target.Name, parameterTypes) ;
				if (method != null)
					result.Add(method) ;
			}
			return result.ToArray(typeof(MethodInfo)) as MethodInfo[] ;
			}
	}
	public class PropertyBasesPolicy : MemberBasesPolicy
	{
		public override MemberInfo[] GetBases(MemberInfo targetProperty) 
		{
			if (targetProperty == null || !(targetProperty is PropertyInfo))
				throw new ArgumentException() ;
			PropertyInfo target = (PropertyInfo)targetProperty ;
			ParameterInfo[] parameters = target.GetIndexParameters() ;
			Type[] parameterTypes = new Type[parameters.Length] ;
			for(int i = 0; i < parameters.Length; i++)
				parameterTypes[i] = parameters[i].ParameterType ;
			ArrayList result = new ArrayList() ;
			Type baseType = target.ReflectedType.BaseType ;
			if (baseType != null)
			{
				PropertyInfo property = baseType.GetProperty(target.Name, parameterTypes) ;
				if (property != null && 
					//Get isnt newSlot. Property is override.
					((target.GetGetMethod() == null || (target.GetGetMethod().Attributes & MethodAttributes.NewSlot) 
					!= MethodAttributes.NewSlot) ||
					// Set isnt newSlot. Property is override.
					(target.GetSetMethod() == null || (target.GetSetMethod().Attributes & MethodAttributes.NewSlot) 
					!= MethodAttributes.NewSlot)))
					result.Add(property) ;
			}
			foreach(Type intf in target.ReflectedType.GetInterfaces())
			{
				if (target.ReflectedType.GetProperty(intf.FullName + "." + target.Name, BindingFlags.NonPublic |
					BindingFlags.Instance, null, null, parameterTypes, null) != null)
					break ;
				PropertyInfo property = intf.GetProperty(target.Name, parameterTypes) ;
				if (property != null)
					result.Add(property) ;
			}
			return result.ToArray(typeof(PropertyInfo)) as PropertyInfo[] ;
			}
	}
	public class ConstructorPolicy : MemberBasesPolicy
	{
		public override MemberInfo[] GetBases(MemberInfo target)
		{
			if (target == null || !(target is ConstructorInfo))
				throw new ArgumentException() ;
			return new MemberInfo[0] ;
		}
	}
	public class NotInheritableTypeBasesPolicy : MemberBasesPolicy
	{
		public override MemberInfo[] GetBases(MemberInfo target)
		{
			if (target == null || !(target is Type))
				throw new ArgumentException() ;
			return ((Type)target).GetInterfaces() ;
		}
	}
	public class NotInheritableMethodBasesPolicy : MemberBasesPolicy
	{
		public override MemberInfo[] GetBases(MemberInfo target)
		{
			if (target == null || !(target is MethodInfo))
				throw new ArgumentException() ;
			return null ;
		}
	}
	public class NotInheritablePropertyBasesPolicy : MemberBasesPolicy
	{
		public override MemberInfo[] GetBases(MemberInfo target)
		{
			if (target == null || !(target is PropertyInfo))
				throw new ArgumentException() ;
			return null ;
		}	
	}
	#endregion

	#region Attributes
	public abstract class AssertionAttribute : System.Attribute, IAssertion
	{
		protected string code ;
		protected Type violation = null ;
		protected string label = null ;
		protected bool inheritable = true ;
		public AssertionAttribute(string boolExpression) 
		{
			this.code = boolExpression ;
		}
		public string BoolExpression
		{
			get
			{
				return code ;
			}
			set
			{
				code = value ;
			}
		}
		public Type AssertionViolation
		{
			get
			{
				return violation ;
			}
			set
			{
				if (value == null)
					throw new ArgumentNullException() ;
				if (!value.IsSubclassOf(typeof(Exception)) ||
					value.GetConstructor(new Type[0]) == null)
					throw new ArgumentException() ;
				violation = value ;
			}
		}
		public string Label
		{
			get
			{
				if (label == null)
					return "" ;
				return label ;
			}
			set
			{
				label = value ;
			}
		}
		public bool Inheritable
		{
			get
			{
				return inheritable ;
			}
			set
			{
				inheritable = value ;
			}
		}
	}
	

	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | 
		 AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
	public class RequireAttribute : AssertionAttribute
	{
		public RequireAttribute(string code) : base(code)
		{
		}
	}
	

	[AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor | 
		 AttributeTargets.Property, AllowMultiple = true, Inherited = false)]
	public class EnsureAttribute : AssertionAttribute
	{
		public EnsureAttribute(string code) : base(code)
		{
		}
	}


	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | 
		 AttributeTargets.Struct, AllowMultiple = true, Inherited = false)]
	public class InvariantAttribute : AssertionAttribute
	{
		public InvariantAttribute(string code) : base(code)
		{
		}
	}
	#endregion

	namespace Exceptions
	{
		
		public class CompilingErrorException : Exception
		{
			public CompilingErrorException() : base() {}
			public CompilingErrorException(string mesg) : base(mesg) {}
			public CompilingErrorException(string mesg, Exception innerException) : 
				base(mesg, innerException) {}
		}
		public class AALCompilingErrorException : Exception
		{
			public AALCompilingErrorException() : base() {}
			public AALCompilingErrorException(string mesg) : base(mesg) {}
			public AALCompilingErrorException(string mesg, Exception innerException) : 
				base(mesg, innerException) {}
		}
		public class IllegalOperationException : Exception
		{
			public IllegalOperationException() : base() {}
			public IllegalOperationException(string mesg) : base(mesg) {}
			public IllegalOperationException(string mesg, Exception innerException) : 
				base(mesg, innerException) {}
		}		
		public class UnCheckedAssertionException : Exception
		{
			public UnCheckedAssertionException() : base() {}
			public UnCheckedAssertionException(string mesg) : base(mesg) {}
			public UnCheckedAssertionException(string mesg, Exception innerException) : 
				base(mesg, innerException) {}
		}
		public class MatchingMethodException : Exception
		{
			public MatchingMethodException() : base() {}
			public MatchingMethodException(string mesg) : base(mesg) {}
			public MatchingMethodException(string mesg, Exception innerException) : 
				base(mesg, innerException) {}
		}
		public class MatchingPropertyException : Exception
		{
			public MatchingPropertyException() : base() {}
			public MatchingPropertyException(string mesg) : base(mesg) {}
			public MatchingPropertyException(string mesg, Exception innerException) : 
				base(mesg, innerException) {}
		}
		public class AssertionException : Exception
		{
			protected string message ;
			public AssertionException() : base() {}
			public AssertionException(string mesg) :base(mesg) {}
			public AssertionException(string mesg, Exception innerException) : 
				base(mesg, innerException) 
			{
			}
			public AssertionException(Exception innerException) : base("", innerException)
			{
			}
			public override string Message
			{
				get
				{
					return (AssertionMessage != null ? (AssertionMessage + "\n") : "") + base.Message ;
				}
			}
			public string AssertionMessage
			{
				get
				{
					return message ;
				}
				set
				{
					message = value ;
				}
			}
		}
		public class PreconditionException : AssertionException
		{
			public PreconditionException() : base() {}
			public PreconditionException(string mesg) : base(mesg) {}
			public PreconditionException(string mesg, Exception innerException) : 
				base(mesg, innerException) {}
			public PreconditionException(Exception inner) : base(inner)
			{
			
			}
		}
		public class PostconditionException : AssertionException
		{
			public PostconditionException() : base() {}
			public PostconditionException(string mesg) : base(mesg) {}
			public PostconditionException(string mesg, Exception innerException) : 
				base(mesg, innerException) {}
			public PostconditionException(Exception inner) : base(inner)
			{
			}
		}
		public class InvariantException : AssertionException
		{
			public InvariantException() : base() {}
			public InvariantException(string mesg) : base(mesg) {}
			public InvariantException(string mesg, Exception innerException) : 
				base(mesg, innerException) {}
			public InvariantException(Exception inner) : base(inner)
			{
			
			}
		}
	}
	
	#region Generation
	public partial class ChacalAssertionManager : AssertionManager
	{
		protected override Assertion CreatePrecondition(RequireAttribute attribute, MemberInfo target)
		{
			return new ChacalAssertion(attribute.BoolExpression, attribute.Label, GetPreScope(target), target) ;
		}
		protected override Assertion CreatePostcondition(EnsureAttribute attribute, MemberInfo target)
		{
			ChacalAssertion postcond = new ChacalAssertion(attribute.BoolExpression, attribute.Label, 
				GetPosScope(target), target) ;
			postcond.IsPostcondition = true ;
			return postcond ;
		}
		protected override Assertion CreateInvariant(InvariantAttribute attribute, Type target)
		{
			return new ChacalAssertion(attribute.BoolExpression, attribute.Label, GetInvScope(target), target) ;
		}

		
		static ChacalAssertionManager() 
		{
            string ALXml = null;
            try
            {
                ResourceManager resources = new ResourceManager("Assertions.Data", Assembly.GetExecutingAssembly());
                if ((ALXml = resources.GetString("Grammar")) == null)
                    throw new InvalidOperationException();
            }
            catch
            {
                ALXml = ALXML;
            }
			XmlDocument doc = new XmlDocument() ;
			doc.LoadXml(ALXml) ;
			GrammarFactory gf = new GrammarFactory(doc.FirstChild, 
				typeof(Compiling.RecursiveParser),
				typeof(Assertions.AALExpression)) ;
			ChacalTokenizer = gf.DefaultTokenizer ;
			ChacalGrammar = gf.CreatedGrammar ;
		}
		
		
		public static ITokenizer ChacalTokenizer ;
		public static Grammar ChacalGrammar ;
	}

	public class ChacalAssertion : Assertion
	{
		DerivationTree tree ;
		string compilingMessage ;
		ArrayList inicializationList, varList ;
		GeneratorNode root ;
		internal bool IsPostcondition = false ;
		
		internal ChacalAssertion(string boolExpression, string label, IDictionary scope, MemberInfo target) : 
			base(boolExpression, label, scope)
		{		
			if (boolExpression == "")
				return ;
			IToken[] tokens = ChacalAssertionManager.ChacalTokenizer.Tokenize(boolExpression) ;
			if (! ChacalAssertionManager.ChacalGrammar.Parse(out tree, tokens))
				compilingMessage = "Syntax error" ;
			else
				compilingMessage = CompilingOKMessage ;
			base.Target = target ;
		}
		

		public override bool EmitAssertion(ILGenerator generator)
		{
			try
			{
				root.Emit(generator, varList) ;
				return true ;
			}
			catch
			{
				return false ;
			}
		}
		public override bool EmitInicializations(ILGenerator generator)
		{
			try
			{
				foreach(GeneratorNode node in inicializationList)
				{
					node.Emit(generator, varList) ;
				}
				return true ;
			}
			catch
			{
				return false ;
			}
		}
		public override bool Check()
		{
			if (BoolExpression == "")
				return true ;
			if (compilingMessage != CompilingOKMessage)
				return false ;
			try
			{
				Hashtable identifierTable = new Hashtable(AssertionScope) ;
				identifierTable["@@root@@"] = new Stack() ;
				identifierTable["@@member@@"] = Target ;
				identifierTable["@@this.GetType()@@"] = Target is Type ? Target : Target is MethodBase ? 
					((MethodBase)Target).ReflectedType : Target is PropertyInfo ? 
					((PropertyInfo)Target).ReflectedType : null;
                identifierTable["@@forced.this@@"] = ForcedReference;
                identifierTable["@@forced.this.GetType()@@"] = ForcedTargetsType;

				identifierTable["@@locals@@"] = 1 ;
				identifierTable["@@Pre.List@@"] = new ArrayList() ;

				tree.Reduce(identifierTable) ;

				root = (GeneratorNode)identifierTable["@@root@@"] ;
				inicializationList = (ArrayList)identifierTable["@@Pre.List@@"] ;
			}
			catch (AALCompilingErrorException error)
			{
				compilingMessage = error.Message ;
				return false ;
			}
			if (!IsPostcondition && inicializationList.Count != 0)
				throw new AALCompilingErrorException("'Pre' property can only be used on postconditions") ;
			varList = new ArrayList(new object[] {0}) ;
			return true ;
		}
		public override string CompilingMessage
		{
			get
			{
				return compilingMessage ;
			}
		}
	}

	internal class AALExpression
	{

		internal static Hashtable DefinedTypes ;
		static public void Start(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			Stack stack = (Stack)parameters["@@root@@"] ;
			parameters["@@root@@"] = stack.Pop() ;
		}
		static public void Simple(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
//					Stack stack = (Stack)parameters["@@root@@"] ;
//					ExpressionNode node = new ALExpression0() ;
//					node[0] = (ExpressionNode)stack.Pop() ;
//					stack.Push(node) ;
		}
		static public void Implies(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node = new ImpliesNode() ;
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void DoubleImplies(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			Stack stack = (Stack)parameters["@@root@@"] ;
			int locals = (int)parameters["@@locals@@"] ;
			parameters["@@locals@@"] = locals + 2 ;
			GeneratorNode node = new DoubleImpliesNode(locals) ;
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void SimpleBoolTerm(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
//					Stack stack = (Stack)parameters["@@root@@"] ;
//					ExpressionNode node = new boolExpression0() ;
//					node[0] = (ExpressionNode)stack.Pop() ;
//					stack.Push(node) ;
		}
		static public void BoolOr(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node = new BoolOrNode() ;
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void SimpleBoolFactor(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
//					Stack stack = (Stack)parameters["@@root@@"] ;
//					ExpressionNode node = new boolTerm0() ;
//					node[0] = (ExpressionNode)stack.Pop() ;
//					stack.Push(node) ;
		}
		static public void BoolAnd(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node = new BoolAndNode() ;
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void BoolFactor(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [boolFactor] --> [factor]
			// if expression.type != Bool Error
			NonTerminalSymbol factor = (NonTerminalSymbol)right[0] ;
			if (factor["type"] != typeof(bool))
				throw new AALCompilingErrorException("Type missmatch!!!") ;
//					Stack stack = (Stack)parameters["@@root@@"] ;
//					ExpressionNode node = new boolFactor0() ;
//					node[0] = (ExpressionNode)stack.Pop() ;
//					stack.Push(node) ;
		}
		static public void BoolNot(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node = new BoolNotNode() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void BoolContained(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
//					Stack stack = (Stack)parameters["@@root@@"] ;
//					ExpressionNode node = new boolFactor8() ;
//					node[0] = (ExpressionNode)stack.Pop() ;
//					stack.Push(node) ;
		}
		static public void InstanceOf(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [boolFactor] --> [factor] is [type]
			NonTerminalSymbol factor = (NonTerminalSymbol)right[0] ;
			CheckType(factor) ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			string typeName = ((NonTerminalSymbol)right[2])["name"] as string ;
			System.Type type = ResolveType(typeName) ;
			if (type == null)
				throw new AALCompilingErrorException("Unresolved type: " + typeName) ;
			if (((System.Type)factor["type"]).IsSubclassOf(typeof(System.ValueType)))
			{
				stack.Pop() ;
				if (type.IsAssignableFrom(((System.Type)factor["type"])))
					stack.Push(new TrueNode()) ;
				else
					stack.Push(new FalseNode()) ;
				return ;
			}
			GeneratorNode node = new IsNode(type) ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void TypedExpression(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [typedExpression] --> [expression]
			NonTerminalSymbol expr = (NonTerminalSymbol)right[0] ;
			if (expr["type"] == null)
				throw new AALCompilingErrorException("Undefined identifier " + expr["undefined"]) ;
			left["type"] = expr["type"] ;
			
		}
		static public void LessThan(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [boolean] --> [expression1] < [expression2]
			NonTerminalSymbol expression1 = (NonTerminalSymbol) right[0],
				expression2 = (NonTerminalSymbol) right[2] ;
			CheckType(expression1) ;
			CheckType(expression2) ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node ;
			System.Type exp1T = (System.Type)expression1["type"],
				exp2T = (System.Type)expression2["type"] ;
			if (exp1T == typeof(int) &&  exp2T == typeof(int))
				node = new LessThanNode() ;
			else
			{
				MethodInfo overload1 = exp1T.GetMethod("op_LessThan", new Type[] {exp1T,exp2T}),
					overload2 = exp2T.GetMethod("op_LessThan", new Type[] {exp1T,exp2T}) ;
				if (overload1 != null && overload2 != null)
					throw new AALCompilingErrorException(
						string.Format("Ambiguous call: operator '<' reciving [{0},{1}]", exp1T, exp2T)) ;
				if (overload1 != null && overload1.ReturnType == typeof(bool))
					node = new BinaryOperatorNode(overload1) ;
				else if (overload2 != null && overload2.ReturnType == typeof(bool))
					node = new BinaryOperatorNode(overload2) ;
				else
					throw new AALCompilingErrorException(
						string.Format("Type missmach: Cannot find an overload for '<' reciving [{0},{1}] or found one with non bool return type", exp1T, exp2T)) ;
			}
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void LessEqual(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [boolean] --> [expression] < = [expression]
			NonTerminalSymbol expression1 = (NonTerminalSymbol) right[0],
				expression2 = (NonTerminalSymbol) right[3] ;
			CheckType(expression1) ;
			CheckType(expression2) ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node ;
			System.Type exp1T = (System.Type)expression1["type"],
				exp2T = (System.Type)expression2["type"] ;
			if (exp1T == typeof(int) &&  exp2T == typeof(int))
				node = new LessOrEqualNode() ;
			else
			{
				MethodInfo overload1 = exp1T.GetMethod("op_LessThanOrEqual", new Type[] {exp1T,exp2T}),
					overload2 = exp2T.GetMethod("op_LessThanOrEqual", new Type[] {exp1T,exp2T}) ;
				if (overload1 != null && overload2 != null)
					throw new AALCompilingErrorException(
						string.Format("Ambiguous call: operator '<=' reciving [{0},{1}]", exp1T, exp2T)) ;
				if (overload1 != null && overload1.ReturnType == typeof(bool))
					node = new BinaryOperatorNode(overload1) ;
				else if (overload2 != null && overload2.ReturnType == typeof(bool))
					node = new BinaryOperatorNode(overload2) ;
				else
					throw new AALCompilingErrorException(
						string.Format("Type missmach: Cannot find an overload for '<=' reciving [{0},{1}] or found one with non bool return type", exp1T, exp2T)) ;
			}
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void GreaterThan(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [boolean] --> [expression] > [expression]
			NonTerminalSymbol expression1 = (NonTerminalSymbol) right[0],
				expression2 = (NonTerminalSymbol) right[2] ;
			CheckType(expression1) ;
			CheckType(expression2) ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node ;
			System.Type exp1T = (System.Type)expression1["type"],
				exp2T = (System.Type)expression2["type"] ;
			if (exp1T == typeof(int) &&  exp2T == typeof(int))
				node = new GreaterThanNode() ;
			else
			{
				MethodInfo overload1 = exp1T.GetMethod("op_GreaterThan", new Type[] {exp1T,exp2T}),
					overload2 = exp2T.GetMethod("op_GreaterThan", new Type[] {exp1T,exp2T}) ;
				if (overload1 != null && overload2 != null)
					throw new AALCompilingErrorException(
						string.Format("Ambiguous call: operator '>' reciving [{0},{1}]", exp1T, exp2T)) ;
				if (overload1 != null && overload1.ReturnType == typeof(bool))
					node = new BinaryOperatorNode(overload1) ;
				else if (overload2 != null && overload2.ReturnType == typeof(bool))
					node = new BinaryOperatorNode(overload2) ;
				else
					throw new AALCompilingErrorException(
						string.Format("Type missmach: Cannot find an overload for '>' reciving [{0},{1}] or found one with non bool return type", exp1T, exp2T)) ;
			}
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void GreaterEqual(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [boolean] --> [expression] > = [expression]
			NonTerminalSymbol expression1 = (NonTerminalSymbol) right[0],
				expression2 = (NonTerminalSymbol) right[3] ;
			CheckType(expression1) ;
			CheckType(expression2) ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node ;
			System.Type exp1T = (System.Type)expression1["type"],
				exp2T = (System.Type)expression2["type"] ;
			if (exp1T == typeof(int) &&  exp2T == typeof(int))
				node = new GreaterOrEqualNode() ;
			else
			{
				MethodInfo overload1 = exp1T.GetMethod("op_GreaterThanOrEqual", new Type[] {exp1T,exp2T}),
					overload2 = exp2T.GetMethod("op_GreaterThanOrEqual", new Type[] {exp1T,exp2T}) ;
				if (overload1 != null && overload2 != null)
					throw new AALCompilingErrorException(
						string.Format("Ambiguous call: operator '>=' reciving [{0},{1}]", exp1T, exp2T)) ;
				if (overload1 != null && overload1.ReturnType == typeof(bool))
					node = new BinaryOperatorNode(overload1) ;
				else if (overload2 != null && overload2.ReturnType == typeof(bool))
					node = new BinaryOperatorNode(overload2) ;
				else
					throw new AALCompilingErrorException(
						string.Format("Type missmach: Cannot find an overload for '>=' reciving [{0},{1}] or found one with non bool return type", exp1T, exp2T)) ;
			}
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void Equal(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [boolean] --> [expression1] = = [expression2]
			NonTerminalSymbol expression1 = (NonTerminalSymbol) right[0],
				expression2 = (NonTerminalSymbol) right[3] ;
			CheckType(expression1) ;
			CheckType(expression2) ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			System.Type exp1T = (System.Type)expression1["type"],
				exp2T = (System.Type)expression2["type"] ;
			MethodInfo overload1 = exp1T.GetMethod("op_Equality", new Type[] {exp1T, exp2T}),
				overload2 = exp2T.GetMethod("op_Equality", new Type[] {exp1T, exp2T}) ;
			GeneratorNode node ;
			if (overload1 != null && overload2 != null)
				throw new AALCompilingErrorException(
					string.Format("Ambiguous call: operator '==' reciving [{0},{1}]", exp1T, exp2T)) ;
			if (overload1 != null && overload1.ReturnType == typeof(bool))
				node = new BinaryOperatorNode(overload1) ;
			else if (overload2 != null && overload2.ReturnType == typeof(bool))
				node = new BinaryOperatorNode(overload2) ;
			else 
//				if (expression1.GetType().IsSubclassOf(typeof(ValueType)) && 
//				expression2.GetType().IsSubclassOf(typeof(ValueType)))
				node = new EqualNode() ;
//			else
//				node = new EqualsMethodNode() ;
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void NotEqual(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [boolean] --> [expression1] ! = [expression2]
			NonTerminalSymbol expression1 = (NonTerminalSymbol) right[0],
				expression2 = (NonTerminalSymbol) right[3] ;
			CheckType(expression1) ;
			CheckType(expression2) ;
			Stack stack = (Stack)parameters["@@root@@"] ;				
			System.Type exp1T = (System.Type)expression1["type"],
				exp2T = (System.Type)expression2["type"] ;
			MethodInfo overload1 = exp1T.GetMethod("op_Inequality", new Type[] {exp1T, exp2T}),
				overload2 = exp2T.GetMethod("op_Inequality", new Type[] {exp1T, exp2T}) ;
			GeneratorNode node ;
			if (overload1 != null && overload2 != null)
				throw new AALCompilingErrorException(
					string.Format("Ambiguous call: operator '!=' reciving [{0},{1}]", exp1T, exp2T)) ;
			if (overload1 != null && overload1.ReturnType == typeof(bool))
				node = new BinaryOperatorNode(overload1) ;
			else if (overload2 != null && overload2.ReturnType == typeof(bool))
				node = new BinaryOperatorNode(overload2) ;
			else 
//				if (expression1.GetType().IsSubclassOf(typeof(ValueType)) && 
//				expression2.GetType().IsSubclassOf(typeof(ValueType)))
//				if (overload1 == overload2)
				node = new NotEqualNode() ;
//			else
//				node = new NotEqualsMethodNode() ;
//				throw new AALCompilingErrorException(
//					string.Format("Type missmach: Cannot find an overload for '!=' reciving [{0},{1}] or found one with non bool return type", exp1T, exp2T)) ;
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void Term(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [expression] --> [term]
			// expression.type = term.type
			NonTerminalSymbol term = (NonTerminalSymbol)right[0] ;
			Stack stack = (Stack)parameters["@@root@@"] ;
				
			if (term["type"] != null)
			{
				left["type"] = term["type"] ;
//						ExpressionNode node = new expression0() ;
//						node[0] = (ExpressionNode)stack.Pop() ;
//						stack.Push(node) ;
			}
			else
			{
				left["type"] = null ;
				left["undefined"] = term["undefined"] ;
				left["full"] = term["full"] ;
				term["full"] = null ;
				Type type = ResolveType((string)left["full"]) ;
				if (type != null)
				{
					left["type"] = type ;
					left["undefined"] = null ;
					left["full"] = null ;
					stack.Push(new StaticNode(type)) ;
				}
			}
		}
		static public void Plus(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [expression] --> [expression] + [term]
			NonTerminalSymbol expression = (NonTerminalSymbol)right[0],
				term = (NonTerminalSymbol) right[2] ;
			GeneratorNode node ;
			System.Type exp1T = (System.Type)expression["type"],
				exp2T = (System.Type)term["type"] ;
			MethodInfo overload = null ;
			if (exp1T == typeof(int) &&  exp2T == typeof(int))
				node = new PlusNode() ;
			else
			{
				MethodInfo overload1 = exp1T.GetMethod("op_Addition", new Type[] {exp1T,exp2T}),
					overload2 = exp2T.GetMethod("op_Addition", new Type[] {exp1T,exp2T}) ;
				if (overload1 != null && overload2 != null)
					throw new AALCompilingErrorException(
						string.Format("Ambiguous call: operator '+' reciving [{0},{1}]", exp1T, exp2T)) ;
				if (overload1 != null)
					node = new BinaryOperatorNode(overload = overload1) ;
				else if (overload2 != null)
					node = new BinaryOperatorNode(overload = overload2) ;
				else
					throw new AALCompilingErrorException(
						string.Format("Type missmach: Cannot find an overload for '+' reciving [{0},{1}] or found one with non bool return type", exp1T, exp2T)) ;
			}
			left["type"] = overload == null ? typeof(int) : overload.ReturnType ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void Minus(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{	
			// [expression] --> [expression] - [term]
			NonTerminalSymbol expression = (NonTerminalSymbol)right[0],
				term = (NonTerminalSymbol) right[2] ;
			GeneratorNode node ;
			System.Type exp1T = (System.Type)expression["type"],
				exp2T = (System.Type)term["type"] ;
			MethodInfo overload = null ;
			if (exp1T == typeof(int) &&  exp2T == typeof(int))
				node = new MinusNode() ;
			else
			{
				MethodInfo overload1 = exp1T.GetMethod("op_Subtraction", new Type[] {exp1T,exp2T}),
					overload2 = exp2T.GetMethod("op_Subtraction", new Type[] {exp1T,exp2T}) ;
				if (overload1 != null && overload2 != null)
					throw new AALCompilingErrorException(
						string.Format("Ambiguous call: operator '-' reciving [{0},{1}]", exp1T, exp2T)) ;
				if (overload1 != null)
					node = new BinaryOperatorNode(overload = overload1) ;
				else if (overload2 != null)
					node = new BinaryOperatorNode(overload = overload2) ;
				else
					throw new AALCompilingErrorException(
						string.Format("Type missmach: Cannot find an overload for '-' reciving [{0},{1}] or found one with non bool return type", exp1T, exp2T)) ;
			}
			left["type"] = overload == null ? typeof(int) : overload.ReturnType ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void BitwiseOr(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [expression] --> [expression] | [term]
			NonTerminalSymbol expression = (NonTerminalSymbol)right[0],
				term = (NonTerminalSymbol) right[2] ;
			GeneratorNode node ;
			System.Type exp1T = (System.Type)expression["type"],
				exp2T = (System.Type)term["type"] ;
			MethodInfo overload = null ;
			if (exp1T != typeof(int) ||  exp2T != typeof(int))
				node = new I4OrNode() ;
			else
			{
				MethodInfo overload1 = exp1T.GetMethod("op_BitwiseOr", new Type[] {exp1T,exp2T}),
					overload2 = exp2T.GetMethod("op_BitwiseOr", new Type[] {exp1T,exp2T}) ;
				if (overload1 != null && overload2 != null)
					throw new AALCompilingErrorException(
						string.Format("Ambiguous call: operator '|' reciving [{0},{1}]", exp1T, exp2T)) ;
				if (overload1 != null)
					node = new BinaryOperatorNode(overload = overload1) ;
				else if (overload2 != null)
					node = new BinaryOperatorNode(overload = overload2) ;
				else
					throw new AALCompilingErrorException(
						string.Format("Type missmach: Cannot find an overload for '|' reciving [{0},{1}] or found one with non bool return type", exp1T, exp2T)) ;
			}
			left["type"] = overload == null ? typeof(int) : overload.ReturnType ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void Factor(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [term] --> [factor]
			NonTerminalSymbol factor = (NonTerminalSymbol) right[0] ;
			if (factor["type"] != null)
			{
				left["type"] = factor["type"] ;
//						Stack stack = (Stack)parameters["@@root@@"] ;
//						GeneratorNode node = new term0() ;
//						node[0] = (GeneratorNode)stack.Pop() ;
//						stack.Push(node) ;
			}
			else
			{
				left["undefined"] = factor["undefined"] ;
				left["full"] = factor["full"] ;
				factor["full"] = null ;
				left["type"] = null ;
			}
		}
		static public void Mult(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [factor] --> [term] * [factor]
			NonTerminalSymbol term = (NonTerminalSymbol) right[0],
				factor = (NonTerminalSymbol) right[2] ;
			GeneratorNode node ;
			System.Type exp1T = (System.Type)term["type"],
				exp2T = (System.Type)factor["type"] ;
			MethodInfo overload = null ;
			if (exp1T == typeof(int) &&  exp2T == typeof(int))
				node = new MultNode() ;
			else
			{
				MethodInfo overload1 = exp1T.GetMethod("op_Multiply", new Type[] {exp1T,exp2T}),
					overload2 = exp2T.GetMethod("op_Multiply", new Type[] {exp1T,exp2T}) ;
				if (overload1 != null && overload2 != null)
					throw new AALCompilingErrorException(
						string.Format("Ambiguous call: operator '*' reciving [{0},{1}]", exp1T, exp2T)) ;
				if (overload1 != null)
					node = new BinaryOperatorNode(overload = overload1) ;
				else if (overload2 != null)
					node = new BinaryOperatorNode(overload = overload2) ;
				else
					throw new AALCompilingErrorException(
						string.Format("Type missmach: Cannot find an overload for '*' reciving [{0},{1}] or found one with non bool return type", exp1T, exp2T)) ;
			}
			left["type"] = overload == null ? typeof(int) : overload.ReturnType ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void Div(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [factor] --> [term] / [factor]
			NonTerminalSymbol term = (NonTerminalSymbol) right[0],
				factor = (NonTerminalSymbol) right[2] ;
			GeneratorNode node ;
			System.Type exp1T = (System.Type)term["type"],
				exp2T = (System.Type)factor["type"] ;
			MethodInfo overload = null ;
			if (exp1T == typeof(int) &&  exp2T == typeof(int))
				node = new DivNode() ;
			else
			{
				MethodInfo overload1 = exp1T.GetMethod("op_Division", new Type[] {exp1T,exp2T}),
					overload2 = exp2T.GetMethod("op_Division", new Type[] {exp1T,exp2T}) ;
				if (overload1 != null && overload2 != null)
					throw new AALCompilingErrorException(
						string.Format("Ambiguous call: operator '/' reciving [{0},{1}]", exp1T, exp2T)) ;
				if (overload1 != null)
					node = new BinaryOperatorNode(overload = overload1) ;
				else if (overload2 != null)
					node = new BinaryOperatorNode(overload = overload2) ;
				else
					throw new AALCompilingErrorException(
						string.Format("Type missmach: Cannot find an overload for '/' reciving [{0},{1}] or found one with non bool return type", exp1T, exp2T)) ;
			}
			left["type"] = overload == null ? typeof(int) : overload.ReturnType ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void Mod(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [factor] --> [term] % [factor]
			NonTerminalSymbol term = (NonTerminalSymbol) right[0],
				factor = (NonTerminalSymbol) right[2] ;
			GeneratorNode node ;
			System.Type exp1T = (System.Type)term["type"],
				exp2T = (System.Type)factor["type"] ;
			MethodInfo overload = null ;
			if (exp1T == typeof(int) &&  exp2T == typeof(int))
				node = new ModNode() ;
			else
			{
				MethodInfo overload1 = exp1T.GetMethod("op_Modulus", new Type[] {exp1T,exp2T}),
					overload2 = exp2T.GetMethod("op_Modulus", new Type[] {exp1T,exp2T}) ;
				if (overload1 != null && overload2 != null)
					throw new AALCompilingErrorException(
						string.Format("Ambiguous call: operator '%' reciving [{0},{1}]", exp1T, exp2T)) ;
				if (overload1 != null)
					node = new BinaryOperatorNode(overload = overload1) ;
				else if (overload2 != null)
					node = new BinaryOperatorNode(overload = overload2) ;
				else
					throw new AALCompilingErrorException(
						string.Format("Type missmach: Cannot find an overload for '%' reciving [{0},{1}] or found one with non bool return type", exp1T, exp2T)) ;
			}
			left["type"] = overload == null ? typeof(int) : overload.ReturnType ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void BitwiseAnd(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [factor] --> [term] & [factor]
			NonTerminalSymbol term = (NonTerminalSymbol) right[0],
				factor = (NonTerminalSymbol) right[2] ;
			GeneratorNode node ;
			System.Type exp1T = (System.Type)term["type"],
				exp2T = (System.Type)factor["type"] ;
			MethodInfo overload = null ;
			if (exp1T == typeof(int) &&  exp2T == typeof(int))
				node = new I4AndNode() ;
			else
			{
				MethodInfo overload1 = exp1T.GetMethod("op_BitwiseAnd", new Type[] {exp1T,exp2T}),
					overload2 = exp2T.GetMethod("op_BitwiseAnd", new Type[] {exp1T,exp2T}) ;
				if (overload1 != null && overload2 != null)
					throw new AALCompilingErrorException(
						string.Format("Ambiguous call: operator '&' reciving [{0},{1}]", exp1T, exp2T)) ;
				if (overload1 != null)
					node = new BinaryOperatorNode(overload = overload1) ;
				else if (overload2 != null)
					node = new BinaryOperatorNode(overload = overload2) ;
				else
					throw new AALCompilingErrorException(
						string.Format("Type missmach: Cannot find an overload for '&' reciving [{0},{1}] or found one with non bool return type", exp1T, exp2T)) ;
			}
			left["type"] = overload == null ? typeof(int) : overload.ReturnType ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void Identifier(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// factor ::= identifier

			// Initializing
			TerminalSymbol identifier = (TerminalSymbol) right[0] ;
			object idInfo = parameters[identifier.Value] ;

			// Naming a Type. Constructing type name
			if (idInfo == null)
			{
				left["type"] = null ;
				left["full"] = identifier.Value ;
				left["undefined"] = identifier.Value ;
				return ;
			}

			Stack stack = (Stack)parameters["@@root@@"] ;
//					ExpressionNode node = new factor0(identifier.Value) ;
//					stack.Push(node) ;

			GeneratorNode node ;
			if (idInfo is object[])
			{
				object[] data = (object[]) idInfo ;
				left["type"] = data[0] as Type ;
				int offset = (int)data[1] ;
				node = new LocalIdNode(offset, idInfo as Type) ;
			} 
			else if (idInfo is ParameterInfo)
			{
				left["type"] = ((ParameterInfo)idInfo).ParameterType ;
				node = new ParameterNode(idInfo as ParameterInfo) ;
			}
			else if (idInfo is PropertyInfo)
			{
				PropertyInfo property = (PropertyInfo)idInfo ;
				left["type"] = property.PropertyType ;

                Type forced = (Type)parameters["@@forced.this.GetType()@@"];
                property = forced.GetProperty(property.Name);

                FieldInfo forcedTarget = (FieldInfo)parameters["@@forced.this@@"];

				node = new PropertyGetNode(property) ;
				node[0] = new TargetFieldLoadNode(forcedTarget) ;
			}
			else if (idInfo is FieldInfo)
			{
				FieldInfo field = ((FieldInfo)idInfo) ;
				left["type"] = field.FieldType ;
				node = new FieldLoadNode(field) ;
				if (field.IsStatic)
					node[0] = new StaticNode(field.ReflectedType) ;
				else
					node[0] = new TargetNode(field.ReflectedType) ;
			}
			else throw new Exception("Unreported error: 0001") ;
			stack.Push(node) ;
		}
		static public void ThisRef(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// <factor> ::= this
			left["type"] = (Type)parameters["@@this.GetType()@@"] ;
			MemberInfo target = (MemberInfo)parameters["@@member@@"] ;
			if (target is MethodInfo && ((MethodInfo)target).IsStatic)
				throw new AALCompilingErrorException("'this' can't be used on a static context") ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			stack.Push(new TargetNode((Type)parameters["@@this.GetType()@@"])) ;
		}
		static public void PreExpression(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [factor] --> [factor].Pre
			Stack stack = (Stack)parameters["@@root@@"] ;
			Type type =  (Type)(left["type"] = ((NonTerminalSymbol)right[0])["type"]) ;
			int offset = (int)parameters["@@locals@@"] ;
			parameters["@@locals@@"] = ((int)parameters["@@locals@@"]) + 1 ;
			GeneratorNode node = new InitPreNode(offset, type) ;
			node[0] = (GeneratorNode)stack.Pop() ;
			((ArrayList)parameters["@@Pre.List@@"]).Add(node) ;
			stack.Push(new LocalIdNode(offset, type)) ;
		}
		static public void Const(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			left["type"] = typeof(int) ;
			int cst = Int32.Parse(((TerminalSymbol)right[0]).Value) ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			stack.Push(new I4ConstNode(cst)) ;
		}
		static public void Contained(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [factor] --> ( [expression] )
			NonTerminalSymbol expression = (NonTerminalSymbol)right[1] ;
			left["type"] = expression["type"] ;
			if (left["type"] == null)
				throw new AALCompilingErrorException("Unknown identifier: " + expression["undefined"]) ;
//					Stack stack = (Stack)parameters["@@root@@"] ;
//					ExpressionNode node = new factor2() ;
//					node[0] = (ExpressionNode)stack.Pop() ;
//					stack.Push(node) ;
		}
		static public void BitwiseNot(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [factor] --> ~ [factor]
			NonTerminalSymbol expression = (NonTerminalSymbol)right[1] ;
			if (expression["type"] != typeof(int))
				throw new AALCompilingErrorException("Type missmatch!!!") ;
			left["type"] = typeof(int) ;				
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node = new I4NotNode() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void Negative(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [factor] --> - [factor]
			NonTerminalSymbol expression = (NonTerminalSymbol)right[1] ;
			if (expression["type"] != typeof(int))
				throw new AALCompilingErrorException("Type missmatch!!!") ;
			left["type"] = typeof(int) ;				
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node = new I4NegativeNode() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void Positive(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [factor] --> - [factor]
			NonTerminalSymbol expression = (NonTerminalSymbol)right[1] ;
			if (expression["type"] != typeof(int))
				throw new AALCompilingErrorException("Type missmatch!!!") ;
			left["type"] = typeof(int) ;				
		}
		static public void FactorIsBool(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			left["type"] = typeof(bool) ;
		}
		static public void Cast(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [factor] --> ( [type] ) [expression]
			NonTerminalSymbol typeS = (NonTerminalSymbol)right[1],
				expression = (NonTerminalSymbol)right[3] ;
			System.Type type = ResolveType((string)typeS["name"]) ;
			if (type == null)
				throw new AALCompilingErrorException("Unresolved type: " + typeS["name"]) ;
			if (!((System.Type)expression["type"]).IsAssignableFrom(type))
				throw new AALCompilingErrorException("�nvalid cast: " +
					expression["type"] + " as " + type);
			left["type"] = type ;				
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node = new CastNode(type) ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}

		static public void ForallCuantified(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			left["type"] = typeof(bool) ;				
			Stack stack = (Stack)parameters["@@root@@"] ;
//					ExpressionNode node = new factor6() ;
//					node[0] = (ExpressionNode)stack.Pop() ;
//					stack.Push(node) ;
		}
		static public void ExistsCuantified(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			left["type"] = typeof(bool) ;
			Stack stack = (Stack)parameters["@@root@@"] ;
//					ExpressionNode node = new factor6() ;
//					node[0] = (ExpressionNode)stack.Pop() ;
//					stack.Push(node) ;
		}
		static public void IndexedExpression(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [factor] --> [expression] [ [param] ]
			NonTerminalSymbol expression = (NonTerminalSymbol) right[0] ;
			NonTerminalSymbol param = (NonTerminalSymbol)right[2] ;
			System.Type arrType = ((System.Type)expression["type"]);
			if (arrType == null)
				throw new AALCompilingErrorException("Unknown Identifier: " + expression["undefined"]) ;
			System.Type[] types = (System.Type[])((ArrayList)param["types"]).
				ToArray(typeof(System.Type)) ;
			GeneratorNode node ;
			PropertyInfo item ;
			if ((item = arrType.GetProperty("Item",types)) != null)
			{
				node = new IndexedExpNode(item.GetGetMethod()) ;
			}
			else
			{
				if (! arrType.IsArray)
					throw new AALCompilingErrorException("Undefined indexer used") ;
				foreach(System.Type t in types)
				{
					if (t != typeof(int))
						throw new AALCompilingErrorException("Type missmatch: array index must be int expression") ;
				}
			}
			Stack stack = (Stack)parameters["@@root@@"] ;
			node = new IndexedExpNode(arrType.GetMethod("Get")) ;
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void EmptyCreation(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [factor] --> new [type] ( [param] )
			NonTerminalSymbol typeS = (NonTerminalSymbol) right[1], 
				param = (NonTerminalSymbol)right[3] ;
			System.Type type = ResolveType((string)typeS["name"]) ;
			if (type == null)
				throw new AALCompilingErrorException("Unresolved type: " + typeS["name"]) ;
			ConstructorInfo ctor = type.GetConstructor(new Type[0]) ;
			if (ctor == null)
			{
				throw new AALCompilingErrorException("Not suitable constructor found to " + type) ;
			}
			left["type"] = type ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node = new ConstructionNode(ctor) ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void ParamCreation(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [factor] --> new [type] ( [param] )
			NonTerminalSymbol typeS = (NonTerminalSymbol) right[1], 
				param = (NonTerminalSymbol)right[3] ;
			System.Type type = ResolveType((string)typeS["name"]) ;
			if (type == null)
				throw new AALCompilingErrorException("Unresolved type: " + typeS["name"]) ;
			System.Type[] ptypes = (System.Type[])((ArrayList)param["types"]).
				ToArray(typeof(System.Type)) ;
			ConstructorInfo ctor = type.GetConstructor(ptypes) ;
			if (ctor == null)
			{
				throw new AALCompilingErrorException("Not suitable constructor found to " + type) ;
			}
			left["type"] = type ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node = new ConstructionNode(ctor) ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void NullFactor(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			left["type"] = typeof(object) ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node = new NullNode() ;
			stack.Push(node) ;
		}
		static public void Int32Type(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [type] --> int
			left["name"] = "System.Int32" ;
		}
		static public void StringType(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [type] --> string
			left["name"] = "System.String" ;
		}
		static public void ObjectType(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [type] --> object
			left["name"] = "System.Object" ;
		}
		static public void BooleanType(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [type] --> object
			left["name"] = "System.Boolean" ;
		}
		static public void Type(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			TerminalSymbol identifier = (TerminalSymbol)right[0] ;
			left["name"] = identifier.Value ;
		}
		static public void TypeDotted(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			NonTerminalSymbol typeS = (NonTerminalSymbol)right[0] ;
			TerminalSymbol identifier = (TerminalSymbol)right[2] ;
			left["name"] = typeS["name"] + "." + identifier.Value ;
		}
		static public void Property(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// <call> ::= <expression> . identifier

			// Initializing...
			NonTerminalSymbol expr = (NonTerminalSymbol) right[0] ;
			TerminalSymbol id = (TerminalSymbol) right[2] ;
			Type type = (Type)expr["type"] ;
			// Searching for static or intance public fields and properties named like id
			if (type != null)
			{
				GeneratorNode node = null ;
				MemberInfo[] member = type.GetMember(id.Value) ;
				if (member.Length == 0) // property or field.
					throw new AALCompilingErrorException("Undefined field or property: " + id.Value) ;
				if (member[0] is PropertyInfo)
				{
					type = ((PropertyInfo)member[0]).PropertyType ;
					node = new PropertyGetNode(member[0] as PropertyInfo) ;
				}
				else if (member[0] is FieldInfo)
				{
					type = ((FieldInfo)member[0]).FieldType ;
					node = new FieldLoadNode(member[0] as FieldInfo) ;
				}
				left ["type"] = type ;
				Stack stack = (Stack)parameters["@@root@@"] ;
				node[0] = (GeneratorNode)stack.Pop() ;
				stack.Push(node) ;
			}
			else // unknown identifier or type for static invoke.
			{
				left["full"] += expr["full"] + "." + id.Value ;
				left["type"] = null ;
				left["undefined"] = expr["undefined"] ;
			}
		}
		static public void CualifiedCall(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// <call> ::= <expression> . <method>

			// Initializing ...
			NonTerminalSymbol expr = (NonTerminalSymbol)right[0],
				methodS = (NonTerminalSymbol)right[2] ;
			System.Type type = (Type)expr["type"] ;
			// Searching for static or instance methods.
			MethodInfo method = type.GetMethod((string)methodS["name"],
				((ArrayList)methodS["types"]).ToArray(typeof(System.Type))as System.Type[]) ;
				if (method == null) 
				{
					string parametersStr = "" ;
					foreach(Type t in ((ArrayList)methodS["types"]))
					{
						parametersStr += ", " + t ;
					}
					parametersStr = parametersStr.Length > 0 ? parametersStr.Substring(2) : "" ;
					throw new AALCompilingErrorException(string.Format("Undefined method: {0}({1}) in {2}",
						((string)methodS["name"]),parametersStr,type)) ;
				}
			if (method.ReturnType == typeof(void))
				throw new AALCompilingErrorException("Type missmatch: " + (string)methodS["name"] + " is Void") ;
			left["type"] = method.ReturnType ;
			// Evaluation tree construction
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node = new MethodCallNode(method) ;
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void SelfCall(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			NonTerminalSymbol methodS = (NonTerminalSymbol)right[0] ;
			MethodInfo method = ((Type)parameters["@@forced.this.GetType()@@"]).
				GetMethod(((string)methodS["name"]),
				((ArrayList)methodS["types"]).ToArray(typeof(System.Type)) 
				as System.Type[]) ;
            FieldInfo field = (FieldInfo)parameters["@@forced.this@@"] ;
			if (method == null) 
			{
				string parametersStr = "" ;
				foreach(Type t in ((ArrayList)methodS["types"]))
				{
					parametersStr += ", " + t ;
				}
				parametersStr = parametersStr.Length > 0 ? parametersStr.Substring(2) : "" ;
				throw new AALCompilingErrorException(
					string.Format("Undefined method: {0}({1}) in {2}",methodS["name"],parametersStr,parameters["@@this@@"])) ;
			}
			if (method.ReturnType == typeof(void))
				throw new AALCompilingErrorException("Type missmatch: " + (string)methodS["name"] + " is Void") ;
			left["type"] = method.ReturnType ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node = new MethodCallNode(method) ;
            node[0] = new TargetFieldLoadNode(field);
			//node[0] = new TargetNode(method.ReflectedType) ;
			node[1] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void NoParamMethod(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			TerminalSymbol id = (TerminalSymbol) right[0] ;
			left["name"] = id.Value ;
			left["types"] = new ArrayList() ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node = new NoParamNode() ;
			stack.Push(node) ;
		}
		static public void ParamMethod(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			TerminalSymbol id = (TerminalSymbol) right[0] ;
			NonTerminalSymbol param = (NonTerminalSymbol)right[2] ;
			left["name"] = id.Value ;
			left["types"] = param["types"] ;
//					Stack stack = (Stack)parameters["@@root@@"] ;
//					GeneratorNode node = new ParamNode(id.Value) ;
//					node[0] = (ExpressionNode)stack.Pop() ;
//					stack.Push(node) ;
		}
		static public void FirstParam(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			NonTerminalSymbol expr = (NonTerminalSymbol)right[0] ;
			if (expr["type"] == null)
				throw new AALCompilingErrorException("Unknown identifier: " + expr["undefined"]) ;
			left["types"] = new ArrayList() ;
			((ArrayList)left["types"]).Add(expr["type"]) ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node = new FirstParamNode(expr["type"] as Type) ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void Parameter(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			NonTerminalSymbol param = (NonTerminalSymbol)right[0],
				expr = (NonTerminalSymbol)right[2] ;
			if (expr["type"] == null)
				throw new AALCompilingErrorException("Unknown identifier: " + expr["undefined"]) ;
			((ArrayList)param["types"]).Add(expr["type"]) ;
			left["types"] = param["types"] ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node = new ParamNode(expr["type"] as Type) ;
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void Forall(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [forallExp] --> forall ( [varDecl] : [ALExpression] )
			NonTerminalSymbol varDecl = (NonTerminalSymbol)right[2] ;
			parameters[varDecl["@@undefine@@"]] = null ;
			string var = (string)varDecl["@@undefine@@"] ;
			varDecl["@@undefine@@"] = null ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			int locals = (int)parameters["@@locals@@"] ;
			parameters["@@locals@@"] = locals + 1 ;
			GeneratorNode node = new ForallNode(locals,(int)varDecl["local"], varDecl["type"] as Type) ;
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void Exists(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			// [existExp] --> exist ( [varDecl] : [ALExpression] )
			NonTerminalSymbol varDecl = (NonTerminalSymbol)right[2] ;
			parameters[varDecl["@@undefine@@"]] = null ;
			string var = (string)varDecl["@@undefine@@"] ;
			varDecl["@@undefine@@"] = null ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			int locals = (int)parameters["@@locals@@"] ;
			parameters["@@locals@@"] = locals + 1 ;
			GeneratorNode node = new ExistsNode(locals,(int)varDecl["local"], varDecl["type"] as Type) ;
			node[1] = (GeneratorNode)stack.Pop() ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public void Declaration(NonTerminalSymbol left, Symbol[] right, IDictionary parameters)
		{
			System.Type eT = typeof(IEnumerable) ;
			NonTerminalSymbol expr = (NonTerminalSymbol)right[3],
				typeS = (NonTerminalSymbol)right[0] ;
			if (expr["type"] == null)
				throw new AALCompilingErrorException("Unknown identifier: " + expr["undefined"]) ;
			TerminalSymbol id = (TerminalSymbol)right[1] ;
			System.Type idtype = ResolveType((string)typeS["name"]) ;
			if (idtype == null)
				throw new AALCompilingErrorException("Unresolved type: " + 
					(string)typeS["name"]) ;
			if (!eT.IsAssignableFrom((Type)expr["type"]))
				throw new AALCompilingErrorException("Type missmatch: expression in variable declaration must be IEnumerable") ;
			if (parameters[id.Value] != null)
				throw new AALCompilingErrorException("Duplicated identifier: " + id.Value) ;
			left["@@undefine@@"] = id.Value ;
			int locals = (int)parameters["@@locals@@"] ;
			parameters[id.Value] = new object[] {idtype, locals} ;
			left["type"] = idtype ;
			left["local"] = locals ;
			parameters["@@locals@@"] =  locals + 1 ;
			Stack stack = (Stack)parameters["@@root@@"] ;
			GeneratorNode node = new VarDeclNode(locals, idtype) ;
			node[0] = (GeneratorNode)stack.Pop() ;
			stack.Push(node) ;
		}
		static public Type ResolveType(string typeName)
		{
//			if (DefinedTypes.Contains(typeName))
//				return (Type)DefinedTypes[typeName] ;
			foreach(Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
			{
				Type result = asm.GetType(typeName) ;
				if (result != null)
					return result ;
			}
			return null ;
		}
		static public void CheckType(Symbol symbol)
		{
			NonTerminalSymbol nt = (NonTerminalSymbol)symbol ;
			if (nt["type"] == null)
				throw new AALCompilingErrorException("Undefined identifier: " + nt["undefined"]) ;
		}
	}
	
	namespace Runtime
	{
		internal abstract class GeneratorNode : IEnumerable
		{
			GeneratorNode[] children ;
			Type returnType ;
			public GeneratorNode(int length, Type returnType)
			{
				this.returnType = returnType ;
				children = new GeneratorNode[length] ;
			}
			public GeneratorNode(int length, Type returnType, Stack children) : this(length, returnType)
			{
				for(int index = Length - 1; index >= 0; index --)
					this[index] = (GeneratorNode)children.Pop() ;
			}
			public GeneratorNode this[int index]
			{
				set
				{
					children[index] = value ;
				}
				get
				{
					return children[index] ;
				}
			}
			public IEnumerator GetEnumerator()
			{
				return children.GetEnumerator() ;
			}
			public abstract void Emit(ILGenerator generator, ArrayList locals) ;
			public int Length
			{
				get
				{
					return children.Length ;
				}
			}
			public Type ExpType
			{
				get
				{
					return returnType ;
				}
				set
				{
					returnType = value ;
				}
			}
		}
		internal class ImpliesNode : GeneratorNode
		{
			public ImpliesNode() : base(2, typeof(bool))
			{
			
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				generator.Emit(OpCodes.Not) ;
				generator.Emit(OpCodes.Ldc_I4_2) ;
				generator.Emit(OpCodes.Rem) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.Or) ;
			}
		}
		internal class DoubleImpliesNode : GeneratorNode
		{
			int locals ;
			public DoubleImpliesNode(int locals) : base(2, typeof(bool))
			{
				this.locals = locals ;
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				LocalBuilder pr1 = generator.DeclareLocal(typeof(bool)),
					pr2 = generator.DeclareLocal(typeof(bool)) ;
				locals.Add(pr1) ;
				locals.Add(pr2) ;
				this[0].Emit(generator, locals) ;
				generator.Emit(OpCodes.Stloc, pr1) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.Stloc, pr2) ;

				generator.Emit(OpCodes.Ldloc, pr1) ;
				generator.Emit(OpCodes.Not) ;
				generator.Emit(OpCodes.Ldc_I4_2) ;
				generator.Emit(OpCodes.Rem) ;
				generator.Emit(OpCodes.Ldloc, pr2) ;
				generator.Emit(OpCodes.Or) ;
				generator.Emit(OpCodes.Ldloc, pr2) ;
				generator.Emit(OpCodes.Not) ;
				generator.Emit(OpCodes.Ldc_I4_2) ;
				generator.Emit(OpCodes.Rem) ;
				generator.Emit(OpCodes.Ldloc, pr1) ;
				generator.Emit(OpCodes.Or) ;
				generator.Emit(OpCodes.And) ;
			}
		}
		internal abstract class OrNode : GeneratorNode
		{
			public OrNode(Type returnType) : base(2,returnType) 
			{
			
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.Or) ;
			}
		}
		internal class BoolOrNode : OrNode
		{
			public BoolOrNode() : base(typeof(bool))
			{
			
			}
		}
		internal class I4OrNode : OrNode
		{
			public I4OrNode() : base(typeof(int))
			{
			
			}
		}
		internal abstract class AndNode : GeneratorNode
		{
			public AndNode(Type returnType) : base(2,returnType) 
			{
				
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.And) ;
			}
		}
		internal class BoolAndNode : AndNode
		{
			public BoolAndNode() : base(typeof(bool))
			{
			
			}
		}
		internal class I4AndNode : AndNode
		{
			public I4AndNode() : base(typeof(int))
			{
			
			}
		}
		internal abstract class NotNode : GeneratorNode
		{	
			public NotNode(Type returnType) : base(1,returnType) 
			{
					
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				generator.Emit(OpCodes.Not) ;
			}	
		}
		internal class BoolNotNode : NotNode
		{
			public BoolNotNode() : base(typeof(bool))
			{
			
			}	
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				base.Emit(generator, locals) ;
				generator.Emit(OpCodes.Ldc_I4_2) ;
				generator.Emit(OpCodes.Rem) ;
			}
		}
		internal class I4NotNode : NotNode
		{
			public I4NotNode() : base(typeof(int))
			{
			
			}
		}
		
		internal class BinaryOperatorNode : GeneratorNode
		{
			MethodInfo binOperator ;
			public BinaryOperatorNode(MethodInfo binOperator) : base(2, binOperator.ReturnType) 
			{
				this.binOperator = binOperator ;			
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				if (binOperator.IsStatic)
//					typeof(System.ValueType).IsAssignableFrom(binOperator.ReflectedType))
					generator.Emit(OpCodes.Call, binOperator) ;
				else
					generator.Emit(OpCodes.Callvirt, binOperator) ;
			}
		}
		internal class UnaryOperatorNode : GeneratorNode
		{
			MethodInfo unaryOperator ;
			public UnaryOperatorNode(MethodInfo unaryOperator) : base(1, unaryOperator.ReturnType) 
			{
				this.unaryOperator = unaryOperator ;			
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				if (typeof(System.ValueType).IsAssignableFrom(unaryOperator.ReflectedType))
					generator.Emit(OpCodes.Call, unaryOperator) ;
				else
					generator.Emit(OpCodes.Callvirt, unaryOperator) ;
			}
		}
		internal class LessThanNode : GeneratorNode
		{	
			public LessThanNode() : base(2, typeof(bool)) 
			{
							
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				Label trueLabel = generator.DefineLabel(),
					falseLabel = generator.DefineLabel(),
					endLabel = generator.DefineLabel() ;					

				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.Blt, trueLabel) ;
				generator.Emit(OpCodes.Br, falseLabel) ;
				generator.MarkLabel(trueLabel) ;
				generator.Emit(OpCodes.Ldc_I4_1) ;
				generator.Emit(OpCodes.Br, endLabel) ;
				generator.MarkLabel(falseLabel) ;
				generator.Emit(OpCodes.Ldc_I4_0) ;
				generator.MarkLabel(endLabel) ;
			}	
		}
		internal class LessOrEqualNode : GeneratorNode
		{	
			public LessOrEqualNode() : base(2, typeof(bool)) 
			{
							
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				Label trueLabel = generator.DefineLabel(),
					falseLabel = generator.DefineLabel(),
					endLabel = generator.DefineLabel() ;					

				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.Ble, trueLabel) ;
				generator.Emit(OpCodes.Br, falseLabel) ;
				generator.MarkLabel(trueLabel) ;
				generator.Emit(OpCodes.Ldc_I4_1) ;
				generator.Emit(OpCodes.Br, endLabel) ;
				generator.MarkLabel(falseLabel) ;
				generator.Emit(OpCodes.Ldc_I4_0) ;
				generator.MarkLabel(endLabel) ;
			}	
		}
		
		internal class GreaterThanNode : GeneratorNode
		{	
			public GreaterThanNode() : base(2, typeof(bool)) 
			{
							
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				Label trueLabel = generator.DefineLabel(),
					falseLabel = generator.DefineLabel(),
					endLabel = generator.DefineLabel() ;					

				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.Bgt, trueLabel) ;
				generator.Emit(OpCodes.Br, falseLabel) ;
				generator.MarkLabel(trueLabel) ;
				generator.Emit(OpCodes.Ldc_I4_1) ;
				generator.Emit(OpCodes.Br, endLabel) ;
				generator.MarkLabel(falseLabel) ;
				generator.Emit(OpCodes.Ldc_I4_0) ;
				generator.MarkLabel(endLabel) ;
			}	
		}

		internal class GreaterOrEqualNode : GeneratorNode
		{	
			public GreaterOrEqualNode() : base(2, typeof(bool)) 
			{
							
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				Label trueLabel = generator.DefineLabel(),
					falseLabel = generator.DefineLabel(),
					endLabel = generator.DefineLabel() ;					

				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.Bge, trueLabel) ;
				generator.Emit(OpCodes.Br, falseLabel) ;
				generator.MarkLabel(trueLabel) ;
				generator.Emit(OpCodes.Ldc_I4_1) ;
				generator.Emit(OpCodes.Br, endLabel) ;
				generator.MarkLabel(falseLabel) ;
				generator.Emit(OpCodes.Ldc_I4_0) ;
				generator.MarkLabel(endLabel) ;
			}	
		}

		internal class EqualNode : GeneratorNode
		{	
			public EqualNode() : base(2, typeof(bool)) 
			{
							
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.Ceq) ;
			}	
		}
		internal class NotEqualNode : GeneratorNode
		{	
			public NotEqualNode() : base(2, typeof(bool)) 
			{
							
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.Ceq) ;
				generator.Emit(OpCodes.Not) ;
				generator.Emit(OpCodes.Ldc_I4_2) ;
				generator.Emit(OpCodes.Rem) ;
			}	
		}
		internal class IsNode : GeneratorNode
		{
			Type type ;
			public IsNode(Type type) : base(1, typeof(bool)) 
			{
				this.type = type ;
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				generator.Emit(OpCodes.Isinst, type) ;
			}				
		}
		internal class TrueNode : GeneratorNode
		{
			public TrueNode() : base(0, typeof(bool))
			{
				
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				generator.Emit(OpCodes.Ldc_I4_1) ;
			}
		}
		internal class FalseNode : GeneratorNode
		{
			public FalseNode() : base(0, typeof(bool))
			{
			
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				generator.Emit(OpCodes.Ldc_I4_0) ;
			}
		}
		internal class PlusNode : GeneratorNode
		{	
			public PlusNode() : base(2, typeof(int)) 
			{
							
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.Add) ;
			}	
		}
		internal class MinusNode : GeneratorNode
		{	
			public MinusNode() : base(2, typeof(int)) 
			{
							
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.Sub) ;
			}	
		}
		internal class MultNode : GeneratorNode
		{	
			public MultNode() : base(2, typeof(int)) 
			{
							
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.Mul) ;
			}	
		}
		internal class DivNode : GeneratorNode
		{	
			public DivNode() : base(2, typeof(int)) 
			{
							
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.Div) ;
			}	
		}
		internal class ModNode : GeneratorNode
		{	
			public ModNode() : base(2, typeof(int)) 
			{
							
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.Rem) ;
			}	
		}
		internal class ParameterNode : GeneratorNode
		{
			ParameterInfo param ;
			public ParameterNode(ParameterInfo param) : base(0, param.ParameterType) 
			{
				this.param = param ;
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
//				int offset = 0 ;
//				if (!(param.Member is MethodBase && ((MethodBase)param.Member).IsStatic))
//					offset = 1 ;
                EmitHelper.LdArg(generator, param);
			}	
		
		}
		internal class ThisNode : GeneratorNode
		{
			public ThisNode(Type thisType) : base(0, thisType)
			{
			
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				generator.Emit(OpCodes.Ldarg_0) ;
			}
		}
		internal class TargetNode : GeneratorNode
		{
			public TargetNode(Type thisType) : base(0, thisType)
			{
			
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				generator.Emit(OpCodes.Ldarg_0) ;
				if (typeof(System.ValueType).IsAssignableFrom(ExpType))
					generator.Emit(OpCodes.Box, ExpType) ;
				// ScaredFinger Modified on July 03, 2004
//				generator.Emit(OpCodes.Callvirt, getTarget) ;
//				generator.Emit(OpCodes.Castclass, ExpType) ;
			}
		}
		internal class LocalIdNode : GeneratorNode
		{
			int offset ;
			public LocalIdNode(int offset, Type returnType) : base(0, returnType)
			{
				this.offset = offset ;
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				if (offset == 0)
					generator.Emit(OpCodes.Ldloc_0) ;
				else
					generator.Emit(OpCodes.Ldloc, (LocalBuilder)locals[offset]) ;
			}	
		
		}
		internal class InitPreNode : GeneratorNode
		{
			int local ;
			public InitPreNode(int local, Type returnType) : base(1, returnType)
			{
				this.local = local ;
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				LocalBuilder localId = generator.DeclareLocal(this.ExpType) ;
				locals.Add(localId) ;
				this[0].Emit(generator, locals) ;
				if (typeof(System.ICloneable).IsAssignableFrom(localId.LocalType))
					generator.Emit(OpCodes.Callvirt, typeof(System.ICloneable).GetMethod("Clone", new Type[0])) ;
				generator.Emit(OpCodes.Stloc, localId) ;
			}
		}
		internal class I4ConstNode : GeneratorNode
		{
			int value ;
			public I4ConstNode(int value) : base(0, typeof(int))
			{
				this.value = value ;
			}

			
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				generator.Emit(OpCodes.Ldc_I4, value) ;
			}	
		
		}
		internal class I4NegativeNode : GeneratorNode
		{
			public I4NegativeNode() : base(1, typeof(int))
			{
			
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				generator.Emit(OpCodes.Neg) ;
			}
		}
		internal class I4PositiveNode : GeneratorNode
		 {
			 public I4PositiveNode() : base(1, typeof(int))
			 {
			
			 }


			 public override void Emit(ILGenerator generator, ArrayList locals)
			 {
				 this[0].Emit(generator, locals) ;
			 }
		 }
		internal class CastNode : GeneratorNode
		{
			Type type ;
			public CastNode(Type type) : base(1,type)
			{
				this.type = type ;
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				if (typeof(System.ValueType).IsAssignableFrom(type))
					generator.Emit(OpCodes.Unbox) ;
				else
					generator.Emit(OpCodes.Castclass, type) ;
			}
		}
		internal class SingleIndexArrayNode : GeneratorNode
		{
			public SingleIndexArrayNode(Type arrayType) : base(2, arrayType)
			{
			
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				if (typeof(System.ValueType).IsAssignableFrom(ExpType))
				{
					generator.Emit(OpCodes.Ldelema) ;
					generator.Emit(OpCodes.Ldobj) ;
				}
				else
					generator.Emit(OpCodes.Ldelem_Ref) ;
			}
		}
		internal class MultiIndexArrayNode : GeneratorNode
		{
			public MultiIndexArrayNode(Type arrayType) : base(2, arrayType)
			{
			
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.Callvirt, this[0].ExpType.GetMethod("Get")) ;
			}
		}
		internal class IndexedExpNode : GeneratorNode
		{
			MethodInfo indexer ;
			public IndexedExpNode(MethodInfo indexer) : base(2, indexer.ReturnType)
			{
				this.indexer = indexer ;
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.Callvirt, indexer) ;
			}
		}
		internal class ConstructionNode : GeneratorNode
		{
			ConstructorInfo ctor ;
			public ConstructionNode(ConstructorInfo ctor)  : base(1, ctor.ReflectedType)
			{
				this.ctor = ctor ;
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				generator.Emit(OpCodes.Newobj, ctor) ;
			}
		}
		internal class NullNode : GeneratorNode
		{
			public NullNode() : base(0, typeof(object))
			{
			
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				generator.Emit(OpCodes.Ldnull) ;
			}
		}
		internal class PropertyGetNode : GeneratorNode
		{
			PropertyInfo property ;

			public PropertyGetNode(PropertyInfo property) : base(1, property.PropertyType)
			{
				this.property = property ;
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				if (typeof(System.ValueType).IsAssignableFrom(this[0].ExpType))
					generator.Emit(OpCodes.Box, this[0].ExpType) ;
				generator.Emit(OpCodes.Callvirt, property.GetGetMethod()) ;
			}
		}
		internal class FieldLoadNode : GeneratorNode
		{
			FieldInfo field ;
			public FieldLoadNode(FieldInfo field) : base(1, field.FieldType)
			{
				this.field = field ;
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				if (field.IsStatic)
					generator.Emit(OpCodes.Ldsfld, field) ;
				else
					generator.Emit(OpCodes.Ldfld, field) ;
			}
		}
        internal class TargetFieldLoadNode : GeneratorNode
        { 
			FieldInfo field ;
            public TargetFieldLoadNode(FieldInfo field)
                : base(0, field.FieldType)
			{
				this.field = field ;
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
                generator.Emit(OpCodes.Ldarg_0);
				if (field.FieldType.IsValueType)
					generator.Emit(OpCodes.Ldflda, field) ;
				else
					generator.Emit(OpCodes.Ldfld, field) ;
			}        
        }
		internal class MethodCallNode : GeneratorNode
		{
			MethodInfo method ;
			public MethodCallNode(MethodInfo method) : base(2, method.ReturnType)
			{
				this.method = method ;
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				if (!method.IsStatic)
					this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				if (typeof(System.ValueType).IsAssignableFrom(this[0].ExpType) ||	method.IsStatic)
					generator.Emit(OpCodes.Call, method) ;
				else
					generator.Emit(OpCodes.Callvirt, method) ;
			}
		}
		internal class FirstParamNode : GeneratorNode
		{
			public FirstParamNode(Type parameter)  : base(1, parameter)
			{
			
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				if (! ExpType.IsSubclassOf(typeof(System.ValueType)) &&
					typeof(System.ValueType).IsAssignableFrom(this[0].ExpType))
					generator.Emit(OpCodes.Box, this[0].ExpType) ;
			}
		}
		internal class ParamNode : GeneratorNode
		{
			public ParamNode(Type parameter) : base(2, parameter)
			{
			
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				if (! ExpType.IsSubclassOf(typeof(System.ValueType)) &&
					typeof(System.ValueType).IsAssignableFrom(this[0].ExpType))
					generator.Emit(OpCodes.Box, this[0].ExpType) ;
				this[1].Emit(generator, locals) ;
			}
		}
		internal class NoParamNode : GeneratorNode
		{
			public NoParamNode() : base(1, typeof(void))
			{
			
			}

		
			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				
			}
		}
		internal class ForallNode : GeneratorNode
		{
			int iterator ;
			int local ;
			Type type ;
			public ForallNode(int iterator, int local, Type type) : base(2, typeof(bool))
			{
				this.iterator = iterator ;
				this.local = local ;
				this.type = type ;			
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				LocalBuilder iterator = generator.DeclareLocal(typeof(IEnumerator)) ;
				locals.Add(iterator) ;
				Label StartIterator = generator.DefineLabel(),
					DefaultReturn = generator.DefineLabel(),
					ReturnFalse = generator.DefineLabel(),
					Return = generator.DefineLabel() ;
				generator.Emit(OpCodes.Callvirt, typeof(IEnumerable).GetMethod("GetEnumerator")) ;
				generator.Emit(OpCodes.Stloc, iterator) ;		//				stloc iterator ;
				generator.MarkLabel(StartIterator) ;		// StartIterator :
				generator.Emit(OpCodes.Ldloc,iterator) ;	//					ldloc iterator ;
				generator.Emit(OpCodes.Callvirt,					//			callvirt IEnumerable::MoveNext(void) ;
					typeof(IEnumerator).GetMethod("MoveNext")) ;
				generator.Emit(OpCodes.Brfalse, DefaultReturn) ;//				brfalse DefaultReturn ;
				generator.Emit(OpCodes.Ldloc, iterator) ;
				generator.Emit(OpCodes.Callvirt, //								callvirt IEnumerable::get_Current(void) ;
					typeof(IEnumerator).GetProperty("Current").GetGetMethod()) ;
				if (type != typeof(object))
				{
					if (typeof(System.ValueType).IsAssignableFrom(type))
						generator.Emit(OpCodes.Unbox, type) ;
					else
						generator.Emit(OpCodes.Castclass, type) ;
				}
				generator.Emit(OpCodes.Stloc, (LocalBuilder)locals[local]) ;//	stloc local ;
				this[1].Emit(generator, locals) ;//								[ALExpression] Code
				generator.Emit(OpCodes.Brfalse, ReturnFalse) ;//				brfalse ReturnFalse ;
				generator.Emit(OpCodes.Br, StartIterator) ;//					br StartIterator ;
				generator.MarkLabel(ReturnFalse) ;//			ReturnFalse :
				generator.Emit(OpCodes.Ldc_I4_0) ;//							ld.I4.0 ; false
				generator.Emit(OpCodes.Br, Return) ;//						br.s Return ;
				generator.MarkLabel(DefaultReturn) ;//			DefaultReturn :
				generator.Emit(OpCodes.Ldc_I4_1) ;//							ld.I4.1 ; true
				generator.MarkLabel(Return) ;				//			Return:
			}
		}
		internal class ExistsNode : GeneratorNode
		{
			int iterator ;
			int local ;
			Type type ;
			public ExistsNode(int iterator, int local, Type type) : base(2, typeof(bool))
			{
				this.iterator = iterator ;
				this.local = local ;
				this.type = type ;
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				LocalBuilder iterator = generator.DeclareLocal(typeof(IEnumerator)) ;
				locals.Add(iterator) ;
				Label StartIterator = generator.DefineLabel(),
					DefaultReturn = generator.DefineLabel(),
					ReturnTrue = generator.DefineLabel(),
					Return = generator.DefineLabel() ;
				generator.Emit(OpCodes.Castclass, typeof(IEnumerable)) ;
				generator.Emit(OpCodes.Callvirt, typeof(IEnumerable).GetMethod("GetEnumerator")) ;
				generator.Emit(OpCodes.Stloc, iterator) ;		//				stloc iterator ;
				generator.MarkLabel(StartIterator) ;		// StartIterator :
				generator.Emit(OpCodes.Ldloc,iterator) ;	//					ldloc iterator ;
				generator.Emit(OpCodes.Callvirt,					//			callvirt IEnumerable::MoveNext(void) ;
					typeof(IEnumerator).GetMethod("MoveNext")) ;
				generator.Emit(OpCodes.Brfalse, DefaultReturn) ;//				brfalse DefaultReturn ;
				generator.Emit(OpCodes.Ldloc, iterator) ;
				generator.Emit(OpCodes.Callvirt, //								callvirt IEnumerable::get_Current(void) ;
					typeof(IEnumerator).GetProperty("Current").GetGetMethod()) ;
				if (typeof(System.ValueType).IsAssignableFrom(type))
					generator.Emit(OpCodes.Unbox) ;
				generator.Emit(OpCodes.Stloc, (LocalBuilder)locals[local]) ;//	stloc local ;
				this[1].Emit(generator, locals) ;//								[ALExpression] Code
				generator.Emit(OpCodes.Brtrue, ReturnTrue) ;//					brtrue ReturnTrue ;
				generator.Emit(OpCodes.Br, StartIterator) ;//					br StartIterator ;
				generator.MarkLabel(ReturnTrue) ;//				ReturnTrue :
				generator.Emit(OpCodes.Ldc_I4_1) ;//							ld.I4.0 ; false
				generator.Emit(OpCodes.Br, Return) ;//						br.s Return ;
				generator.MarkLabel(DefaultReturn) ;//			DefaultReturn :
				generator.Emit(OpCodes.Ldc_I4_0) ;//							ld.I4.1 ; true
				generator.MarkLabel(Return) ; //				Return :
			}
		
		}
		internal class VarDeclNode : GeneratorNode
		{
			int local ;
			Type type ;
			public VarDeclNode(int local, Type type) : base(1, typeof(void))
			{
				this.local = local ;
				this.type = type ;
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				LocalBuilder localVar = generator.DeclareLocal(type) ;
				locals.Add(localVar) ;
				this[0].Emit(generator, locals) ;
			}
		}
		internal class StaticNode : GeneratorNode
		{
			public StaticNode(Type type) : base(0, type)
			{
			
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
			
			}
		}
		internal class EqualsMethodNode : GeneratorNode
		{
			public EqualsMethodNode() : base(2, typeof(bool))
			{
			
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.Callvirt, typeof(object).GetMethod("Equals")) ;
			}
		}
		internal class NotEqualsMethodNode : GeneratorNode
		{
			public NotEqualsMethodNode() : base(2, typeof(bool))
			{
			
			}


			public override void Emit(ILGenerator generator, ArrayList locals)
			{
				this[0].Emit(generator, locals) ;
				this[1].Emit(generator, locals) ;
				generator.Emit(OpCodes.Callvirt, typeof(object).GetMethod("Equals")) ;
				generator.Emit(OpCodes.Not) ;
				generator.Emit(OpCodes.Ldc_I4_2) ;
				generator.Emit(OpCodes.Rem) ;
			}
		}
	}
	#region Proxy
//	public interface ITrustedType
//	{
//		object Target
//		{
//			get ;
//			set ;
//		}
//	}
//	[AttributeUsage(AttributeTargets.Assembly)]
//	public class TrustedAttribute : Attribute
//	{
//		string Asserted ;
//		internal static ConstructorInfo TrustedAttributeCtor = 
//			typeof(TrustedAttribute).GetConstructor(new Type[] {typeof(string)}) ;
//		public TrustedAttribute(string AssertedName)
//		{
//			this.Asserted = AssertedName ;
//		}
//		public string AssertedName
//		{
//			get
//			{
//				return Asserted ;
//			}
//		}
//	}
//	public class TrustedTypesTable 
//	{
//		struct TrustedPair
//		{
//			public bool Completed ;
//			public TypeBuilder TrustedType ;
//		}
//		Hashtable trustedTypes = new Hashtable() ;
//		public TypeBuilder this[Type index]
//		{
//			get
//			{
//				TrustedPair pair = (TrustedPair)trustedTypes[index.FullName] ;
//				return pair.TrustedType ;
//			}
//			set
//			{
//				if (value == null)
//					throw new ArgumentNullException() ;
//				TrustedPair pair ;
//				pair.Completed = false ;
//				pair.TrustedType = value ;
//				trustedTypes[index.FullName] = pair ;
//			}
//		}
//		public bool Contains(Type index)
//		{
//			return trustedTypes.Contains(index.FullName) ;
//		}
//		public bool IsCompleted(Type index)
//		{
//			TrustedPair pair = (TrustedPair)trustedTypes[index.FullName] ;
//			return pair.Completed ;
//		}
//		public void SetCompleted(Type index)
//		{
//			TrustedPair pair = (TrustedPair)trustedTypes[index.FullName] ;
//			pair.Completed = true ;
//		}
//	}
//	public class ProxyBuilder 
//	{
//		public const string ProxyPrefix = "Trusted." ;
//		public static PropertyInfo TargetProperty = typeof(ITrustedType).GetProperty("Target") ;
//		public static MethodInfo GetTarget = TargetProperty.GetGetMethod() ;
//		public static MethodInfo SetTarget = TargetProperty.GetSetMethod() ;
//
//		public event PercentIndicator TypePercentIndicator ;
//		public event PercentIndicator MemberPercentIndicator ;
//
//		MethodBuilder entryPoint = null ;
//		MethodInfo prototypeEntryPoint = null ;
//		string proxyFileName = null ;
//		AssertionManager manager ;
//		TrustedTypesTable trustedTypes = new TrustedTypesTable() ;
//		Hashtable TrustedTypes, DefinedTypes ;
//
//		public AssertionManager Manager
//		{
//			get
//			{
//				return manager ;
//			}
//			set
//			{
//				manager = value ;
//			}
//		}
//
//		
//		public ProxyBuilder() : this(new ChacalAssertionManager())
//		{
//		}
//
//		public ProxyBuilder(AssertionManager manager)
//		{
//			this.manager = manager ;
//		}
//
//
//		public static bool IsTrusted(Assembly assembly)
//		{
//			return  GetAssertedAssembly(assembly) != null ;
//		}
//		public void CreateProxy(Assembly assertedAssembly)
//		{
//			if (IsTrusted(assertedAssembly))
//				throw new ArgumentException("Can't create proxy on a Trusted assembly") ;
//			
//			TrustedTypes = new Hashtable() ;
//			AALExpression.DefinedTypes = DefinedTypes = new Hashtable() ;
//			int total = assertedAssembly.GetTypes().Length ;
//			int current = 0 ;
//			string location = assertedAssembly.Location ;
//			location = location.Substring(0, location.LastIndexOf("\\")) ;
//			// Output file name
//			proxyFileName = CreateProxyFileName(assertedAssembly) ;
//			// Output assembly name
//			AssemblyName proxyAsmName = CreateProxyName(assertedAssembly.GetName()) ;
//
//			// Keeping an eye on original entry point
//			prototypeEntryPoint = assertedAssembly.EntryPoint ;
//			// Creating proxy assembly builder
//			AssemblyBuilder proxyAsm = AppDomain.CurrentDomain.DefineDynamicAssembly(proxyAsmName, 
//				AssemblyBuilderAccess.Save, location) ;
//			CustomAttributeBuilder cattr = new CustomAttributeBuilder(TrustedAttribute.TrustedAttributeCtor, new object[] {assertedAssembly.GetName().Name}) ;
//			proxyAsm.SetCustomAttribute(cattr) ;
//			mod = proxyAsm.DefineDynamicModule(proxyFileName, true) ;
//			foreach(Type type in assertedAssembly.GetTypes())
//			{
//				DefinedTypes[type.FullName] = mod.DefineType(type.FullName, type.Attributes) ;
//				TrustedTypes[type.FullName] = null ;
//			}
//			foreach(Type type in assertedAssembly.GetTypes())
//			if (! (type.IsEnum || type.IsSubclassOf(typeof(System.Delegate)) ||
//				type.FullName.IndexOf("+") != -1))
//			{
//				if (TypePercentIndicator != null)
//					TypePercentIndicator(current++, total) ;
//				CreateType(type) ;
//			}
//			if (entryPoint != null) // If entry point found, lets put it were it must be !!
//				proxyAsm.SetEntryPoint(entryPoint) ;
//			proxyAsm.Save(proxyFileName) ;
//		}
//		
//
//		ModuleBuilder mod ;
//		private Type CreateType(Type type)
//		{
//			FieldInfo reference = null ;
//			if (TrustedTypes[type.FullName] != null)
//				return (Type)TrustedTypes[type.FullName] ;
//			if (!TrustedTypes.Contains(type.FullName))
//				return type ;
//			
//			TypeBuilder typBuilder = (TypeBuilder)(TrustedTypes[type.FullName] = DefinedTypes[type.FullName]) ;
//			if (!type.IsInterface) 
//			{
//				if (!TrustedTypes.Contains(type.BaseType.FullName))
//					typBuilder.SetParent(type.BaseType) ;
//				else if (TrustedTypes[type.BaseType.FullName] != null)
//					typBuilder.SetParent(TrustedTypes[type.BaseType.FullName] as Type) ;
//				else
//					typBuilder.SetParent(CreateType(type.BaseType)) ;
//				typBuilder.AddInterfaceImplementation(typeof(ITrustedType)) ;
//				reference = CreateTarget(typBuilder, type) ;
//			}
//	
//			foreach(Type interfaceImpl in type.GetInterfaces())
//				if (!TrustedTypes.Contains(interfaceImpl.FullName))
//					typBuilder.AddInterfaceImplementation(interfaceImpl) ;
//				else if (TrustedTypes[interfaceImpl.FullName] != null)
//					typBuilder.AddInterfaceImplementation(TrustedTypes[interfaceImpl.FullName] as Type) ;
//				else
//					typBuilder.AddInterfaceImplementation(CreateType(interfaceImpl)) ;
//
//			int current = 0 ;
//			int total = type.GetMembers().Length ;
//
//			if (!type.IsInterface)
//			{
//				ConstructorInfo defaultCtor = null ;
//				Type super = TrustedTypes[type.BaseType.FullName] as Type ;
//				super = super == null ? type.BaseType : super ;
//				super = super.GetConstructor(new Type[0]) == null ? typeof(object) : super ;
//				if (type.GetConstructor(new Type[0]) == null)
//					defaultCtor = CreateDefaultCtor(super.GetConstructor(new Type[0]), typBuilder) ;
//				else
//					defaultCtor = super.GetConstructor(new Type[0]) ;
//
//				CreateSpecialCtor(defaultCtor, type, typBuilder) ;
//				
//				foreach(ConstructorInfo ctor in type.GetConstructors())
//				{
//					if (MemberPercentIndicator != null)
//						MemberPercentIndicator(current ++, total) ;
//					CreateConstructor(type, reference, typBuilder, ctor, defaultCtor) ;
//				}
//			}
//
//			foreach(PropertyInfo property in type.GetProperties(BindingFlags.Instance	| BindingFlags.Public |
//				BindingFlags.DeclaredOnly ))
//			{				
//				if (MemberPercentIndicator != null)
//					MemberPercentIndicator(current ++, total) ;
//				CreateInstanceProperty(type, reference, typBuilder, property) ;
//			}
//
//			foreach(MethodInfo instanceMethod in type.GetMethods(BindingFlags.Instance | BindingFlags.Public | 
//				BindingFlags.DeclaredOnly))
//			{
//				if (MemberPercentIndicator != null)
//					MemberPercentIndicator(current ++, total) ;
//				if ((instanceMethod.Attributes & MethodAttributes.SpecialName) != MethodAttributes.SpecialName)
//					CreateInstanceMethod(type, reference, typBuilder, instanceMethod) ;
//			}
//
//			foreach(MethodInfo classMethod in type.GetMethods(BindingFlags.Static |	BindingFlags.Public |
//				BindingFlags.NonPublic | BindingFlags.DeclaredOnly))
//			{
//				if (MemberPercentIndicator != null)
//					MemberPercentIndicator(current ++, total) ;
//				MethodBuilder tmp = CreateClassMethod(type, typBuilder, classMethod) ;
//				if (classMethod == prototypeEntryPoint)
//					entryPoint = tmp ;
//			}
//
//			return (Type)(TrustedTypes[typBuilder.FullName] = typBuilder.CreateType()) ;
//		}
//		private ConstructorBuilder CreateDefaultCtor(ConstructorInfo super, TypeBuilder typBuilder)
//		{
//			MethodAttributes ctorAttr = MethodAttributes.Private | MethodAttributes.SpecialName | 
//			 MethodAttributes.RTSpecialName | MethodAttributes.HideBySig ;
//			ConstructorBuilder result = typBuilder.DefineConstructor(ctorAttr, CallingConventions.Standard, new Type[0]) ;
//			ILGenerator generator = result.GetILGenerator() ;
//			generator.Emit(OpCodes.Ldarg_0) ;
//			generator.Emit(OpCodes.Call, super) ;
//			generator.Emit(OpCodes.Ret) ;
//			return result ;
//		}
//		private void CreateConstructor(Type type, FieldInfo reference, TypeBuilder typBuilder, ConstructorInfo ctor, ConstructorInfo defaultCtor) 
//		{
//			ConstructorBuilder ctrBuilder = typBuilder.DefineConstructor(ctor.Attributes, ctor.CallingConvention, 
//				GetParametersTypes(ctor.GetParameters())) ;
//
//			ILGenerator ilGenerator = ctrBuilder.GetILGenerator() ;
//			ilGenerator.DeclareLocal(typeof(object)) ;
//
//			Assertion precondition = manager.GetPreconditions(ctor),
//				postcondition = manager.GetPostconditions(ctor),
//				invariant = manager.GetInvariants(ctor.ReflectedType) ;
//
//			if (!precondition.Check())
//				throw new AALCompilingErrorException(precondition.Label + ":" + precondition.CompilingMessage) ;
//			if (!postcondition.Check())
//				throw new AALCompilingErrorException(postcondition.Label + ":" + postcondition.CompilingMessage) ;
//			if (!invariant.Check())
//				throw new AALCompilingErrorException(invariant.Label + ":" + invariant.CompilingMessage) ;
//
//			#region Code generation
//			ilGenerator.Emit(OpCodes.Ldarg_0) ;
//			ilGenerator.Emit(OpCodes.Call, defaultCtor) ;
//			EmitAssertion(precondition, AssertionManager.ckPre, ilGenerator) ;
//			ilGenerator.Emit(OpCodes.Ldarg_0) ;
//			for(int paramIndex = 0 ; paramIndex < ctor.GetParameters().Length; paramIndex ++)
//			{
//				ilGenerator.Emit(OpCodes.Ldarg, paramIndex + 1) ;
//				if (TrustedTypes.Contains(ctor.GetParameters()[paramIndex].ParameterType.FullName))
//				{
//					ilGenerator.Emit(OpCodes.Callvirt, GetTarget) ;
//					ilGenerator.Emit(OpCodes.Castclass, ctor.GetParameters()[paramIndex].ParameterType) ;
//				}
//			}
//			ilGenerator.Emit(OpCodes.Newobj, ctor) ;
//			ilGenerator.Emit(OpCodes.Callvirt, SetTarget) ;			
//			EmitAssertion(postcondition, AssertionManager.ckPos, ilGenerator) ;
//			EmitAssertion(invariant, AssertionManager.ckInv, ilGenerator) ;
//			ilGenerator.Emit(OpCodes.Ret) ;
//			#endregion
//		}
//		private ConstructorBuilder CreateSpecialCtor(ConstructorInfo emptyCtor, Type targetType, TypeBuilder typBuilder)
//		{
//			MethodAttributes ctorAttr = MethodAttributes.Private | MethodAttributes.SpecialName | 
//				MethodAttributes.RTSpecialName | MethodAttributes.HideBySig ;
//			ConstructorBuilder result = typBuilder.DefineConstructor(ctorAttr, CallingConventions.Standard, new Type[] {targetType}) ;
//			ILGenerator generator = result.GetILGenerator() ;
//			generator.Emit(OpCodes.Ldarg_0) ;
//			generator.Emit(OpCodes.Call, emptyCtor) ;
//			generator.Emit(OpCodes.Ldarg_0) ;
//			generator.Emit(OpCodes.Ldarg_1) ;
//			generator.Emit(OpCodes.Callvirt, typeof(ITrustedType).GetMethod("set_Target")) ;
//			generator.Emit(OpCodes.Ret) ;
//			SetSpecialCtor(targetType, result) ;
//			return result ;
//		}
//		private ConstructorInfo GetSpecialCtor(Type targetType)
//		{
//			return (ConstructorInfo)specialCtor[targetType.FullName] ;
//		}
//		private void SetSpecialCtor(Type targetType, ConstructorInfo ctor)
//		{
//			specialCtor[targetType.FullName] = ctor ;
//		}
//		Hashtable specialCtor = new Hashtable() ;
//		private void CreateInstanceProperty(Type type, FieldInfo reference, TypeBuilder typBuilder, PropertyInfo property)
//		{
//			bool specialReturn = false ;
//
//			Type returnType = property.PropertyType ;
//			if (!TrustedTypes.Contains(returnType.FullName))
//			{
//			
//			}
//			else
//			{
//				specialReturn = true ;
//				if (TrustedTypes[returnType.FullName] != null)
//					returnType = (Type)TrustedTypes[returnType.FullName] ;
//				else
//					returnType = (Type)(TrustedTypes[returnType.FullName] = CreateType(returnType)) ;
//			}
//			PropertyBuilder proBuilder = typBuilder.DefineProperty(property.Name, property.Attributes, 
//				returnType, GetParametersTypes(property.GetIndexParameters())) ;
//			if (property.GetGetMethod() != null)
//				proBuilder.SetGetMethod(CreateInstancePropertyGet(type, returnType, specialReturn, reference, typBuilder, property)) ;
//			if (property.GetSetMethod() != null)
//				proBuilder.SetSetMethod(CreateInstancePropertySet(type, reference, typBuilder, property)) ;
//		}
//		private MethodBuilder CreateInstancePropertyGet(Type type, Type returnType, bool specialReturn, FieldInfo reference, TypeBuilder typBuilder, PropertyInfo property)
//		{
//			MethodInfo getPrototype = property.GetGetMethod() ;
//
//			MethodBuilder getMethod = typBuilder.DefineMethod(getPrototype.Name, getPrototype.Attributes,
//				getPrototype.CallingConvention, returnType, GetParametersTypes(getPrototype.GetParameters())) ;
//			if (!getPrototype.IsAbstract)
//			{
//				ILGenerator generator = getMethod.GetILGenerator() ;
//				LocalBuilder result = generator.DeclareLocal(getPrototype.ReturnType) ;
//				Assertion precondition = manager.GetPreconditions(getPrototype),
//					postcondition = manager.GetPostconditions(getPrototype),
//					invariants = manager.GetInvariants(property.ReflectedType),
//					propPrecondition = manager.GetPreconditions(property),
//					propPostcondition = manager.GetPostconditions(property) ;
//
//				if (!precondition.Check())
//					throw new AALCompilingErrorException(precondition.Label + ":" + precondition.CompilingMessage) ;
//				if (!postcondition.Check())
//					throw new AALCompilingErrorException(postcondition.Label + ":" + postcondition.CompilingMessage) ;
//				if (!invariants.Check())
//					throw new AALCompilingErrorException(invariants.Label + ":" + invariants.CompilingMessage) ;
//				if (!propPrecondition.Check())
//					throw new AALCompilingErrorException(propPrecondition.Label + ":" + propPrecondition.CompilingMessage) ;
//				if (!propPostcondition.Check())
//					throw new AALCompilingErrorException(propPostcondition.Label + ":" + propPostcondition.CompilingMessage) ;
//
//
//				postcondition.EmitInicializations(generator) ;
//
//				EmitAssertion(invariants, AssertionManager.ckInv, generator) ;
//				EmitAssertion(propPrecondition, AssertionManager.ckPre, generator) ;
//				EmitAssertion(precondition, AssertionManager.ckPre, generator) ;
//				generator.Emit(OpCodes.Ldarg_0) ;
//				generator.Emit(OpCodes.Callvirt, GetTarget) ;
//				generator.Emit(OpCodes.Castclass, type) ;
//				generator.Emit(OpCodes.Call, getPrototype) ;
//				generator.Emit(OpCodes.Stloc, result) ;
//				EmitAssertion(propPostcondition, AssertionManager.ckPos, generator) ;
//				EmitAssertion(postcondition, AssertionManager.ckPos, generator) ;
//				EmitAssertion(invariants, AssertionManager.ckInv, generator) ;
//				generator.Emit(OpCodes.Ldloc, result) ;
//				if (specialReturn)
//				{
//					generator.Emit(OpCodes.Newobj, GetSpecialCtor(getPrototype.ReturnType)) ;
//				}
//				generator.Emit(OpCodes.Ret) ;
//			}
//			return getMethod ;
//		}
//		private MethodBuilder CreateInstancePropertySet(Type type, FieldInfo reference, TypeBuilder typBuilder, PropertyInfo property)
//		{
//			MethodInfo setPrototype = property.GetSetMethod() ;
//			MethodBuilder setMethod = typBuilder.DefineMethod(setPrototype.Name, setPrototype.Attributes,
//				setPrototype.CallingConvention, setPrototype.ReturnType, GetParametersTypes(setPrototype.GetParameters())) ;
//			if (!setPrototype.IsAbstract)
//			{
//				ILGenerator generator = setMethod.GetILGenerator() ;
//				generator.DeclareLocal(typeof(object)) ;
//				Assertion precondition = manager.GetPreconditions(setPrototype),
//					postcondition = manager.GetPostconditions(setPrototype),
//					invariants = manager.GetInvariants(property.ReflectedType),
//					propPrecondition = manager.GetPreconditions(property),
//					propPostcondition = manager.GetPostconditions(property) ;
//
//				if (!precondition.Check())
//					throw new AALCompilingErrorException(precondition.Label + ":" + precondition.CompilingMessage) ;
//				if (!postcondition.Check())
//					throw new AALCompilingErrorException(postcondition.Label + ":" + postcondition.CompilingMessage) ;
//				if (!invariants.Check())
//					throw new AALCompilingErrorException(invariants.Label + ":" + invariants.CompilingMessage) ;
//				if (!propPrecondition.Check())
//					throw new AALCompilingErrorException(propPrecondition.Label + ":" + propPrecondition.CompilingMessage) ;
//				if (!propPostcondition.Check())
//					throw new AALCompilingErrorException(propPostcondition.Label + ":" + propPostcondition.CompilingMessage) ;
//
//				postcondition.EmitInicializations(generator) ;
//
//				EmitAssertion(invariants, AssertionManager.ckInv, generator) ;
//				EmitAssertion(propPrecondition, AssertionManager.ckPre, generator) ;
//				EmitAssertion(precondition, AssertionManager.ckPre, generator) ;
//				generator.Emit(OpCodes.Ldarg_0) ;
//				if (property.ReflectedType.IsSubclassOf(typeof(System.ValueType)))
//					generator.Emit(OpCodes.Box, typBuilder) ;
//				generator.Emit(OpCodes.Callvirt,GetTarget) ;
//				generator.Emit(OpCodes.Castclass, type) ;
//				foreach(ParameterInfo parameter in setPrototype.GetParameters())
//					generator.Emit(OpCodes.Ldarg, parameter.Position + 1) ;
//				generator.Emit(OpCodes.Call, setPrototype) ;
//				EmitAssertion(propPostcondition, AssertionManager.ckPos, generator) ;
//				EmitAssertion(postcondition, AssertionManager.ckPos, generator) ;
//				EmitAssertion(invariants, AssertionManager.ckInv, generator) ;
//				generator.Emit(OpCodes.Ret) ;
//			}
//			return setMethod ;
//		}
//		private MethodBuilder CreateInstanceMethod(Type type, FieldInfo reference, TypeBuilder typBuilder, MethodInfo methodPrototype)
//		{
//			bool specialReturn = false ;
//
//			Type returnType = methodPrototype.ReturnType ;
//			if (returnType == typeof(void) || !TrustedTypes.Contains(returnType.FullName))
//			{
//			
//			}
//			else
//			{
//				specialReturn = true ;
//				if (TrustedTypes[returnType.FullName] != null)
//					returnType = (Type)TrustedTypes[returnType.FullName] ;
//				else
//					returnType = (Type)(TrustedTypes[returnType.FullName] = CreateType(returnType)) ;
//			}
//
//			MethodBuilder method = typBuilder.DefineMethod(methodPrototype.Name, methodPrototype.Attributes,
//				methodPrototype.CallingConvention, returnType, 
//				GetParametersTypes(methodPrototype.GetParameters())) ;
//			if (!methodPrototype.IsAbstract)
//			{
//				LocalBuilder result = null ;
//				ILGenerator generator = method.GetILGenerator() ;
//				if (methodPrototype.ReturnType != typeof(void))
//				{
//					result = generator.DeclareLocal(methodPrototype.ReturnType) ;
//				}
//				else
//					generator.DeclareLocal(typeof(object)) ;
//
//				Assertion precondition = manager.GetPreconditions(methodPrototype),
//					postcondition = manager.GetPostconditions(methodPrototype),
//					invariants = manager.GetInvariants(methodPrototype.ReflectedType) ;
//
//				if (!precondition.Check())
//					throw new AALCompilingErrorException(precondition.Label + ":" + precondition.CompilingMessage) ;
//				if (!postcondition.Check())
//					throw new AALCompilingErrorException(postcondition.Label + ":" + postcondition.CompilingMessage) ;
//				if (!invariants.Check())
//					throw new AALCompilingErrorException(invariants.Label + ":" + invariants.CompilingMessage) ;
//
//				postcondition.EmitInicializations(generator) ;
//
//				EmitAssertion(invariants, AssertionManager.ckInv, generator) ;
//				EmitAssertion(precondition, AssertionManager.ckPre, generator) ;
//				generator.Emit(OpCodes.Ldarg_0) ;
//				generator.Emit(OpCodes.Callvirt,GetTarget) ;
//				generator.Emit(OpCodes.Castclass, type) ;
//				for(int paramIndex = 0 ; paramIndex < methodPrototype.GetParameters().Length; paramIndex ++)			
//				{
//					generator.Emit(OpCodes.Ldarg, paramIndex + 1) ;
//					if (TrustedTypes.Contains(methodPrototype.GetParameters()[paramIndex].ParameterType.FullName))
//					{
//						generator.Emit(OpCodes.Callvirt, GetTarget) ;
//						generator.Emit(OpCodes.Castclass, methodPrototype.GetParameters()[paramIndex].ParameterType) ;
//					}
//				}
//				generator.Emit(OpCodes.Callvirt, methodPrototype) ;
//				if (result != null)
//				{
//					generator.Emit(OpCodes.Stloc, result) ;
//				}
//				EmitAssertion(postcondition, AssertionManager.ckPos, generator) ;
//				EmitAssertion(invariants, AssertionManager.ckInv, generator) ;
//				if (result != null)
//				{
//					generator.Emit(OpCodes.Ldloc, result) ;
//				}
//				if (specialReturn)
//				{
//					generator.Emit(OpCodes.Newobj, GetSpecialCtor(methodPrototype.ReturnType)) ;
//				}
//				generator.Emit(OpCodes.Ret) ;
//			}
//			return method ;
//		}
//		private MethodBuilder CreateClassMethod(Type type, TypeBuilder typBuilder, MethodInfo classMethodPrototype)
//		{
//			bool specialReturn = false ;
//
//			Type returnType = classMethodPrototype.ReturnType ;
//			if (returnType == typeof(void) || !TrustedTypes.Contains(returnType.FullName))
//			{
//			
//			}
//			else
//			{
//				specialReturn = true ;
//				if (TrustedTypes[returnType.FullName] != null)
//					returnType = (Type)TrustedTypes[returnType.FullName] ;
//				else
//					returnType = (Type)(TrustedTypes[returnType.FullName] = CreateType(returnType)) ;
//			}
//
//			MethodBuilder method = typBuilder.DefineMethod(classMethodPrototype.Name, classMethodPrototype.Attributes,
//				classMethodPrototype.CallingConvention, returnType, 
//				GetParametersTypes(classMethodPrototype.GetParameters())) ;
//		
//			ILGenerator ilGenerator = method.GetILGenerator() ;
//			LocalBuilder result = null ;
//			if (classMethodPrototype.ReturnType != typeof(void))
//			{
//				result = ilGenerator.DeclareLocal(classMethodPrototype.ReturnType) ;
//			}
//			else
//				ilGenerator.DeclareLocal(typeof(object)) ;
//
//			Assertion precondition = manager.GetPreconditions(classMethodPrototype),
//				postcondition = manager.GetPostconditions(classMethodPrototype) ;
//
//			if (!precondition.Check())
//				throw new AALCompilingErrorException(precondition.Label + ":" + precondition.CompilingMessage) ;
//			if (!postcondition.Check())
//				throw new AALCompilingErrorException(postcondition.Label + ":" + postcondition.CompilingMessage) ;
//
//			#region Generation
//			postcondition.EmitInicializations(ilGenerator) ;
//
//			EmitAssertion(precondition, AssertionManager.ckPre, ilGenerator) ;
//			for(int paramIndex = 0; paramIndex < classMethodPrototype.GetParameters().Length; paramIndex ++)
//			{
//				ilGenerator.Emit(OpCodes.Ldarg, paramIndex) ;
//				if (TrustedTypes.Contains(classMethodPrototype.GetParameters()[paramIndex].ParameterType.FullName))					
//				{
//					ilGenerator.Emit(OpCodes.Callvirt, GetTarget) ;
//					ilGenerator.Emit(OpCodes.Castclass, classMethodPrototype.GetParameters()[paramIndex].ParameterType) ;
//				}
//			}
//			ilGenerator.Emit(OpCodes.Call, classMethodPrototype) ;
//			if (result != null)
//			{
//				ilGenerator.Emit(OpCodes.Stloc, result) ;
//			}
//				EmitAssertion(postcondition, AssertionManager.ckPos, ilGenerator) ;
//			if (result != null)
//			{
//				ilGenerator.Emit(OpCodes.Ldloc, result) ;
//			}
//			if (specialReturn)
//			{
//				ilGenerator.Emit(OpCodes.Newobj, GetSpecialCtor(classMethodPrototype.ReturnType)) ;
//			}
//			ilGenerator.Emit(OpCodes.Ret) ;
//			#endregion
//			return method ;
//		}
//		private FieldBuilder CreateTarget(TypeBuilder typBuilder, Type targetType)
//		{
//			MethodAttributes attributes = MethodAttributes.Public | MethodAttributes.HideBySig | 
//				MethodAttributes.NewSlot | MethodAttributes.SpecialName | MethodAttributes.Final |
//				MethodAttributes.Virtual ;
//			FieldBuilder result = typBuilder.DefineField("target", typeof(object), FieldAttributes.Private) ;
//			PropertyBuilder property = typBuilder.DefineProperty("Target", PropertyAttributes.None, 
//				typeof(object), new Type[0]) ;
//			MethodBuilder getMethod = typBuilder.DefineMethod("get_Target", attributes, typeof(object), new Type[0]),
//				setMethod = typBuilder.DefineMethod("set_Target", attributes, typeof(void), new Type[]{typeof(object)}) ;
//			// Generating Get Method
//			ILGenerator generator = getMethod.GetILGenerator() ;
//			generator.Emit(OpCodes.Ldarg_0) ;
//			generator.Emit(OpCodes.Ldfld, result) ;
//			generator.Emit(OpCodes.Ret) ;
//			property.SetGetMethod(getMethod) ;
//			// Generating Set Method
//			generator = setMethod.GetILGenerator() ;
//			generator.Emit(OpCodes.Ldarg_0) ;
//			generator.Emit(OpCodes.Ldarg_1) ;
//			generator.Emit(OpCodes.Stfld, result) ;
//			generator.Emit(OpCodes.Ret) ;
//			property.SetSetMethod(setMethod) ;
//			return result ;
//		}
//		private void CreateParamArray(ILGenerator ilGenerator, int length)
//		{
//			ilGenerator.Emit(OpCodes.Ldc_I4, (int)length) ;
//			ilGenerator.Emit(OpCodes.Newarr, typeof(object)) ;
//			for(int i = 0; i < length; i++)
//			{
//				ilGenerator.Emit(OpCodes.Ldc_I4, (int)i) ;
//				ilGenerator.Emit(OpCodes.Ldarg, (int)i + 1) ;
//				ilGenerator.Emit(OpCodes.Stelem_Ref) ;
//			}
//		}
//
//		private void CreateParamArrayStatic(ILGenerator ilGenerator, int length)
//		{
//			for(int i = 0; i < length; i++)
//			{
//				ilGenerator.Emit(OpCodes.Ldarg, (int)i) ;
//			}
//		}
//
//		
//		private Type[] GetParametersTypes(ParameterInfo[] param)
//		{
//			Type[] types = new Type[param.Length] ;
//			for(int i = 0; i < types.Length; i++)
//				types[i] = CreateType(param[i].ParameterType) ;
//			return types ;
//		}
//		private AssemblyName CreateProxyName(AssemblyName assertedAssemblyName)
//		{
//			AssemblyName result = new AssemblyName() ;
//			result.Name = ProxyPrefix + assertedAssemblyName.Name ;
////			result.CodeBase = assertedAssemblyName.CodeBase ;
//			result.CultureInfo = assertedAssemblyName.CultureInfo ;
////			result.Flags = assertedAssemblyName.Flags ;
//			result.Version = assertedAssemblyName.Version ;
//			return result ;	
//		}
//		private static string CreateProxyFileName(Assembly prototype)
//		{
//			return ProxyPrefix + prototype.GetName().Name + (prototype.EntryPoint == null? ".dll" : ".exe") ;
//		}
//
//		private static string GetAssertedAssembly(Assembly assembly)
//		{
//			TrustedAttribute[] attr = (TrustedAttribute[])assembly.GetCustomAttributes(typeof(TrustedAttribute), false) ;
//			if (attr.Length == 0)
//				return null ;
//			return attr[0].AssertedName ;
//		}
//		private static void EmitAssertion(Assertion assertion, FieldInfo goFlag, ILGenerator generator)
//		{
//			if (assertion.IsBlank)
//				return ;
//			Label end = generator.DefineLabel() ;
//
//			generator.Emit(OpCodes.Ldsfld, goFlag) ;
//			generator.Emit(OpCodes.Brfalse, end) ;
//			generator.Emit(OpCodes.Ldc_I4_0) ;
//			generator.Emit(OpCodes.Stsfld, goFlag) ;
//			assertion.EmitAssertion(generator) ;
//			generator.Emit(OpCodes.Ldc_I4_1) ;
//			generator.Emit(OpCodes.Stsfld, goFlag) ;
//			generator.MarkLabel(end) ;
//			generator.Emit(OpCodes.Nop) ;
//		}
//	}

	#endregion
	#endregion
	
	namespace Documentation
	{
		using System.Threading ;

		internal struct Pair
		{
			public string Name ;
			public object Value ;
			public Pair(string name, object value)
			{
				Name = name ;
				Value = value ;
			}
		}
		public class AssemblyDocExtractor
		{
			static string Comment = "Generated with Assertions(c) documentation tool, WebOO Group, University of Havana" ;

			Assembly target ;
			string outputPath ;
			bool delete ;
			Thread thread ;

			public AssemblyDocExtractor(Assembly target)
			{
				Target = target ;
				thread = new Thread(new ThreadStart(this.CreateNavigableDocumentation)) ;
			}
			public AssemblyDocExtractor()
			{
				thread = new Thread(new ThreadStart(this.CreateNavigableDocumentation)) ;
			}


			public Assembly Target
			{
				get
				{
					return target ;
				}
				set
				{
					if (value == null)
						throw new ArgumentNullException("value") ;
					target = value ;
				}
			}
			public string OutputPath
			{
				get
				{
					return outputPath ;
				}
				set
				{
					if (value == null)
						throw new ArgumentNullException("value") ;
					outputPath = value ;
				}
			}
			public bool Delete
			{
				get
				{
					return delete ;
				}
				set
				{
					delete = value ;
				}
			}


			#region Synchronous Methods
			public XmlDocument ExtractDocumentation()
			{
				if (target == null)
					throw new NullReferenceException("Target uninitialized") ;
				XmlDocument document = new XmlDocument() ;
				XmlComment comment = document.CreateComment(Comment) ;
				Documenter.DefaultAssemblyDocumenter.TypeProgress += TypeProgress ;
				Documenter.DefaultTypeDocumenter.MemberProgress += MemberProgress ;
				document.AppendChild(Documenter.DefaultAssemblyDocumenter.GetDocumentation(document, target)) ;
				Documenter.DefaultAssemblyDocumenter.TypeProgress -= TypeProgress ;
				Documenter.DefaultTypeDocumenter.MemberProgress -= MemberProgress ;
				return document ;
			}
			public void CreateNavigableDocumentation()
			{
				#region Preconditions
				if (target == null)
					throw new NullReferenceException("Target uninitialized") ;
				if (outputPath == null)
					throw new NullReferenceException("OutputPath uninitialized") ;
				#endregion

				if (Directory.Exists(outputPath))
				{
					if (delete)
						Directory.Delete(outputPath, true) ;
					else
						throw new Exception("Cannot create documentation on an existing folder") ;
				}
				DirectoryInfo folder = Directory.CreateDirectory(outputPath) ;

				XmlDocument doc = ExtractDocumentation(), xml = new XmlDocument() ;
				ResourceManager resource = new ResourceManager("Assertions.Data", Assembly.GetExecutingAssembly()) ;
				
				XslTransform typeXSLT = new XslTransform(), assemblyXSLT = new XslTransform() ;
				xml.LoadXml(resource.GetString("IndexXSLT")) ;
				assemblyXSLT.Load(xml.CreateNavigator()) ;

				xml = new XmlDocument() ;
				xml.LoadXml(resource.GetString("TypeXSLT")) ;
				typeXSLT.Load(xml.CreateNavigator()) ;

				Stream output = File.Create(outputPath + "\\" + "index.html") ;
				assemblyXSLT.Transform(doc.CreateNavigator(), null, output) ;
				output.Close() ;
				
				foreach(XmlNode node in doc["assembly"].ChildNodes)
				{
					xml = new XmlDocument() ;
					string t = outputPath + "\\" + ((XmlAttribute)node.Attributes.GetNamedItem("name")).Value + ".html" ;
					output = File.Create(t) ;
					xml.AppendChild(xml.ImportNode(node, true)) ;
					typeXSLT.Transform(xml.CreateNavigator(), null, output) ;
					output.Close() ;
				}

				OnFinish() ;
			}
			public void CreateNavigableDocumentation(string outputPath, bool delete)
			{
				this.outputPath = outputPath ;
				this.delete = delete ;
				CreateNavigableDocumentation() ;
			}
			#endregion

			#region Asynchronous Methods
			public void ASYNCCreateNavigableDocumentation()
			{
				thread.Start() ;
			}
			public void ASYNCCreateNavigableDocumentation(string outputPath, bool delete)
			{
				this.outputPath = outputPath ;
				this.delete = delete ;
				thread.Start() ;
			}
			public void Abort()
			{
				thread.Abort() ;
				OnFinish() ;
			}
			public void Suspend()
			{
				thread.Suspend() ;
			}
			public void Resume()
			{
				thread.Resume() ;
			}
			#endregion

			#region Events and Triggers
			public event PercentIndicator MemberProgress ;
			public event PercentIndicator TypeProgress ;
			public event EventHandler Finish ;

			void OnFinish()
			{
				if (Finish != null)
					Finish(this, EventArgs.Empty) ;
			}
			#endregion
		}
		abstract public class Documenter
		{
			#region Static Methods
			
			public static XmlDocument CreateAssemblyDocumentation(Assembly assembly)
			{
				XmlDocument document = new XmlDocument() ;
				XmlComment comment = document.CreateComment("") ;
				document.AppendChild(DefaultAssemblyDocumenter.GetDocumentation(document, assembly)) ;
				return document ;
			}
			public static void WriteHTMLDoc(Assembly assembly, Stream stream)
			{
				XmlDocument doc = CreateAssemblyDocumentation(assembly),
					xml = new XmlDocument() ;
				ResourceManager resource = new ResourceManager("Assertions.Data", Assembly.GetExecutingAssembly()) ;
				xml.LoadXml(resource.GetString("AssertionsXSLT")) ;
				XslTransform xsl = new XslTransform() ;
				xsl.Load(xml.CreateNavigator()) ;
				xsl.Transform(doc.CreateNavigator(), null, stream) ;
			}
			public static void CreateNavigableDocumentaion(Assembly assembly, string folderPath, bool delete)
			{
				if (Directory.Exists(folderPath))
				{
					if (delete)
						Directory.Delete(folderPath, true) ;
					else
						throw new Exception("Cannot create documentation on an existing folder") ;
				}
				DirectoryInfo folder = Directory.CreateDirectory(folderPath) ;

				XmlDocument doc = CreateAssemblyDocumentation(assembly), xml = new XmlDocument() ;
				ResourceManager resource = new ResourceManager("Assertions.Data", Assembly.GetExecutingAssembly()) ;
				
				XslTransform typeXSLT = new XslTransform(), assemblyXSLT = new XslTransform() ;
				xml.LoadXml(resource.GetString("IndexXSLT")) ;
				assemblyXSLT.Load(xml.CreateNavigator()) ;

				xml = new XmlDocument() ;
				xml.LoadXml(resource.GetString("TypeXSLT")) ;
				typeXSLT.Load(xml.CreateNavigator()) ;

				Stream output = File.Create(folderPath + "\\" + "index.html") ;
				assemblyXSLT.Transform(doc.CreateNavigator(), null, output) ;
				output.Close() ;
				
				foreach(XmlNode node in doc["assembly"].ChildNodes)
				{
					xml = new XmlDocument() ;
					string t = folderPath + "\\" + ((XmlAttribute)node.Attributes.GetNamedItem("name")).Value + ".html" ;
					output = File.Create(t) ;
					xml.AppendChild(xml.ImportNode(node, true)) ;
					typeXSLT.Transform(xml.CreateNavigator(), null, output) ;
					output.Close() ;
				}
			}
			#endregion

			#region Implementation
			public static AssertionManager DefaultManager = new ChacalAssertionManager() ;

			protected IDictionary docSolver ;
			public Documenter()
			{
				docSolver = new Hashtable() ;
			}
			public Documenter GetChildDocumenter(string child)
			{
				if (child == null)
					throw new ArgumentNullException("child") ;
				return (Documenter)docSolver[child] ;
			}
			public void SetChildDocumenter(string child, Documenter documenter)
			{
				if (child == null | documenter == null)
					throw new ArgumentNullException((child == null?"child":"") + 
						((child == null && documenter == null)?", ":"") + (documenter == null?"documenter":"")) ;
				docSolver[child] = documenter ;
			}
			public XmlElement GetDocumentation(XmlDocument document, object local)
			{
				XmlElement result = GetLocalNode(document, local) ;
				foreach(object child in Children(local))
				{
					result.AppendChild(GetChildDocumenter(GetChildKey(child)).GetDocumentation(document, child)) ;
				}
				return result ;
			}
			
			public static XmlAttribute CreateAttribute(XmlDocument document, string name, string value)
			{
				XmlAttribute result = document.CreateAttribute(name) ;
				result.Value = value ;
				return result ;
			}
			
			
			public const BindingFlags FullBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | 
				BindingFlags.Instance |	BindingFlags.Static ;
			public const BindingFlags NonPublic = BindingFlags.NonPublic | 
				BindingFlags.Instance |	BindingFlags.Static ;

			
			public static AssemblyDocumenter DefaultAssemblyDocumenter = new AssemblyDocumenter() ;
			public static StructuredTypeDocumenter DefaultTypeDocumenter = new StructuredTypeDocumenter() ;
			public static MethodDocumenter DefaultMethodDocumenter = new MethodDocumenter() ;
			public static CtorDocumenter DefaultCtorDocumenter = new CtorDocumenter() ;
			public static PropertyDocumenter DefaultPropertyDocumenter = new PropertyDocumenter() ;
			public static AssertionDocumenter DefaultInvariantDocumenter = new AssertionDocumenter("invariant") ;
			public static AssertionDocumenter DefaultPreconditionDocumenter = new AssertionDocumenter("precondition") ;
			public static AssertionDocumenter DefaultPostconditionDocumenter = new AssertionDocumenter("postcondition") ;
			public static AssertionDocumenter DefaultAndGroupDocumenter = new AssertionDocumenter("assertionANDGroup") ;
			public static AssertionDocumenter DefaultAssertionDocumenter = new AssertionDocumenter("assertion") ;
			public static PropertyAccessDocumenter DefaultSetDocumenter = new PropertyAccessDocumenter("set") ;
			public static PropertyAccessDocumenter DefaultGetDocumenter = new PropertyAccessDocumenter("get") ;
			public static ErrorDocumenter DefaultErrorDocumenter = new ErrorDocumenter() ;
			public static ParameterDocumenter DefaultParameterDocumenter = new ParameterDocumenter() ;
			public static EnumDocumenter DefaultEnumDocumenter = new EnumDocumenter() ;
			public static EnumValueDocumenter DefaultEnumValueDocumenter = new EnumValueDocumenter() ;
			public static DelegateDocumenter DefaultDelegateDocumenter = new DelegateDocumenter() ;
			
			static Documenter()
			{
				DefaultAssemblyDocumenter.SetChildDocumenter("StructuredType", DefaultTypeDocumenter) ;
				DefaultAssemblyDocumenter.SetChildDocumenter("Enum", DefaultEnumDocumenter) ;
				DefaultAssemblyDocumenter.SetChildDocumenter("Delegate", DefaultDelegateDocumenter) ;

				DefaultTypeDocumenter.SetChildDocumenter("Method", DefaultMethodDocumenter) ;
				DefaultTypeDocumenter.SetChildDocumenter("Constructor", DefaultCtorDocumenter) ;
				DefaultTypeDocumenter.SetChildDocumenter("Property", DefaultPropertyDocumenter) ;
				DefaultTypeDocumenter.SetChildDocumenter("Invariant", DefaultInvariantDocumenter) ;
				DefaultTypeDocumenter.SetChildDocumenter("Error", DefaultErrorDocumenter) ;
 
				DefaultMethodDocumenter.SetChildDocumenter("Precondition", DefaultPreconditionDocumenter) ;
				DefaultMethodDocumenter.SetChildDocumenter("Postcondition", DefaultPostconditionDocumenter) ;
				DefaultMethodDocumenter.SetChildDocumenter("Error", DefaultErrorDocumenter) ;
				DefaultMethodDocumenter.SetChildDocumenter("Parameter", DefaultParameterDocumenter) ;
				
				DefaultCtorDocumenter.SetChildDocumenter("Precondition", DefaultPreconditionDocumenter) ;
				DefaultCtorDocumenter.SetChildDocumenter("Postcondition", DefaultPostconditionDocumenter) ;
				DefaultCtorDocumenter.SetChildDocumenter("Error", DefaultErrorDocumenter) ;
				DefaultCtorDocumenter.SetChildDocumenter("Parameter", DefaultParameterDocumenter) ;

				DefaultPropertyDocumenter.SetChildDocumenter("Precondition", DefaultPreconditionDocumenter) ;
				DefaultPropertyDocumenter.SetChildDocumenter("Postcondition", DefaultPostconditionDocumenter) ;
				DefaultPropertyDocumenter.SetChildDocumenter("set", DefaultSetDocumenter) ;
				DefaultPropertyDocumenter.SetChildDocumenter("get", DefaultGetDocumenter) ;
				DefaultPropertyDocumenter.SetChildDocumenter("Error", DefaultErrorDocumenter) ;

				DefaultInvariantDocumenter.SetChildDocumenter("And", DefaultAndGroupDocumenter) ;

				DefaultPreconditionDocumenter.SetChildDocumenter("And", DefaultAndGroupDocumenter) ;

				DefaultPostconditionDocumenter.SetChildDocumenter("And", DefaultAndGroupDocumenter) ;

				DefaultAndGroupDocumenter.SetChildDocumenter("Single", DefaultAssertionDocumenter) ;
				DefaultAndGroupDocumenter.SetChildDocumenter("And", DefaultAndGroupDocumenter) ;

				DefaultSetDocumenter.SetChildDocumenter("Precondition", DefaultPreconditionDocumenter) ;
				DefaultSetDocumenter.SetChildDocumenter("Postcondition", DefaultPostconditionDocumenter) ;

				DefaultGetDocumenter.SetChildDocumenter("Precondition", DefaultPreconditionDocumenter) ;
				DefaultGetDocumenter.SetChildDocumenter("Postcondition", DefaultPostconditionDocumenter) ;

				DefaultEnumDocumenter.SetChildDocumenter("Value", DefaultEnumValueDocumenter) ;
			}

			#endregion

			public static PercentIndicator TypePercentIndicatorListener ;
			public static PercentIndicator MemberPercentIndicatorListener ;

			#region Abstract methods
			abstract public string GetChildKey(object child) ;
			abstract public XmlElement GetLocalNode(XmlDocument document, object local) ;
			abstract public IEnumerable Children(object local) ;
			#endregion
		}
		public class AssemblyDocumenter : Documenter
		{
			public AssemblyDocumenter()
			{
			
			}
			public AssemblyDocumenter(PercentIndicator typeProgress)
			{
				this.TypeProgress += typeProgress ;
			}


			override public string GetChildKey(object child)
			{
				Type typeChild = child as Type ;
				if (typeChild != null)
				{
					if (typeChild.IsSubclassOf(typeof(System.Delegate)))
						return "Delegate" ;
					if (typeChild.IsEnum)
						return "Enum" ;
					return "StructuredType" ;
				}
				return null ;
			}
			override public XmlElement GetLocalNode(XmlDocument document, object local)
			{
				Assembly assemblyNode = (Assembly)local ;
				XmlElement result = document.CreateElement("assembly") ;
				result.Attributes.Append(Documenter.CreateAttribute(document, "name", assemblyNode.FullName)) ;
				return result ;
			}
			override public IEnumerable Children(object local)
			{
				Assembly assembly = (Assembly)local ;
				PercentEnumerable pe = new PercentEnumerable(assembly.GetTypes()) ;
				pe.PercentIndicatorListener += TypeProgress ;
				return pe ;
			}

			public event PercentIndicator TypeProgress ;
		}
		public class StructuredTypeDocumenter : Documenter
		{
			public StructuredTypeDocumenter()
			{
			
			}
			public StructuredTypeDocumenter(PercentIndicator memberProgress)
			{
				MemberProgress += memberProgress ;
			}


			override public string GetChildKey(object child)
			{
				MemberInfo memberChild = child as MemberInfo ;
				if (memberChild != null)
					return memberChild.MemberType.ToString() ;
				AssertionANDGroup attr = child as AssertionANDGroup ;
				if (attr != null)
					return "Invariant" ;
				Exception exception = child as Exception ;
				if (exception != null)
					return "Error" ;
				return null ;
			}
			override public XmlElement GetLocalNode(XmlDocument document, object local)
			{
				Type typeNode = (Type)local ;
				XmlElement result = document.CreateElement(typeNode.IsClass ? "class" : 
					typeNode.IsInterface ? "interface" : "struct") ;
				result.Attributes.Append(Documenter.CreateAttribute(document, "name", typeNode.FullName)) ;
				result.Attributes.Append(Documenter.CreateAttribute(document, "attributes", 
					typeNode.Attributes.ToString())) ;
				return result ;
			}
			override public IEnumerable Children(object local)
			{
				Type typeNode = (Type)local ;
				ArrayList children = new ArrayList() ;
				try 
				{
					children.Add(DefaultManager.GetInvariants(typeNode)) ;
				}
				catch(Exception exception)
				{
					children.Add(exception) ;
				}
				foreach(ConstructorInfo ctor in typeNode.GetConstructors())
					children.Add(ctor) ;
				foreach(MethodInfo method in typeNode.GetMethods(FullBindingFlags))
					if (!method.IsSpecialName)
						children.Add(method) ;
				foreach(PropertyInfo property in typeNode.GetProperties(FullBindingFlags) )
					children.Add(property) ;
				PercentEnumerable pe = new PercentEnumerable((object[])children.ToArray(typeof(object))) ;
				pe.PercentIndicatorListener += MemberProgress ;
				return pe ;
			}


			public event PercentIndicator MemberProgress ;
		}
		public class EnumDocumenter : Documenter
		{
			public override string GetChildKey(object child)
			{
				return "Value" ;
			}
			public override IEnumerable Children(object local)
			{
				Type enumType = (Type)local ;
				Array values = Enum.GetValues(enumType) ;
				object[] children = new object[values.Length] ;
				for(int index = 0; children.Length > index; index++)
					children[index] = new Pair(Enum.GetName(enumType, values.GetValue(index)), values.GetValue(index)) ;
				return children ;
			}
			public override XmlElement GetLocalNode(XmlDocument document, object local)
			{
				Type enumType = (Type)local ;
				XmlElement result = document.CreateElement("enum") ;
				result.Attributes.Append(CreateAttribute(document, "UnderlyingType", Enum.GetUnderlyingType(enumType).FullName)) ;
				return result ;
			}
		}
		public class EnumValueDocumenter : Documenter
		{
			public override XmlElement GetLocalNode(XmlDocument document, object local)
			{
				Pair pair = (Pair)local ;
				XmlElement result = document.CreateElement("element") ;
				result.Attributes.Append(CreateAttribute(document, "name", pair.Name)) ;
				result.Attributes.Append(CreateAttribute(document, "value", pair.Value.ToString())) ;
				return result ;
			}
			public override string GetChildKey(object child)
			{
				return null ;
			}
			public override IEnumerable Children(object local)
			{
				return new object[0] ;
			}
		}
		public class DelegateDocumenter : Documenter
		{
			public override string GetChildKey(object child)
			{
				return "" ;
			}
			public override XmlElement GetLocalNode(XmlDocument document, object local)
			{
				Type delegateType = (Type)local ;
				XmlElement result = document.CreateElement("delegate") ;
				result.Attributes.Append(CreateAttribute(document, "name", delegateType.Name)) ;
				return result ;
			}
			public override IEnumerable Children(object local)
			{
				return new object[0] ;
			}
		}
		public abstract class MemberDocumenter : Documenter
		{
			override public string GetChildKey(object child)
			{
				AssertionORGroup precondition = child as AssertionORGroup ;
				if (precondition != null)
					return "Precondition" ;
				AssertionANDGroup postcondition = child as AssertionANDGroup ;
				if (postcondition != null)
					return "Postcondition" ;
				Exception exception = child as Exception ;
				if (exception != null)
					return "Error" ;
				return null ;
			}
			override public IEnumerable Children(object local)
			{
				MemberInfo memberNode = (MemberInfo)local ;
				ArrayList children = new ArrayList() ;
				try 
				{
					if (local is MethodInfo)
						children.Add(DefaultManager.GetPreconditions(memberNode as MethodInfo)) ;
					else if (local is ConstructorInfo)
						children.Add(DefaultManager.GetPreconditions(memberNode as ConstructorInfo)) ;
					else if (local is PropertyInfo)
						children.Add(DefaultManager.GetPreconditions(memberNode as PropertyInfo)) ;
				} 
				catch(Exception exception)
				{
					children.Add(exception) ;
				}
				try
				{
					if (local is MethodInfo)
						children.Add(DefaultManager.GetPostconditions(memberNode as MethodInfo)) ;
					else if (local is ConstructorInfo)
						children.Add(DefaultManager.GetPostconditions(memberNode as ConstructorInfo)) ;
					else if (local is PropertyInfo)
						children.Add(DefaultManager.GetPostconditions(memberNode as PropertyInfo)) ;
				}
				catch(Exception exception)
				{
					children.Add(exception) ;
				}
				return children ;
			}
			public static string GetMethodString(MethodInfo method)
			{
				return string.Format("{0} {1}({2})", method.ReturnType, method.Name, 
					GetParametersString(method.GetParameters())) ;
			}
			public static string GetCtorString(ConstructorInfo ctor)
			{
				return string.Format("{0}({1})", ctor.ReflectedType.Name, GetParametersString(ctor.GetParameters())) ;				
			}
			public static string GetPropertyString(PropertyInfo prop)
			{
				string param = GetParametersString(prop.GetIndexParameters()) ;
				return string.Format("{0} {1}{3}{2}{4}", prop.PropertyType, prop.Name, param,
					param != "" ? "[":"",
					param != "" ? "]":"") ;
			}
			public static string GetParametersString(ParameterInfo[] parameters)
			{
				string result = "" ;
				foreach(ParameterInfo parameter in parameters)
					result += string.Format("{0}{1} {2}, ", parameter.IsOut?"out ":"", parameter.ParameterType, parameter.Name) ;
				return (result.Substring(Math.Max(0, result.Length - 2)) == ", ")? result.Substring(0,result.Length - 2): result ;
			}
		}
		public class MethodDocumenter : MemberDocumenter
		{
			override public XmlElement GetLocalNode(XmlDocument document, object local)
			{
				MethodInfo methodNode = (MethodInfo)local ;
				XmlElement result = document.CreateElement("method") ;
				result.Attributes.Append(Documenter.CreateAttribute(document, "signature", GetMethodString(methodNode))) ;
				result.Attributes.Append(Documenter.CreateAttribute(document, "name", methodNode.Name)) ;
				return result ;
			}
			override public string GetChildKey(object child)
			{
				string result = base.GetChildKey(child) ;
				if (result == null)
					return "Parameter" ;
				return result ;
			}
			override public IEnumerable Children(object local)
			{
				MethodBase method = local as MethodBase ;
				ArrayList result = new ArrayList(method.GetParameters()) ;
				foreach(object child in base.Children(local))
					result.Add(child) ;
				return result ;
			}
		}
		public class CtorDocumenter : MemberDocumenter
		{
			override public XmlElement GetLocalNode(XmlDocument document, object local)
			{
				ConstructorInfo ctorNode = (ConstructorInfo)local ;
				XmlElement result = document.CreateElement("ctor") ;
				result.Attributes.Append(Documenter.CreateAttribute(document, "signature", 
					GetCtorString(ctorNode))) ;
				return result ;
			}
			override public string GetChildKey(object child)
			{
				string result = base.GetChildKey(child) ;
				if (result == null)
					return "Parameter" ;
				return result ;
			}
			override public IEnumerable Children(object local)
			{
				MethodBase method = local as MethodBase ;
				ArrayList result = new ArrayList(method.GetParameters()) ;
				foreach(object child in base.Children(local))
					result.Add(child) ;
				return result ;
			}
		}
		public class ParameterDocumenter : Documenter
		{
			override public XmlElement GetLocalNode(XmlDocument document, object local)
			{
				ParameterInfo parameter = (ParameterInfo)local ;
				XmlElement result = document.CreateElement("parameter") ;
				result.Attributes.Append(CreateAttribute(document, "name", parameter.Name)) ;
				result.Attributes.Append(CreateAttribute(document, "type", parameter.ParameterType.Name)) ;
				result.Attributes.Append(CreateAttribute(document, "IsOut", parameter.IsOut.ToString())) ;
				return result ;
			}
			override public IEnumerable Children(object local)
			{
				return new object[0] ;
			}
			override public string GetChildKey(object child)
			{
				return "" ;
			}
		}
		public class PropertyDocumenter : MemberDocumenter
		{
			override public XmlElement GetLocalNode(XmlDocument document, object local)
			{
				PropertyInfo propertyNode = (PropertyInfo)local ;
				XmlElement result = document.CreateElement("property") ;
				result.Attributes.Append(Documenter.CreateAttribute(document, "signature", 
					GetPropertyString(propertyNode))) ;
				return result ;
			}
			override public string GetChildKey(object child)
			{
				MethodInfo access = child as MethodInfo ;
				if (access != null)
					return access.Name.Substring(0, access.Name.IndexOf("_")) ;
				return base.GetChildKey(child) ;
			}
			override public IEnumerable Children(object local)
			{
				ArrayList children = (ArrayList)base.Children(local) ;
				PropertyInfo property = (PropertyInfo)local ;
				if (property.GetSetMethod() != null)
					children.Add(property.GetSetMethod()) ;
				if (property.GetGetMethod() != null)
					children.Add(property.GetGetMethod()) ;
				return children ;
			}
		}
		public class PropertyAccessDocumenter : MemberDocumenter
		{
			string accessName ;
			public PropertyAccessDocumenter(string accessName)
			{
				this.accessName = accessName ;
			}
			override public XmlElement GetLocalNode(XmlDocument document, object local) 
			{
				return document.CreateElement(accessName) ;
			}
		}

		public class AssertionDocumenter : Documenter
		{
			string name ;
			public AssertionDocumenter(string name)
			{
				this.name = name ;
			}
			override public string GetChildKey(object child)
			{
				AssertionANDGroup andGroup = child as AssertionANDGroup ;
				if (andGroup != null)
					return "And" ;
				AssertionORGroup orGroup = child as AssertionORGroup ;
				if (orGroup != null)
					return "Or" ;
				return "Single" ;
			}
			override public XmlElement GetLocalNode(XmlDocument document, object local)
			{
				Assertion assertion = (Assertion)local ;
				if (!assertion.Check())
				{
					XmlElement te = document.CreateElement("error") ;
					te.InnerText = assertion.Label + ":" + assertion.CompilingMessage ;
					return te ;
				}
				XmlElement result = document.CreateElement(name) ;
				result.Attributes.Append(Documenter.CreateAttribute(document, "code", assertion.BoolExpression)) ;
				result.AppendChild(GetXmlCode(document, assertion.BoolExpression)) ;
				result.Attributes.Append(Documenter.CreateAttribute(document, "label", assertion.Label)) ;
				result.Attributes.Append(Documenter.CreateAttribute(document, "exception", 
					assertion.AssertionViolation == null?"Defaul" : assertion.AssertionViolation.FullName)) ;
				return result ;				
			}
			override public IEnumerable Children(object local)
			{
				AssertionGroup group = local as AssertionGroup ;
				if (group != null)
					return group ;
				return new object[0] ;
			}

			
			public XmlElement GetXmlCode(XmlDocument document, string code)
			{
				string[] names = {"key", "identifier", "const", "", "operator"} ;
				XmlElement result = document.CreateElement("code") ;
				foreach(IToken token in ChacalAssertionManager.ChacalTokenizer.Tokenize(code))
				{
					XmlElement codeNode = document.CreateElement("codenode") ;
					codeNode.Attributes.Append(CreateAttribute(document, "style", names[(token.Type % 10) / 2])) ;
					codeNode.Attributes.Append(CreateAttribute(document, "value", token.Value)) ;
					result.AppendChild(codeNode) ;
				}
				return result ;
			}
		}
		public class ErrorDocumenter : Documenter
		{
			string label ;
			public ErrorDocumenter() : this("error")
			{
			
			}
			public ErrorDocumenter(string label)
			{
				this.label = label ;
			}
			override public string GetChildKey(object child)
			{
				return null ;
			}
			override public XmlElement GetLocalNode(XmlDocument document, object local)
			{
				XmlElement node = document.CreateElement(label) ;
				node.InnerText = (local is Exception) ? ((Exception)local).Message : local.ToString() ;
				return node ;
			}
			override public IEnumerable Children(object local)
			{
				return new object[0] ;
			}
		}

		public interface IPercentIndicatorListener
		{
			event PercentIndicator PercentIndicatorListener ;
		}


		public delegate void PercentIndicator(int current, int total) ;

		public class PercentEnumerator : IEnumerator, IPercentIndicatorListener
		{
			object[] array ;
			int index = -1 ;
			IEnumerator enumerator ;
			public event PercentIndicator PercentIndicatorListener ;
			public PercentEnumerator(object[] array)
			{
				this.array = array ;
				this.index = 0 ;
				this.enumerator = array.GetEnumerator() ;
			}
			public object Current
			{
				get
				{
					return enumerator.Current ;
				}
			}
			public bool MoveNext()
			{
				bool result = enumerator.MoveNext() ;
				if (result)
				{
					index ++ ;
					if (PercentIndicatorListener != null)
						PercentIndicatorListener(index,array.Length) ;
				}
				return result ;
				
			}
			public void Reset()
			{
				enumerator.Reset() ;
				index = -1 ;
			}
		}
		public class PercentEnumerable : IEnumerable, IPercentIndicatorListener
		{
			object[] array ;
			public PercentEnumerable(object[] array)
			{
				this.array = array ;
			}
			public event PercentIndicator PercentIndicatorListener ;
			public IEnumerator GetEnumerator()
			{
				PercentEnumerator pe = new PercentEnumerator(array) ;
				pe.PercentIndicatorListener += this.PercentIndicatorListener ;
				return pe ;
			}
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect SunHotels
Spain Spain
I Received a Bachelor's Degree in Computer Science at the Mathematics and Computer Science Faculty, University of Havana, Cuba.

I mainly work in web applications using C# and some Javascript. Some very few times do some Java.

Comments and Discussions