Index: tests/testcases/net2/generics/generic-ref-parameter.boo
===================================================================
--- tests/testcases/net2/generics/generic-ref-parameter.boo (revision 0)
+++ tests/testcases/net2/generics/generic-ref-parameter.boo (revision 0)
@@ -0,0 +1,13 @@
+import System.Collections.Generic
+
+class Foo:
+ pass
+
+d = Dictionary[of string, Foo]()
+f1 = Foo()
+d["Key"] = f1
+
+f2 as Foo
+d.TryGetValue("Key", f2)
+
+assert f1 is f2
Index: tests/testcases/net2/generics/generic-method-invocation-1.boo
===================================================================
--- tests/testcases/net2/generics/generic-method-invocation-1.boo (revision 0)
+++ tests/testcases/net2/generics/generic-method-invocation-1.boo (revision 0)
@@ -0,0 +1,12 @@
+"""
+01
+02
+03
+04
+"""
+
+import System
+
+ints = (1,2,3,4)
+strings = Array.ConvertAll[of int, string](ints, {i as int | i.ToString("00")})
+for s in strings: print s
Index: tests/testcases/net2/generics/generic-method-invocation-2.boo
===================================================================
--- tests/testcases/net2/generics/generic-method-invocation-2.boo (revision 0)
+++ tests/testcases/net2/generics/generic-method-invocation-2.boo (revision 0)
@@ -0,0 +1,21 @@
+"""
+Foo #1
+Foo #2
+Foo #3
+Foo #4
+"""
+
+import System
+
+class Foo:
+ public _i as int
+
+ public def constructor(i as int):
+ _i = i
+
+ public def ToString():
+ return "Foo #${_i}";
+
+ints = (1,2,3,4)
+strings = Array.ConvertAll[of int, Foo](ints, {i as int | Foo(i)})
+for s in strings: print s
Index: src/Boo.Lang.Compiler/TypeSystem/InternalMethod.cs
===================================================================
--- src/Boo.Lang.Compiler/TypeSystem/InternalMethod.cs (revision 2443)
+++ src/Boo.Lang.Compiler/TypeSystem/InternalMethod.cs (working copy)
@@ -409,6 +409,16 @@
override public string ToString()
{
return _typeSystemServices.GetSignature(this);
+ }
+
+ IGenericMethodInfo IMethod.GenericMethodInfo
+ {
+ get { return null; }
}
+
+ IGenericMethodDefinitionInfo IMethod.GenericMethodDefinitionInfo
+ {
+ get { return null; }
+ }
}
}
Index: src/Boo.Lang.Compiler/TypeSystem/ExternalMethod.cs
===================================================================
--- src/Boo.Lang.Compiler/TypeSystem/ExternalMethod.cs (revision 2443)
+++ src/Boo.Lang.Compiler/TypeSystem/ExternalMethod.cs (working copy)
@@ -170,7 +170,7 @@
}
}
- public string Name
+ public virtual string Name
{
get
{
@@ -178,7 +178,7 @@
}
}
- public string FullName
+ public virtual string FullName
{
get
{
@@ -288,5 +288,52 @@
{
return _typeSystemServices.GetSignature(this);
}
+
+#if NET_2_0
+ ExternalGenericMethodDefinitionInfo _genericMethodDefinitionInfo = null;
+ public IGenericMethodDefinitionInfo GenericMethodDefinitionInfo
+ {
+ get
+ {
+ if (MethodInfo.IsGenericMethodDefinition)
+ {
+ if (_genericMethodDefinitionInfo == null)
+ {
+ _genericMethodDefinitionInfo =
+ new ExternalGenericMethodDefinitionInfo(_typeSystemServices, this);
+ }
+ return _genericMethodDefinitionInfo;
+ }
+ return null;
+ }
+ }
+
+ ExternalGenericMethodInfo _genericMethodInfo = null;
+ public virtual IGenericMethodInfo GenericMethodInfo
+ {
+ get
+ {
+ if (MethodInfo.IsGenericMethod)
+ {
+ if (_genericMethodInfo == null)
+ {
+ _genericMethodInfo = new ExternalGenericMethodInfo(_typeSystemServices, this);
+ }
+ return _genericMethodInfo;
+ }
+ return null;
+ }
+ }
+#else
+ IGenericMethodDefinitionInfo IMethod.GenericMethodDefinitionInfo
+ {
+ get { return null; }
+ }
+
+ IGenericMethodInfo IMethod.GenericMethodInfo
+ {
+ get { return null; }
+ }
+#endif
}
}
Index: src/Boo.Lang.Compiler/TypeSystem/GenericTypeMapper.cs
===================================================================
--- src/Boo.Lang.Compiler/TypeSystem/GenericTypeMapper.cs (revision 0)
+++ src/Boo.Lang.Compiler/TypeSystem/GenericTypeMapper.cs (revision 0)
@@ -0,0 +1,192 @@
+#region license
+// Copyright (c) 2003, 2004, 2005 Rodrigo B. de Oliveira (rbo@acm.org)
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Rodrigo B. de Oliveira nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+#if NET_2_0
+
+namespace Boo.Lang.Compiler.TypeSystem
+{
+ using System;
+ using System.Text;
+ using System.Reflection;
+ using System.Collections.Generic;
+
+ public interface ITypeMapper
+ {
+ IType MapType(IType sourceType);
+ }
+
+ ///
+ /// A basic mapper of generic parameters into arguments.
+ ///
+ public class GenericTypeMapper : ITypeMapper
+ {
+ #region Data Members
+
+ TypeSystemServices _tss;
+ Dictionary _map = new Dictionary();
+
+ #endregion
+
+ #region Constructor
+
+ public GenericTypeMapper(TypeSystemServices tss, IGenericParameter[] parameters, IType[] arguments)
+ {
+ _tss = tss;
+ for (int i = 0; i < parameters.Length; i++)
+ {
+ _map.Add(parameters[i], arguments[i]);
+ }
+ }
+
+ ///
+ /// Maps a type involving generic parameters to the corresponding type after substituting concrete
+ /// arguments for generic parameters.
+ ///
+ ///
+ /// If the source type is a generic parameter, it is mapped to the corresponding argument.
+ /// If the source type is an open generic type using any of the specified generic parameters, it
+ /// is mapped to a closed constructed type based on the specified arguments.
+ /// TODO: complete this
+ ///
+ public IType MapType(IType sourceType)
+ {
+ if (sourceType == null)
+ {
+ return null;
+ }
+
+ // If sourceType is a reference type, map its element type
+ if (sourceType.IsByRef)
+ {
+ return MapType(sourceType.GetElementType());
+ }
+
+ // Map generic parameter to corresponding argument
+ IGenericParameter gp = sourceType as IGenericParameter;
+ if (null != gp && _map.ContainsKey(gp))
+ {
+ return _map[gp];
+ }
+
+ // Map open constructed type using generic parameters to closed constructed type
+ // using corresponding arguments
+ if (null != sourceType.GenericTypeInfo)
+ {
+ IType[] mappedArguments = Array.ConvertAll(
+ sourceType.GenericTypeInfo.GenericArguments,
+ MapType);
+
+ IType mapped = sourceType.GenericTypeInfo.
+ GenericDefinition.GenericTypeDefinitionInfo.
+ MakeGenericType(mappedArguments);
+
+ return mapped;
+ }
+
+ // Map array types
+ IArrayType array = (sourceType as IArrayType);
+ if (array != null)
+ {
+ IType elementType = array.GetElementType();
+ IType mappedElementType = MapType(elementType);
+ if (mappedElementType != elementType)
+ {
+ return _tss.GetArrayType(mappedElementType, array.GetArrayRank());
+ }
+ }
+
+ // Map callable types
+ ICallableType callable = sourceType as ICallableType;
+ if (callable != null)
+ {
+ CallableSignature signature = callable.GetSignature();
+
+ IType returnType = MapType(signature.ReturnType);
+ IParameter[] parameters = Array.ConvertAll(
+ signature.Parameters,
+ delegate(IParameter p) { return new MappedParameter(_tss, (ExternalParameter)p, this); });
+
+ CallableSignature mappedSignature = new CallableSignature(
+ parameters, returnType, signature.AcceptVarArgs);
+
+ return _tss.GetCallableType(mappedSignature);
+ }
+
+ // If source type doesn't require mapping, return it as is
+ return sourceType;
+ }
+
+ #endregion
+ }
+
+ #region class MappedParameter
+
+ ///
+ /// A parameter in a mixed generic type's method or constructor, or a mixed generic method.
+ ///
+ public class MappedParameter : IParameter
+ {
+ private ITypeMapper _typeMapper;
+ private ExternalParameter _baseParameter;
+
+ public MappedParameter(TypeSystemServices tss, ExternalParameter parameter, ITypeMapper typeMapper)
+ {
+ _typeMapper = typeMapper;
+ _baseParameter = parameter;
+ }
+
+ public bool IsByRef
+ {
+ get { return _baseParameter.IsByRef; }
+ }
+
+ public IType Type
+ {
+ get { return _typeMapper.MapType(_baseParameter.Type); }
+ }
+
+ public string Name
+ {
+ get { return _baseParameter.Name; }
+ }
+
+ public string FullName
+ {
+ get { return _baseParameter.FullName; }
+ }
+
+ public EntityType EntityType
+ {
+ get { return EntityType.Parameter; }
+ }
+ }
+
+ #endregion
+}
+
+#endif
Index: src/Boo.Lang.Compiler/TypeSystem/IEntity.cs
===================================================================
--- src/Boo.Lang.Compiler/TypeSystem/IEntity.cs (revision 2443)
+++ src/Boo.Lang.Compiler/TypeSystem/IEntity.cs (working copy)
@@ -211,13 +211,26 @@
bool FullyConstructed { get; }
}
+ public interface IGenericMethodDefinitionInfo
+ {
+ IGenericParameter[] GenericParameters { get; }
+ IMethod MakeGenericMethod(params IType[] arguments);
+ }
+
+ public interface IGenericMethodInfo
+ {
+ IType[] GenericArguments { get; }
+ IMethod GenericDefinition { get; }
+ bool FullyConstructed { get; }
+ }
+
public interface IGenericParameter: IType
{
IType DeclaringType { get; }
int GenericParameterPosition { get; }
// TODO: Constraints { get; }
- }
-
+ }
+
public interface ICallableType : IType
{
CallableSignature GetSignature();
@@ -326,6 +339,16 @@
bool IsPInvoke
{
get;
+ }
+
+ IGenericMethodInfo GenericMethodInfo
+ {
+ get;
+ }
+
+ IGenericMethodDefinitionInfo GenericMethodDefinitionInfo
+ {
+ get;
}
}
Index: src/Boo.Lang.Compiler/TypeSystem/ExternalGenericMethodInfo.cs
===================================================================
--- src/Boo.Lang.Compiler/TypeSystem/ExternalGenericMethodInfo.cs (revision 0)
+++ src/Boo.Lang.Compiler/TypeSystem/ExternalGenericMethodInfo.cs (revision 0)
@@ -0,0 +1,75 @@
+#region license
+// Copyright (c) 2003, 2004, 2005 Rodrigo B. de Oliveira (rbo@acm.org)
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Rodrigo B. de Oliveira nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+#if NET_2_0
+
+namespace Boo.Lang.Compiler.TypeSystem
+{
+ using System;
+
+ public class ExternalGenericMethodInfo : IGenericMethodInfo
+ {
+ ExternalMethod _method;
+ TypeSystemServices _tss;
+ IType[] _arguments = null;
+
+ public ExternalGenericMethodInfo(TypeSystemServices tss, ExternalMethod method)
+ {
+ _method = method;
+ _tss = tss;
+ }
+
+ public IMethod GenericDefinition
+ {
+ get
+ {
+ return _tss.Map(((System.Reflection.MethodInfo)_method.MethodInfo).GetGenericMethodDefinition());
+ }
+ }
+
+ public IType[] GenericArguments
+ {
+ get
+ {
+ if (_arguments == null)
+ {
+ _arguments = Array.ConvertAll(
+ _method.MethodInfo.GetGenericArguments(), _tss.Map);
+ }
+
+ return _arguments;
+ }
+ }
+
+ public bool FullyConstructed
+ {
+ get { return !_method.MethodInfo.ContainsGenericParameters; }
+ }
+ }
+}
+#endif
Index: src/Boo.Lang.Compiler/TypeSystem/MixedGenericMethod.cs
===================================================================
--- src/Boo.Lang.Compiler/TypeSystem/MixedGenericMethod.cs (revision 0)
+++ src/Boo.Lang.Compiler/TypeSystem/MixedGenericMethod.cs (revision 0)
@@ -0,0 +1,179 @@
+#region license
+// Copyright (c) 2003, 2004, 2005 Rodrigo B. de Oliveira (rbo@acm.org)
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Rodrigo B. de Oliveira nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+#if NET_2_0
+
+namespace Boo.Lang.Compiler.TypeSystem
+{
+ using System;
+ using System.Text;
+ using System.Reflection;
+ using System.Collections.Generic;
+
+ ///
+ /// A generic method constructed from an external definition but involving internal parameters.
+ ///
+ public class MixedGenericMethod : ExternalMethod, IGenericMethodInfo, ITypeMapper
+ {
+ #region Data Members
+
+ ExternalMethod _definition;
+ IType[] _arguments = null;
+ GenericTypeMapper _typeMapper;
+ bool _constructed;
+ string _name = null;
+ string _fullName = null;
+
+ #endregion
+
+ #region Constructor
+
+ public MixedGenericMethod(TypeSystemServices tss, ExternalMethod definition, IType[] arguments) : base(tss, definition.MethodInfo)
+ {
+ _definition = definition;
+ _arguments = arguments;
+ _constructed = IsConstructed();
+ _typeMapper = new GenericTypeMapper(
+ tss,
+ definition.GenericMethodDefinitionInfo.GenericParameters,
+ arguments);
+ }
+
+ #endregion
+
+ #region IGenericMethodInfo members
+
+ public IType[] GenericArguments
+ {
+ get { return _arguments; }
+ }
+
+ public IMethod GenericDefinition
+ {
+ get { return _definition; }
+ }
+
+ public bool FullyConstructed
+ {
+ get { return _constructed; }
+ }
+
+ #endregion
+
+ #region Properties
+
+ public override string Name
+ {
+ get
+ {
+ if (_name == null)
+ {
+ _name = BuildName(false);
+ }
+ return _name;
+ }
+ }
+
+ public override string FullName
+ {
+ get
+ {
+ if (_fullName == null)
+ {
+ _fullName = BuildName(true);
+ }
+ return _fullName;
+ }
+ }
+
+ public override IType ReturnType
+ {
+ get { return MapType(_definition.ReturnType); }
+ }
+
+ public override IGenericMethodInfo GenericMethodInfo
+ {
+ get { return this; }
+ }
+
+ #endregion
+
+ #region Private Methods
+
+ private bool IsConstructed()
+ {
+ foreach (IType arg in _arguments)
+ {
+ if (arg is IGenericParameter) return false;
+ }
+
+ return true;
+ }
+
+ private string BuildName(bool full)
+ {
+ Converter argumentName = delegate(IType type)
+ {
+ return full ? "[" + type.FullName + "]" : type.Name;
+ };
+
+ string[] typeNames = Array.ConvertAll(_arguments, argumentName);
+
+ return string.Format(
+ "{0}[{1}]",
+ full ? _definition.FullName : _definition.Name,
+ string.Join(", ", typeNames));
+ }
+
+ #endregion
+
+ #region Public Methods
+
+ public override string ToString()
+ {
+ return FullName;
+ }
+
+ public override IParameter[] GetParameters()
+ {
+ return Array.ConvertAll(
+ _definition.GetParameters(),
+ delegate(IParameter p) { return new MappedParameter(
+ _typeSystemServices, (ExternalParameter)p, this); });
+ }
+
+ public IType MapType(IType sourceType)
+ {
+ return _typeMapper.MapType(sourceType);
+ }
+
+ #endregion
+ }
+}
+
+#endif
Index: src/Boo.Lang.Compiler/TypeSystem/ExternalGenericMethodDefinitionInfo.cs
===================================================================
--- src/Boo.Lang.Compiler/TypeSystem/ExternalGenericMethodDefinitionInfo.cs (revision 0)
+++ src/Boo.Lang.Compiler/TypeSystem/ExternalGenericMethodDefinitionInfo.cs (revision 0)
@@ -0,0 +1,68 @@
+#region license
+// Copyright (c) 2003, 2004, 2005 Rodrigo B. de Oliveira (rbo@acm.org)
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Rodrigo B. de Oliveira nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+#if NET_2_0
+
+namespace Boo.Lang.Compiler.TypeSystem
+{
+ using System;
+ using System.Collections.Generic;
+
+ public class ExternalGenericMethodDefinitionInfo : AbstractExternalGenericDefinitionInfo, IGenericMethodDefinitionInfo
+ {
+ private ExternalMethod _method;
+
+ public ExternalGenericMethodDefinitionInfo(TypeSystemServices tss, ExternalMethod method) : base(tss)
+ {
+ _method = method;
+ }
+
+ public IMethod MakeGenericMethod(IType[] arguments)
+ {
+ return (IMethod)MakeGenericEntity(arguments);
+ }
+
+ protected override Type[] GetActualGenericParameters()
+ {
+ return _method.MethodInfo.GetGenericArguments();
+ }
+
+ protected override IEntity MakeExternalEntity(Type[] arguments)
+ {
+ return _tss.Map(((System.Reflection.MethodInfo)_method.MethodInfo).MakeGenericMethod(arguments));
+ }
+
+ protected override IEntity MakeMixedEntity(IType[] arguments)
+ {
+ return new MixedGenericMethod(_tss, _method, arguments);
+ }
+ }
+}
+
+#endif
+
Index: src/Boo.Lang.Compiler/TypeSystem/AbstractExternalGenericDefinitionInfo.cs
===================================================================
--- src/Boo.Lang.Compiler/TypeSystem/AbstractExternalGenericDefinitionInfo.cs (revision 0)
+++ src/Boo.Lang.Compiler/TypeSystem/AbstractExternalGenericDefinitionInfo.cs (revision 0)
@@ -0,0 +1,174 @@
+#region license
+// Copyright (c) 2003, 2004, 2005 Rodrigo B. de Oliveira (rbo@acm.org)
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+// * Neither the name of Rodrigo B. de Oliveira nor the names of its
+// contributors may be used to endorse or promote products derived from this
+// software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+// THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#endregion
+
+#if NET_2_0
+
+namespace Boo.Lang.Compiler.TypeSystem
+{
+ using System;
+ using System.Collections.Generic;
+
+ public abstract class AbstractExternalGenericDefinitionInfo
+ {
+ protected TypeSystemServices _tss;
+ private IGenericParameter[] _parameters;
+ private Dictionary _instances =
+ new Dictionary(new GenericArgumentsComparer());
+
+ public AbstractExternalGenericDefinitionInfo(TypeSystemServices tss)
+ {
+ _tss = tss;
+ }
+
+ public IGenericParameter[] GenericParameters
+ {
+ get
+ {
+ if (null == _parameters)
+ {
+ _parameters = Array.ConvertAll(
+ GetActualGenericParameters(),
+ delegate(Type t) { return (ExternalGenericParameter)_tss.Map(t); });
+ }
+ return _parameters;
+ }
+ }
+
+ protected IEntity MakeGenericEntity(IType[] arguments)
+ {
+ if (Array.TrueForAll(arguments, IsExternal))
+ {
+ Type[] actualTypes = Array.ConvertAll(arguments, GetSystemType);
+
+ return MakeExternalEntity(actualTypes);
+ }
+ else if (_instances.ContainsKey(arguments))
+ {
+ return _instances[arguments];
+ }
+ else
+ {
+ IEntity instance = MakeMixedEntity(arguments);
+ _instances.Add(arguments, instance);
+
+ return instance;
+ }
+ }
+
+ protected abstract Type[] GetActualGenericParameters();
+ protected abstract IEntity MakeMixedEntity(IType[] arguments);
+ protected abstract IEntity MakeExternalEntity(Type[] arguments);
+
+ private bool IsExternal(IType type)
+ {
+ if (type is ExternalType && !(type is MixedGenericType))
+ {
+ return true;
+ }
+
+ if (type is ArrayType)
+ {
+ return IsExternal(type.GetElementType());
+ }
+
+ return false;
+ }
+
+ private Type GetSystemType(IType type)
+ {
+ if (type is ExternalType)
+ {
+ return ((ExternalType)type).ActualType;
+ }
+
+ ArrayType arrayType = type as ArrayType;
+ if (arrayType != null)
+ {
+ Type elementType = GetSystemType(arrayType.GetElementType());
+
+ return Array.CreateInstance(
+ elementType,
+ new int[arrayType.GetArrayRank()]).GetType();
+ }
+
+ return null;
+ }
+
+ private class GenericArgumentsComparer: IEqualityComparer
+ {
+ public bool Equals(IType[] x, IType[] y)
+ {
+ for (int i = 0; i < x.Length; i++)
+ {
+ if ((x[i] == null && y[i] != null) || (!x[i].Equals(y[i])))
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ public int GetHashCode(IType[] args)
+ {
+ // Make a simple hash code from the hash codes of the arguments
+ int hash = 0;
+ for (int i = 0; i < args.Length; i++)
+ {
+ hash ^= i ^ args[i].GetHashCode();
+ }
+
+ return hash;
+ }
+ }
+ }
+
+ public class ExternalGenericParameter : ExternalType, IGenericParameter
+ {
+ public ExternalGenericParameter(TypeSystemServices tss, Type type) : base(tss, type)
+ {
+ }
+
+ public int GenericParameterPosition
+ {
+ get { return ActualType.GenericParameterPosition; }
+ }
+
+ public override string FullName
+ {
+ get
+ {
+ // FIXME: use DeclaringMethod rather than DeclaringType for
+ // parameters of generic methods
+ return string.Format("{0}.{1}", DeclaringType.FullName, Name);
+ }
+ }
+ }
+}
+#endif
+
Index: src/Boo.Lang.Compiler/TypeSystem/ExternalGenericTypeInfo.cs
===================================================================
--- src/Boo.Lang.Compiler/TypeSystem/ExternalGenericTypeInfo.cs (revision 2443)
+++ src/Boo.Lang.Compiler/TypeSystem/ExternalGenericTypeInfo.cs (working copy)
@@ -34,18 +34,24 @@
public class ExternalGenericTypeInfo : IGenericTypeInfo
{
- TypeSystemServices _tss;
ExternalType _type;
+ TypeSystemServices _tss;
IType[] _arguments = null;
- bool _constructed;
public ExternalGenericTypeInfo(TypeSystemServices tss, ExternalType type)
{
- _tss = tss;
_type = type;
- _constructed = !_type.ActualType.ContainsGenericParameters;
+ _tss = tss;
}
+ public IType GenericDefinition
+ {
+ get
+ {
+ return _tss.Map(_type.ActualType.GetGenericTypeDefinition());
+ }
+ }
+
public IType[] GenericArguments
{
get
@@ -53,26 +59,17 @@
if (_arguments == null)
{
_arguments = Array.ConvertAll(
- _type.ActualType.GetGenericArguments(),
- _tss.Map);
+ _type.ActualType.GetGenericArguments(), _tss.Map);
}
return _arguments;
}
}
-
- public IType GenericDefinition
+
+ public bool FullyConstructed
{
- get
- {
- return _tss.Map(_type.ActualType.GetGenericTypeDefinition());
- }
+ get { return !_type.ActualType.ContainsGenericParameters; }
}
-
- public bool FullyConstructed
- {
- get { return _constructed; }
- }
}
}
#endif
Index: src/Boo.Lang.Compiler/TypeSystem/MixedGenericType.cs
===================================================================
--- src/Boo.Lang.Compiler/TypeSystem/MixedGenericType.cs (revision 2443)
+++ src/Boo.Lang.Compiler/TypeSystem/MixedGenericType.cs (working copy)
@@ -1,4 +1,4 @@
-#region license
+#region license
// Copyright (c) 2003, 2004, 2005 Rodrigo B. de Oliveira (rbo@acm.org)
// All rights reserved.
//
@@ -38,13 +38,14 @@
///
/// A generic type constructed from an external definition but involving internal parameters.
///
- public class MixedGenericType : ExternalType, IGenericTypeInfo
+ public class MixedGenericType : ExternalType, IGenericTypeInfo, ITypeMapper
{
#region Data Members
ExternalType _definition;
- IType[] _arguments = null;
- bool _constructed;
+ IType[] _arguments;
+ GenericTypeMapper _typeMapper;
+ bool _constructed;
string _name = null;
string _fullName = null;
Dictionary _mappedMembers = new Dictionary();
@@ -58,6 +59,10 @@
_definition = definition;
_arguments = arguments;
_constructed = IsConstructed();
+ _typeMapper = new GenericTypeMapper(
+ tss,
+ definition.GenericTypeDefinitionInfo.GenericParameters,
+ arguments);
}
#endregion
@@ -117,6 +122,11 @@
}
}
+ public GenericTypeMapper TypeMapper
+ {
+ get { return _typeMapper; }
+ }
+
#endregion
#region Private Methods
@@ -222,68 +232,16 @@
#region Mapping methods
- ///
- /// Maps a type involving generic parameters to the corresponding type after substituting concrete
- /// arguments for generic parameters.
- ///
- ///
- /// If the source type is a generic parameter of this type's definition, it is mapped to the
- /// corresponding argument.
- /// If the source type is an open generic type using parameters from the type's definition, it
- /// is mapped to a closed constructed type based on this type's arguments.
- /// If the source type is an array of a generic parameter of this type's definition, it is mapped
- /// to the array type of the corresponding argument, of the same rank.
- ///
- protected IType MapType(IType sourceType)
+ public IType MapType(IType sourceType)
{
- if (sourceType == null)
- {
- return null;
- }
-
- // If sourceType is a reference type, map its element type
- if (sourceType.IsByRef)
- {
- return MapType(sourceType.GetElementType());
- }
-
- // Map generic parameter to corresponding argument
- IGenericParameter gp = sourceType as IGenericParameter;
- if (null != gp && gp.DeclaringType == _definition)
- {
- return GenericArguments[gp.GenericParameterPosition];
- }
-
// Map own definition to this mixed type
if (sourceType == GenericDefinition)
{
return this;
}
- // Map open constructed type using generic parameters to closed constructed type
- // using corresponding arguments
- if (null != sourceType.GenericTypeInfo)
- {
- IType[] mappedArguments = Array.ConvertAll(
- sourceType.GenericTypeInfo.GenericArguments,
- MapType);
-
- IType mapped = sourceType.GenericTypeInfo.
- GenericDefinition.GenericTypeDefinitionInfo.
- MakeGenericType(mappedArguments);
-
- return mapped;
- }
-
- // Map array of generic parameter to array of corresponding argument
- IArrayType array = (sourceType as IArrayType);
- if (array != null)
- {
- return _typeSystemServices.GetArrayType(MapType(array.GetElementType()), array.GetArrayRank());
- }
-
- // If source type doesn't require mapping, return it as is
- return sourceType;
+ // For all other cases use the generic type mapper
+ return _typeMapper.MapType(sourceType);
}
///
@@ -353,7 +311,6 @@
public override IType DeclaringType
{
- // get { return _parentType; }
get { return _parentType.MapType(base.DeclaringType); }
}
@@ -377,7 +334,7 @@
{
return new MappedParameter(_typeSystemServices, (ExternalParameter)p, _parentType);
});
- }
+ }
}
#endregion
@@ -414,50 +371,6 @@
#endregion
- #region class MappedParameter
-
- ///
- /// A parameter in a method or constructor of a mixed generic type.
- ///
- public class MappedParameter : IParameter
- {
- private MixedGenericType _parentType;
- private ExternalParameter _baseParameter;
-
- public MappedParameter(TypeSystemServices tss, ExternalParameter parameter, MixedGenericType parentType)
- {
- _parentType = parentType;
- _baseParameter = parameter;
- }
-
- public bool IsByRef
- {
- get { return _baseParameter.IsByRef; }
- }
-
- public IType Type
- {
- get { return _parentType.MapType(_baseParameter.Type); }
- }
-
- public string Name
- {
- get { return _baseParameter.Name; }
- }
-
- public string FullName
- {
- get { return _baseParameter.FullName; }
- }
-
- public EntityType EntityType
- {
- get { return EntityType.Parameter; }
- }
- }
-
- #endregion
-
#region class MappedProperty
public class MappedProperty : ExternalProperty
Index: src/Boo.Lang.Compiler/TypeSystem/ExternalGenericTypeDefinitionInfo.cs
===================================================================
--- src/Boo.Lang.Compiler/TypeSystem/ExternalGenericTypeDefinitionInfo.cs (revision 2443)
+++ src/Boo.Lang.Compiler/TypeSystem/ExternalGenericTypeDefinitionInfo.cs (working copy)
@@ -33,56 +33,31 @@
using System;
using System.Collections.Generic;
- public class ExternalGenericTypeDefinitionInfo : IGenericTypeDefinitionInfo
+ public class ExternalGenericTypeDefinitionInfo : AbstractExternalGenericDefinitionInfo, IGenericTypeDefinitionInfo
{
private ExternalType _type;
- private TypeSystemServices _tss;
- private IGenericParameter[] _parameters;
- private IDictionary _instances;
- public ExternalGenericTypeDefinitionInfo(TypeSystemServices tss, ExternalType type)
+ public ExternalGenericTypeDefinitionInfo(TypeSystemServices tss, ExternalType type) : base(tss)
{
- _tss = tss;
_type = type;
- _instances = new Dictionary(new GenericArgumentsComparer());
}
- public IGenericParameter[] GenericParameters
- {
- get
- {
- if (null == _parameters)
- {
- _parameters = Array.ConvertAll(
- _type.ActualType.GetGenericArguments(),
- delegate(Type t) { return new ExternalGenericParameter(_tss, t); });
- }
- return _parameters;
- }
- }
-
public IType MakeGenericType(IType[] arguments)
- {
- if (Array.TrueForAll(arguments, IsExternal))
- {
- Type[] actualTypes = Array.ConvertAll(arguments, GetSystemType);
-
- return _tss.Map(_type.ActualType.MakeGenericType(actualTypes));
- }
- else if (_instances.ContainsKey(arguments))
- {
- return _instances[arguments];
- }
- else
- {
- IType instance = CreateMixedType(arguments);
- _instances.Add(arguments, instance);
-
- return instance;
- }
+ {
+ return (IType)MakeGenericEntity(arguments);
}
+
+ protected override Type[] GetActualGenericParameters()
+ {
+ return _type.ActualType.GetGenericArguments();
+ }
+
+ protected override IEntity MakeExternalEntity(Type[] arguments)
+ {
+ return _tss.Map(_type.ActualType.MakeGenericType(arguments));
+ }
- private IType CreateMixedType(IType[] arguments)
+ protected override IEntity MakeMixedEntity(IType[] arguments)
{
ExternalCallableType callable = _type as ExternalCallableType;
if (null != callable)
@@ -93,92 +68,8 @@
{
return new MixedGenericType(_tss, _type, arguments);
}
- }
-
- private bool IsExternal(IType type)
- {
- if (type is ExternalType && !(type is MixedGenericType))
- {
- return true;
- }
-
- if (type is ArrayType)
- {
- return IsExternal(type.GetElementType());
- }
-
- return false;
- }
-
- private Type GetSystemType(IType type)
- {
- if (type is ExternalType)
- {
- return ((ExternalType)type).ActualType;
- }
-
- ArrayType arrayType = type as ArrayType;
- if (arrayType != null)
- {
- Type elementType = GetSystemType(arrayType.GetElementType());
-
- return Array.CreateInstance(
- elementType,
- new int[arrayType.GetArrayRank()]).GetType();
- }
-
- return null;
- }
-
- private class GenericArgumentsComparer: IEqualityComparer
- {
- public bool Equals(IType[] x, IType[] y)
- {
- for (int i = 0; i < x.Length; i++)
- {
- if ((x[i] == null && y[i] != null) || (!x[i].Equals(y[i])))
- {
- return false;
- }
- }
-
- return true;
- }
-
- public int GetHashCode(IType[] args)
- {
- // Make a simple hash code from the hash codes of the arguments
- int hash = 0;
- for (int i = 0; i < args.Length; i++)
- {
- hash ^= i ^ args[i].GetHashCode();
- }
-
- return hash;
- }
- }
+ }
}
-
-
- public class ExternalGenericParameter : ExternalType, IGenericParameter
- {
- public ExternalGenericParameter(TypeSystemServices tss, Type type) : base(tss, type)
- {
- }
-
- public int GenericParameterPosition
- {
- get { return ActualType.GenericParameterPosition; }
- }
-
- public override string FullName
- {
- get
- {
- return string.Format("{0}.{1}", DeclaringType.FullName, Name);
- }
- }
- }
}
#endif
Index: src/Boo.Lang.Compiler/Steps/ProcessMethodBodies.cs
===================================================================
--- src/Boo.Lang.Compiler/Steps/ProcessMethodBodies.cs (revision 2443)
+++ src/Boo.Lang.Compiler/Steps/ProcessMethodBodies.cs (working copy)
@@ -2101,10 +2101,20 @@
return;
}
- IType genericType = ((IType)node.Target.Entity).GenericTypeDefinitionInfo.MakeGenericType(GetGenericArguments(node));
- Bind(node, genericType);
- BindExpressionType(node, this.TypeSystemServices.TypeType);
-
+ switch (node.Target.Entity.EntityType)
+ {
+ case EntityType.Type:
+ IType genericType = ((IType)node.Target.Entity).GenericTypeDefinitionInfo.MakeGenericType(GetGenericArguments(node));
+ Bind(node, genericType);
+ BindExpressionType(node, this.TypeSystemServices.TypeType);
+ break;
+
+ case EntityType.Method:
+ IMethod genericMethod = ((IMethod)node.Target.Entity).GenericMethodDefinitionInfo.MakeGenericMethod(GetGenericArguments(node));
+ Bind(node, genericMethod);
+ BindExpressionType(node, genericMethod.ReturnType);
+ break;
+ }
}
private IType[] GetGenericArguments(GenericReferenceExpression node)
@@ -2122,15 +2132,31 @@
{
IEntity entity = node.Target.Entity;
IType type = entity as IType;
- if (type == null || type.GenericTypeDefinitionInfo == null)
+ IMethod method = entity as IMethod;
+ IGenericParameter[] parameters = null;
+
+ // Test for a generic type definition
+ if (type != null && type.GenericTypeDefinitionInfo != null)
{
+ parameters = type.GenericTypeDefinitionInfo.GenericParameters;
+ }
+ // Test for a generic method definition
+ else if (method != null && method.GenericMethodDefinitionInfo != null)
+ {
+ parameters = method.GenericMethodDefinitionInfo.GenericParameters;
+ }
+
+ if (parameters == null)
+ {
return CompilerErrorFactory.NotAGenericDefinition(AstUtil.GetMemberAnchor(node.Target), entity.FullName);
}
- IGenericParameter[] parameters = type.GenericTypeDefinitionInfo.GenericParameters;
- if (parameters.Length != node.GenericArguments.Count) return CompilerErrorFactory.GenericDefinitionArgumentCount(AstUtil.GetMemberAnchor(node.Target), entity.FullName, parameters.Length);
+ if (parameters.Length != node.GenericArguments.Count)
+ {
+ return CompilerErrorFactory.GenericDefinitionArgumentCount(AstUtil.GetMemberAnchor(node.Target), entity.FullName, parameters.Length);
+ }
- return null;
+ return null;
}
override public void OnReferenceExpression(ReferenceExpression node)
Index: src/Boo.Lang.Compiler/Steps/EmitAssembly.cs
===================================================================
--- src/Boo.Lang.Compiler/Steps/EmitAssembly.cs (revision 2443)
+++ src/Boo.Lang.Compiler/Steps/EmitAssembly.cs (working copy)
@@ -3707,6 +3707,13 @@
if (null != mapped && mapped.MethodInfo.DeclaringType.IsGenericType)
{
return MapGenericMethod(mapped.DeclaringType, (MethodInfo)mapped.MethodInfo);
+ }
+
+ // If method is a mixed generic method, get its mapped MethodInfo
+ MixedGenericMethod generic = entity as MixedGenericMethod;
+ if (null != generic)
+ {
+ return MapGenericMethod(generic);
}
#endif
ExternalMethod external = entity as ExternalMethod;
@@ -3759,6 +3766,18 @@
}
///
+ /// Maps a generic method to its constructed version.
+ ///
+ private MethodInfo MapGenericMethod(MixedGenericMethod method)
+ {
+ Type[] arguments = Array.ConvertAll(
+ method.GenericArguments,
+ GetSystemType);
+
+ return ((MethodInfo)method.MethodInfo).MakeGenericMethod(arguments);
+ }
+
+ ///
/// Maps a field declared on a generic type definition or an open constructed type
/// to the corresponding field on a closed constructed type.
///