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 ;
}
}
}
}