/* Copyright 2010,2011 Kevin Glynn (kevin.glynn@twigletsoftware.com) */ using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.Text.RegularExpressions; using System.IO; using System.Xml; using System.Xml.Schema; using System.Xml.Serialization; using Twiglet.CS2J.Translator.Utils; // These Template classes are in-memory versions of the xml translation templates // (we use C# to directly persist to / from files). // We have overloaded Equals to test value equality for these template objects. For now its only // used by unit tests (to check that the object survives xml serialization / deserialization // unscathed). But it might be useful down the road. // By overloading Equals, we also have to overload GetHashCode (well, its highly reccomended)... namespace Twiglet.CS2J.Translator.TypeRep { public class TemplateUtilities { public static string Substitute(string c, Dictionary argMap) { String ret = c; if (argMap.ContainsKey(c)) { ret = argMap[c].TypeName; } return ret; } private class TypeVarMapper { private Dictionary myArgMap; public TypeVarMapper(Dictionary inArgMap) { myArgMap = inArgMap; } public string ReplaceFromMap(Match m) { if (myArgMap.ContainsKey(m.Value)) { return myArgMap[m.Value].mkSafeTypeName(); } return m.Value; } } public static string SubstituteInType(String type, Dictionary argMap) { if (String.IsNullOrEmpty(type) || argMap == null) return type; TypeVarMapper mapper = new TypeVarMapper(argMap); return Regex.Replace(type, @"([\w|\.]+)*", new MatchEvaluator(mapper.ReplaceFromMap)); } private static string OldSubstituteInType(String type, Dictionary argMap) { if (String.IsNullOrEmpty(type)) return type; string ret = type; // type is either "string" or "string*[type,type,...]*" or string[] // Match match = Regex.Match(type, @"^([\w|\.]+)(?:\s*\*\[\s*([\w|\.]+)(?:\s*,\s*([\w|\.]+))*\s*\]\*)?$"); Match match = Regex.Match(type, @"([\w|\.]+)*"); if (match.Success) { CaptureCollection captures = match.Captures; StringBuilder buf = new StringBuilder(); buf.Append(Substitute(captures[0].Value, argMap)); if ( captures.Count > 1) { bool first = true; buf.Append("["); for (int i = 1; i < captures.Count; i++) { if (!first) { buf.Append(", "); } buf.Append(Substitute(captures[i].Value, argMap)); first = false; } buf.Append("]"); } ret = buf.ToString(); } return ret; } } public interface IApplyTypeArgs { // Instantiate type arguments "in-situ" void Apply(Dictionary args); } public enum Javastyle { Clean, MarkAuto } public class TypeRepRef { private class TypeVarMapper { private Dictionary myArgMap; private TypeRepRef inTy; public TypeVarMapper(Dictionary inArgMap, TypeRepRef ty) { myArgMap = inArgMap; inTy = ty; } public string ReplaceFromMap(Match m) { if (myArgMap.ContainsKey(m.Value)) { // If the replacement type is primitive then tell cs2j to use the Boxed version when emitting type. inTy.ForceBoxed = true; return myArgMap[m.Value].mkSafeTypeName(); } return m.Value; } } // if ForceBoxed is true then any primitive types should be emitted as the boxed rep. private bool _forceBoxed = false; [XmlAttribute("box")] [System.ComponentModel.DefaultValueAttribute(false)] public bool ForceBoxed { get { return _forceBoxed; } set { _forceBoxed = value; } } private string _type = ""; [XmlText] public string Type { get { return _type; } set { _type = value.Replace("<","*[").Replace(">","]*"); } } public TypeRepRef() { } public TypeRepRef(TypeRepRef copyFrom) { ForceBoxed = copyFrom.ForceBoxed; Type = copyFrom.Type; } public TypeRepRef(string t) { ForceBoxed = false; Type = t; } public void SubstituteInType(Dictionary argMap) { if (!String.IsNullOrEmpty(Type)) { TypeVarMapper mapper = new TypeVarMapper(argMap, this); Type = Regex.Replace(Type, @"([\w|\.]+)*", new MatchEvaluator(mapper.ReplaceFromMap)); } } // public static implicit operator string(TypeRepRef t) // { // return t.ToString(); // } public override string ToString() { return Type; } #region Equality public bool Equals (TypeRepRef other) { if (other == null) return false; return ForceBoxed == other.ForceBoxed && Type == other.Type; } public override bool Equals (object obj) { TypeRepRef temp = obj as TypeRepRef; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (TypeRepRef a1, TypeRepRef a2) { return Object.Equals (a1, a2); } public static bool operator != (TypeRepRef a1, TypeRepRef a2) { return !(a1 == a2); } public override int GetHashCode () { return (Type ?? String.Empty).GetHashCode () ^ ForceBoxed.GetHashCode(); } #endregion } // Simple pairs to represent formal parameters public class ParamRepTemplate : IEquatable, IApplyTypeArgs { private TypeRepRef _type = null; public TypeRepRef Type { get { return _type; } set { _type=value; } } public string Name { get; set; } // ref or out param? [XmlAttribute("byref")] [System.ComponentModel.DefaultValueAttribute(false)] public bool IsByRef{ get; set; } public ParamRepTemplate () { IsByRef = false; } public ParamRepTemplate(ParamRepTemplate copyFrom) { if (copyFrom.Type != null) { Type = new TypeRepRef(copyFrom.Type); } if (!String.IsNullOrEmpty(copyFrom.Name)) { Name = copyFrom.Name; } IsByRef = copyFrom.IsByRef; } public ParamRepTemplate (string t, string a) { Type = new TypeRepRef(t); Name = a; IsByRef = false; } public ParamRepTemplate (string t, string a, bool isbyref) { Type = new TypeRepRef(t); Name = a; IsByRef = isbyref; } public void Apply(Dictionary args) { Type.SubstituteInType(args); } #region Equality public bool Equals (ParamRepTemplate other) { if (other == null) return false; return Type == other.Type && Name == other.Name && IsByRef == other.IsByRef; } public override bool Equals (object obj) { ParamRepTemplate temp = obj as ParamRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (ParamRepTemplate a1, ParamRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (ParamRepTemplate a1, ParamRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { int hashCode = Type != null ? Type.GetHashCode() : 0; return hashCode ^ (Name ?? String.Empty).GetHashCode () ^ IsByRef.GetHashCode(); } #endregion } // Represents a variable number of parameters public class ParamArrayRepTemplate : ParamRepTemplate, IEquatable { public ParamArrayRepTemplate () { } public ParamArrayRepTemplate(ParamArrayRepTemplate copyFrom) : base(copyFrom) { } public ParamArrayRepTemplate (string t, string a) : base(t, a) { } #region Equality public bool Equals (ParamArrayRepTemplate other) { return base.Equals(other); } public override bool Equals (object obj) { ParamArrayRepTemplate temp = obj as ParamArrayRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (ParamArrayRepTemplate a1, ParamArrayRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (ParamArrayRepTemplate a1, ParamArrayRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { return base.GetHashCode (); } #endregion } // A namespace alias entry. public class AliasRepTemplate : IEquatable { public string Alias { get; set; } public string Namespace { get; set; } public AliasRepTemplate() { Alias = null; Namespace = null; } public AliasRepTemplate(AliasRepTemplate copyFrom) { if (!String.IsNullOrEmpty(copyFrom.Alias)) { Alias = copyFrom.Alias; } if (!String.IsNullOrEmpty(copyFrom.Namespace)) { Namespace = copyFrom.Namespace; } } public AliasRepTemplate (string a, string u) { Alias = a; Namespace = u; } #region Equality public bool Equals (AliasRepTemplate other) { if (other == null) return false; return Alias == other.Alias && Namespace == other.Namespace; } public override bool Equals (object obj) { AliasRepTemplate temp = obj as AliasRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (AliasRepTemplate a1, AliasRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (AliasRepTemplate a1, AliasRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { return (Alias ?? String.Empty).GetHashCode () ^ (Namespace ?? String.Empty).GetHashCode (); } #endregion } // Never directly create a TranslationBase. Its a common root for translatable language entities public abstract class TranslationBase : IEquatable, IApplyTypeArgs { // Java imports required to make Java translation run private string[] _imports = null; [XmlArrayItem("Import")] public virtual string[] Imports { get { // if _java is not set then see if we have default imports, otherwise // assume imports is already correctly (un)set if (_imports == null && _java == null) { return mkImports(); } return _imports; } set { _imports = value; } } // The Java translation for this C# entity protected string _java = null; public virtual string Java { get { if (_java == null) { return mkJava(); } else { return _java; } } set { _java = value; } } // Emit this warning if we use this translation protected string _warning = null; public virtual string Warning { get { return _warning; } set { _warning = value; } } // Optional, but if present will let mkJava generate better java guess in some cases private TypeRepTemplate _surroundingType; [XmlIgnore] public TypeRepTemplate SurroundingType { get { return _surroundingType; } set { _surroundingType=value; } } public virtual string[] mkImports() { return null; } public string[] mkImports(Javastyle style) { string[] imports = mkImports(); if (style == Javastyle.MarkAuto) { for (int i = 0; i < imports.Length; i++) { imports[i] = imports[i] + " /*auto*/"; } } return imports; } public abstract string mkJava(); public string mkJava(Javastyle style) { string unAdornedJava = mkJava(); if (style == Javastyle.MarkAuto) { return "/*auto (/*" + unAdornedJava + "/*)*/"; } else { return unAdornedJava; } } protected TranslationBase() { Imports = null; } protected TranslationBase(TypeRepTemplate parent, TranslationBase copyFrom) { int len = 0; if (copyFrom.Imports != null) { len = copyFrom.Imports.Length; Imports = new String[len]; for (int i = 0; i < len; i++) { Imports[i] = copyFrom.Imports[i]; } } if (!String.IsNullOrEmpty(copyFrom.Java)) { Java = copyFrom.Java; } if (!String.IsNullOrEmpty(copyFrom.Warning)) { Warning = copyFrom.Warning; } SurroundingType = parent; } protected TranslationBase(string java) { Imports = null; Java = java; } protected TranslationBase (string[] imps, string java) { Imports = imps; Java = java; } protected string mkJavaParams(IList pars, ParamArrayRepTemplate paramarr) { StringBuilder parStr = new StringBuilder(); parStr.Append("("); foreach (ParamRepTemplate p in pars) { parStr.Append("${"+p.Name+"},"); } if (parStr[parStr.Length-1] == ',') { // remove trailing comma parStr.Remove(parStr.Length-1,1); } if (paramarr != null) { // ${*]n} means all parameters with position (1,2,..) greater than n // so ${*]0} means all arguments, ${*]1} means all but first etc. parStr.Append("${" + (pars.Count > 0 ? "," : "") + "*]"+pars.Count.ToString()+"}"); } parStr.Append(")"); return parStr.ToString(); } protected string mkTypeParams(String[] pars) { StringBuilder parStr = new StringBuilder(); parStr.Append("*["); foreach (string p in pars) { parStr.Append("${"+p+"},"); } if (parStr[parStr.Length-1] == ',') { parStr.Remove(parStr.Length-1,1); } parStr.Append("]*"); return parStr.ToString(); } // Instantiate type arguments public virtual void Apply(Dictionary args) { } #region Equality public bool Equals (TranslationBase other) { if (other == null) return false; if (Imports != other.Imports) { if (Imports == null || other.Imports == null || Imports.Length != other.Imports.Length) return false; for (int i = 0; i < Imports.Length; i++) { if (Imports[i] != other.Imports[i]) return false; } } return Java == other.Java && Warning == other.Warning; } public override bool Equals (object obj) { TranslationBase temp = obj as TranslationBase; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (TranslationBase a1, TranslationBase a2) { return Object.Equals (a1, a2); } public static bool operator != (TranslationBase a1, TranslationBase a2) { return !(a1 == a2); } public override int GetHashCode () { int hashCode = 0; if (Imports != null) { foreach (string e in Imports) { hashCode ^= e.GetHashCode(); } } return (Java ?? String.Empty).GetHashCode () ^ (Warning ?? String.Empty).GetHashCode () ^ hashCode; } #endregion } public class IterableRepTemplate : TranslationBase, IEquatable { public TypeRepRef ElementType { get; set; } public override string mkJava() { return "${expr}"; } public IterableRepTemplate () : base() { } public IterableRepTemplate(String ty) : base() { ElementType = new TypeRepRef(ty); } public IterableRepTemplate(TypeRepTemplate parent, IterableRepTemplate copyFrom) : base(parent, copyFrom) { if (copyFrom != null) { ElementType = new TypeRepRef(copyFrom.ElementType); } } public IterableRepTemplate (String ty, string[] imps, string javaRep) : base(imps, javaRep) { ElementType = new TypeRepRef(ty); } public override void Apply(Dictionary args) { if (ElementType != null) { ElementType.SubstituteInType(args); } base.Apply(args); } #region Equality public bool Equals (IterableRepTemplate other) { if (other == null) return false; return ElementType == other.ElementType && base.Equals(other); } public override bool Equals (object obj) { IterableRepTemplate temp = obj as IterableRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (IterableRepTemplate a1, IterableRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (IterableRepTemplate a1, IterableRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { int hashCode = ElementType != null ? ElementType.GetHashCode() : 0; return hashCode ^ base.GetHashCode (); } #endregion } public class ConstructorRepTemplate : TranslationBase, IEquatable { private List _params = null; [XmlArrayItem("Param")] public List Params { get { if (_params == null) _params = new List (); return _params; } } private ParamArrayRepTemplate _paramArray = null; public ParamArrayRepTemplate ParamArray { get { return _paramArray; } set { _paramArray = value; } } public override string mkJava() { string constructorName = "CONSTRUCTOR"; if (SurroundingType != null) { constructorName = SurroundingType.TypeName.Substring(SurroundingType.TypeName.LastIndexOf('.') + 1); if (SurroundingType.TypeParams != null && SurroundingType.TypeParams.Length > 0) { constructorName += mkTypeParams(SurroundingType.TypeParams); } } return "new " + constructorName + mkJavaParams(Params, ParamArray); } public override string[] mkImports() { if (SurroundingType != null) { return new string[] {SurroundingType.TypeName}; } else { return null; } } public ConstructorRepTemplate() : base() { } public ConstructorRepTemplate(TypeRepTemplate parent, ConstructorRepTemplate copyFrom) : base(parent, copyFrom) { foreach (ParamRepTemplate p in copyFrom.Params) { Params.Add(new ParamRepTemplate(p)); } ParamArray = copyFrom.ParamArray; } public ConstructorRepTemplate (List pars) : base() { _params = pars; } public ConstructorRepTemplate (List pars, string[] imps, string javaRep) : base(imps, javaRep) { _params = pars; } public override void Apply(Dictionary args) { if (Params != null) { foreach(ParamRepTemplate p in Params) { p.Apply(args); } } if (ParamArray != null) ParamArray.Apply(args); base.Apply(args); } #region Equality public bool Equals (ConstructorRepTemplate other) { if (other == null) return false; if (Params != other.Params) { if (Params == null || other.Params == null || Params.Count != other.Params.Count) return false; for (int i = 0; i < Params.Count; i++) { if (Params[i] != other.Params[i]) return false; } } if (ParamArray != other.ParamArray) return false; return base.Equals(other); } public override bool Equals (object obj) { ConstructorRepTemplate temp = obj as ConstructorRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (ConstructorRepTemplate a1, ConstructorRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (ConstructorRepTemplate a1, ConstructorRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { int hashCode = 0; foreach (ParamRepTemplate o in Params) { hashCode = hashCode ^ o.GetHashCode() ; } return base.GetHashCode () ^ hashCode ^ (ParamArray == null ? 0 : ParamArray.GetHashCode()); } #endregion } // Method has the same info as a delegate as a constructor plus a name and return type public class MethodRepTemplate : ConstructorRepTemplate, IEquatable { // Method name public string Name { get; set; } // Method name in Java (defaults to Name) private string _javaName = null; public string JavaName { get { return (_javaName == null || _javaName.Length == 0) ? Name : _javaName; } set { _javaName = value; } } private string[] _typeParams = null; [XmlArrayItem("Name")] public string[] TypeParams { get { if (_typeParams == null) { TypeParams = new string[0]; } return _typeParams; } set { // First time that TypeParams is set then create InstantiatedTypes as corresponding list of TypeVars if (value != null && InstantiatedTypes == null) { InstantiatedTypes = new TypeRepTemplate[value.Length]; for (int i = 0; i < value.Length; i++) { InstantiatedTypes[i] = new TypeVarRepTemplate(value[i]); } } _typeParams = value; } } [XmlIgnore] public TypeRepTemplate[] InstantiatedTypes { get; set; } // Return type private TypeRepRef _return = new TypeRepRef(); public TypeRepRef Return { get { return _return; } set { _return=value; } } // isStatic method? private bool _isStatic = false; [XmlAttribute("static")] [System.ComponentModel.DefaultValueAttribute(false)] public bool IsStatic { get { return _isStatic; } set { _isStatic = value; } } private bool _isPartialDefiner = false; [XmlAttribute("partial")] [System.ComponentModel.DefaultValueAttribute(false)] public bool IsPartialDefiner { get { return _isPartialDefiner; } set { _isPartialDefiner = value; } } public MethodRepTemplate() { IsStatic = false; IsPartialDefiner = false; } public MethodRepTemplate(TypeRepTemplate parent, MethodRepTemplate copyFrom) : base(parent, copyFrom) { if (!String.IsNullOrEmpty(copyFrom.Name)) { Name = copyFrom.Name; } int len = 0; if (copyFrom.TypeParams != null) { len = copyFrom.TypeParams.Length; TypeParams = new String[len]; for (int i = 0; i < len; i++) { TypeParams[i] = copyFrom.TypeParams[i]; } } if (copyFrom.InstantiatedTypes != null) { len = copyFrom.InstantiatedTypes.Length; InstantiatedTypes = new TypeRepTemplate[len]; for (int i = 0; i < len; i++) { InstantiatedTypes[i] = copyFrom.InstantiatedTypes[i].Instantiate(null); } } Return = new TypeRepRef(copyFrom.Return); IsStatic = copyFrom.IsStatic; IsPartialDefiner = copyFrom.IsPartialDefiner; } public MethodRepTemplate(string retType, string methodName, string[] tParams, List pars, string[] imps, string javaRep) : base(pars, imps, javaRep) { Name = methodName; TypeParams = tParams; Return = new TypeRepRef(retType); IsStatic = false; IsPartialDefiner = false; } public MethodRepTemplate (string retType, string methodName, string[] tParams, List pars) : this(retType, methodName, tParams, pars, null, null) { } public override string[] mkImports() { if (IsStatic && SurroundingType != null) { return new string[] {SurroundingType.TypeName}; } else { return null; } } public override string mkJava() { StringBuilder methStr = new StringBuilder(); // if we only have the definition, not the implementation, then don't emit any calls in the Java if (IsPartialDefiner) { return String.Empty; } if (IsStatic) { if (SurroundingType != null) { methStr.Append(SurroundingType.TypeName.Substring(SurroundingType.TypeName.LastIndexOf('.') + 1) + "."); } else { methStr.Append("TYPENAME."); } } else { methStr.Append("${this:16}."); } methStr.Append(JavaName); return methStr.ToString() + mkJavaParams(Params, ParamArray); } // TODO: filter out redefined type names public override void Apply(Dictionary args) { if (Return != null) { Return.SubstituteInType(args); } base.Apply(args); } #region Equality public bool Equals (MethodRepTemplate other) { if (other == null) return false; if (TypeParams != other.TypeParams) { if (TypeParams == null || other.TypeParams == null || TypeParams.Length != other.TypeParams.Length) return false; for (int i = 0; i < TypeParams.Length; i++) { if (TypeParams[i] != other.TypeParams[i]) return false; } } if (InstantiatedTypes != other.InstantiatedTypes) { if (InstantiatedTypes == null || other.InstantiatedTypes == null || InstantiatedTypes.Length != other.InstantiatedTypes.Length) return false; for (int i = 0; i < InstantiatedTypes.Length; i++) { if (InstantiatedTypes[i] != other.InstantiatedTypes[i]) return false; } } return Return == other.Return && Name == other.Name && JavaName == other.JavaName && IsStatic == other.IsStatic && IsPartialDefiner == other.IsPartialDefiner && base.Equals(other); } public override bool Equals (object obj) { MethodRepTemplate temp = obj as MethodRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (MethodRepTemplate a1, MethodRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (MethodRepTemplate a1, MethodRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { int hashCode = 0; if (TypeParams != null) { foreach (string o in TypeParams) { hashCode = hashCode ^ o.GetHashCode() ; } } if (InstantiatedTypes != null) { foreach (TypeRepTemplate o in InstantiatedTypes) { hashCode = hashCode ^ o.GetHashCode() ; } } hashCode = hashCode ^ (Return != null ? Return.GetHashCode() : 0); return hashCode ^ (Name ?? String.Empty).GetHashCode () ^ (JavaName ?? String.Empty).GetHashCode () ^ IsStatic.GetHashCode() ^ IsPartialDefiner.GetHashCode() ^ base.GetHashCode(); } #endregion } public class InvokeRepTemplate : MethodRepTemplate { public InvokeRepTemplate() { } public InvokeRepTemplate(TypeRepTemplate parent, MethodRepTemplate copyFrom) : base(parent, copyFrom) { } public InvokeRepTemplate (string retType, string methodName, string[] tParams, List pars) : base(retType, methodName, tParams, pars) { } // public override string mkJava() // { // return "${this:16}.Invoke" + mkJavaParams(this.Params); // } } // A user-defined cast from one type to another public class CastRepTemplate : TranslationBase, IEquatable { // From and To are fully qualified types private TypeRepRef _from; public TypeRepRef From { get { return _from; } set { _from = value; } } private TypeRepRef _to; public TypeRepRef To { get { return _to; } set { _to= value; } } public CastRepTemplate() : base() { } public CastRepTemplate(TypeRepTemplate parent, CastRepTemplate copyFrom) : base(parent, copyFrom) { if (copyFrom.From != null) { From = new TypeRepRef(copyFrom.From); } if (copyFrom.To != null) { To = new TypeRepRef(copyFrom.To); } } public CastRepTemplate (string fType, string tType, string[] imps, string java) : base(imps, java) { From = new TypeRepRef(fType); To = new TypeRepRef(tType); } public CastRepTemplate (string fType, string tType) : this(fType, tType, null, null) { } public override string[] mkImports() { if (SurroundingType != null) { return new string[] {SurroundingType.TypeName}; } else { return null; } } public override string mkJava() { if (From == null || To == null) { return null; } else { if (SurroundingType != null) { String myType = SurroundingType.TypeName.Substring(SurroundingType.TypeName.LastIndexOf('.') + 1); String toType = To.Type.Substring(To.Type.LastIndexOf('.') + 1); if (myType == toType) { // just overload various casts to my type return myType + ".__cast(${expr})"; } else { return myType + ".__cast${TYPEOF_totype}(${expr})"; } } else { return "__cast_" + To.Type.Replace('.','_') + "(${expr})"; } } } public override void Apply(Dictionary args) { if (From != null) { From.SubstituteInType(args); } if (To != null) { To.SubstituteInType(args); } base.Apply(args); } #region Equality public bool Equals (CastRepTemplate other) { if (other == null) return false; return From == other.From && To == other.To && base.Equals(other); } public override bool Equals (object obj) { CastRepTemplate temp = obj as CastRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (CastRepTemplate a1, CastRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (CastRepTemplate a1, CastRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { int hashCode = From != null ? From.GetHashCode() : 0; hashCode = hashCode ^ (To != null ? To.GetHashCode() : 0); return hashCode ^ base.GetHashCode(); } #endregion } // A member field definition public class FieldRepTemplate : TranslationBase, IEquatable { private TypeRepRef _type; public TypeRepRef Type { get { return _type; } set { _type=value; } } public string Name { get; set; } public FieldRepTemplate() : base() { } public FieldRepTemplate(TypeRepTemplate parent, FieldRepTemplate copyFrom) : base(parent, copyFrom) { if (!String.IsNullOrEmpty(copyFrom.Name)) { Name = copyFrom.Name; } if (copyFrom.Type != null) { Type = new TypeRepRef(copyFrom.Type); } } public FieldRepTemplate(string fType, string fName, string[] imps, string javaGet) : base(imps, javaGet) { Type = new TypeRepRef(fType); Name = fName; } public FieldRepTemplate (string fType, string fName) : this(fType, fName, null, null) { } public override string mkJava() { return "${this:16}." + Name; } public override void Apply(Dictionary args) { if (Type != null) { Type.SubstituteInType(args); } base.Apply(args); } #region Equality public bool Equals (FieldRepTemplate other) { if (other == null) return false; return Type == other.Type && Name == other.Name && base.Equals(other); } public override bool Equals (object obj) { FieldRepTemplate temp = obj as FieldRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (FieldRepTemplate a1, FieldRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (FieldRepTemplate a1, FieldRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { int hashCode = Type != null ? Type.GetHashCode() : 0; return hashCode ^ (Name ?? String.Empty).GetHashCode() ^ base.GetHashCode(); } #endregion } // A property definition. We need separate java translations for getter and setter. If JavaGet is null // then we can use Java (from TranslationBase) as the translation for gets. // Imports are shared between getter and setter (might lead to some unneccessary extra imports, but I'm // guessing that normally imports will be the same for both) public class PropRepTemplate : FieldRepTemplate, IEquatable { protected string _javaGet = null; [XmlElementAttribute("Get")] public virtual string JavaGet { get { if (!CanRead) return null; if (_javaGet == null) { if (_java == null) { return (CanRead ? "${this:16}.get" + Name + "()" : null); } else { return _java; } } else { return _javaGet; } } set { _javaGet = value; } } /* public override string Java { get { return JavaGet; } } */ protected string _javaSet = null; [XmlElementAttribute("Set")] public virtual string JavaSet { get { if (_javaSet == null) { return (CanWrite ? "${this:16}.set" + Name + "(${value})" : null); } else { return _javaSet; } } set { _javaSet = value; } } // canRead? private bool _canRead = true; [XmlAttribute("read")] [System.ComponentModel.DefaultValueAttribute(true)] public bool CanRead { get { return _canRead; } set { _canRead = value; } } // canWrite? private bool _canWrite = true; [XmlAttribute("write")] [System.ComponentModel.DefaultValueAttribute(true)] public bool CanWrite { get { return _canWrite; } set { _canWrite = value; } } public PropRepTemplate() : base() { } public PropRepTemplate(TypeRepTemplate parent, PropRepTemplate copyFrom) : base(parent, copyFrom) { if (!String.IsNullOrEmpty(copyFrom.JavaGet)) { JavaGet = copyFrom.JavaGet; } if (!String.IsNullOrEmpty(copyFrom.JavaSet)) { JavaSet = copyFrom.JavaSet; } CanRead = copyFrom.CanRead; CanWrite = copyFrom.CanWrite; } public PropRepTemplate(string fType, string fName, string[] imps, string javaGet, string javaSet) : base(fType, fName, imps, null) { JavaGet = javaGet; JavaSet = javaSet; } public PropRepTemplate (string fType, string fName) : this(fType, fName, null, null, null) { } public override string mkJava () { // favour JavaGet return JavaGet; } #region Equality public bool Equals (PropRepTemplate other) { if (other == null) return false; return JavaGet == other.JavaGet && JavaSet == other.JavaSet && base.Equals(other); } public override bool Equals (object obj) { PropRepTemplate temp = obj as PropRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (PropRepTemplate a1, PropRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (PropRepTemplate a1, PropRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { return (JavaGet ?? String.Empty).GetHashCode () ^ (JavaSet ?? String.Empty).GetHashCode () ^ base.GetHashCode (); } #endregion } // An indexer is like a unnamed property that has params public class IndexerRepTemplate : PropRepTemplate, IEquatable { private List _params = null; [XmlArrayItem("Param")] public List Params { get { if (_params == null) _params = new List (); return _params; } } private ParamArrayRepTemplate _paramArray = null; public ParamArrayRepTemplate ParamArray { get { return _paramArray; } set { _paramArray = value; } } private List _setParams = null; private List SetParams { get { if (_setParams == null) { _setParams = new List (); foreach (ParamRepTemplate p in Params) { _setParams.Add(p); } _setParams.Add(new ParamRepTemplate(Type.Type,"value")); } return _setParams; } } private ParamArrayRepTemplate _setParamArray = null; public ParamArrayRepTemplate SetParamArray { get { if (_setParamArray == null) { return ParamArray; } else { return _setParamArray; } } set { _setParamArray = value; } } [XmlElementAttribute("Get")] public override string JavaGet { get { if (!CanRead) return null; if (_javaGet == null) { if (_java == null) { return (CanRead ? "${this:16}.get___idx" + mkJavaParams(Params, ParamArray) : null); } else { return _java; } } else { return _javaGet; } } set { _javaGet = value; } } [XmlElementAttribute("Set")] public override string JavaSet { get { if (_javaSet == null) { return (CanWrite ? "${this:16}.set___idx" + mkJavaParams(SetParams, SetParamArray): null); } else { return _javaSet; } } set { _javaSet = value; } } public IndexerRepTemplate() : base() { } public IndexerRepTemplate(TypeRepTemplate parent, IndexerRepTemplate copyFrom) : base(parent, copyFrom) { foreach (ParamRepTemplate p in copyFrom.Params) { Params.Add(new ParamRepTemplate(p)); } if (copyFrom._setParams != null) { foreach (ParamRepTemplate p in copyFrom._setParams) { SetParams.Add(new ParamRepTemplate(p)); } } _paramArray = copyFrom._paramArray; _setParamArray = copyFrom._setParamArray; if (!String.IsNullOrEmpty(copyFrom.JavaGet)) { JavaGet = copyFrom.JavaGet; } if (!String.IsNullOrEmpty(copyFrom.JavaSet)) { JavaSet = copyFrom.JavaSet; } } public IndexerRepTemplate(string fType, List pars) : base(fType, "this") { _params = pars; } public IndexerRepTemplate (string fType, List pars, string[] imps, string javaGet, string javaSet) : base(fType, "this",imps,javaGet,javaSet) { _params = pars; } public override void Apply(Dictionary args) { if (Params != null) { foreach(ParamRepTemplate p in Params) { p.Apply(args); } } if (_setParams != null) { foreach(ParamRepTemplate p in _setParams) { p.Apply(args); } } if (_paramArray != null) _paramArray.Apply(args); if (_setParamArray != null) _setParamArray.Apply(args); base.Apply(args); } #region Equality public bool Equals (IndexerRepTemplate other) { if (other == null) return false; if (Params != other.Params) { if (Params == null || other.Params == null || Params.Count != other.Params.Count) return false; for (int i = 0; i < Params.Count; i++) { if (Params[i] != other.Params[i]) return false; } } if (ParamArray != other.ParamArray) return false; if (SetParamArray != other.SetParamArray) return false; return base.Equals(other); } public override bool Equals (object obj) { IndexerRepTemplate temp = obj as IndexerRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (IndexerRepTemplate a1, IndexerRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (IndexerRepTemplate a1, IndexerRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { int hashCode = 0; foreach (ParamRepTemplate o in Params) { hashCode = hashCode ^ o.GetHashCode() ; } return base.GetHashCode () ^ hashCode ^ (ParamArray == null ? 0 : ParamArray.GetHashCode()) ^ (_setParamArray == null ? 0 : _setParamArray.GetHashCode()); } #endregion } // A member of an enum, may also have a numeric value public class EnumMemberRepTemplate : TranslationBase, IEquatable { public string Name { get; set; } public string Value { get; set; } public EnumMemberRepTemplate() : base() { } public EnumMemberRepTemplate(TypeRepTemplate parent, EnumMemberRepTemplate copyFrom) : base(parent, copyFrom) { if (!String.IsNullOrEmpty(copyFrom.Name)) { Name = copyFrom.Name; } if (!String.IsNullOrEmpty(copyFrom.Value)) { Value = copyFrom.Value; } } public EnumMemberRepTemplate (string n) : this(n, null, null, null) { } public EnumMemberRepTemplate (string n, string v) : this(n, v, null, null) { } public EnumMemberRepTemplate (string n, string v, string[] imps, string java) : base(imps, java) { Name = n; Value = v; } public override string mkJava() { return "${this:16}." + Name; } #region Equality public bool Equals (EnumMemberRepTemplate other) { if (other == null) return false; return Name == other.Name && Value == other.Value && base.Equals(other); } public override bool Equals (object obj) { EnumMemberRepTemplate temp = obj as EnumMemberRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (EnumMemberRepTemplate a1, EnumMemberRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (EnumMemberRepTemplate a1, EnumMemberRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { return (Name ?? String.Empty).GetHashCode () ^ (Value ?? String.Empty).GetHashCode () ^ base.GetHashCode (); } #endregion } // Base Template for classes, interfaces, enums, etc. [Serializable] public abstract class TypeRepTemplate : TranslationBase, IEquatable { private string _variant = ""; // Translation Variant [XmlAttribute("variant")] [System.ComponentModel.DefaultValueAttribute("")] public string Variant { get { if (_variant == null) { _variant = ""; } return _variant; } set { _variant = value; } } // Type Name [XmlElementAttribute("Name")] public string TypeName { get; set; } private string[] _typeParams = null; [XmlArrayItem("Name")] public string[] TypeParams { get { if (_typeParams == null) { TypeParams = new string[0]; } return _typeParams; } set { // First time that TypeParams is set then create InstantiatedTypes as corresponding list of TypeVars if (value != null && InstantiatedTypes == null) { InstantiatedTypes = new TypeRepTemplate[value.Length]; for (int i = 0; i < value.Length; i++) { InstantiatedTypes[i] = new TypeVarRepTemplate(value[i]); } } _typeParams = value; } } [XmlIgnore] public TypeRepTemplate[] InstantiatedTypes { get; set; } [XmlIgnore] public Dictionary TyVarMap { get { Dictionary ret = new Dictionary(TypeParams.Length); for (int i = 0; i < TypeParams.Length; i++) { ret[TypeParams[i]] = InstantiatedTypes[i]; } return ret; } } // Path to use when resolving types [XmlArrayItem("Use")] public string[] Uses { get; set; } // Aliases for namespaces [XmlArrayItem("Alias")] public AliasRepTemplate[] Aliases { get; set; } protected List _casts = null; [XmlArrayItem("Cast")] public virtual List Casts { get { if (_casts == null) _casts = new List (); return _casts; } } private string[] _inherits; [XmlArrayItem("Type")] public string[] Inherits { get { if (_inherits == null) { _inherits = new string[] { "System.Object" }; } return _inherits; } set { if (value != null) { _inherits= new string[value.Length]; for (int i = 0; i < value.Length; i++) { _inherits[i] = (value[i] != null ? value[i].Replace("<","*[").Replace(">","]*") : null); } } else { _inherits = null; } } } // Client can set IsExplicitNull. If so then null IsA anytype private bool _isExplicitNull = false; [XmlIgnore] public bool IsExplicitNull { get { return _isExplicitNull; } set { _isExplicitNull = value; } } // Set if value is wrapped in a RefSupport object (used for ref and out params) private bool _isWrapped = false; [XmlIgnore] public bool IsWrapped { get { return _isWrapped; } set { _isWrapped = value; } } // Client can set _isUnboxedType. If so then we know the expression / type is unboxed private bool _isUnboxedType = false; [XmlIgnore] public bool IsUnboxedType { get { return _isUnboxedType; } set { _isUnboxedType = value; } } private String _boxedJava = null; public String BoxedJava { get { if (String.IsNullOrEmpty(_boxedJava)) { _boxedJava = Java; } return _boxedJava; } set { _boxedJava = value; } } // True if we have a separate representation for boxed and unboxed versions // (true for primitive types like int) private bool hasBoxedRep = false; [XmlAttribute("has_boxed_rep")] [System.ComponentModel.DefaultValueAttribute(false)] public bool HasBoxedRep { get { return hasBoxedRep; } set { hasBoxedRep = value; } } [XmlIgnore] public string BoxExpressionTemplate { get { return (String.IsNullOrEmpty(BoxedJava) ? "" : "((" + BoxedJava + ")${expr})"); } } // Equivalent to "this is TypeVarRepTemplate" [XmlIgnore] public virtual bool IsTypeVar { get { return (this is TypeVarRepTemplate); } } // Equivalent to "this is UnknownRepTemplate" [XmlIgnore] public virtual bool IsUnknownType { get { return (this is UnknownRepTemplate); } } // Ugly, keep a copy of the tree. Its convenient if these are passed around with the type private object _tree = null; [XmlIgnore] public object Tree { get { return _tree; } set { _tree = value; } } public TypeRepTemplate() : base() { TypeName = null; Uses = null; Aliases = null; } protected TypeRepTemplate(string typeName) : this() { TypeName = typeName; } protected TypeRepTemplate(TypeRepTemplate copyFrom) :base(null, copyFrom) { if (!String.IsNullOrEmpty(copyFrom.TypeName)) { TypeName = copyFrom.TypeName; } int len = 0; if (copyFrom.TypeParams != null) { len = copyFrom.TypeParams.Length; TypeParams = new String[len]; for (int i = 0; i < len; i++) { TypeParams[i] = copyFrom.TypeParams[i]; } } if (copyFrom.InstantiatedTypes != null) { len = copyFrom.InstantiatedTypes.Length; InstantiatedTypes = new TypeRepTemplate[len]; for (int i = 0; i < len; i++) { InstantiatedTypes[i] = copyFrom.InstantiatedTypes[i]; } } if (copyFrom.Uses != null) { len = copyFrom.Uses.Length; Uses = new String[len]; for (int i = 0; i < len; i++) { Uses[i] = copyFrom.Uses[i]; } } if (copyFrom.Aliases != null) { len = copyFrom.Aliases.Length; Aliases = new AliasRepTemplate[len]; for (int i = 0; i < len; i++) { Aliases[i] = new AliasRepTemplate(copyFrom.Aliases[i]); } } foreach (CastRepTemplate c in copyFrom.Casts) { Casts.Add(new CastRepTemplate(this, c)); } if (copyFrom.Inherits != null) { len = copyFrom.Inherits.Length; Inherits = new String[len]; for (int i = 0; i < len; i++) { Inherits[i] = copyFrom.Inherits[i]; } } IsExplicitNull = copyFrom.IsExplicitNull; IsUnboxedType = copyFrom.IsUnboxedType; Variant = copyFrom.Variant; BoxedJava = copyFrom.BoxedJava; HasBoxedRep = copyFrom.HasBoxedRep; Tree = copyFrom.Tree; } protected TypeRepTemplate(string tName, string[] tParams, string[] usePath, AliasRepTemplate[] aliases, string[] imports, string javaTemplate) : base(imports, javaTemplate) { TypeName = tName; TypeParams = tParams; Uses = usePath; Aliases = aliases; } public override string mkJava() { string ret = String.Empty; if (TypeName != null && TypeName != String.Empty) { ret = TypeName.Substring(TypeName.LastIndexOf('.') + 1); if (TypeParams != null && TypeParams.Length > 0) { ret += mkTypeParams(TypeParams); } } return ret; } public override string[] mkImports() { if (TypeName != null) { return new string[] {TypeName}; } else { return null; } } protected Dictionary mkTypeMap(ICollection args) { Dictionary ret = new Dictionary(); if (args == null) { return ret; } if (args.Count == TypeParams.Length) { int i = 0; foreach (TypeRepTemplate sub in args) { ret[TypeParams[i]] = sub; i++; } } else { throw new ArgumentOutOfRangeException("Incorrect number of type arguments supplied when instantiating generic type"); } return ret; } // Make a copy of 'this' and instantiate type variables with types and type variables. public abstract TypeRepTemplate Instantiate(ICollection args); public override void Apply(Dictionary args) { if (Casts != null) { foreach(CastRepTemplate c in Casts) { c.Apply(args); } } if (Inherits != null) { for(int i = 0; i < Inherits.Length; i++) { Inherits[i] = TemplateUtilities.SubstituteInType(Inherits[i],args); } } InstantiatedTypes = new TypeRepTemplate[InstantiatedTypes.Length]; if (args != null) { for (int i = 0; i < TypeParams.Length; i++) { InstantiatedTypes[i] = args[TypeParams[i]]; } } BoxedJava = TemplateUtilities.SubstituteInType(BoxedJava,args); base.Apply(args); } // Resolve a method call (name and arg types) public virtual ResolveResult Resolve(String name, IList args, DirectoryHT AppEnv) { if (Inherits != null) { foreach (String b in Inherits) { TypeRepTemplate baseType = BuildType(b, AppEnv); if (baseType != null) { ResolveResult ret = baseType.Resolve(name,args,AppEnv); if (ret != null) return ret; } } } return null; } // Resolve a field or property access public virtual ResolveResult Resolve(String name, bool forWrite, DirectoryHT AppEnv) { if (Inherits != null) { foreach (String b in Inherits) { TypeRepTemplate baseType = BuildType(b, AppEnv); if (baseType != null) { ResolveResult ret = baseType.Resolve(name, forWrite, AppEnv); if (ret != null) return ret; } } } return null; } // Resolve a indexer call (arg types) public virtual ResolveResult ResolveIndexer(IList args, DirectoryHT AppEnv) { if (Inherits != null) { foreach (String b in Inherits) { TypeRepTemplate baseType = BuildType(b, AppEnv); if (baseType != null) { ResolveResult ret = baseType.ResolveIndexer(args,AppEnv); if (ret != null) return ret; } } } return null; } // Resolve a cast from this type to castTo public virtual ResolveResult ResolveCastTo(TypeRepTemplate castTo, DirectoryHT AppEnv) { if (Casts != null) { foreach (CastRepTemplate c in Casts) { if (c.To != null) { // Is this a cast from us? TypeRepTemplate fromTy = null; if (c.From != null) { fromTy = BuildType(c.From, AppEnv); } if (c.From == null || (fromTy != null && fromTy.TypeName == TypeName)) { // cast from us TypeRepTemplate toTy = BuildType(c.To, AppEnv); if (toTy.IsA(castTo, AppEnv) && castTo.IsA(toTy, AppEnv)) { ResolveResult res = new ResolveResult(); res.Result = c; res.ResultType = toTy; return res; } } } } } if (Inherits != null) { foreach (String b in Inherits) { TypeRepTemplate baseType = BuildType(b, AppEnv); if (baseType != null) { ResolveResult ret = baseType.ResolveCastTo(castTo,AppEnv); if (ret != null) return ret; } } } return null; } // Resolve a cast to this type from castFrom public virtual ResolveResult ResolveCastFrom(TypeRepTemplate castFrom, DirectoryHT AppEnv) { if (Casts != null) { foreach (CastRepTemplate c in Casts) { if (c.From != null) { // Is this a cast to us? TypeRepTemplate toTy = null; if (c.To != null) { toTy = BuildType(c.To, AppEnv); } if (c.To == null || (toTy != null && toTy.TypeName == TypeName)) { // cast to us TypeRepTemplate fromTy = BuildType(c.From, AppEnv); if (castFrom.IsA(fromTy, AppEnv) && fromTy.IsA(castFrom, AppEnv)) { ResolveResult res = new ResolveResult(); res.Result = c; res.ResultType = toTy; return res; } } } } } return null; } public virtual ResolveResult ResolveIterable(DirectoryHT AppEnv) { if (Inherits != null) { foreach (String b in Inherits) { TypeRepTemplate baseType = BuildType(b, AppEnv); if (baseType != null) { ResolveResult ret = baseType.ResolveIterable(AppEnv); if (ret != null) return ret; } } } return null; } // Returns true if other is a subclass, or implements our interface public virtual bool IsA (TypeRepTemplate other, DirectoryHT AppEnv) { if (this.IsExplicitNull) { return true; } if (other.TypeName == this.TypeName) { // See if generic arguments 'match' if (InstantiatedTypes != null && other.InstantiatedTypes != null && InstantiatedTypes.Length == other.InstantiatedTypes.Length) { bool isA = true; for (int i = 0; i < InstantiatedTypes.Length; i++) { if (!InstantiatedTypes[i].IsA(other.InstantiatedTypes[i],AppEnv)) { isA = false; break; } } return isA; } else { // might be equal if they both represent "nothing" return (InstantiatedTypes == null && (other.InstantiatedTypes == null || other.InstantiatedTypes.Length == 0)) || (other.InstantiatedTypes == null && (InstantiatedTypes == null || InstantiatedTypes.Length == 0)); } } else if (Inherits != null) { foreach (String ibase in Inherits) { TypeRepTemplate tbase = BuildType(ibase, AppEnv, new UnknownRepTemplate(ibase)); if (tbase.IsA(other,AppEnv)) { return true; } } } return false; } private class ParseResult { public ParseResult(List inParses, String inStr) { Parses = inParses; RemainingStr = inStr; } public List Parses; public String RemainingStr; } // returns a list of type reps from a string representation: // (*[, , ...]*)?([])*, ..... private ParseResult buildTypeList(string typeList, DirectoryHT AppEnv) { List types = new List(); string typeStr = typeList.TrimStart(); bool moreTypes = true; while (moreTypes) { // get type name from the start int nameEnd = typeStr.IndexOfAny(new char[] { '*','[',']',','}); string typeName = typeStr.Substring(0,(nameEnd >= 0 ? nameEnd : typeStr.Length)).TrimEnd(); typeStr = typeStr.Substring(typeName.Length).TrimStart(); // build basetype TypeRepTemplate typeRep = null; // Is it a type var? foreach (string p in TypeParams) { if (p == typeName) { typeRep = new TypeVarRepTemplate(typeName); break; } } if (typeRep == null) { // Not a type var, look for a type List tyArgs = new List(); // Do we have type arguments? if (typeStr.Length > 0 && typeStr.StartsWith("*[")) { // isolate type arguments ParseResult args = buildTypeList(typeStr.Substring(2), AppEnv); tyArgs = args.Parses; typeStr = args.RemainingStr.TrimStart(); if (typeStr.StartsWith("]*")) { typeStr = typeStr.Substring(2).TrimStart(); } else { throw new Exception("buildTypeList: Cannot parse " + types); } } typeRep = AppEnv.Search(this.Uses, typeName + (tyArgs.Count > 0 ? "'" + tyArgs.Count.ToString() : ""), new UnknownRepTemplate(typeName)); if (!typeRep.IsUnknownType && tyArgs.Count > 0) { typeRep = typeRep.Instantiate(tyArgs); } } // Take care of arrays .... while (typeStr.StartsWith("[]")) { TypeRepTemplate arrayType = AppEnv.Search("System.Array'1", new UnknownRepTemplate("System.Array'1")); typeRep = arrayType.Instantiate(new TypeRepTemplate[] { typeRep }); typeStr = typeStr.Substring(2).TrimStart(); } types.Add(typeRep); moreTypes = typeStr.StartsWith(","); if (moreTypes) { typeStr = typeStr.Substring(1).TrimStart(); } } return new ParseResult(types, typeStr); } // Builds a type rep from a string representation // "type_name" // "[]" // "[, ...]" public TypeRepTemplate BuildType(TypeRepRef typeRep, DirectoryHT AppEnv) { return BuildType(typeRep.Type, AppEnv, null); } public TypeRepTemplate BuildType(string typeRep, DirectoryHT AppEnv) { return BuildType(typeRep, AppEnv, null); } public TypeRepTemplate BuildType(TypeRepRef typeRep, DirectoryHT AppEnv, TypeRepTemplate def) { return BuildType(typeRep.Type, AppEnv, def); } public TypeRepTemplate BuildType(string typeRep, DirectoryHT AppEnv, TypeRepTemplate def) { if (String.IsNullOrEmpty(typeRep)) return def; ParseResult parseTypes = buildTypeList(typeRep, AppEnv); if (parseTypes.Parses != null && parseTypes.Parses.Count == 1 && String.IsNullOrEmpty(parseTypes.RemainingStr.Trim())) { return parseTypes.Parses.ToArray()[0] ?? def; } else { return def; } } #region deserialization private static XmlReaderSettings _templateReaderSettings = null; /// /// Reader Settings used when reading translation templates. Validate against schemas /// public static XmlReaderSettings TemplateReaderSettings { get { if (_templateReaderSettings == null) { _templateReaderSettings = new XmlReaderSettings(); _templateReaderSettings.ValidationType = ValidationType.Schema; _templateReaderSettings.ValidationFlags |= XmlSchemaValidationFlags.ReportValidationWarnings; _templateReaderSettings.ValidationEventHandler += new ValidationEventHandler(ValidationCallBack); } return _templateReaderSettings; } } // Display any warnings or errors while validating translation templates. private static void ValidationCallBack(object sender, ValidationEventArgs args) { if (args.Severity == XmlSeverityType.Warning) Console.WriteLine("\tWarning: Matching schema not found. No validation occurred." + args.Message); else Console.WriteLine("\tValidation error: " + args.Message); } private static object Deserialize (Stream fs, System.Type t) { object o = null; // Create the XmlReader object. // XmlReader reader = XmlReader.Create(fs, TemplateReaderSettings); XmlSerializer serializer = new XmlSerializer (t, Constants.TranslationTemplateNamespace); //o = serializer.Deserialize (reader); o = serializer.Deserialize (fs); return o; } private static TypeRepTemplate Deserialize (Stream s) { TypeRepTemplate ret = null; XmlReaderSettings settings = new XmlReaderSettings (); settings.IgnoreWhitespace = true; settings.IgnoreComments = true; XmlReader reader = XmlReader.Create (s, settings); //XmlTextReader reader = new XmlTextReader(s); string typeType = null; // class, interface, enum, etc. bool found = false; while (reader.Read () && !found) { if (reader.NodeType == XmlNodeType.Element) { switch (reader.LocalName) { case "Class": typeType = "Twiglet.CS2J.Translator.TypeRep.ClassRepTemplate"; break; case "Struct": typeType = "Twiglet.CS2J.Translator.TypeRep.StructRepTemplate"; break; case "Interface": typeType = "Twiglet.CS2J.Translator.TypeRep.InterfaceRepTemplate"; break; case "Enum": typeType = "Twiglet.CS2J.Translator.TypeRep.EnumRepTemplate"; break; case "Delegate": typeType = "Twiglet.CS2J.Translator.TypeRep.DelegateRepTemplate"; break; default: typeType = "UnknownType"; break; } found = true; } } s.Seek (0, SeekOrigin.Begin); ret = (TypeRepTemplate)Deserialize (s, System.Type.GetType (typeType)); return ret; } public static TypeRepTemplate newInstance (Stream s) { return (TypeRepTemplate)Deserialize (s); } #endregion deserialization #region Equality public bool Equals (TypeRepTemplate other) { if (other == null) return false; if (Uses != other.Uses) { if (Uses == null || other.Uses == null || Uses.Length != other.Uses.Length) return false; for (int i = 0; i < Uses.Length; i++) { if (Uses[i] != other.Uses[i]) return false; } } if (Aliases != other.Aliases) { if (Aliases == null || other.Aliases == null || Aliases.Length != other.Aliases.Length) return false; for (int i = 0; i < Aliases.Length; i++) { if (Aliases[i] != other.Aliases[i]) return false; } } if (TypeParams != other.TypeParams) { if (TypeParams == null || other.TypeParams == null || TypeParams.Length != other.TypeParams.Length) return false; for (int i = 0; i < TypeParams.Length; i++) { if (TypeParams[i] != other.TypeParams[i]) return false; } } if (Casts != other.Casts) { if (Casts == null || other.Casts == null || Casts.Count != other.Casts.Count) return false; for (int i = 0; i < Casts.Count; i++) { if (Casts[i] != other.Casts[i]) return false; } } if (InstantiatedTypes != other.InstantiatedTypes) { if (InstantiatedTypes == null || other.InstantiatedTypes == null || InstantiatedTypes.Length != other.InstantiatedTypes.Length) return false; for (int i = 0; i < InstantiatedTypes.Length; i++) { if (InstantiatedTypes[i] != other.InstantiatedTypes[i]) return false; } } return IsExplicitNull == other.IsExplicitNull && IsUnboxedType == other.IsUnboxedType && TypeName == other.TypeName && Variant == other.Variant && BoxedJava == other.BoxedJava && base.Equals(other); } public override bool Equals (object obj) { TypeRepTemplate temp = obj as TypeRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (TypeRepTemplate a1, TypeRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (TypeRepTemplate a1, TypeRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { int hashCode = base.GetHashCode (); if (Uses != null) { foreach (string e in Uses) { hashCode ^= e.GetHashCode(); } } if (Aliases != null) { foreach (AliasRepTemplate e in Aliases) { hashCode ^= e.GetHashCode(); } } if (TypeParams != null) { foreach (string e in TypeParams) { hashCode ^= e.GetHashCode(); } } if (Casts != null) { foreach (CastRepTemplate e in Casts) { hashCode ^= e.GetHashCode(); } } if (InstantiatedTypes != null) { foreach (TypeRepTemplate ty in InstantiatedTypes) { hashCode ^= ty.GetHashCode(); } } return (Java ?? String.Empty).GetHashCode() ^ IsExplicitNull.GetHashCode() ^ IsUnboxedType.GetHashCode() ^ Variant.GetHashCode() ^ BoxedJava.GetHashCode() ^ hashCode; } #endregion public string mkFormattedTypeName(bool incNameSpace, string langle, string rangle) { StringBuilder fmt = new StringBuilder(); if (TypeName == "System.Array") { fmt.Append(InstantiatedTypes[0].mkFormattedTypeName(incNameSpace, langle, rangle)); fmt.Append("[]"); } else { fmt.Append(TypeName.Substring(incNameSpace ? 0 : TypeName.LastIndexOf('.')+1)); if (InstantiatedTypes != null && InstantiatedTypes.Length > 0) { bool isFirst = true; fmt.Append(langle); foreach (TypeRepTemplate t in InstantiatedTypes) { if (!isFirst) fmt.Append(", "); fmt.Append(t.mkFormattedTypeName(incNameSpace, langle, rangle)); isFirst = false; } fmt.Append(rangle); } } return fmt.ToString(); } public string mkFormattedTypeName() { return mkFormattedTypeName(true, "<", ">"); } public string mkSafeTypeName() { return mkFormattedTypeName(true, "*[", "]*"); } public override String ToString() { return mkFormattedTypeName(); } } [XmlType("Enum")] public class EnumRepTemplate : TypeRepTemplate, IEquatable { private List _members = null; [XmlArrayItem("Member")] public List Members { get { if (_members == null) _members = new List (); return _members; } } private List _enumCasts = null; private List EnumCasts { get { if (_enumCasts == null) { _enumCasts = new List (); CastRepTemplate kast = new CastRepTemplate(); kast.From = new TypeRepRef("System.Int32"); kast.Java = "${TYPEOF_totype:16}.values()[${expr}]"; _enumCasts.Add(kast); kast = new CastRepTemplate(); kast.To = new TypeRepRef("System.Int32"); kast.Java = "((Enum)${expr}).ordinal()"; _enumCasts.Add(kast); } return _enumCasts; } } [XmlArrayItem("Cast")] public override List Casts { get { if (_casts == null) { return EnumCasts; } else { return _casts; } } } public EnumRepTemplate() : base() { Inherits = new string[] { "System.Enum" }; } public EnumRepTemplate(EnumRepTemplate copyFrom) : base(copyFrom) { foreach (EnumMemberRepTemplate m in copyFrom.Members) { Members.Add(new EnumMemberRepTemplate(this, m)); } } public EnumRepTemplate (List ms) : base() { _members = ms; } public override ResolveResult Resolve(String name, bool forWrite, DirectoryHT AppEnv) { if (Members != null) { foreach (EnumMemberRepTemplate m in Members) { if (m.Name == name) { ResolveResult res = new ResolveResult(); res.Result = m; res.ResultType = this; return res; } } } return base.Resolve(name, forWrite, AppEnv); } public override TypeRepTemplate Instantiate(ICollection args) { EnumRepTemplate copy = new EnumRepTemplate(this); if (args != null && args.Count != 0) { copy.Apply(mkTypeMap(args)); } return copy; } #region Equality public bool Equals (EnumRepTemplate other) { if (other == null) return false; if (Members != other.Members) { if (Members == null || other.Members == null || Members.Count != other.Members.Count) return false; for (int i = 0; i < Members.Count; i++) { if (Members[i] != other.Members[i]) return false; } } return base.Equals(other); } public override bool Equals (object obj) { EnumRepTemplate temp = obj as EnumRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (EnumRepTemplate a1, EnumRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (EnumRepTemplate a1, EnumRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { int hashCode = base.GetHashCode (); if (Members != null) { foreach (EnumMemberRepTemplate e in Members) { hashCode ^= e.GetHashCode(); } } return hashCode; } #endregion } [XmlType("Delegate")] public class DelegateRepTemplate : InterfaceRepTemplate, IEquatable { private InvokeRepTemplate _invoke = null; public InvokeRepTemplate Invoke { get { return _invoke; } set { _invoke = value; } } public DelegateRepTemplate() : base() { } public DelegateRepTemplate(DelegateRepTemplate copyFrom) : base(copyFrom) { if (copyFrom.Invoke != null) { Invoke = new InvokeRepTemplate(this, copyFrom.Invoke); } } public override ResolveResult Resolve(String name, IList args, DirectoryHT AppEnv) { if ("Invoke" == name && matchParamsToArgs(Invoke.Params, Invoke.ParamArray, args, AppEnv)) { ResolveResult res = new ResolveResult(); res.Result = Invoke; res.ResultType = BuildType(Invoke.Return, AppEnv); return res; } return base.Resolve(name, args, AppEnv); } public override void Apply(Dictionary args) { Invoke.Apply(args); base.Apply(args); } public override TypeRepTemplate Instantiate(ICollection args) { DelegateRepTemplate copy = new DelegateRepTemplate(this); if (args != null && args.Count != 0) { copy.Apply(mkTypeMap(args)); } return copy; } #region Equality public bool Equals (DelegateRepTemplate other) { if (other == null) return false; return Invoke == other.Invoke && base.Equals(other); } public override bool Equals (object obj) { DelegateRepTemplate temp = obj as DelegateRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (DelegateRepTemplate a1, DelegateRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (DelegateRepTemplate a1, DelegateRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { int hashCode = base.GetHashCode (); return (Invoke ?? new InvokeRepTemplate()).GetHashCode() ^ hashCode; } #endregion } // Base Template for classes, interfaces, etc. [XmlType("Interface")] public class InterfaceRepTemplate : TypeRepTemplate, IEquatable { private List _methods = null; [XmlArrayItem("Method")] public List Methods { get { if (_methods == null) _methods = new List (); return _methods; } } private List _properties = null; [XmlArrayItem("Property")] public List Properties { get { if (_properties == null) _properties = new List (); return _properties; } } private List _events = null; [XmlArrayItem("Event")] public List Events { get { if (_events == null) _events = new List (); return _events; } } private List _indexers = null; [XmlArrayItem("Indexer")] public List Indexers { get { if (_indexers == null) _indexers = new List (); return _indexers; } } private IterableRepTemplate _iterable = null; public IterableRepTemplate Iterable { get { return _iterable; } set { _iterable = value; } } public InterfaceRepTemplate () : base() { Inherits = null; } public InterfaceRepTemplate(InterfaceRepTemplate copyFrom) : base(copyFrom) { foreach (MethodRepTemplate m in copyFrom.Methods) { Methods.Add(new MethodRepTemplate(this, m)); } foreach (PropRepTemplate p in copyFrom.Properties) { Properties.Add(new PropRepTemplate(this, p)); } foreach (FieldRepTemplate e in copyFrom.Events) { Events.Add(new FieldRepTemplate(this, e)); } foreach (IndexerRepTemplate i in copyFrom.Indexers) { Indexers.Add(new IndexerRepTemplate(this, i)); } if (copyFrom.Iterable != null) { Iterable = new IterableRepTemplate(this, copyFrom.Iterable); } } public InterfaceRepTemplate(string typeName) : base(typeName) { } protected InterfaceRepTemplate(string tName, string[] tParams, string[] usePath, AliasRepTemplate[] aliases, string[] inherits, List ms, List ps, List es, List ixs, string[] imps, string javaTemplate) : base(tName, tParams, usePath, aliases, imps, javaTemplate) { Inherits = inherits; _methods = ms; _properties = ps; _events = es; _indexers = ixs; } public override void Apply(Dictionary args) { if (Methods != null) { foreach(MethodRepTemplate m in Methods) { m.Apply(args); } } if (Properties != null) { foreach(PropRepTemplate p in Properties) { p.Apply(args); } } if (Events != null) { foreach(FieldRepTemplate e in Events) { e.Apply(args); } } if (Indexers != null) { foreach (IndexerRepTemplate i in Indexers) { i.Apply(args); } } if (Iterable != null) { Iterable.Apply(args); } base.Apply(args); } // Returns true if we are a subclass of other, or implements its interface // public override bool IsA (TypeRepTemplate other, DirectoryHT AppEnv) { // InterfaceRepTemplate i = other as InterfaceRepTemplate; // if (i == null) // { // return false; // } // if (i.TypeName == this.TypeName) // { // return true; // } // return base.IsA(other,AppEnv); // } // public override ResolveResult Resolve(String name, bool forWrite, DirectoryHT AppEnv) { if (Properties != null) { foreach (PropRepTemplate p in Properties) { if (p.Name == name && ((forWrite && p.CanWrite) || (!forWrite && p.CanRead))) { ResolveResult res = new ResolveResult(); res.Result = p; res.ResultType = BuildType(p.Type, AppEnv); return res; } } } return base.Resolve(name, forWrite, AppEnv); } /// /// Can we match Params + ParamArray against args /// /// protected bool matchParamsToArgs(IList param, ParamArrayRepTemplate paramArray, IList args, DirectoryHT AppEnv) { int argsLength = args == null ? 0 : args.Count; int paramsLength = param == null ? 0 : param.Count; if (paramsLength > 0) { // Check fixed parameters against args if (argsLength < paramsLength) { // Length of required fixed Parameters is greater than number of available arguments return false; } else { // Check fixed Parameters against args // check that for each argument in the caller its type 'IsA' the type of the formal parameter for (int idx = 0; idx < paramsLength; idx++) { if (args[idx] == null || !args[idx].IsA(BuildType(param[idx].Type, AppEnv, new UnknownRepTemplate(param[idx].Type.Type)),AppEnv)) { // An argument doesn't match return false; } } } } if (argsLength == paramsLength) // OK, fixed args check out. return true; if (paramArray == null) // Extra args and no param array return false; // We have args left over, check param argument. String paramsTypeStr = paramArray.Type.Type ?? "System.Object"; if (!paramsTypeStr.EndsWith("[]")) // Type should be an array, maybe print a warning if it isn't? paramsTypeStr = paramsTypeStr + "[]"; TypeRepTemplate paramsType = BuildType(paramsTypeStr, AppEnv, new UnknownRepTemplate(paramsTypeStr)); if (argsLength == paramsLength + 1) { if (args[argsLength - 1].IsA(paramsType, AppEnv)) { // Can pass an array as final argument return true; } } // Check additional args against params element type // Remove final array marker paramsTypeStr = paramsTypeStr.Remove(paramsTypeStr.Length-2); paramsType = BuildType(paramsTypeStr, AppEnv, new UnknownRepTemplate(paramsTypeStr)); for (int idx = paramsLength; idx < argsLength; idx++) { if (args[idx] == null || !args[idx].IsA(paramsType,AppEnv)) return false; } return true; } public override ResolveResult Resolve(String name, IList args, DirectoryHT AppEnv) { if (Methods != null) { ResolveResult res = null; foreach (MethodRepTemplate m in Methods) { if (m.Name == name && matchParamsToArgs(m.Params, m.ParamArray, args, AppEnv)) { res = new ResolveResult(); res.Result = m; res.ResultType = BuildType(m.Return, AppEnv); if (!m.IsPartialDefiner) return res; } } if (res != null) { // We must have only found a partial result, nothing to implement it, so return the partial result return res; } } // Look for a property which holds a delegate with the right type if (Properties != null) { foreach (PropRepTemplate p in Properties) { if (p.Name == name) { // Is p's type a delegate? DelegateRepTemplate del = BuildType(p.Type, AppEnv, null) as DelegateRepTemplate; if (del != null && matchParamsToArgs(del.Invoke.Params, del.Invoke.ParamArray, args, AppEnv)) { ResolveResult delRes = new ResolveResult(); delRes.Result = del; delRes.ResultType = BuildType(del.Invoke.Return, AppEnv); DelegateResolveResult res = new DelegateResolveResult(); res.Result = p; res.ResultType = BuildType(p.Type, AppEnv); res.DelegateResult = delRes; return res; } } } } return base.Resolve(name, args, AppEnv); } public override ResolveResult ResolveIndexer(IList args, DirectoryHT AppEnv) { if (Indexers != null) { foreach (IndexerRepTemplate i in Indexers) { if (matchParamsToArgs(i.Params, i.ParamArray, args, AppEnv)) { ResolveResult res = new ResolveResult(); res.Result = i; res.ResultType = BuildType(i.Type, AppEnv); return res; } } } return base.ResolveIndexer(args, AppEnv); } public override ResolveResult ResolveIterable(DirectoryHT AppEnv) { if (Iterable != null) { ResolveResult res = new ResolveResult(); res.Result = Iterable; res.ResultType = BuildType(Iterable.ElementType, AppEnv); return res; } return base.ResolveIterable(AppEnv); } public override TypeRepTemplate Instantiate(ICollection args) { InterfaceRepTemplate copy = new InterfaceRepTemplate(this); if (args != null && args.Count != 0) { copy.Apply(mkTypeMap(args)); } return copy; } #region Equality public bool Equals (InterfaceRepTemplate other) { if (other == null) return false; if (Inherits != other.Inherits) { if (Inherits == null || other.Inherits == null || Inherits.Length != other.Inherits.Length) return false; for (int i = 0; i < Inherits.Length; i++) { if (Inherits[i] != other.Inherits[i]) return false; } } if (Methods != other.Methods) { if (Methods == null || other.Methods == null || Methods.Count != other.Methods.Count) return false; for (int i = 0; i < Methods.Count; i++) { if (Methods[i] != other.Methods[i]) return false; } } if (Properties != other.Properties) { if (Properties == null || other.Properties == null || Properties.Count != other.Properties.Count) return false; for (int i = 0; i < Properties.Count; i++) { if (Properties[i] != other.Properties[i]) return false; } } if (Events != other.Events) { if (Events == null || other.Events == null || Events.Count != other.Events.Count) return false; for (int i = 0; i < Events.Count; i++) { if (Events[i] != other.Events[i]) return false; } } if (Indexers != other.Indexers) { if (Indexers == null || other.Indexers == null || Indexers.Count != other.Indexers.Count) return false; for (int i = 0; i < Indexers.Count; i++) { if (Indexers[i] != other.Indexers[i]) return false; } } return base.Equals(other); } public override bool Equals (object obj) { InterfaceRepTemplate temp = obj as InterfaceRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (InterfaceRepTemplate a1, InterfaceRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (InterfaceRepTemplate a1, InterfaceRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { int hashCode = base.GetHashCode (); if (Inherits != null) { foreach (string e in Inherits) { hashCode ^= e.GetHashCode(); } } if (Methods != null) { foreach (MethodRepTemplate e in Methods) { hashCode ^= e.GetHashCode(); } } if (Properties != null) { foreach (PropRepTemplate e in Properties) { hashCode ^= e.GetHashCode(); } } if (Events != null) { foreach (FieldRepTemplate e in Events) { hashCode ^= e.GetHashCode(); } } if (Indexers != null) { foreach (IndexerRepTemplate e in Indexers) { hashCode ^= e.GetHashCode(); } } return hashCode; } #endregion } [XmlType("Class")] public class ClassRepTemplate : InterfaceRepTemplate, IEquatable { private List _constructors = null; [XmlArrayItem("Constructor")] public List Constructors { get { if (_constructors == null) _constructors = new List (); return _constructors; } } private List _fields = null; [XmlArrayItem("Field")] public List Fields { get { if (_fields == null) _fields = new List (); return _fields; } } private List _unaryOps = null; [XmlArrayItem("UnaryOp")] public List UnaryOps { get { if (_unaryOps == null) _unaryOps = new List (); return _unaryOps; } } private List _binaryOps = null; [XmlArrayItem("BinaryOp")] public List BinaryOps { get { if (_binaryOps == null) _binaryOps = new List (); return _binaryOps; } } public ClassRepTemplate () { } public ClassRepTemplate(ClassRepTemplate copyFrom) : base(copyFrom) { foreach (ConstructorRepTemplate c in copyFrom.Constructors) { Constructors.Add(new ConstructorRepTemplate(this, c)); } foreach (FieldRepTemplate f in copyFrom.Fields) { Fields.Add(new FieldRepTemplate(this, f)); } foreach (MethodRepTemplate u in copyFrom.UnaryOps) { UnaryOps.Add(new MethodRepTemplate(this, u)); } foreach (MethodRepTemplate b in copyFrom.BinaryOps) { BinaryOps.Add(new MethodRepTemplate(this, b)); } } public ClassRepTemplate(string typeName) : base(typeName) { } public ClassRepTemplate(string tName, string[] tParams, string[] usePath, AliasRepTemplate[] aliases, string[] inherits, List cs, List ms, List ps, List fs, List es, List ixs, List cts, string[] imports, string javaTemplate) : base(tName, tParams, usePath, aliases, inherits, ms, ps, es, ixs, imports, javaTemplate) { _constructors = cs; _fields = fs; _casts = cts; } public ClassRepTemplate (string tName, string[] tParams, string[] usePath, AliasRepTemplate[] aliases, string[] inherits, List cs, List ms, List ps, List fs, List es, List ixs, List cts) : base(tName, tParams, usePath, aliases, inherits, ms, ps, es, ixs, null, null) { _constructors = cs; _fields = fs; _casts = cts; } public override void Apply(Dictionary args) { if (Constructors != null) { foreach(ConstructorRepTemplate c in Constructors) { c.Apply(args); } } if (Fields != null) { foreach(FieldRepTemplate f in Fields) { f.Apply(args); } } if (UnaryOps != null) { foreach(MethodRepTemplate u in UnaryOps) { u.Apply(args); } } if (BinaryOps != null) { foreach(MethodRepTemplate b in BinaryOps) { b.Apply(args); } } base.Apply(args); } public override ResolveResult Resolve(String name, IList args, DirectoryHT AppEnv) { // Look for a property which holds a delegate with the right type if (Fields != null) { foreach (FieldRepTemplate f in Fields) { if (f.Name == name) { // Is f's type a delegate? DelegateRepTemplate del = BuildType(f.Type, AppEnv, null) as DelegateRepTemplate; if (del != null && matchParamsToArgs(del.Invoke.Params, del.Invoke.ParamArray, args, AppEnv)) { ResolveResult delRes = new ResolveResult(); delRes.Result = del; delRes.ResultType = BuildType(del.Invoke.Return, AppEnv); DelegateResolveResult res = new DelegateResolveResult(); res.Result = f; res.ResultType = BuildType(f.Type, AppEnv); res.DelegateResult = delRes; return res; } } } } return base.Resolve(name, args, AppEnv); } public override ResolveResult Resolve(String name, bool forWrite, DirectoryHT AppEnv) { if (Fields != null) { foreach (FieldRepTemplate f in Fields) { if (f.Name == name) { ResolveResult res = new ResolveResult(); res.Result = f; res.ResultType = BuildType(f.Type, AppEnv); return res; } } } return base.Resolve(name, forWrite, AppEnv); } public ResolveResult Resolve(IList args, DirectoryHT AppEnv) { if (Constructors != null) { foreach (ConstructorRepTemplate c in Constructors) { if (matchParamsToArgs(c.Params, c.ParamArray, args, AppEnv)) { ResolveResult res = new ResolveResult(); res.Result = c; res.ResultType = this; return res; } } } // We don't search base, constructors aren't inherited return null; } public override TypeRepTemplate Instantiate(ICollection args) { ClassRepTemplate copy = new ClassRepTemplate(this); if (args != null && args.Count != 0) { copy.Apply(mkTypeMap(args)); } return copy; } #region Equality public bool Equals (ClassRepTemplate other) { if (other == null) return false; if (Constructors != other.Constructors) { if (Constructors == null || other.Constructors == null || Constructors.Count != other.Constructors.Count) return false; for (int i = 0; i < Constructors.Count; i++) { if (Constructors[i] != other.Constructors[i]) return false; } } if (Fields != other.Fields) { if (Fields == null || other.Fields == null || Fields.Count != other.Fields.Count) return false; for (int i = 0; i < Fields.Count; i++) { if (Fields[i] != other.Fields[i]) return false; } } if (UnaryOps != other.UnaryOps) { if (UnaryOps == null || other.UnaryOps == null || UnaryOps.Count != other.UnaryOps.Count) return false; for (int i = 0; i < UnaryOps.Count; i++) { if (UnaryOps[i] != other.UnaryOps[i]) return false; } } if (BinaryOps != other.BinaryOps) { if (BinaryOps == null || other.BinaryOps == null || BinaryOps.Count != other.BinaryOps.Count) return false; for (int i = 0; i < BinaryOps.Count; i++) { if (BinaryOps[i] != other.BinaryOps[i]) return false; } } return base.Equals(other); } public override bool Equals (object obj) { ClassRepTemplate temp = obj as ClassRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (ClassRepTemplate a1, ClassRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (ClassRepTemplate a1, ClassRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { int hashCode = base.GetHashCode (); if (Constructors != null) { foreach (ConstructorRepTemplate e in Constructors) { hashCode ^= e.GetHashCode(); } } if (Fields != null) { foreach (FieldRepTemplate e in Fields) { hashCode ^= e.GetHashCode(); } } return hashCode; } #endregion } [XmlType("Struct")] public class StructRepTemplate : ClassRepTemplate, IEquatable { public StructRepTemplate () { } public StructRepTemplate(StructRepTemplate copyFrom) : base(copyFrom) { } public StructRepTemplate(string typeName) : base(typeName) { } public StructRepTemplate (string tName, string[] tParams, string[] usePath, AliasRepTemplate[] aliases, string[] inherits, List cs, List ms, List ps, List fs, List es, List ixs, List cts, string[] imports, string javaTemplate) : base(tName, tParams, usePath, aliases, inherits, cs, ms, ps, fs, es, ixs, cts, imports, javaTemplate) { } public StructRepTemplate (string tName, string[] tParams, string[] usePath, AliasRepTemplate[] aliases, string[] inherits, List cs, List ms, List ps, List fs, List es, List ixs, List cts) : base(tName, tParams, usePath, aliases, inherits, cs, ms, ps, fs, es, ixs, cts, null, null) { } public override ResolveResult Resolve(String name, bool forWrite, DirectoryHT AppEnv) { return base.Resolve(name, forWrite, AppEnv); } #region Equality public bool Equals (StructRepTemplate other) { return base.Equals(other); } public override bool Equals (object obj) { StructRepTemplate temp = obj as StructRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (StructRepTemplate a1, StructRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (StructRepTemplate a1, StructRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { return base.GetHashCode (); } #endregion } [XmlType("UnknownType")] // For now, making as compatible as we can so inheriting from struct public class UnknownRepTemplate : StructRepTemplate, IEquatable { public UnknownRepTemplate () { } public UnknownRepTemplate (string typeName) : base(typeName) { // If we are creating an UnknownRepTemplate for System.Object then don't // inherit from ourselves, else we get stack overflow when resolving. // This should only happen in the case that we don't have a valid // net-templates-dir with a definition for System.Object. if (typeName != "System.Object") { Inherits = new String[] { "System.Object" }; } else { Inherits = new String[] { }; } } public UnknownRepTemplate (TypeRepRef typeName) : this(typeName.Type) { } public UnknownRepTemplate (UnknownRepTemplate copyFrom) : base(copyFrom) { } public override string[] Imports { get { return new string[0]; } } public override string mkJava() { return TypeName; } public override TypeRepTemplate Instantiate(ICollection args) { UnknownRepTemplate copy = new UnknownRepTemplate(this); // don't instantiate, its an unknown type: copy.Apply(mkTypeMap(args)); return copy; } #region Equality public bool Equals (UnknownRepTemplate other) { return base.Equals(other); } public override bool Equals (object obj) { UnknownRepTemplate temp = obj as UnknownRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (UnknownRepTemplate a1, UnknownRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (UnknownRepTemplate a1, UnknownRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { return base.GetHashCode (); } #endregion } [XmlType("TypeVariable")] // Represents Type Variables. We inherit from ClassRepTemplate to that // Type Variables have the same interface as types, but we can override as // neccessary public class TypeVarRepTemplate : ClassRepTemplate, IEquatable { public TypeVarRepTemplate () { } public TypeVarRepTemplate (string typeName) : base(typeName) { Inherits = new String[] { "System.Object" }; } public TypeVarRepTemplate (TypeVarRepTemplate copyFrom) : base(copyFrom) { } public override string[] Imports { get { return new string[0]; } } public override TypeRepTemplate Instantiate(ICollection args) { TypeVarRepTemplate copy = new TypeVarRepTemplate(this); if (args != null && args.Count > 0) { copy.TypeName = args.GetEnumerator().Current.TypeName; } return copy; } public override bool IsA (TypeRepTemplate other, DirectoryHT AppEnv) { return base.IsA(other, AppEnv); } #region Equality public bool Equals (TypeVarRepTemplate other) { return base.Equals(other); } public override bool Equals (object obj) { TypeVarRepTemplate temp = obj as TypeVarRepTemplate; if (!Object.ReferenceEquals (temp, null)) return this.Equals (temp); return false; } public static bool operator == (TypeVarRepTemplate a1, TypeVarRepTemplate a2) { return Object.Equals (a1, a2); } public static bool operator != (TypeVarRepTemplate a1, TypeVarRepTemplate a2) { return !(a1 == a2); } public override int GetHashCode () { return base.GetHashCode (); } #endregion } public class ResolveResult { public TranslationBase Result { get; set; } public TypeRepTemplate ResultType { get; set; } } // Used when the result of resolving the callee of an APPLY node is a pointer to a delegate public class DelegateResolveResult : ResolveResult { public ResolveResult DelegateResult { get; set; } } }