mirror of
https://github.com/twiglet/cs2j.git
synced 2025-01-18 13:15:17 +01:00
Add TypeVarRepTemplates, keep track of type var instantiations
This commit is contained in:
parent
f82c7c8627
commit
0b380e063d
@ -1490,6 +1490,41 @@ namespace Twiglet.CS2J.Translator.TypeRep
|
||||
}
|
||||
}
|
||||
|
||||
// Equivalent to "this is TypeVarRepTemplate"
|
||||
[XmlIgnore]
|
||||
public bool IsTypeVar
|
||||
{
|
||||
get
|
||||
{
|
||||
return (this is TypeVarRepTemplate);
|
||||
}
|
||||
}
|
||||
|
||||
// Type Arguments that this (generic) type has been instantiated with
|
||||
private TypeRepTemplate[] _instantiatedTypes = null;
|
||||
[XmlIgnore]
|
||||
public TypeRepTemplate[] InstantiatedTypes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_instantiatedTypes == null)
|
||||
{
|
||||
// Create from the TypeParams
|
||||
int numParams = TypeParams == null ? 0 : TypeParams.Length;
|
||||
_instantiatedTypes = new TypeRepTemplate[numParams];
|
||||
for (int i = 0; i < numParams; i++)
|
||||
{
|
||||
_instantiatedTypes[i] = new TypeVarRepTemplate(TypeParams[i]);
|
||||
}
|
||||
}
|
||||
return _instantiatedTypes;
|
||||
}
|
||||
set
|
||||
{
|
||||
_instantiatedTypes = value;
|
||||
}
|
||||
}
|
||||
|
||||
public TypeRepTemplate()
|
||||
: base()
|
||||
{
|
||||
@ -1586,19 +1621,34 @@ namespace Twiglet.CS2J.Translator.TypeRep
|
||||
}
|
||||
}
|
||||
|
||||
protected Dictionary<String,TypeRepTemplate> mkTypeMap(TypeRepTemplate[] args) {
|
||||
Dictionary<String,TypeRepTemplate> ret = new Dictionary<string,TypeRepTemplate>();
|
||||
if (args.Length == TypeParams.Length)
|
||||
// IMPORTANT: Call this on the fresh copy because it has the side effect of updating this type's TypeParams.
|
||||
protected Dictionary<string,TypeRepTemplate> mkTypeMap(ICollection<TypeRepTemplate> args) {
|
||||
Dictionary<string,TypeRepTemplate> ret = new Dictionary<string,TypeRepTemplate>();
|
||||
if (args.Count == TypeParams.Length)
|
||||
{
|
||||
for (int i = 0; i < args.Length; i++)
|
||||
List<string> remTypeParams = new List<string>();
|
||||
int i = 0;
|
||||
foreach (TypeRepTemplate sub in args)
|
||||
{
|
||||
ret[TypeParams[i]] = args[i];
|
||||
if (sub.IsTypeVar)
|
||||
{
|
||||
remTypeParams.Add(sub.TypeName);
|
||||
}
|
||||
ret[TypeParams[i]] = sub;
|
||||
i++;
|
||||
}
|
||||
TypeParams = remTypeParams.ToArray();
|
||||
}
|
||||
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(TypeRepTemplate[] args);
|
||||
public abstract TypeRepTemplate Instantiate(ICollection<TypeRepTemplate> args);
|
||||
|
||||
|
||||
public override void Apply(Dictionary<string,TypeRepTemplate> args)
|
||||
@ -1617,6 +1667,16 @@ namespace Twiglet.CS2J.Translator.TypeRep
|
||||
Inherits[i] = TemplateUtilities.SubstituteInType(Inherits[i],args);
|
||||
}
|
||||
}
|
||||
if (InstantiatedTypes != null)
|
||||
{
|
||||
for(int i = 0; i < InstantiatedTypes.Length; i++)
|
||||
{
|
||||
if (InstantiatedTypes[i].IsTypeVar && args.ContainsKey(InstantiatedTypes[i].TypeName))
|
||||
{
|
||||
InstantiatedTypes[i] = args[InstantiatedTypes[i].TypeName];
|
||||
}
|
||||
}
|
||||
}
|
||||
base.Apply(args);
|
||||
}
|
||||
|
||||
@ -1776,11 +1836,32 @@ namespace Twiglet.CS2J.Translator.TypeRep
|
||||
|
||||
// Returns true if other is a subclass, or implements our interface
|
||||
public virtual bool IsA (TypeRepTemplate other, DirectoryHT<TypeRepTemplate> AppEnv) {
|
||||
if (this.IsExplicitNull || other.TypeName == this.TypeName)
|
||||
if (this.IsExplicitNull)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
if (Inherits != null)
|
||||
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
|
||||
{
|
||||
return InstantiatedTypes == other.InstantiatedTypes;
|
||||
}
|
||||
}
|
||||
else if (Inherits != null)
|
||||
{
|
||||
foreach (String ibase in Inherits)
|
||||
{
|
||||
@ -1819,7 +1900,7 @@ namespace Twiglet.CS2J.Translator.TypeRep
|
||||
}
|
||||
else
|
||||
{
|
||||
TypeRepTemplate arrayType = AppEnv.Search("System.Array");
|
||||
TypeRepTemplate arrayType = AppEnv.Search("System.Array'1");
|
||||
return arrayType.Instantiate(new TypeRepTemplate[] { baseTypeRep });
|
||||
}
|
||||
}
|
||||
@ -1938,6 +2019,16 @@ namespace Twiglet.CS2J.Translator.TypeRep
|
||||
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 && base.Equals(other);
|
||||
}
|
||||
@ -1985,14 +2076,60 @@ namespace Twiglet.CS2J.Translator.TypeRep
|
||||
hashCode ^= e.GetHashCode();
|
||||
}
|
||||
}
|
||||
if (InstantiatedTypes != null)
|
||||
{
|
||||
foreach (TypeRepTemplate t in InstantiatedTypes)
|
||||
{
|
||||
hashCode ^= t.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
return (Java ?? String.Empty).GetHashCode() ^ IsExplicitNull.GetHashCode() ^ IsUnboxedType.GetHashCode() ^ hashCode;
|
||||
}
|
||||
#endregion
|
||||
|
||||
private string _formattedTypeName = null;
|
||||
protected string mkFormattedTypeName(bool incNameSpace)
|
||||
{
|
||||
if (_formattedTypeName == null)
|
||||
{
|
||||
|
||||
StringBuilder fmt = new StringBuilder();
|
||||
if (TypeName == "System.Array")
|
||||
{
|
||||
fmt.Append(InstantiatedTypes[0].mkFormattedTypeName(incNameSpace));
|
||||
fmt.Append("[]");
|
||||
}
|
||||
else
|
||||
{
|
||||
fmt.Append(TypeName.Substring(incNameSpace ? 0 : TypeName.LastIndexOf('.')+1));
|
||||
if (InstantiatedTypes.Length > 0)
|
||||
{
|
||||
bool isFirst = true;
|
||||
fmt.Append("<");
|
||||
foreach (TypeRepTemplate t in InstantiatedTypes)
|
||||
{
|
||||
if (!isFirst)
|
||||
fmt.Append(", ");
|
||||
fmt.Append(t.mkFormattedTypeName(incNameSpace));
|
||||
isFirst = false;
|
||||
}
|
||||
fmt.Append(">");
|
||||
}
|
||||
}
|
||||
_formattedTypeName = fmt.ToString();
|
||||
}
|
||||
return _formattedTypeName;
|
||||
}
|
||||
|
||||
protected string mkFormattedTypeName()
|
||||
{
|
||||
return mkFormattedTypeName(true);
|
||||
}
|
||||
|
||||
public override String ToString()
|
||||
{
|
||||
return this.TypeName;
|
||||
return mkFormattedTypeName();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2078,7 +2215,7 @@ namespace Twiglet.CS2J.Translator.TypeRep
|
||||
}
|
||||
return base.Resolve(name, AppEnv);
|
||||
}
|
||||
public override TypeRepTemplate Instantiate(TypeRepTemplate[] args)
|
||||
public override TypeRepTemplate Instantiate(ICollection<TypeRepTemplate> args)
|
||||
{
|
||||
EnumRepTemplate copy = new EnumRepTemplate(this);
|
||||
copy.Apply(mkTypeMap(args));
|
||||
@ -2204,7 +2341,7 @@ namespace Twiglet.CS2J.Translator.TypeRep
|
||||
}
|
||||
base.Apply(args);
|
||||
}
|
||||
public override TypeRepTemplate Instantiate(TypeRepTemplate[] args)
|
||||
public override TypeRepTemplate Instantiate(ICollection<TypeRepTemplate> args)
|
||||
{
|
||||
DelegateRepTemplate copy = new DelegateRepTemplate(this);
|
||||
copy.Apply(mkTypeMap(args));
|
||||
@ -2537,7 +2674,7 @@ namespace Twiglet.CS2J.Translator.TypeRep
|
||||
}
|
||||
return base.ResolveIterable(AppEnv);
|
||||
}
|
||||
public override TypeRepTemplate Instantiate(TypeRepTemplate[] args)
|
||||
public override TypeRepTemplate Instantiate(ICollection<TypeRepTemplate> args)
|
||||
{
|
||||
InterfaceRepTemplate copy = new InterfaceRepTemplate(this);
|
||||
copy.Apply(mkTypeMap(args));
|
||||
@ -2847,10 +2984,10 @@ namespace Twiglet.CS2J.Translator.TypeRep
|
||||
// We don't search base, constructors aren't inherited
|
||||
return null;
|
||||
}
|
||||
public override TypeRepTemplate Instantiate(TypeRepTemplate[] args)
|
||||
public override TypeRepTemplate Instantiate(ICollection<TypeRepTemplate> args)
|
||||
{
|
||||
ClassRepTemplate copy = new ClassRepTemplate(this);
|
||||
copy.Apply(mkTypeMap(args));
|
||||
copy.Apply(copy.mkTypeMap(args));
|
||||
return copy;
|
||||
}
|
||||
|
||||
@ -3028,15 +3165,19 @@ namespace Twiglet.CS2J.Translator.TypeRep
|
||||
Inherits = new String[] { "System.Object" };
|
||||
}
|
||||
|
||||
public UnknownRepTemplate (UnknownRepTemplate copyFrom) : base(copyFrom)
|
||||
{
|
||||
}
|
||||
|
||||
public override string[] Imports {
|
||||
get {
|
||||
return new string[0];
|
||||
}
|
||||
}
|
||||
public override TypeRepTemplate Instantiate(TypeRepTemplate[] args)
|
||||
public override TypeRepTemplate Instantiate(ICollection<TypeRepTemplate> args)
|
||||
{
|
||||
StructRepTemplate copy = new StructRepTemplate(this);
|
||||
copy.Apply(mkTypeMap(args));
|
||||
UnknownRepTemplate copy = new UnknownRepTemplate(this);
|
||||
// don't instantiate, its an unknown type: copy.Apply(mkTypeMap(args));
|
||||
return copy;
|
||||
}
|
||||
|
||||
@ -3073,6 +3214,80 @@ namespace Twiglet.CS2J.Translator.TypeRep
|
||||
#endregion
|
||||
|
||||
|
||||
}
|
||||
|
||||
[XmlType("TypeVariable")]
|
||||
// Represents Type Variables. We inherit from StructRepTemplate to that
|
||||
// Type Variables have the same interface as types, but we can override as
|
||||
// neccessary
|
||||
public class TypeVarRepTemplate : StructRepTemplate, IEquatable<TypeVarRepTemplate>
|
||||
{
|
||||
|
||||
public TypeVarRepTemplate ()
|
||||
{
|
||||
}
|
||||
|
||||
public TypeVarRepTemplate (string typeName) : base(typeName)
|
||||
{
|
||||
}
|
||||
|
||||
public TypeVarRepTemplate (TypeVarRepTemplate copyFrom) : base(copyFrom)
|
||||
{
|
||||
}
|
||||
|
||||
public override string[] Imports {
|
||||
get {
|
||||
return new string[0];
|
||||
}
|
||||
}
|
||||
|
||||
public override TypeRepTemplate Instantiate(ICollection<TypeRepTemplate> 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<TypeRepTemplate> AppEnv) {
|
||||
return false;
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user