Index: src/Boo.Lang.Compiler/Boo.Lang.Compiler.csproj =================================================================== --- src/Boo.Lang.Compiler/Boo.Lang.Compiler.csproj (revision 2352) +++ src/Boo.Lang.Compiler/Boo.Lang.Compiler.csproj (working copy) @@ -19,11 +19,11 @@ ..\boo.snk False File + false false 4 - false false false false @@ -34,7 +34,6 @@ false 4 - false true false false @@ -412,7 +411,7 @@ - + @@ -445,7 +444,8 @@ - + + Index: src/Boo.Lang.Compiler/Steps/EmitAssembly.cs =================================================================== --- src/Boo.Lang.Compiler/Steps/EmitAssembly.cs (revision 2352) +++ src/Boo.Lang.Compiler/Steps/EmitAssembly.cs (working copy) @@ -1,2582 +1,2582 @@ -#region license -// Copyright (c) 2004, 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 - -using System; -using System.Collections; -using System.Diagnostics; -using System.Diagnostics.SymbolStore; -using System.IO; -using System.Reflection; -using System.Reflection.Emit; -using System.Resources; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading; -using Boo.Lang.Compiler.Ast; -using Boo.Lang.Compiler.TypeSystem; -using Boo.Lang.Runtime; -using Attribute = Boo.Lang.Compiler.Ast.Attribute; -using Module = Boo.Lang.Compiler.Ast.Module; - -namespace Boo.Lang.Compiler.Steps -{ - class LoopInfo - { - public Label BreakLabel; - - public Label ContinueLabel; - - public int TryBlockDepth; - - public LoopInfo(Label breakLabel, Label continueLabel, int tryBlockDepth) - { - BreakLabel = breakLabel; - ContinueLabel = continueLabel; - TryBlockDepth = tryBlockDepth; - } - } - - public class EmitAssembly : AbstractVisitorCompilerStep - { - static ConstructorInfo DebuggableAttribute_Constructor = typeof(DebuggableAttribute).GetConstructor(new Type[] { Types.Bool, Types.Bool }); - - static ConstructorInfo DuckTypedAttribute_Constructor = Types.DuckTypedAttribute.GetConstructor(new Type[0]); - - static ConstructorInfo ParamArrayAttribute_Constructor = Types.ParamArrayAttribute.GetConstructor(new Type[0]); - - static MethodInfo RuntimeServices_NormalizeArrayIndex = Types.RuntimeServices.GetMethod("NormalizeArrayIndex"); - - static MethodInfo RuntimeServices_ToBool_Object = Types.RuntimeServices.GetMethod("ToBool", new Type[] { Types.Object }); - - static MethodInfo RuntimeServices_ToBool_Decimal = Types.RuntimeServices.GetMethod("ToBool", new Type[] { Types.Decimal }); - - static MethodInfo Builtins_ArrayTypedConstructor = Types.Builtins.GetMethod("array", new Type[] { Types.Type, Types.Int }); - - static MethodInfo Builtins_ArrayTypedCollectionConstructor = Types.Builtins.GetMethod("array", new Type[] { Types.Type, Types.ICollection }); - - static MethodInfo Math_Pow = typeof(Math).GetMethod("Pow"); - - static ConstructorInfo List_EmptyConstructor = Types.List.GetConstructor(Type.EmptyTypes); - - static ConstructorInfo List_ArrayBoolConstructor = Types.List.GetConstructor(new Type[] { Types.ObjectArray, Types.Bool }); - - static ConstructorInfo Hash_Constructor = Types.Hash.GetConstructor(new Type[0]); - - static ConstructorInfo Regex_Constructor = typeof(Regex).GetConstructor(new Type[] { Types.String }); - - static MethodInfo Hash_Add = Types.Hash.GetMethod("Add", new Type[] { typeof(object), typeof(object) }); - - static ConstructorInfo TimeSpan_LongConstructor = Types.TimeSpan.GetConstructor(new Type[] { typeof(long) }); - - static MethodInfo Type_GetTypeFromHandle = Types.Type.GetMethod("GetTypeFromHandle"); - - AssemblyBuilder _asmBuilder; - - ModuleBuilder _moduleBuilder; - - Hashtable _symbolDocWriters = new Hashtable(); - - // IL generation state - ILGenerator _il; - Label _returnLabel; // current label for method return - LocalBuilder _returnValueLocal; // returnValueLocal - IType _returnType; - int _tryBlock; // are we in a try block? - bool _checked = true; - bool _rawArrayIndexing = false; - Hashtable _typeCache = new Hashtable(); - - // keeps track of types on the IL stack - Stack _types = new Stack(); - - Stack _loopInfoStack = new Stack(); - - AttributeCollection _assemblyAttributes = new AttributeCollection(); - - LoopInfo _currentLoopInfo; - - void EnterLoop(Label breakLabel, Label continueLabel) - { - _loopInfoStack.Push(_currentLoopInfo); - _currentLoopInfo = new LoopInfo(breakLabel, continueLabel, _tryBlock); - } - - bool InTryInLoop() - { - return _tryBlock > _currentLoopInfo.TryBlockDepth; - } - - void LeaveLoop() - { - _currentLoopInfo = (LoopInfo)_loopInfoStack.Pop(); - } - - void PushType(IType type) - { - _types.Push(type); - } - - void PushBool() - { - PushType(TypeSystemServices.BoolType); - } - - void PushVoid() - { - PushType(TypeSystemServices.VoidType); - } - - IType PopType() - { - return (IType)_types.Pop(); - } - - IType PeekTypeOnStack() - { - return (IType)_types.Peek(); - } - - void AssertStackIsEmpty(string message) - { - if (0 != _types.Count) - { - throw new ApplicationException( - string.Format("{0}: {1} items still on the stack.", message, _types.Count) - ); - } - } - - override public void Run() - { - if (Errors.Count > 0) - { - return; - } - - GatherAssemblyAttributes(); - SetUpAssembly(); - - DefineTypes(); - - DefineResources(); - DefineAssemblyAttributes(); - DefineEntryPoint(); - } - - void GatherAssemblyAttributes() - { - foreach (Module module in CompileUnit.Modules) - { - foreach (Attribute attribute in module.AssemblyAttributes) - { - _assemblyAttributes.Add(attribute); - } - } - } - - void DefineTypes() - { - if (CompileUnit.Modules.Count > 0) - { - List types = CollectTypes(); - - foreach (TypeDefinition type in types) - { - DefineType(type); - } - - foreach (TypeDefinition type in types) - { - DefineTypeMembers(type); - } - - foreach (Module module in CompileUnit.Modules) - { - OnModule(module); - } - - EmitAttributes(); - CreateTypes(types); - } - } - - class AttributeEmitVisitor : DepthFirstVisitor - { - EmitAssembly _emitter; - - public AttributeEmitVisitor(EmitAssembly emitter) - { - _emitter = emitter; - } - - public override void OnField(Field node) - { - _emitter.EmitFieldAttributes(node); - } - - public override void OnEnumMember(EnumMember node) - { - _emitter.EmitFieldAttributes(node); - } - - public override void OnEvent(Event node) - { - _emitter.EmitEventAttributes(node); - } - - public override void OnProperty(Property node) - { - Visit(node.Getter); - Visit(node.Setter); - _emitter.EmitPropertyAttributes(node); - } - - public override void OnConstructor(Constructor node) - { - Visit(node.Parameters); - _emitter.EmitConstructorAttributes(node); - } - - public override void OnMethod(Method node) - { - Visit(node.Parameters); - _emitter.EmitMethodAttributes(node); - } - - public override void OnParameterDeclaration(ParameterDeclaration node) - { - _emitter.EmitParameterAttributes(node); - } - - public override void LeaveClassDefinition(ClassDefinition node) - { - _emitter.EmitTypeAttributes(node); - } - - public override void LeaveInterfaceDefinition(InterfaceDefinition node) - { - _emitter.EmitTypeAttributes(node); - } - - public override void LeaveEnumDefinition(EnumDefinition node) - { - _emitter.EmitTypeAttributes(node); - } - } - - delegate void CustomAttributeSetter(CustomAttributeBuilder attribute); - - void EmitAttributes(INodeWithAttributes node, CustomAttributeSetter setCustomAttribute) - { - foreach (Attribute attribute in node.Attributes) - { - setCustomAttribute(GetCustomAttributeBuilder(attribute)); - } - } - - void EmitPropertyAttributes(Property node) - { - PropertyBuilder builder = GetPropertyBuilder(node); - EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute)); - } - - void EmitParameterAttributes(ParameterDeclaration node) - { - ParameterBuilder builder = (ParameterBuilder)GetBuilder(node); - EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute)); - } - - void EmitEventAttributes(Event node) - { - EventBuilder builder = (EventBuilder)GetBuilder(node); - EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute)); - } - - void EmitConstructorAttributes(Constructor node) - { - ConstructorBuilder builder = (ConstructorBuilder)GetBuilder(node); - EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute)); - } - - void EmitMethodAttributes(Method node) - { - MethodBuilder builder = GetMethodBuilder(node); - EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute)); - } - - void EmitTypeAttributes(TypeDefinition node) - { - TypeBuilder builder = GetTypeBuilder(node); - EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute)); - } - - void EmitFieldAttributes(TypeMember node) - { - FieldBuilder builder = GetFieldBuilder(node); - EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute)); - } - - void EmitAttributes() - { - AttributeEmitVisitor visitor = new AttributeEmitVisitor(this); - foreach (Module module in CompileUnit.Modules) - { - module.Accept(visitor); - } - } - - void CreateTypes(List types) - { - new TypeCreator(this, types).Run(); - } - - /// - /// Ensures that all types are created in the correct order. - /// - class TypeCreator - { - EmitAssembly _emitter; - - Hashtable _created; - - List _types; - - TypeMember _current; - - public TypeCreator(EmitAssembly emitter, List types) - { - _emitter = emitter; - _types = types; - _created = new Hashtable(); - } - - public void Run() - { - ResolveEventHandler resolveHandler = new ResolveEventHandler(OnTypeResolve); - AppDomain current = Thread.GetDomain(); - - try - { - current.TypeResolve += resolveHandler; - CreateTypes(); - } - finally - { - current.TypeResolve -= resolveHandler; - } - } - - void CreateTypes() - { - foreach (TypeMember type in _types) - { - CreateType(type); - } - } - - void CreateType(TypeMember type) - { - if (!_created.ContainsKey(type)) - { - TypeMember saved = _current; - _current = type; - - _created.Add(type, type); - - Trace("creating type '{0}'", type); - - if (IsNestedType(type)) - { - CreateType((TypeMember)type.ParentNode); - } - - TypeDefinition typedef = type as TypeDefinition; - if (null != typedef) - { - foreach (TypeReference baseTypeRef in typedef.BaseTypes) - { - AbstractInternalType tag = _emitter.GetType(baseTypeRef) as AbstractInternalType; - if (null != tag) - { - CreateType(tag.TypeDefinition); - } - } - } - - ((AbstractInternalType)type.Entity).GeneratedType = _emitter.GetTypeBuilder(type).CreateType(); - - Trace("type '{0}' successfully created", type); - - _current = saved; - } - } - - bool IsNestedType(TypeMember type) - { - NodeType parent = type.ParentNode.NodeType; - return (NodeType.ClassDefinition == parent) || - (NodeType.InterfaceDefinition == parent); - } - - Assembly OnTypeResolve(object sender, ResolveEventArgs args) - { - Trace("OnTypeResolve('{0}') during '{1}' creation.", args.Name, _current); - - // TypeResolve is generated whenever a type - // contains fields of a value type not created yet. - // All we need to do is look for value type fields - // and create them all. - ClassDefinition classdef = _current as ClassDefinition; - foreach (TypeMember member in classdef.Members) - { - if (NodeType.Field == member.NodeType) - { - AbstractInternalType type = _emitter.GetType(((Field)member).Type) as AbstractInternalType; - if (type != null && type.IsValueType) - { - CreateType(type.TypeDefinition); - } - } - } - - return _emitter._asmBuilder; - } - - void Trace(string format, params object[] args) - { - _emitter.Context.TraceVerbose(format, args); - } - } - - List CollectTypes() - { - List types = new List(); - foreach (Module module in CompileUnit.Modules) - { - CollectTypes(types, module.Members); - } - return types; - } - - void CollectTypes(List types, TypeMemberCollection members) - { - foreach (TypeMember member in members) - { - switch (member.NodeType) - { - case NodeType.InterfaceDefinition: - case NodeType.ClassDefinition: - { - types.Add(member); - CollectTypes(types, ((TypeDefinition)member).Members); - break; - } - case NodeType.EnumDefinition: - { - types.Add(member); - break; - } - } - } - } - - override public void Dispose() - { - base.Dispose(); - - _asmBuilder = null; - _moduleBuilder = null; - _symbolDocWriters.Clear(); - _il = null; - _returnValueLocal = null; - _returnType = null; - _tryBlock = 0; - _checked = true; - _rawArrayIndexing = false; - _types.Clear(); - _typeCache.Clear(); - _builders.Clear(); - _assemblyAttributes.Clear(); - } - - override public void OnAttribute(Attribute node) - { - } - - override public void OnModule(Module module) - { - Visit(module.Members); - } - - override public void OnEnumDefinition(EnumDefinition node) - { - Type baseType = typeof(int); - - TypeBuilder builder = GetTypeBuilder(node); - - builder.DefineField("value__", baseType, - FieldAttributes.Public | - FieldAttributes.SpecialName | - FieldAttributes.RTSpecialName); - - foreach (EnumMember member in node.Members) - { - FieldBuilder field = builder.DefineField(member.Name, builder, - FieldAttributes.Public | - FieldAttributes.Static | - FieldAttributes.Literal); - field.SetConstant((int)member.Initializer.Value); - SetBuilder(member, field); - } - } - - override public void OnArrayTypeReference(ArrayTypeReference node) - { - } - - override public void OnClassDefinition(ClassDefinition node) - { - EmitTypeDefinition(node); - } - - override public void OnField(Field node) - { - FieldBuilder builder = GetFieldBuilder(node); - if (builder.IsLiteral) - { - builder.SetConstant(GetInternalFieldStaticValue((InternalField)node.Entity)); - } - } - - override public void OnInterfaceDefinition(InterfaceDefinition node) - { - TypeBuilder builder = GetTypeBuilder(node); - foreach (TypeReference baseType in node.BaseTypes) - { - builder.AddInterfaceImplementation(GetSystemType(baseType)); - } - } - - override public void OnCallableDefinition(CallableDefinition node) - { - NotImplemented(node, "Unexpected callable definition!"); - } - - void EmitTypeDefinition(TypeDefinition node) - { - TypeBuilder current = GetTypeBuilder(node); - EmitBaseTypesAndAttributes(node, current); - Visit(node.Members); - } - - override public void OnMethod(Method method) - { - if (method.IsRuntime) return; - if (IsPInvoke(method)) return; - - MethodBuilder methodBuilder = GetMethodBuilder(method); - if (null != method.ExplicitInfo) - { - IMethod ifaceMethod = (IMethod)method.ExplicitInfo.Entity; - MethodInfo ifaceInfo = GetMethodInfo(ifaceMethod); - MethodInfo implInfo = GetMethodInfo((IMethod)method.Entity); - - TypeBuilder typeBuilder = GetTypeBuilder(method.DeclaringType); - typeBuilder.DefineMethodOverride(implInfo, ifaceInfo); - } - - EmitMethod(method, methodBuilder.GetILGenerator()); - } - - void EmitMethod(Method method, ILGenerator generator) - { - _il = generator; - - DefineLabels(method); - Visit(method.Locals); - - BeginMethodBody(GetEntity(method).ReturnType); - Visit(method.Body); - EndMethodBody(); - } - - void BeginMethodBody(IType returnType) - { - _returnType = returnType; - _returnLabel = _il.DefineLabel(); - if (TypeSystemServices.VoidType != _returnType) - { - _returnValueLocal = _il.DeclareLocal(GetSystemType(_returnType)); - } - } - - void EndMethodBody() - { - _il.MarkLabel(_returnLabel); - if (null != _returnValueLocal) - { - _il.Emit(OpCodes.Ldloc, _returnValueLocal); - _returnValueLocal = null; - } - _il.Emit(OpCodes.Ret); - } - - private bool IsPInvoke(Method method) - { - return GetEntity(method).IsPInvoke; - } - - override public void OnBlock(Block block) - { - bool currentChecked = _checked; - _checked = AstAnnotations.IsChecked(block); - - bool currentArrayIndexing = _rawArrayIndexing; - _rawArrayIndexing = AstAnnotations.IsRawIndexing(block); - - Visit(block.Statements); - - _rawArrayIndexing = currentArrayIndexing; - _checked = currentChecked; - } - - void DefineLabels(Method method) - { - foreach (InternalLabel label in ((InternalMethod)method.Entity).Labels) - { - label.Label = _il.DefineLabel(); - } - } - - override public void OnConstructor(Constructor constructor) - { - if (constructor.IsRuntime) return; - - ConstructorBuilder builder = GetConstructorBuilder(constructor); - EmitMethod(constructor, builder.GetILGenerator()); - } - - override public void OnLocal(Local local) - { - InternalLocal info = GetInternalLocal(local); - info.LocalBuilder = _il.DeclareLocal(GetSystemType(local)); - if (Parameters.Debug) - { - info.LocalBuilder.SetLocalSymInfo(local.Name); - } - } - - override public void OnForStatement(ForStatement node) - { - NotImplemented("ForStatement"); - } - - override public void OnReturnStatement(ReturnStatement node) - { - EmitDebugInfo(node); - OpCode retOpCode = _tryBlock > 0 ? OpCodes.Leave : OpCodes.Br; - - if (null != node.Expression) - { - Visit(node.Expression); - EmitCastIfNeeded(_returnType, PopType()); - _il.Emit(OpCodes.Stloc, _returnValueLocal); - } - _il.Emit(retOpCode, _returnLabel); - EmitNopDebugInfo(node); - } - - override public void OnRaiseStatement(RaiseStatement node) - { - EmitDebugInfo(node); - if (node.Exception == null) - { - _il.Emit(OpCodes.Rethrow); - } - else - { - Visit(node.Exception); PopType(); - _il.Emit(OpCodes.Throw); - } - EmitNopDebugInfo(node); - } - - private void EmitNopDebugInfo(Statement node) - { - // HACK: workaround - mono reports the position of - // raise as being the position of the next instruction - // after it - if (EmitDebugInfo(node)) - { - _il.Emit(OpCodes.Nop); - } - } - - override public void OnTryStatement(TryStatement node) - { - ++_tryBlock; - - _il.BeginExceptionBlock(); - Visit(node.ProtectedBlock); - Visit(node.ExceptionHandlers); - if (null != node.EnsureBlock) - { - _il.BeginFinallyBlock(); - Visit(node.EnsureBlock); - } - _il.EndExceptionBlock(); - - --_tryBlock; - } - - override public void OnExceptionHandler(ExceptionHandler node) - { - _il.BeginCatchBlock(GetSystemType(node.Declaration)); - _il.Emit(OpCodes.Stloc, GetLocalBuilder(node.Declaration)); - Visit(node.Block); - } - - override public void OnUnpackStatement(UnpackStatement node) - { - NotImplemented("Unpacking"); - } - - override public bool EnterExpressionStatement(ExpressionStatement node) - { - EmitDebugInfo(node); - return true; - } - - override public void LeaveExpressionStatement(ExpressionStatement node) - { - // if the type of the inner expression is not - // void we need to pop its return value to leave - // the stack sane - DiscardValueOnStack(); - AssertStackIsEmpty("stack must be empty after a statement!"); - - EmitNopDebugInfo(node); - } - - void DiscardValueOnStack() - { - if (PopType() != TypeSystemServices.VoidType) - { - _il.Emit(OpCodes.Pop); - } - } - - override public void OnUnlessStatement(UnlessStatement node) - { - Label endLabel = _il.DefineLabel(); - EmitDebugInfo(node); - EmitBranchTrue(node.Condition, endLabel); - EmitNopDebugInfo(node); - node.Block.Accept(this); - _il.MarkLabel(endLabel); - } - - void OnSwitch(MethodInvocationExpression node) - { - ExpressionCollection args = node.Arguments; - Visit(args[0]); - EmitCastIfNeeded(TypeSystemServices.IntType, PopType()); - - Label[] labels = new Label[args.Count-1]; - for (int i=0; i 0) - { - EmitObjectArray(node.Items); - _il.Emit(OpCodes.Ldc_I4_1); - _il.Emit(OpCodes.Newobj, List_ArrayBoolConstructor); - } - else - { - _il.Emit(OpCodes.Newobj, List_EmptyConstructor); - } - PushType(TypeSystemServices.ListType); - } - - override public void OnArrayLiteralExpression(ArrayLiteralExpression node) - { - IArrayType type = (IArrayType)node.ExpressionType; - EmitArray(type.GetElementType(), node.Items); - PushType(type); - } - - override public void OnRELiteralExpression(RELiteralExpression node) - { - _il.Emit(OpCodes.Ldstr, RuntimeServices.Mid(node.Value, 1, -1)); - _il.Emit(OpCodes.Newobj, Regex_Constructor); - PushType(node.ExpressionType); - } - - override public void OnStringLiteralExpression(StringLiteralExpression node) - { - _il.Emit(OpCodes.Ldstr, node.Value); - PushType(TypeSystemServices.StringType); - } - - override public void OnCharLiteralExpression(CharLiteralExpression node) - { - _il.Emit(OpCodes.Ldc_I4, node.Value[0]); - PushType(TypeSystemServices.CharType); - } - - override public void OnSlicingExpression(SlicingExpression node) - { - if (AstUtil.IsLhsOfAssignment(node)) - { - return; - } - - Visit(node.Target); - - IArrayType type = (IArrayType)PopType(); - EmitNormalizedArrayIndex(node, node.Indices[0].Begin); - - IType elementType = type.GetElementType(); - OpCode opcode = GetLoadEntityOpCode(elementType); - if (OpCodes.Ldelema.Value == opcode.Value) - { - Type systemType = GetSystemType(elementType); - _il.Emit(opcode, systemType); - _il.Emit(OpCodes.Ldobj, systemType); - } - else - { - _il.Emit(opcode); - } - PushType(elementType); - } - - void EmitNormalizedArrayIndex(SlicingExpression sourceNode, Expression index) - { - bool isNegative = false; - if (CanBeNegative(index, ref isNegative) - && !_rawArrayIndexing - && !AstAnnotations.IsRawIndexing(sourceNode)) - { - if (isNegative) - { - _il.Emit(OpCodes.Dup); - _il.Emit(OpCodes.Ldlen); - EmitLoadInt(index); - _il.Emit(OpCodes.Add); - } - else - { - _il.Emit(OpCodes.Dup); - EmitLoadInt(index); - _il.EmitCall(OpCodes.Call, RuntimeServices_NormalizeArrayIndex, null); - } - } - else - { - EmitLoadInt(index); - } - } - - bool CanBeNegative(Expression expression, ref bool isNegative) - { - IntegerLiteralExpression integer = expression as IntegerLiteralExpression; - if (null != integer) - { - if (integer.Value >= 0) - { - return false; - } - isNegative = true; - } - return true; - } - - void EmitLoadInt(Expression expression) - { - Visit(expression); - EmitCastIfNeeded(TypeSystemServices.IntType, PopType()); - } - - override public void OnExpressionInterpolationExpression(ExpressionInterpolationExpression node) - { - Type stringBuilderType = typeof(StringBuilder); - ConstructorInfo constructor = stringBuilderType.GetConstructor(new Type[0]); - MethodInfo appendObject = stringBuilderType.GetMethod("Append", new Type[] { typeof(object) }); - MethodInfo appendString = stringBuilderType.GetMethod("Append", new Type[] { typeof(string) }); - - _il.Emit(OpCodes.Newobj, constructor); - - foreach (Expression arg in node.Expressions) - { - Visit(arg); - - IType argType = PopType(); - if (TypeSystemServices.StringType == argType) - { - _il.EmitCall(OpCodes.Call, appendString, null); - } - else - { - EmitCastIfNeeded(TypeSystemServices.ObjectType, argType); - _il.EmitCall(OpCodes.Call, appendObject, null); - } - } - _il.EmitCall(OpCodes.Call, stringBuilderType.GetMethod("ToString", new Type[0]), null); - PushType(TypeSystemServices.StringType); - } - - void LoadMemberTarget(Expression self, IMember member) - { - if (member.DeclaringType.IsValueType) - { - LoadAddress(self); - } - else - { - Visit(self); - PopType(); - } - } - - void EmitLoadFieldAddress(Expression expression, IField field) - { - if (field.IsStatic) - { - _il.Emit(OpCodes.Ldsflda, GetFieldInfo(field)); - } - else - { - LoadMemberTarget(((MemberReferenceExpression)expression).Target, field); - _il.Emit(OpCodes.Ldflda, GetFieldInfo(field)); - } - } - - void EmitLoadField(Expression self, IField fieldInfo) - { - if (fieldInfo.IsStatic) - { - if (fieldInfo.IsLiteral) - { - EmitLoadLiteralField(self, fieldInfo); - } - else - { - _il.Emit(OpCodes.Ldsfld, GetFieldInfo(fieldInfo)); - } - } - else - { - LoadMemberTarget(self, fieldInfo); - _il.Emit(OpCodes.Ldfld, GetFieldInfo(fieldInfo)); - } - PushType(fieldInfo.Type); - } - - object GetStaticValue(IField field) - { - InternalField internalField = field as InternalField; - if (null != internalField) - { - return GetInternalFieldStaticValue(internalField); - } - return field.StaticValue; - } - - object GetInternalFieldStaticValue(InternalField field) - { - return GetValue(field.Type, (Expression)field.StaticValue); - } - - void EmitLoadLiteralField(Node node, IField fieldInfo) - { - object value = GetStaticValue(fieldInfo); - if (null == value) - { - _il.Emit(OpCodes.Ldnull); - } - else - { - TypeCode type = Type.GetTypeCode(value.GetType()); - switch (type) - { - case TypeCode.Byte: - { - _il.Emit(OpCodes.Ldc_I4, (int)(byte)value); - _il.Emit(OpCodes.Conv_U1); - break; - } - - case TypeCode.SByte: - { - _il.Emit(OpCodes.Ldc_I4, (int)(sbyte)value); - _il.Emit(OpCodes.Conv_I1); - break; - } - - case TypeCode.Char: - { - _il.Emit(OpCodes.Ldc_I4, (int)(char)value); - break; - } - - case TypeCode.Int16: - { - _il.Emit(OpCodes.Ldc_I4, (int)(short)value); - break; - } - - case TypeCode.UInt16: - { - _il.Emit(OpCodes.Ldc_I4, (int)(ushort)value); - break; - } - - case TypeCode.Int32: - { - _il.Emit(OpCodes.Ldc_I4, (int)value); - break; - } - - case TypeCode.UInt32: - { - uint uValue = (uint)value; - unchecked - { - _il.Emit(OpCodes.Ldc_I4, (int)uValue); - } - _il.Emit(OpCodes.Conv_U4); - break; - } - - case TypeCode.Int64: - { - _il.Emit(OpCodes.Ldc_I8, (long)value); - break; - } - - case TypeCode.UInt64: - { - ulong uValue = (ulong)value; - unchecked - { - _il.Emit(OpCodes.Ldc_I8, (long)uValue); - } - _il.Emit(OpCodes.Conv_U8); - break; - } - - case TypeCode.Single: - { - _il.Emit(OpCodes.Ldc_R4, (float)value); - break; - } - - case TypeCode.Double: - { - _il.Emit(OpCodes.Ldc_R8, (double)value); - break; - } - - case TypeCode.String: - { - _il.Emit(OpCodes.Ldstr, (string)value); - break; - } - - default: - { - NotImplemented(node, "Literal: " + type.ToString()); - break; - } - } - } - } - - override public void OnGenericReferenceExpression(GenericReferenceExpression node) +#region license +// Copyright (c) 2004, 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 + +using System; +using System.Collections; +using System.Diagnostics; +using System.Diagnostics.SymbolStore; +using System.IO; +using System.Reflection; +using System.Reflection.Emit; +using System.Resources; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using Boo.Lang.Compiler.Ast; +using Boo.Lang.Compiler.TypeSystem; +using Boo.Lang.Runtime; +using Attribute = Boo.Lang.Compiler.Ast.Attribute; +using Module = Boo.Lang.Compiler.Ast.Module; + +namespace Boo.Lang.Compiler.Steps +{ + class LoopInfo + { + public Label BreakLabel; + + public Label ContinueLabel; + + public int TryBlockDepth; + + public LoopInfo(Label breakLabel, Label continueLabel, int tryBlockDepth) { + BreakLabel = breakLabel; + ContinueLabel = continueLabel; + TryBlockDepth = tryBlockDepth; + } + } + + public class EmitAssembly : AbstractVisitorCompilerStep + { + static ConstructorInfo DebuggableAttribute_Constructor = typeof(DebuggableAttribute).GetConstructor(new Type[] { Types.Bool, Types.Bool }); + + static ConstructorInfo DuckTypedAttribute_Constructor = Types.DuckTypedAttribute.GetConstructor(new Type[0]); + + static ConstructorInfo ParamArrayAttribute_Constructor = Types.ParamArrayAttribute.GetConstructor(new Type[0]); + + static MethodInfo RuntimeServices_NormalizeArrayIndex = Types.RuntimeServices.GetMethod("NormalizeArrayIndex"); + + static MethodInfo RuntimeServices_ToBool_Object = Types.RuntimeServices.GetMethod("ToBool", new Type[] { Types.Object }); + + static MethodInfo RuntimeServices_ToBool_Decimal = Types.RuntimeServices.GetMethod("ToBool", new Type[] { Types.Decimal }); + + static MethodInfo Builtins_ArrayTypedConstructor = Types.Builtins.GetMethod("array", new Type[] { Types.Type, Types.Int }); + + static MethodInfo Builtins_ArrayTypedCollectionConstructor = Types.Builtins.GetMethod("array", new Type[] { Types.Type, Types.ICollection }); + + static MethodInfo Math_Pow = typeof(Math).GetMethod("Pow"); + + static ConstructorInfo List_EmptyConstructor = Types.List.GetConstructor(Type.EmptyTypes); + + static ConstructorInfo List_ArrayBoolConstructor = Types.List.GetConstructor(new Type[] { Types.ObjectArray, Types.Bool }); + + static ConstructorInfo Hash_Constructor = Types.Hash.GetConstructor(new Type[0]); + + static ConstructorInfo Regex_Constructor = typeof(Regex).GetConstructor(new Type[] { Types.String }); + + static MethodInfo Hash_Add = Types.Hash.GetMethod("Add", new Type[] { typeof(object), typeof(object) }); + + static ConstructorInfo TimeSpan_LongConstructor = Types.TimeSpan.GetConstructor(new Type[] { typeof(long) }); + + static MethodInfo Type_GetTypeFromHandle = Types.Type.GetMethod("GetTypeFromHandle"); + + AssemblyBuilder _asmBuilder; + + ModuleBuilder _moduleBuilder; + + Hashtable _symbolDocWriters = new Hashtable(); + + // IL generation state + ILGenerator _il; + Label _returnLabel; // current label for method return + LocalBuilder _returnValueLocal; // returnValueLocal + IType _returnType; + int _tryBlock; // are we in a try block? + bool _checked = true; + bool _rawArrayIndexing = false; + Hashtable _typeCache = new Hashtable(); + + // keeps track of types on the IL stack + Stack _types = new Stack(); + + Stack _loopInfoStack = new Stack(); + + AttributeCollection _assemblyAttributes = new AttributeCollection(); + + LoopInfo _currentLoopInfo; + + void EnterLoop(Label breakLabel, Label continueLabel) + { + _loopInfoStack.Push(_currentLoopInfo); + _currentLoopInfo = new LoopInfo(breakLabel, continueLabel, _tryBlock); + } + + bool InTryInLoop() + { + return _tryBlock > _currentLoopInfo.TryBlockDepth; + } + + void LeaveLoop() + { + _currentLoopInfo = (LoopInfo)_loopInfoStack.Pop(); + } + + void PushType(IType type) + { + _types.Push(type); + } + + void PushBool() + { + PushType(TypeSystemServices.BoolType); + } + + void PushVoid() + { + PushType(TypeSystemServices.VoidType); + } + + IType PopType() + { + return (IType)_types.Pop(); + } + + IType PeekTypeOnStack() + { + return (IType)_types.Peek(); + } + + void AssertStackIsEmpty(string message) + { + if (0 != _types.Count) + { + throw new ApplicationException( + string.Format("{0}: {1} items still on the stack.", message, _types.Count) + ); + } + } + + override public void Run() + { + if (Errors.Count > 0) + { + return; + } + + GatherAssemblyAttributes(); + SetUpAssembly(); + + DefineTypes(); + + DefineResources(); + DefineAssemblyAttributes(); + DefineEntryPoint(); + } + + void GatherAssemblyAttributes() + { + foreach (Module module in CompileUnit.Modules) + { + foreach (Attribute attribute in module.AssemblyAttributes) + { + _assemblyAttributes.Add(attribute); + } + } + } + + void DefineTypes() + { + if (CompileUnit.Modules.Count > 0) + { + List types = CollectTypes(); + + foreach (TypeDefinition type in types) + { + DefineType(type); + } + + foreach (TypeDefinition type in types) + { + DefineTypeMembers(type); + } + + foreach (Module module in CompileUnit.Modules) + { + OnModule(module); + } + + EmitAttributes(); + CreateTypes(types); + } + } + + class AttributeEmitVisitor : DepthFirstVisitor + { + EmitAssembly _emitter; + + public AttributeEmitVisitor(EmitAssembly emitter) + { + _emitter = emitter; + } + + public override void OnField(Field node) + { + _emitter.EmitFieldAttributes(node); + } + + public override void OnEnumMember(EnumMember node) + { + _emitter.EmitFieldAttributes(node); + } + + public override void OnEvent(Event node) + { + _emitter.EmitEventAttributes(node); + } + + public override void OnProperty(Property node) + { + Visit(node.Getter); + Visit(node.Setter); + _emitter.EmitPropertyAttributes(node); + } + + public override void OnConstructor(Constructor node) + { + Visit(node.Parameters); + _emitter.EmitConstructorAttributes(node); + } + + public override void OnMethod(Method node) + { + Visit(node.Parameters); + _emitter.EmitMethodAttributes(node); + } + + public override void OnParameterDeclaration(ParameterDeclaration node) + { + _emitter.EmitParameterAttributes(node); + } + + public override void LeaveClassDefinition(ClassDefinition node) + { + _emitter.EmitTypeAttributes(node); + } + + public override void LeaveInterfaceDefinition(InterfaceDefinition node) + { + _emitter.EmitTypeAttributes(node); + } + + public override void LeaveEnumDefinition(EnumDefinition node) + { + _emitter.EmitTypeAttributes(node); + } + } + + delegate void CustomAttributeSetter(CustomAttributeBuilder attribute); + + void EmitAttributes(INodeWithAttributes node, CustomAttributeSetter setCustomAttribute) + { + foreach (Attribute attribute in node.Attributes) + { + setCustomAttribute(GetCustomAttributeBuilder(attribute)); + } + } + + void EmitPropertyAttributes(Property node) + { + PropertyBuilder builder = GetPropertyBuilder(node); + EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute)); + } + + void EmitParameterAttributes(ParameterDeclaration node) + { + ParameterBuilder builder = (ParameterBuilder)GetBuilder(node); + EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute)); + } + + void EmitEventAttributes(Event node) + { + EventBuilder builder = (EventBuilder)GetBuilder(node); + EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute)); + } + + void EmitConstructorAttributes(Constructor node) + { + ConstructorBuilder builder = (ConstructorBuilder)GetBuilder(node); + EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute)); + } + + void EmitMethodAttributes(Method node) + { + MethodBuilder builder = GetMethodBuilder(node); + EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute)); + } + + void EmitTypeAttributes(TypeDefinition node) + { + TypeBuilder builder = GetTypeBuilder(node); + EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute)); + } + + void EmitFieldAttributes(TypeMember node) + { + FieldBuilder builder = GetFieldBuilder(node); + EmitAttributes(node, new CustomAttributeSetter(builder.SetCustomAttribute)); + } + + void EmitAttributes() + { + AttributeEmitVisitor visitor = new AttributeEmitVisitor(this); + foreach (Module module in CompileUnit.Modules) + { + module.Accept(visitor); + } + } + + void CreateTypes(List types) + { + new TypeCreator(this, types).Run(); + } + + /// + /// Ensures that all types are created in the correct order. + /// + class TypeCreator + { + EmitAssembly _emitter; + + Hashtable _created; + + List _types; + + TypeMember _current; + + public TypeCreator(EmitAssembly emitter, List types) + { + _emitter = emitter; + _types = types; + _created = new Hashtable(); + } + + public void Run() + { + ResolveEventHandler resolveHandler = new ResolveEventHandler(OnTypeResolve); + AppDomain current = Thread.GetDomain(); + + try + { + current.TypeResolve += resolveHandler; + CreateTypes(); + } + finally + { + current.TypeResolve -= resolveHandler; + } + } + + void CreateTypes() + { + foreach (TypeMember type in _types) + { + CreateType(type); + } + } + + void CreateType(TypeMember type) + { + if (!_created.ContainsKey(type)) + { + TypeMember saved = _current; + _current = type; + + _created.Add(type, type); + + Trace("creating type '{0}'", type); + + if (IsNestedType(type)) + { + CreateType((TypeMember)type.ParentNode); + } + + TypeDefinition typedef = type as TypeDefinition; + if (null != typedef) + { + foreach (TypeReference baseTypeRef in typedef.BaseTypes) + { + AbstractInternalType tag = _emitter.GetType(baseTypeRef) as AbstractInternalType; + if (null != tag) + { + CreateType(tag.TypeDefinition); + } + } + } + + ((AbstractInternalType)type.Entity).GeneratedType = _emitter.GetTypeBuilder(type).CreateType(); + + Trace("type '{0}' successfully created", type); + + _current = saved; + } + } + + bool IsNestedType(TypeMember type) + { + NodeType parent = type.ParentNode.NodeType; + return (NodeType.ClassDefinition == parent) || + (NodeType.InterfaceDefinition == parent); + } + + Assembly OnTypeResolve(object sender, ResolveEventArgs args) + { + Trace("OnTypeResolve('{0}') during '{1}' creation.", args.Name, _current); + + // TypeResolve is generated whenever a type + // contains fields of a value type not created yet. + // All we need to do is look for value type fields + // and create them all. + ClassDefinition classdef = _current as ClassDefinition; + foreach (TypeMember member in classdef.Members) + { + if (NodeType.Field == member.NodeType) + { + AbstractInternalType type = _emitter.GetType(((Field)member).Type) as AbstractInternalType; + if (type != null && type.IsValueType) + { + CreateType(type.TypeDefinition); + } + } + } + + return _emitter._asmBuilder; + } + + void Trace(string format, params object[] args) + { + _emitter.Context.TraceVerbose(format, args); + } + } + + List CollectTypes() + { + List types = new List(); + foreach (Module module in CompileUnit.Modules) + { + CollectTypes(types, module.Members); + } + return types; + } + + void CollectTypes(List types, TypeMemberCollection members) + { + foreach (TypeMember member in members) + { + switch (member.NodeType) + { + case NodeType.InterfaceDefinition: + case NodeType.ClassDefinition: + { + types.Add(member); + CollectTypes(types, ((TypeDefinition)member).Members); + break; + } + case NodeType.EnumDefinition: + { + types.Add(member); + break; + } + } + } + } + + override public void Dispose() + { + base.Dispose(); + + _asmBuilder = null; + _moduleBuilder = null; + _symbolDocWriters.Clear(); + _il = null; + _returnValueLocal = null; + _returnType = null; + _tryBlock = 0; + _checked = true; + _rawArrayIndexing = false; + _types.Clear(); + _typeCache.Clear(); + _builders.Clear(); + _assemblyAttributes.Clear(); + } + + override public void OnAttribute(Attribute node) + { + } + + override public void OnModule(Module module) + { + Visit(module.Members); + } + + override public void OnEnumDefinition(EnumDefinition node) + { + Type baseType = typeof(int); + + TypeBuilder builder = GetTypeBuilder(node); + + builder.DefineField("value__", baseType, + FieldAttributes.Public | + FieldAttributes.SpecialName | + FieldAttributes.RTSpecialName); + + foreach (EnumMember member in node.Members) + { + FieldBuilder field = builder.DefineField(member.Name, builder, + FieldAttributes.Public | + FieldAttributes.Static | + FieldAttributes.Literal); + field.SetConstant((int)member.Initializer.Value); + SetBuilder(member, field); + } + } + + override public void OnArrayTypeReference(ArrayTypeReference node) + { + } + + override public void OnClassDefinition(ClassDefinition node) + { + EmitTypeDefinition(node); + } + + override public void OnField(Field node) + { + FieldBuilder builder = GetFieldBuilder(node); + if (builder.IsLiteral) + { + builder.SetConstant(GetInternalFieldStaticValue((InternalField)node.Entity)); + } + } + + override public void OnInterfaceDefinition(InterfaceDefinition node) + { + TypeBuilder builder = GetTypeBuilder(node); + foreach (TypeReference baseType in node.BaseTypes) + { + builder.AddInterfaceImplementation(GetSystemType(baseType)); + } + } + + override public void OnCallableDefinition(CallableDefinition node) + { + NotImplemented(node, "Unexpected callable definition!"); + } + + void EmitTypeDefinition(TypeDefinition node) + { + TypeBuilder current = GetTypeBuilder(node); + EmitBaseTypesAndAttributes(node, current); + Visit(node.Members); + } + + override public void OnMethod(Method method) + { + if (method.IsRuntime) return; + if (IsPInvoke(method)) return; + + MethodBuilder methodBuilder = GetMethodBuilder(method); + if (null != method.ExplicitInfo) + { + IMethod ifaceMethod = (IMethod)method.ExplicitInfo.Entity; + MethodInfo ifaceInfo = GetMethodInfo(ifaceMethod); + MethodInfo implInfo = GetMethodInfo((IMethod)method.Entity); + + TypeBuilder typeBuilder = GetTypeBuilder(method.DeclaringType); + typeBuilder.DefineMethodOverride(implInfo, ifaceInfo); + } + + EmitMethod(method, methodBuilder.GetILGenerator()); + } + + void EmitMethod(Method method, ILGenerator generator) + { + _il = generator; + + DefineLabels(method); + Visit(method.Locals); + + BeginMethodBody(GetEntity(method).ReturnType); + Visit(method.Body); + EndMethodBody(); + } + + void BeginMethodBody(IType returnType) + { + _returnType = returnType; + _returnLabel = _il.DefineLabel(); + if (TypeSystemServices.VoidType != _returnType) + { + _returnValueLocal = _il.DeclareLocal(GetSystemType(_returnType)); + } + } + + void EndMethodBody() + { + _il.MarkLabel(_returnLabel); + if (null != _returnValueLocal) + { + _il.Emit(OpCodes.Ldloc, _returnValueLocal); + _returnValueLocal = null; + } + _il.Emit(OpCodes.Ret); + } + + private bool IsPInvoke(Method method) + { + return GetEntity(method).IsPInvoke; + } + + override public void OnBlock(Block block) + { + bool currentChecked = _checked; + _checked = AstAnnotations.IsChecked(block); + + bool currentArrayIndexing = _rawArrayIndexing; + _rawArrayIndexing = AstAnnotations.IsRawIndexing(block); + + Visit(block.Statements); + + _rawArrayIndexing = currentArrayIndexing; + _checked = currentChecked; + } + + void DefineLabels(Method method) + { + foreach (InternalLabel label in ((InternalMethod)method.Entity).Labels) + { + label.Label = _il.DefineLabel(); + } + } + + override public void OnConstructor(Constructor constructor) + { + if (constructor.IsRuntime) return; + + ConstructorBuilder builder = GetConstructorBuilder(constructor); + EmitMethod(constructor, builder.GetILGenerator()); + } + + override public void OnLocal(Local local) + { + InternalLocal info = GetInternalLocal(local); + info.LocalBuilder = _il.DeclareLocal(GetSystemType(local)); + if (Parameters.Debug) + { + info.LocalBuilder.SetLocalSymInfo(local.Name); + } + } + + override public void OnForStatement(ForStatement node) + { + NotImplemented("ForStatement"); + } + + override public void OnReturnStatement(ReturnStatement node) + { + EmitDebugInfo(node); + OpCode retOpCode = _tryBlock > 0 ? OpCodes.Leave : OpCodes.Br; + + if (null != node.Expression) + { + Visit(node.Expression); + EmitCastIfNeeded(_returnType, PopType()); + _il.Emit(OpCodes.Stloc, _returnValueLocal); + } + _il.Emit(retOpCode, _returnLabel); + EmitNopDebugInfo(node); + } + + override public void OnRaiseStatement(RaiseStatement node) + { + EmitDebugInfo(node); + if (node.Exception == null) + { + _il.Emit(OpCodes.Rethrow); + } + else + { + Visit(node.Exception); PopType(); + _il.Emit(OpCodes.Throw); + } + EmitNopDebugInfo(node); + } + + private void EmitNopDebugInfo(Statement node) + { + // HACK: workaround - mono reports the position of + // raise as being the position of the next instruction + // after it + if (EmitDebugInfo(node)) + { + _il.Emit(OpCodes.Nop); + } + } + + override public void OnTryStatement(TryStatement node) + { + ++_tryBlock; + + _il.BeginExceptionBlock(); + Visit(node.ProtectedBlock); + Visit(node.ExceptionHandlers); + if (null != node.EnsureBlock) + { + _il.BeginFinallyBlock(); + Visit(node.EnsureBlock); + } + _il.EndExceptionBlock(); + + --_tryBlock; + } + + override public void OnExceptionHandler(ExceptionHandler node) + { + _il.BeginCatchBlock(GetSystemType(node.Declaration)); + _il.Emit(OpCodes.Stloc, GetLocalBuilder(node.Declaration)); + Visit(node.Block); + } + + override public void OnUnpackStatement(UnpackStatement node) + { + NotImplemented("Unpacking"); + } + + override public bool EnterExpressionStatement(ExpressionStatement node) + { + EmitDebugInfo(node); + return true; + } + + override public void LeaveExpressionStatement(ExpressionStatement node) + { + // if the type of the inner expression is not + // void we need to pop its return value to leave + // the stack sane + DiscardValueOnStack(); + AssertStackIsEmpty("stack must be empty after a statement!"); + + EmitNopDebugInfo(node); + } + + void DiscardValueOnStack() + { + if (PopType() != TypeSystemServices.VoidType) + { + _il.Emit(OpCodes.Pop); + } + } + + override public void OnUnlessStatement(UnlessStatement node) + { + Label endLabel = _il.DefineLabel(); + EmitDebugInfo(node); + EmitBranchTrue(node.Condition, endLabel); + EmitNopDebugInfo(node); + node.Block.Accept(this); + _il.MarkLabel(endLabel); + } + + void OnSwitch(MethodInvocationExpression node) + { + ExpressionCollection args = node.Arguments; + Visit(args[0]); + EmitCastIfNeeded(TypeSystemServices.IntType, PopType()); + + Label[] labels = new Label[args.Count-1]; + for (int i=0; i 0) + { + EmitObjectArray(node.Items); + _il.Emit(OpCodes.Ldc_I4_1); + _il.Emit(OpCodes.Newobj, List_ArrayBoolConstructor); + } + else + { + _il.Emit(OpCodes.Newobj, List_EmptyConstructor); + } + PushType(TypeSystemServices.ListType); + } + + override public void OnArrayLiteralExpression(ArrayLiteralExpression node) + { + IArrayType type = (IArrayType)node.ExpressionType; + EmitArray(type.GetElementType(), node.Items); + PushType(type); + } + + override public void OnRELiteralExpression(RELiteralExpression node) + { + _il.Emit(OpCodes.Ldstr, RuntimeServices.Mid(node.Value, 1, -1)); + _il.Emit(OpCodes.Newobj, Regex_Constructor); + PushType(node.ExpressionType); + } + + override public void OnStringLiteralExpression(StringLiteralExpression node) + { + _il.Emit(OpCodes.Ldstr, node.Value); + PushType(TypeSystemServices.StringType); + } + + override public void OnCharLiteralExpression(CharLiteralExpression node) + { + _il.Emit(OpCodes.Ldc_I4, node.Value[0]); + PushType(TypeSystemServices.CharType); + } + + override public void OnSlicingExpression(SlicingExpression node) + { + if (AstUtil.IsLhsOfAssignment(node)) + { + return; + } + + Visit(node.Target); + + IArrayType type = (IArrayType)PopType(); + EmitNormalizedArrayIndex(node, node.Indices[0].Begin); + + IType elementType = type.GetElementType(); + OpCode opcode = GetLoadEntityOpCode(elementType); + if (OpCodes.Ldelema.Value == opcode.Value) + { + Type systemType = GetSystemType(elementType); + _il.Emit(opcode, systemType); + _il.Emit(OpCodes.Ldobj, systemType); + } + else + { + _il.Emit(opcode); + } + PushType(elementType); + } + + void EmitNormalizedArrayIndex(SlicingExpression sourceNode, Expression index) + { + bool isNegative = false; + if (CanBeNegative(index, ref isNegative) + && !_rawArrayIndexing + && !AstAnnotations.IsRawIndexing(sourceNode)) + { + if (isNegative) + { + _il.Emit(OpCodes.Dup); + _il.Emit(OpCodes.Ldlen); + EmitLoadInt(index); + _il.Emit(OpCodes.Add); + } + else + { + _il.Emit(OpCodes.Dup); + EmitLoadInt(index); + _il.EmitCall(OpCodes.Call, RuntimeServices_NormalizeArrayIndex, null); + } + } + else + { + EmitLoadInt(index); + } + } + + bool CanBeNegative(Expression expression, ref bool isNegative) + { + IntegerLiteralExpression integer = expression as IntegerLiteralExpression; + if (null != integer) + { + if (integer.Value >= 0) + { + return false; + } + isNegative = true; + } + return true; + } + + void EmitLoadInt(Expression expression) + { + Visit(expression); + EmitCastIfNeeded(TypeSystemServices.IntType, PopType()); + } + + override public void OnExpressionInterpolationExpression(ExpressionInterpolationExpression node) + { + Type stringBuilderType = typeof(StringBuilder); + ConstructorInfo constructor = stringBuilderType.GetConstructor(new Type[0]); + MethodInfo appendObject = stringBuilderType.GetMethod("Append", new Type[] { typeof(object) }); + MethodInfo appendString = stringBuilderType.GetMethod("Append", new Type[] { typeof(string) }); + + _il.Emit(OpCodes.Newobj, constructor); + + foreach (Expression arg in node.Expressions) + { + Visit(arg); + + IType argType = PopType(); + if (TypeSystemServices.StringType == argType) + { + _il.EmitCall(OpCodes.Call, appendString, null); + } + else + { + EmitCastIfNeeded(TypeSystemServices.ObjectType, argType); + _il.EmitCall(OpCodes.Call, appendObject, null); + } + } + _il.EmitCall(OpCodes.Call, stringBuilderType.GetMethod("ToString", new Type[0]), null); + PushType(TypeSystemServices.StringType); + } + + void LoadMemberTarget(Expression self, IMember member) + { + if (member.DeclaringType.IsValueType) + { + LoadAddress(self); + } + else + { + Visit(self); + PopType(); + } + } + + void EmitLoadFieldAddress(Expression expression, IField field) + { + if (field.IsStatic) + { + _il.Emit(OpCodes.Ldsflda, GetFieldInfo(field)); + } + else + { + LoadMemberTarget(((MemberReferenceExpression)expression).Target, field); + _il.Emit(OpCodes.Ldflda, GetFieldInfo(field)); + } + } + + void EmitLoadField(Expression self, IField fieldInfo) + { + if (fieldInfo.IsStatic) + { + if (fieldInfo.IsLiteral) + { + EmitLoadLiteralField(self, fieldInfo); + } + else + { + _il.Emit(OpCodes.Ldsfld, GetFieldInfo(fieldInfo)); + } + } + else + { + LoadMemberTarget(self, fieldInfo); + _il.Emit(OpCodes.Ldfld, GetFieldInfo(fieldInfo)); + } + PushType(fieldInfo.Type); + } + + object GetStaticValue(IField field) + { + InternalField internalField = field as InternalField; + if (null != internalField) + { + return GetInternalFieldStaticValue(internalField); + } + return field.StaticValue; + } + + object GetInternalFieldStaticValue(InternalField field) + { + return GetValue(field.Type, (Expression)field.StaticValue); + } + + void EmitLoadLiteralField(Node node, IField fieldInfo) + { + object value = GetStaticValue(fieldInfo); + if (null == value) + { + _il.Emit(OpCodes.Ldnull); + } + else + { + TypeCode type = Type.GetTypeCode(value.GetType()); + switch (type) + { + case TypeCode.Byte: + { + _il.Emit(OpCodes.Ldc_I4, (int)(byte)value); + _il.Emit(OpCodes.Conv_U1); + break; + } + + case TypeCode.SByte: + { + _il.Emit(OpCodes.Ldc_I4, (int)(sbyte)value); + _il.Emit(OpCodes.Conv_I1); + break; + } + + case TypeCode.Char: + { + _il.Emit(OpCodes.Ldc_I4, (int)(char)value); + break; + } + + case TypeCode.Int16: + { + _il.Emit(OpCodes.Ldc_I4, (int)(short)value); + break; + } + + case TypeCode.UInt16: + { + _il.Emit(OpCodes.Ldc_I4, (int)(ushort)value); + break; + } + + case TypeCode.Int32: + { + _il.Emit(OpCodes.Ldc_I4, (int)value); + break; + } + + case TypeCode.UInt32: + { + uint uValue = (uint)value; + unchecked + { + _il.Emit(OpCodes.Ldc_I4, (int)uValue); + } + _il.Emit(OpCodes.Conv_U4); + break; + } + + case TypeCode.Int64: + { + _il.Emit(OpCodes.Ldc_I8, (long)value); + break; + } + + case TypeCode.UInt64: + { + ulong uValue = (ulong)value; + unchecked + { + _il.Emit(OpCodes.Ldc_I8, (long)uValue); + } + _il.Emit(OpCodes.Conv_U8); + break; + } + + case TypeCode.Single: + { + _il.Emit(OpCodes.Ldc_R4, (float)value); + break; + } + + case TypeCode.Double: + { + _il.Emit(OpCodes.Ldc_R8, (double)value); + break; + } + + case TypeCode.String: + { + _il.Emit(OpCodes.Ldstr, (string)value); + break; + } + + default: + { + NotImplemented(node, "Literal: " + type.ToString()); + break; + } + } + } + } + + override public void OnGenericReferenceExpression(GenericReferenceExpression node) + { IEntity tag = TypeSystem.TypeSystemServices.GetEntity(node); switch (tag.EntityType) { @@ -2592,2073 +2592,2106 @@ break; } } - } - - override public void OnMemberReferenceExpression(MemberReferenceExpression node) - { - IEntity tag = TypeSystem.TypeSystemServices.GetEntity(node); - switch (tag.EntityType) - { - case EntityType.Method: - { - node.Target.Accept(this); - break; - } - - case EntityType.Field: - { - EmitLoadField(node.Target, (IField)tag); - break; - } - - case EntityType.Type: - { - EmitGetTypeFromHandle(GetSystemType(node)); - break; - } - - default: - { - NotImplemented(node, tag.ToString()); - break; - } - } - } - - void LoadAddress(Expression expression) - { - if (NodeType.SelfLiteralExpression == expression.NodeType) - { - if (expression.ExpressionType.IsValueType) - { - _il.Emit(OpCodes.Ldarg_0); - return; - } - } - - IEntity tag = expression.Entity; - if (null != tag) - { - switch (tag.EntityType) - { - case EntityType.Local: - { - _il.Emit(OpCodes.Ldloca, ((InternalLocal)tag).LocalBuilder); - return; - } - - case EntityType.Parameter: - { - InternalParameter param = (InternalParameter)tag; - if (param.Parameter.IsByRef) - { - LoadParam(param); - } - else - { - _il.Emit(OpCodes.Ldarga, param.Index); - } - return; - } - - case EntityType.Field: - { - IField field = (IField)tag; - if (!field.IsLiteral) - { - EmitLoadFieldAddress(expression, field); - return; - } - break; - } - } - } - - if (IsValueTypeArraySlicing(expression)) - { - SlicingExpression slicing = (SlicingExpression)expression; - Visit(slicing.Target); - IArrayType arrayType = (IArrayType)PopType(); - EmitNormalizedArrayIndex(slicing, slicing.Indices[0].Begin); - _il.Emit(OpCodes.Ldelema, GetSystemType(arrayType.GetElementType())); - } - else - { - // declare local to hold value type - Visit(expression); - LocalBuilder temp = _il.DeclareLocal(GetSystemType(PopType())); - _il.Emit(OpCodes.Stloc, temp); - _il.Emit(OpCodes.Ldloca, temp); - } - } - - bool IsValueTypeArraySlicing(Expression expression) - { - SlicingExpression slicing = expression as SlicingExpression; - if (null != slicing) - { - IArrayType type = (IArrayType)slicing.Target.ExpressionType; - return type.GetElementType().IsValueType; - } - return false; - } - - override public void OnSelfLiteralExpression(SelfLiteralExpression node) - { - _il.Emit(OpCodes.Ldarg_0); - if (node.ExpressionType.IsValueType) - { - _il.Emit(OpCodes.Ldobj, GetSystemType(node.ExpressionType)); - } - PushType(node.ExpressionType); - } - - override public void OnSuperLiteralExpression(SuperLiteralExpression node) - { - _il.Emit(OpCodes.Ldarg_0); - if (node.ExpressionType.IsValueType) - { - _il.Emit(OpCodes.Ldobj, GetSystemType(node.ExpressionType)); - } - PushType(node.ExpressionType); - } - - override public void OnNullLiteralExpression(NullLiteralExpression node) - { - _il.Emit(OpCodes.Ldnull); - PushType(null); - } - - override public void OnReferenceExpression(ReferenceExpression node) - { - IEntity info = TypeSystem.TypeSystemServices.GetEntity(node); - switch (info.EntityType) - { - case EntityType.Local: - { - InternalLocal local = (InternalLocal)info; - LocalBuilder builder = local.LocalBuilder; - _il.Emit(OpCodes.Ldloc, builder); - PushType(local.Type); - break; - } - - case EntityType.Parameter: - { - InternalParameter param = (InternalParameter)info; - LoadParam(param); - - if (param.Parameter.IsByRef) - { - OpCode code = GetLoadRefParamCode(param.Type); - if (code.Value == OpCodes.Ldobj.Value) - { - _il.Emit(code, GetSystemType(param.Type)); - } - else { - _il.Emit(code); - } - } - PushType(param.Type); - break; - } - - case EntityType.Array: - case EntityType.Type: - { - EmitGetTypeFromHandle(GetSystemType(node)); - break; - } - - default: - { - NotImplemented(node, info.ToString()); - break; - } - - } - } - - void LoadParam(InternalParameter param) - { - int index = param.Index; - - switch (index) - { - case 0: - { - _il.Emit(OpCodes.Ldarg_0); - break; - } - - case 1: - { - _il.Emit(OpCodes.Ldarg_1); - break; - } - - case 2: - { - _il.Emit(OpCodes.Ldarg_2); - break; - } - - case 3: - { - _il.Emit(OpCodes.Ldarg_3); - break; - } - - default: - { - if (index < 256) - { - _il.Emit(OpCodes.Ldarg_S, index); - } - else - { - _il.Emit(OpCodes.Ldarg, index); - } - break; - } - } - } - void SetLocal(BinaryExpression node, InternalLocal tag, bool leaveValueOnStack) - { - node.Right.Accept(this); // leaves type on stack - - IType typeOnStack = null; - - if (leaveValueOnStack) - { - typeOnStack = PeekTypeOnStack(); - _il.Emit(OpCodes.Dup); - } - else - { - typeOnStack = PopType(); - } - EmitAssignment(tag, typeOnStack); - } - - void EmitAssignment(InternalLocal tag, IType typeOnStack) - { - // todo: assignment result must be type on the left in the - // case of casting - LocalBuilder local = tag.LocalBuilder; - EmitCastIfNeeded(tag.Type, typeOnStack); - _il.Emit(OpCodes.Stloc, local); - } - - void SetField(Node sourceNode, IField field, Expression reference, Expression value, bool leaveValueOnStack) - { - OpCode opSetField = OpCodes.Stsfld; - if (!field.IsStatic) - { - opSetField = OpCodes.Stfld; - if (null != reference) - { - LoadMemberTarget( - ((MemberReferenceExpression)reference).Target, - field); - } - } - - value.Accept(this); - EmitCastIfNeeded(field.Type, PopType()); - - FieldInfo fi = GetFieldInfo(field); - LocalBuilder local = null; - if (leaveValueOnStack) - { - _il.Emit(OpCodes.Dup); - local = _il.DeclareLocal(fi.FieldType); - _il.Emit(OpCodes.Stloc, local); - } - - _il.Emit(opSetField, fi); - - if (leaveValueOnStack) - { - _il.Emit(OpCodes.Ldloc, local); - PushType(field.Type); - } - } - - void SetProperty(Node sourceNode, IProperty property, Expression reference, Expression value, bool leaveValueOnStack) - { - OpCode callOpCode = OpCodes.Call; - - MethodInfo setMethod = GetMethodInfo(property.GetSetMethod()); - - if (null != reference) - { - if (!setMethod.IsStatic) - { - Expression target = ((MemberReferenceExpression)reference).Target; - if (setMethod.DeclaringType.IsValueType) - { - LoadAddress(target); - } - else - { - callOpCode = OpCodes.Callvirt; - target.Accept(this); - PopType(); - } - } - } - - value.Accept(this); - EmitCastIfNeeded(property.Type, PopType()); - - LocalBuilder local = null; - if (leaveValueOnStack) - { - _il.Emit(OpCodes.Dup); - local = _il.DeclareLocal(GetSystemType(property.Type)); - _il.Emit(OpCodes.Stloc, local); - } - - _il.EmitCall(callOpCode, setMethod, null); - - if (leaveValueOnStack) - { - _il.Emit(OpCodes.Ldloc, local); - PushType(property.Type); - } - } - - bool EmitDebugInfo(Node node) - { - return EmitDebugInfo(node, node); - } - - bool EmitDebugInfo(Node startNode, Node endNode) - { - if (!Parameters.Debug) return false; - - LexicalInfo start = startNode.LexicalInfo; - if (!start.IsValid) return false; - - ISymbolDocumentWriter writer = GetDocumentWriter(start.FullPath); - if (null == writer) return false; - - try - { - _il.MarkSequencePoint(writer, start.Line, 0, start.Line+1, 0); - } - catch (Exception x) - { - Error(CompilerErrorFactory.InternalError(startNode, x)); - return false; - } - - return true; - } - - private ISymbolDocumentWriter GetDocumentWriter(string fname) - { - ISymbolDocumentWriter writer = GetCachedDocumentWriter(fname); - if (null != writer) return writer; - - writer = _moduleBuilder.DefineDocument( - fname, - Guid.Empty, - Guid.Empty, - SymDocumentType.Text); - _symbolDocWriters.Add(fname, writer); - - return writer; - } - - private ISymbolDocumentWriter GetCachedDocumentWriter(string fname) - { - return (ISymbolDocumentWriter) _symbolDocWriters[fname]; - } - - bool IsBoolOrInt(IType type) - { - return TypeSystemServices.BoolType == type || - TypeSystemServices.IntType == type; - } - - void PushArguments(IMethodBase entity, ExpressionCollection args) - { - IParameter[] parameters = entity.GetParameters(); - for (int i=0; i 1) - { - type = Array.CreateInstance(GetSystemType(arrayType.GetElementType()), new int[arrayType.GetArrayRank()]).GetType(); - } - else - { - type = Array.CreateInstance(GetSystemType(arrayType.GetElementType()), 0).GetType(); - } - } - } - else - { - if (Null.Default == tag) - { - type = Types.Object; - } - else - { - type = (Type)GetBuilder(((AbstractInternalType)tag).TypeDefinition); - } - } - } - if (null == type) - { - throw new InvalidOperationException(string.Format("Could not find a Type for {0}.", tag)); - } - _typeCache.Add(tag, type); - } - return type; - } - - IType GetSimpleEntityType(IArrayType tag) - { - return GetSimpleEntityType(tag.GetElementType()); - } - - IType GetSimpleEntityType(IType tag) - { - if (tag.IsArray) - { - return GetSimpleEntityType(((IArrayType)tag).GetElementType()); - } - return tag; - } - - string GetArrayTypeName(IType tag) - { - StringBuilder builder = new StringBuilder(); - GetArrayTypeName(builder, tag); - return builder.ToString(); - } - - void GetArrayTypeName(StringBuilder buffer, IType tag) - { - if (tag.IsArray) - { - IArrayType array = (IArrayType)tag; - GetArrayTypeName(buffer, array.GetElementType()); - buffer.Append("["); - for (int i = 1; i < array.GetArrayRank(); i++) - { - buffer.Append(","); - } - buffer.Append("]"); - } - else - { - AppendFullTypeName(buffer, tag); - } - } - - void AppendFullTypeName(StringBuilder buffer, IType type) - { - AbstractInternalType internalType = (AbstractInternalType)type; - AppendFullTypeName(buffer, internalType.TypeDefinition); - } - - void AppendFullTypeName(StringBuilder buffer, TypeDefinition type) - { - TypeDefinition parent = type.DeclaringType; - if (null != parent) - { - if (NodeType.Module == parent.NodeType) - { - NamespaceDeclaration ns = parent.EnclosingNamespace; - if (null != ns) - { - buffer.Append(ns.Name); - buffer.Append('.'); - } - } - else - { - AppendFullTypeName(buffer, parent); - buffer.Append('+'); // nested type - } - } - buffer.Append(type.Name); - } - - TypeAttributes GetNestedTypeAttributes(TypeMember type) - { - return GetExtendedTypeAttributes(GetNestedTypeAccessibility(type), type); - } - - TypeAttributes GetNestedTypeAccessibility(TypeMember type) - { - if (type.IsPublic) return TypeAttributes.NestedPublic; - if (type.IsInternal) return TypeAttributes.NestedAssembly; - return TypeAttributes.NestedPrivate; - } - - TypeAttributes GetTypeAttributes(TypeMember type) - { - TypeAttributes attributes = type.IsPublic ? TypeAttributes.Public : TypeAttributes.NotPublic; - return GetExtendedTypeAttributes(attributes, type); - } - - TypeAttributes GetExtendedTypeAttributes(TypeAttributes attributes, TypeMember type) - { - switch (type.NodeType) - { - case NodeType.ClassDefinition: - { - attributes |= (TypeAttributes.AnsiClass | TypeAttributes.AutoLayout); - attributes |= TypeAttributes.Class; - attributes |= TypeAttributes.BeforeFieldInit; - - if (!type.IsTransient) - { - attributes |= TypeAttributes.Serializable; - } - if (type.IsAbstract) - { - attributes |= TypeAttributes.Abstract; - } - if (type.IsFinal) - { - attributes |= TypeAttributes.Sealed; - } - if (((IType)type.Entity).IsValueType) - { - attributes |= TypeAttributes.SequentialLayout; - } - break; - } - - case NodeType.EnumDefinition: - { - attributes |= TypeAttributes.Sealed; - attributes |= TypeAttributes.Serializable; - break; - } - - case NodeType.InterfaceDefinition: - { - attributes |= (TypeAttributes.Interface | TypeAttributes.Abstract); - break; - } - - case NodeType.Module: - { - attributes |= TypeAttributes.Sealed; - break; - } - } - return attributes; - } - - PropertyAttributes GetPropertyAttributes(Property property) - { - PropertyAttributes attributes = PropertyAttributes.None; - - if (property.ExplicitInfo != null) - { - attributes |= PropertyAttributes.SpecialName | PropertyAttributes.RTSpecialName; - } - return attributes; - } - - MethodAttributes GetMethodAttributesFromTypeMember(TypeMember member) - { - MethodAttributes attributes = (MethodAttributes)0; - if (member.IsPublic) - { - attributes = MethodAttributes.Public; - } - else if (member.IsProtected) - { - attributes = member.IsInternal - ? MethodAttributes.FamORAssem - : MethodAttributes.Family; - } - else if (member.IsPrivate) - { - attributes = MethodAttributes.Private; - } - else if (member.IsInternal) - { - attributes = MethodAttributes.Assembly; - } - if (member.IsStatic) - { - attributes |= MethodAttributes.Static; - - if (member.Name.StartsWith("op_")) - { - attributes |= MethodAttributes.SpecialName; - } - } - if (member.IsFinal) - { - attributes |= MethodAttributes.Final; - } - if (member.IsAbstract) - { - attributes |= (MethodAttributes.Abstract | MethodAttributes.Virtual); - } - if (member.IsVirtual || member.IsOverride) - { - attributes |= MethodAttributes.Virtual; - } - return attributes; - } - - MethodAttributes GetPropertyMethodAttributes(TypeMember property) - { - MethodAttributes attributes = MethodAttributes.SpecialName | MethodAttributes.HideBySig; - attributes |= GetMethodAttributesFromTypeMember(property); - return attributes; - } - - MethodAttributes GetMethodAttributes(Method method) - { - MethodAttributes attributes = MethodAttributes.HideBySig; - if (method.ExplicitInfo != null) - { - attributes |= MethodAttributes.NewSlot; - } - if (IsPInvoke(method)) - { - Debug.Assert(method.IsStatic); - attributes |= MethodAttributes.PinvokeImpl; - } - attributes |= GetMethodAttributesFromTypeMember(method); - return attributes; - } - - FieldAttributes GetFieldAttributes(Field field) - { - FieldAttributes attributes = 0; - if (field.IsProtected) - { - attributes |= FieldAttributes.Family; - } - else if (field.IsPublic) - { - attributes |= FieldAttributes.Public; - } - else if (field.IsPrivate) - { - attributes |= FieldAttributes.Private; - } - else if (field.IsInternal) - { - attributes |= FieldAttributes.Assembly; - } - if (field.IsStatic) - { - attributes |= FieldAttributes.Static; - } - if (field.IsTransient) - { - attributes |= FieldAttributes.NotSerialized; - } - if (field.IsFinal) - { - IField entity = (IField)field.Entity; - if (entity.IsLiteral) - { - attributes |= FieldAttributes.Literal; - } - else - { - attributes |= FieldAttributes.InitOnly; - } - } - return attributes; - } - - ParameterAttributes GetParameterAttributes(ParameterDeclaration param) - { - return ParameterAttributes.None; - } - - void DefineEvent(TypeBuilder typeBuilder, Event node) - { - EventBuilder builder = typeBuilder.DefineEvent(node.Name, - EventAttributes.None, - GetSystemType(node.Type)); - //MethodAttributes attribs = GetPropertyMethodAttributes(node); - MethodAttributes baseAttributes = MethodAttributes.SpecialName; - builder.SetAddOnMethod(DefineMethod(typeBuilder, node.Add, baseAttributes|GetMethodAttributes(node.Add))); - builder.SetRemoveOnMethod(DefineMethod(typeBuilder, node.Remove, baseAttributes|GetMethodAttributes(node.Remove))); - - if (null != node.Raise) - { - builder.SetRaiseMethod(DefineMethod(typeBuilder, node.Raise, baseAttributes|GetMethodAttributes(node.Raise))); - } - - SetBuilder(node, builder); - } - - void DefineProperty(TypeBuilder typeBuilder, Property property) - { - string name; - if (property.ExplicitInfo != null) - { - name = property.ExplicitInfo.InterfaceType.Name + "." + property.Name; - } - else - { - name = property.Name; - } - - PropertyBuilder builder = typeBuilder.DefineProperty(name, - GetPropertyAttributes(property), - GetSystemType(property.Type), - GetParameterTypes(property.Parameters)); - Method getter = property.Getter; - Method setter = property.Setter; - - MethodAttributes attribs = GetPropertyMethodAttributes(property); - if (null != getter) - { - MethodBuilder getterBuilder = - DefineMethod(typeBuilder, getter, attribs); - builder.SetGetMethod(getterBuilder); - } - if (null != setter) - { - MethodBuilder setterBuilder = - DefineMethod(typeBuilder, setter, attribs); - builder.SetSetMethod(setterBuilder); - } - bool isDuckTyped = GetEntity(property).IsDuckTyped; - if (isDuckTyped) - { - builder.SetCustomAttribute(CreateDuckTypedCustomAttribute()); - } - - SetBuilder(property, builder); - } - - void DefineField(TypeBuilder typeBuilder, Field field) - { - FieldBuilder builder = typeBuilder.DefineField(field.Name, - GetSystemType(field), - GetFieldAttributes(field)); - SetBuilder(field, builder); - } - - delegate ParameterBuilder ParameterFactory(int index, System.Reflection.ParameterAttributes attributes, string name); - - void DefineParameters(ConstructorBuilder builder, ParameterDeclarationCollection parameters) - { - DefineParameters(parameters, new ParameterFactory(builder.DefineParameter)); - } - - void DefineParameters(MethodBuilder builder, ParameterDeclarationCollection parameters) - { - DefineParameters(parameters, new ParameterFactory(builder.DefineParameter)); - } - - void DefineParameters(ParameterDeclarationCollection parameters, ParameterFactory defineParameter) - { - int last = parameters.Count - 1; - for (int i=0; i 0) - { - PropertyInfo[] namedProperties; - object[] propertyValues; - FieldInfo[] namedFields; - object[] fieldValues; - GetNamedValues(namedArgs, - out namedProperties, out propertyValues, - out namedFields, out fieldValues); - return new CustomAttributeBuilder( - constructorInfo, constructorArgs, - namedProperties, propertyValues, - namedFields, fieldValues); - } - return new CustomAttributeBuilder(constructorInfo, constructorArgs); - } - - void GetNamedValues(ExpressionPairCollection values, - out PropertyInfo[] outNamedProperties, - out object[] outPropertyValues, - out FieldInfo[] outNamedFields, - out object[] outFieldValues) - { - List namedProperties = new List(); - List propertyValues = new List(); - List namedFields = new List(); - List fieldValues = new List(); - foreach (ExpressionPair pair in values) - { - ITypedEntity entity = (ITypedEntity)GetEntity(pair.First); - object value = GetValue(entity.Type, pair.Second); - if (EntityType.Property == entity.EntityType) - { - namedProperties.Add(GetPropertyInfo(entity)); - propertyValues.Add(value); - } - else - { - namedFields.Add(GetFieldInfo((IField)entity)); - fieldValues.Add(value); - } - } - - outNamedProperties = (PropertyInfo[])namedProperties.ToArray(typeof(PropertyInfo)); - outPropertyValues = propertyValues.ToArray(); - outNamedFields = (FieldInfo[])namedFields.ToArray(typeof(FieldInfo)); - outFieldValues = fieldValues.ToArray(); - } - - object[] GetValues(IParameter[] targetParameters, ExpressionCollection expressions) - { - object[] values = new object[expressions.Count]; - for (int i=0; i 0) - { - if (!Path.IsPathRooted(fname)) - { - fname = ResolveRelative(outputFile, srcFile, fname); - } - using (FileStream stream = File.OpenRead(fname)) - { - //Parameters.DelaySign is ignored. - return new StrongNameKeyPair(stream); - } - } - return null; - } - - string ResolveRelative(string targetFile, string srcFile, string relativeFile) - { - //relative to current directory: - string fname = Path.GetFullPath(relativeFile); - if (File.Exists(fname)) - { - return fname; - } - - //relative to source file: - if (srcFile != null) - { - fname = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(srcFile), - relativeFile)); - if (File.Exists(fname)) - { - return fname; - } - } - - //relative to output assembly: - if (targetFile != null) - { - fname = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(targetFile), - relativeFile)); - } - return fname; - } - - Version GetAssemblyVersion() - { - string version = GetAssemblyAttributeValue("System.Reflection.AssemblyVersionAttribute"); - if (null == version) - { - version = "0.0.0.0"; - } - /* 1.0.* -- BUILD -- based on days since January 1, 2000 - * 1.0.0.* -- REVISION -- based on seconds since midnight, January 1, 2000, divided by 2 * - */ - string[] sliced = version.Split('.'); - if (sliced.Length > 2) - { - DateTime baseTime = new DateTime(2000, 1, 1); - TimeSpan mark = (DateTime.Now - baseTime); - if (sliced[2].StartsWith("*")) - { - sliced[2] = Math.Round(mark.TotalDays).ToString(); - } - if (sliced.Length > 3) - { - if (sliced[3].StartsWith("*")) - { - sliced[3] = Math.Round(mark.TotalSeconds).ToString(); - } - } - version = Boo.Lang.Builtins.join(sliced, "."); - } - return new Version(version); - } - - string GetAssemblyAttributeValue(string name) - { - Attribute attribute = GetAssemblyAttribute(name); - if (null != attribute) - { - return ((StringLiteralExpression)attribute.Arguments[0]).Value; - } - return null; - } - - Attribute GetAssemblyAttribute(string name) - { - Attribute[] attributes = _assemblyAttributes.Get(name); - if (attributes.Length > 0) - { - Debug.Assert(1 == attributes.Length); - return attributes[0]; - } - return null; - } - - protected override IType GetExpressionType(Expression node) - { - IType type = base.GetExpressionType(node); - if (TypeSystemServices.IsUnknown(type)) throw CompilerErrorFactory.InvalidNode(node); - return type; - } - } -} + } + + override public void OnMemberReferenceExpression(MemberReferenceExpression node) + { + IEntity tag = TypeSystem.TypeSystemServices.GetEntity(node); + switch (tag.EntityType) + { + case EntityType.Method: + { + node.Target.Accept(this); + break; + } + + case EntityType.Field: + { + EmitLoadField(node.Target, (IField)tag); + break; + } + + case EntityType.Type: + { + EmitGetTypeFromHandle(GetSystemType(node)); + break; + } + + default: + { + NotImplemented(node, tag.ToString()); + break; + } + } + } + + void LoadAddress(Expression expression) + { + if (NodeType.SelfLiteralExpression == expression.NodeType) + { + if (expression.ExpressionType.IsValueType) + { + _il.Emit(OpCodes.Ldarg_0); + return; + } + } + + IEntity tag = expression.Entity; + if (null != tag) + { + switch (tag.EntityType) + { + case EntityType.Local: + { + _il.Emit(OpCodes.Ldloca, ((InternalLocal)tag).LocalBuilder); + return; + } + + case EntityType.Parameter: + { + InternalParameter param = (InternalParameter)tag; + if (param.Parameter.IsByRef) + { + LoadParam(param); + } + else + { + _il.Emit(OpCodes.Ldarga, param.Index); + } + return; + } + + case EntityType.Field: + { + IField field = (IField)tag; + if (!field.IsLiteral) + { + EmitLoadFieldAddress(expression, field); + return; + } + break; + } + } + } + + if (IsValueTypeArraySlicing(expression)) + { + SlicingExpression slicing = (SlicingExpression)expression; + Visit(slicing.Target); + IArrayType arrayType = (IArrayType)PopType(); + EmitNormalizedArrayIndex(slicing, slicing.Indices[0].Begin); + _il.Emit(OpCodes.Ldelema, GetSystemType(arrayType.GetElementType())); + } + else + { + // declare local to hold value type + Visit(expression); + LocalBuilder temp = _il.DeclareLocal(GetSystemType(PopType())); + _il.Emit(OpCodes.Stloc, temp); + _il.Emit(OpCodes.Ldloca, temp); + } + } + + bool IsValueTypeArraySlicing(Expression expression) + { + SlicingExpression slicing = expression as SlicingExpression; + if (null != slicing) + { + IArrayType type = (IArrayType)slicing.Target.ExpressionType; + return type.GetElementType().IsValueType; + } + return false; + } + + override public void OnSelfLiteralExpression(SelfLiteralExpression node) + { + _il.Emit(OpCodes.Ldarg_0); + if (node.ExpressionType.IsValueType) + { + _il.Emit(OpCodes.Ldobj, GetSystemType(node.ExpressionType)); + } + PushType(node.ExpressionType); + } + + override public void OnSuperLiteralExpression(SuperLiteralExpression node) + { + _il.Emit(OpCodes.Ldarg_0); + if (node.ExpressionType.IsValueType) + { + _il.Emit(OpCodes.Ldobj, GetSystemType(node.ExpressionType)); + } + PushType(node.ExpressionType); + } + + override public void OnNullLiteralExpression(NullLiteralExpression node) + { + _il.Emit(OpCodes.Ldnull); + PushType(null); + } + + override public void OnReferenceExpression(ReferenceExpression node) + { + IEntity info = TypeSystem.TypeSystemServices.GetEntity(node); + switch (info.EntityType) + { + case EntityType.Local: + { + InternalLocal local = (InternalLocal)info; + LocalBuilder builder = local.LocalBuilder; + _il.Emit(OpCodes.Ldloc, builder); + PushType(local.Type); + break; + } + + case EntityType.Parameter: + { + InternalParameter param = (InternalParameter)info; + LoadParam(param); + + if (param.Parameter.IsByRef) + { + OpCode code = GetLoadRefParamCode(param.Type); + if (code.Value == OpCodes.Ldobj.Value) + { + _il.Emit(code, GetSystemType(param.Type)); + } + else { + _il.Emit(code); + } + } + PushType(param.Type); + break; + } + + case EntityType.Array: + case EntityType.Type: + { + EmitGetTypeFromHandle(GetSystemType(node)); + break; + } + + default: + { + NotImplemented(node, info.ToString()); + break; + } + + } + } + + void LoadParam(InternalParameter param) + { + int index = param.Index; + + switch (index) + { + case 0: + { + _il.Emit(OpCodes.Ldarg_0); + break; + } + + case 1: + { + _il.Emit(OpCodes.Ldarg_1); + break; + } + + case 2: + { + _il.Emit(OpCodes.Ldarg_2); + break; + } + + case 3: + { + _il.Emit(OpCodes.Ldarg_3); + break; + } + + default: + { + if (index < 256) + { + _il.Emit(OpCodes.Ldarg_S, index); + } + else + { + _il.Emit(OpCodes.Ldarg, index); + } + break; + } + } + } + void SetLocal(BinaryExpression node, InternalLocal tag, bool leaveValueOnStack) + { + node.Right.Accept(this); // leaves type on stack + + IType typeOnStack = null; + + if (leaveValueOnStack) + { + typeOnStack = PeekTypeOnStack(); + _il.Emit(OpCodes.Dup); + } + else + { + typeOnStack = PopType(); + } + EmitAssignment(tag, typeOnStack); + } + + void EmitAssignment(InternalLocal tag, IType typeOnStack) + { + // todo: assignment result must be type on the left in the + // case of casting + LocalBuilder local = tag.LocalBuilder; + EmitCastIfNeeded(tag.Type, typeOnStack); + _il.Emit(OpCodes.Stloc, local); + } + + void SetField(Node sourceNode, IField field, Expression reference, Expression value, bool leaveValueOnStack) + { + OpCode opSetField = OpCodes.Stsfld; + if (!field.IsStatic) + { + opSetField = OpCodes.Stfld; + if (null != reference) + { + LoadMemberTarget( + ((MemberReferenceExpression)reference).Target, + field); + } + } + + value.Accept(this); + EmitCastIfNeeded(field.Type, PopType()); + + FieldInfo fi = GetFieldInfo(field); + LocalBuilder local = null; + if (leaveValueOnStack) + { + _il.Emit(OpCodes.Dup); + local = _il.DeclareLocal(fi.FieldType); + _il.Emit(OpCodes.Stloc, local); + } + + _il.Emit(opSetField, fi); + + if (leaveValueOnStack) + { + _il.Emit(OpCodes.Ldloc, local); + PushType(field.Type); + } + } + + void SetProperty(Node sourceNode, IProperty property, Expression reference, Expression value, bool leaveValueOnStack) + { + OpCode callOpCode = OpCodes.Call; + + MethodInfo setMethod = GetMethodInfo(property.GetSetMethod()); + + if (null != reference) + { + if (!setMethod.IsStatic) + { + Expression target = ((MemberReferenceExpression)reference).Target; + if (setMethod.DeclaringType.IsValueType) + { + LoadAddress(target); + } + else + { + callOpCode = OpCodes.Callvirt; + target.Accept(this); + PopType(); + } + } + } + + value.Accept(this); + EmitCastIfNeeded(property.Type, PopType()); + + LocalBuilder local = null; + if (leaveValueOnStack) + { + _il.Emit(OpCodes.Dup); + local = _il.DeclareLocal(GetSystemType(property.Type)); + _il.Emit(OpCodes.Stloc, local); + } + + _il.EmitCall(callOpCode, setMethod, null); + + if (leaveValueOnStack) + { + _il.Emit(OpCodes.Ldloc, local); + PushType(property.Type); + } + } + + bool EmitDebugInfo(Node node) + { + return EmitDebugInfo(node, node); + } + + bool EmitDebugInfo(Node startNode, Node endNode) + { + if (!Parameters.Debug) return false; + + LexicalInfo start = startNode.LexicalInfo; + if (!start.IsValid) return false; + + ISymbolDocumentWriter writer = GetDocumentWriter(start.FullPath); + if (null == writer) return false; + + try + { + _il.MarkSequencePoint(writer, start.Line, 0, start.Line+1, 0); + } + catch (Exception x) + { + Error(CompilerErrorFactory.InternalError(startNode, x)); + return false; + } + + return true; + } + + private ISymbolDocumentWriter GetDocumentWriter(string fname) + { + ISymbolDocumentWriter writer = GetCachedDocumentWriter(fname); + if (null != writer) return writer; + + writer = _moduleBuilder.DefineDocument( + fname, + Guid.Empty, + Guid.Empty, + SymDocumentType.Text); + _symbolDocWriters.Add(fname, writer); + + return writer; + } + + private ISymbolDocumentWriter GetCachedDocumentWriter(string fname) + { + return (ISymbolDocumentWriter) _symbolDocWriters[fname]; + } + + bool IsBoolOrInt(IType type) + { + return TypeSystemServices.BoolType == type || + TypeSystemServices.IntType == type; + } + + void PushArguments(IMethodBase entity, ExpressionCollection args) + { + IParameter[] parameters = entity.GetParameters(); + for (int i=0; i 1) + { + type = Array.CreateInstance(GetSystemType(arrayType.GetElementType()), new int[arrayType.GetArrayRank()]).GetType(); + } + else + { + type = Array.CreateInstance(GetSystemType(arrayType.GetElementType()), 0).GetType(); + } + } + } + else if (Null.Default == tag) + { + type = Types.Object; + } + else + { + type = (Type)GetBuilder(((AbstractInternalType)tag).TypeDefinition); + } + + if (null == type) + { + throw new InvalidOperationException(string.Format("Could not find a Type for {0}.", tag)); + } + + _typeCache.Add(tag, type); + return type; + } + + IType GetSimpleEntityType(IArrayType tag) + { + return GetSimpleEntityType(tag.GetElementType()); + } + + IType GetSimpleEntityType(IType tag) + { + if (tag.IsArray) + { + return GetSimpleEntityType(((IArrayType)tag).GetElementType()); + } + return tag; + } + + string GetArrayTypeName(IType tag) + { + StringBuilder builder = new StringBuilder(); + GetArrayTypeName(builder, tag); + return builder.ToString(); + } + + void GetArrayTypeName(StringBuilder buffer, IType tag) + { + if (tag.IsArray) + { + IArrayType array = (IArrayType)tag; + GetArrayTypeName(buffer, array.GetElementType()); + buffer.Append("["); + for (int i = 1; i < array.GetArrayRank(); i++) + { + buffer.Append(","); + } + buffer.Append("]"); + } + else + { + AppendFullTypeName(buffer, tag); + } + } + + void AppendFullTypeName(StringBuilder buffer, IType type) + { + AbstractInternalType internalType = (AbstractInternalType)type; + AppendFullTypeName(buffer, internalType.TypeDefinition); + } + + void AppendFullTypeName(StringBuilder buffer, TypeDefinition type) + { + TypeDefinition parent = type.DeclaringType; + if (null != parent) + { + if (NodeType.Module == parent.NodeType) + { + NamespaceDeclaration ns = parent.EnclosingNamespace; + if (null != ns) + { + buffer.Append(ns.Name); + buffer.Append('.'); + } + } + else + { + AppendFullTypeName(buffer, parent); + buffer.Append('+'); // nested type + } + } + buffer.Append(type.Name); + } + + TypeAttributes GetNestedTypeAttributes(TypeMember type) + { + return GetExtendedTypeAttributes(GetNestedTypeAccessibility(type), type); + } + + TypeAttributes GetNestedTypeAccessibility(TypeMember type) + { + if (type.IsPublic) return TypeAttributes.NestedPublic; + if (type.IsInternal) return TypeAttributes.NestedAssembly; + return TypeAttributes.NestedPrivate; + } + + TypeAttributes GetTypeAttributes(TypeMember type) + { + TypeAttributes attributes = type.IsPublic ? TypeAttributes.Public : TypeAttributes.NotPublic; + return GetExtendedTypeAttributes(attributes, type); + } + + TypeAttributes GetExtendedTypeAttributes(TypeAttributes attributes, TypeMember type) + { + switch (type.NodeType) + { + case NodeType.ClassDefinition: + { + attributes |= (TypeAttributes.AnsiClass | TypeAttributes.AutoLayout); + attributes |= TypeAttributes.Class; + attributes |= TypeAttributes.BeforeFieldInit; + + if (!type.IsTransient) + { + attributes |= TypeAttributes.Serializable; + } + if (type.IsAbstract) + { + attributes |= TypeAttributes.Abstract; + } + if (type.IsFinal) + { + attributes |= TypeAttributes.Sealed; + } + if (((IType)type.Entity).IsValueType) + { + attributes |= TypeAttributes.SequentialLayout; + } + break; + } + + case NodeType.EnumDefinition: + { + attributes |= TypeAttributes.Sealed; + attributes |= TypeAttributes.Serializable; + break; + } + + case NodeType.InterfaceDefinition: + { + attributes |= (TypeAttributes.Interface | TypeAttributes.Abstract); + break; + } + + case NodeType.Module: + { + attributes |= TypeAttributes.Sealed; + break; + } + } + return attributes; + } + + PropertyAttributes GetPropertyAttributes(Property property) + { + PropertyAttributes attributes = PropertyAttributes.None; + + if (property.ExplicitInfo != null) + { + attributes |= PropertyAttributes.SpecialName | PropertyAttributes.RTSpecialName; + } + return attributes; + } + + MethodAttributes GetMethodAttributesFromTypeMember(TypeMember member) + { + MethodAttributes attributes = (MethodAttributes)0; + if (member.IsPublic) + { + attributes = MethodAttributes.Public; + } + else if (member.IsProtected) + { + attributes = member.IsInternal + ? MethodAttributes.FamORAssem + : MethodAttributes.Family; + } + else if (member.IsPrivate) + { + attributes = MethodAttributes.Private; + } + else if (member.IsInternal) + { + attributes = MethodAttributes.Assembly; + } + if (member.IsStatic) + { + attributes |= MethodAttributes.Static; + + if (member.Name.StartsWith("op_")) + { + attributes |= MethodAttributes.SpecialName; + } + } + if (member.IsFinal) + { + attributes |= MethodAttributes.Final; + } + if (member.IsAbstract) + { + attributes |= (MethodAttributes.Abstract | MethodAttributes.Virtual); + } + if (member.IsVirtual || member.IsOverride) + { + attributes |= MethodAttributes.Virtual; + } + return attributes; + } + + MethodAttributes GetPropertyMethodAttributes(TypeMember property) + { + MethodAttributes attributes = MethodAttributes.SpecialName | MethodAttributes.HideBySig; + attributes |= GetMethodAttributesFromTypeMember(property); + return attributes; + } + + MethodAttributes GetMethodAttributes(Method method) + { + MethodAttributes attributes = MethodAttributes.HideBySig; + if (method.ExplicitInfo != null) + { + attributes |= MethodAttributes.NewSlot; + } + if (IsPInvoke(method)) + { + Debug.Assert(method.IsStatic); + attributes |= MethodAttributes.PinvokeImpl; + } + attributes |= GetMethodAttributesFromTypeMember(method); + return attributes; + } + + FieldAttributes GetFieldAttributes(Field field) + { + FieldAttributes attributes = 0; + if (field.IsProtected) + { + attributes |= FieldAttributes.Family; + } + else if (field.IsPublic) + { + attributes |= FieldAttributes.Public; + } + else if (field.IsPrivate) + { + attributes |= FieldAttributes.Private; + } + else if (field.IsInternal) + { + attributes |= FieldAttributes.Assembly; + } + if (field.IsStatic) + { + attributes |= FieldAttributes.Static; + } + if (field.IsTransient) + { + attributes |= FieldAttributes.NotSerialized; + } + if (field.IsFinal) + { + IField entity = (IField)field.Entity; + if (entity.IsLiteral) + { + attributes |= FieldAttributes.Literal; + } + else + { + attributes |= FieldAttributes.InitOnly; + } + } + return attributes; + } + + ParameterAttributes GetParameterAttributes(ParameterDeclaration param) + { + return ParameterAttributes.None; + } + + void DefineEvent(TypeBuilder typeBuilder, Event node) + { + EventBuilder builder = typeBuilder.DefineEvent(node.Name, + EventAttributes.None, + GetSystemType(node.Type)); + //MethodAttributes attribs = GetPropertyMethodAttributes(node); + MethodAttributes baseAttributes = MethodAttributes.SpecialName; + builder.SetAddOnMethod(DefineMethod(typeBuilder, node.Add, baseAttributes|GetMethodAttributes(node.Add))); + builder.SetRemoveOnMethod(DefineMethod(typeBuilder, node.Remove, baseAttributes|GetMethodAttributes(node.Remove))); + + if (null != node.Raise) + { + builder.SetRaiseMethod(DefineMethod(typeBuilder, node.Raise, baseAttributes|GetMethodAttributes(node.Raise))); + } + + SetBuilder(node, builder); + } + + void DefineProperty(TypeBuilder typeBuilder, Property property) + { + string name; + if (property.ExplicitInfo != null) + { + name = property.ExplicitInfo.InterfaceType.Name + "." + property.Name; + } + else + { + name = property.Name; + } + + PropertyBuilder builder = typeBuilder.DefineProperty(name, + GetPropertyAttributes(property), + GetSystemType(property.Type), + GetParameterTypes(property.Parameters)); + Method getter = property.Getter; + Method setter = property.Setter; + + MethodAttributes attribs = GetPropertyMethodAttributes(property); + if (null != getter) + { + MethodBuilder getterBuilder = + DefineMethod(typeBuilder, getter, attribs); + builder.SetGetMethod(getterBuilder); + } + if (null != setter) + { + MethodBuilder setterBuilder = + DefineMethod(typeBuilder, setter, attribs); + builder.SetSetMethod(setterBuilder); + } + bool isDuckTyped = GetEntity(property).IsDuckTyped; + if (isDuckTyped) + { + builder.SetCustomAttribute(CreateDuckTypedCustomAttribute()); + } + + SetBuilder(property, builder); + } + + void DefineField(TypeBuilder typeBuilder, Field field) + { + FieldBuilder builder = typeBuilder.DefineField(field.Name, + GetSystemType(field), + GetFieldAttributes(field)); + SetBuilder(field, builder); + } + + delegate ParameterBuilder ParameterFactory(int index, System.Reflection.ParameterAttributes attributes, string name); + + void DefineParameters(ConstructorBuilder builder, ParameterDeclarationCollection parameters) + { + DefineParameters(parameters, new ParameterFactory(builder.DefineParameter)); + } + + void DefineParameters(MethodBuilder builder, ParameterDeclarationCollection parameters) + { + DefineParameters(parameters, new ParameterFactory(builder.DefineParameter)); + } + + void DefineParameters(ParameterDeclarationCollection parameters, ParameterFactory defineParameter) + { + int last = parameters.Count - 1; + for (int i=0; i 0) + { + PropertyInfo[] namedProperties; + object[] propertyValues; + FieldInfo[] namedFields; + object[] fieldValues; + GetNamedValues(namedArgs, + out namedProperties, out propertyValues, + out namedFields, out fieldValues); + return new CustomAttributeBuilder( + constructorInfo, constructorArgs, + namedProperties, propertyValues, + namedFields, fieldValues); + } + return new CustomAttributeBuilder(constructorInfo, constructorArgs); + } + + void GetNamedValues(ExpressionPairCollection values, + out PropertyInfo[] outNamedProperties, + out object[] outPropertyValues, + out FieldInfo[] outNamedFields, + out object[] outFieldValues) + { + List namedProperties = new List(); + List propertyValues = new List(); + List namedFields = new List(); + List fieldValues = new List(); + foreach (ExpressionPair pair in values) + { + ITypedEntity entity = (ITypedEntity)GetEntity(pair.First); + object value = GetValue(entity.Type, pair.Second); + if (EntityType.Property == entity.EntityType) + { + namedProperties.Add(GetPropertyInfo(entity)); + propertyValues.Add(value); + } + else + { + namedFields.Add(GetFieldInfo((IField)entity)); + fieldValues.Add(value); + } + } + + outNamedProperties = (PropertyInfo[])namedProperties.ToArray(typeof(PropertyInfo)); + outPropertyValues = propertyValues.ToArray(); + outNamedFields = (FieldInfo[])namedFields.ToArray(typeof(FieldInfo)); + outFieldValues = fieldValues.ToArray(); + } + + object[] GetValues(IParameter[] targetParameters, ExpressionCollection expressions) + { + object[] values = new object[expressions.Count]; + for (int i=0; i 0) + { + if (!Path.IsPathRooted(fname)) + { + fname = ResolveRelative(outputFile, srcFile, fname); + } + using (FileStream stream = File.OpenRead(fname)) + { + //Parameters.DelaySign is ignored. + return new StrongNameKeyPair(stream); + } + } + return null; + } + + string ResolveRelative(string targetFile, string srcFile, string relativeFile) + { + //relative to current directory: + string fname = Path.GetFullPath(relativeFile); + if (File.Exists(fname)) + { + return fname; + } + + //relative to source file: + if (srcFile != null) + { + fname = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(srcFile), + relativeFile)); + if (File.Exists(fname)) + { + return fname; + } + } + + //relative to output assembly: + if (targetFile != null) + { + fname = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(targetFile), + relativeFile)); + } + return fname; + } + + Version GetAssemblyVersion() + { + string version = GetAssemblyAttributeValue("System.Reflection.AssemblyVersionAttribute"); + if (null == version) + { + version = "0.0.0.0"; + } + /* 1.0.* -- BUILD -- based on days since January 1, 2000 + * 1.0.0.* -- REVISION -- based on seconds since midnight, January 1, 2000, divided by 2 * + */ + string[] sliced = version.Split('.'); + if (sliced.Length > 2) + { + DateTime baseTime = new DateTime(2000, 1, 1); + TimeSpan mark = (DateTime.Now - baseTime); + if (sliced[2].StartsWith("*")) + { + sliced[2] = Math.Round(mark.TotalDays).ToString(); + } + if (sliced.Length > 3) + { + if (sliced[3].StartsWith("*")) + { + sliced[3] = Math.Round(mark.TotalSeconds).ToString(); + } + } + version = Boo.Lang.Builtins.join(sliced, "."); + } + return new Version(version); + } + + string GetAssemblyAttributeValue(string name) + { + Attribute attribute = GetAssemblyAttribute(name); + if (null != attribute) + { + return ((StringLiteralExpression)attribute.Arguments[0]).Value; + } + return null; + } + + Attribute GetAssemblyAttribute(string name) + { + Attribute[] attributes = _assemblyAttributes.Get(name); + if (attributes.Length > 0) + { + Debug.Assert(1 == attributes.Length); + return attributes[0]; + } + return null; + } + + protected override IType GetExpressionType(Expression node) + { + IType type = base.GetExpressionType(node); + if (TypeSystemServices.IsUnknown(type)) throw CompilerErrorFactory.InvalidNode(node); + return type; + } + } +} Index: src/Boo.Lang.Compiler/Steps/ProcessMethodBodies.cs =================================================================== --- src/Boo.Lang.Compiler/Steps/ProcessMethodBodies.cs (revision 2352) +++ src/Boo.Lang.Compiler/Steps/ProcessMethodBodies.cs (working copy) @@ -2032,8 +2032,7 @@ return; } - IGenericTypeDefinition typeDef = (IGenericTypeDefinition) node.Target.Entity; - IType genericType = typeDef.MakeGenericType(GetGenericArguments(node)); + IType genericType = ((IType)node.Target.Entity).GenericTypeDefinitionInfo.MakeGenericType(GetGenericArguments(node)); Bind(node, genericType); BindExpressionType(node, this.TypeSystemServices.TypeType); @@ -2053,10 +2052,13 @@ CompilerError CheckGenericReferenceExpression(GenericReferenceExpression node) { IEntity entity = node.Target.Entity; - IGenericTypeDefinition typeDef = entity as IGenericTypeDefinition; - if (typeDef == null) return CompilerErrorFactory.NotAGenericDefinition(AstUtil.GetMemberAnchor(node.Target), entity.FullName); + IType type = entity as IType; + if (type == null || type.GenericTypeDefinitionInfo == null) + { + return CompilerErrorFactory.NotAGenericDefinition(AstUtil.GetMemberAnchor(node.Target), entity.FullName); + } - IGenericParameter[] parameters = typeDef.GetGenericParameters(); + IGenericParameter[] parameters = type.GenericTypeDefinitionInfo.GenericParameters; if (parameters.Length != node.GenericArguments.Count) return CompilerErrorFactory.GenericDefinitionArgumentCount(AstUtil.GetMemberAnchor(node.Target), entity.FullName, parameters.Length); return null; @@ -2300,6 +2302,7 @@ Error(node); return; } + BindExpressionType(node, GetInferredType(memberInfo)); } else Index: src/Boo.Lang.Compiler/TypeSystem/AbstractInternalType.cs =================================================================== --- src/Boo.Lang.Compiler/TypeSystem/AbstractInternalType.cs (revision 2352) +++ src/Boo.Lang.Compiler/TypeSystem/AbstractInternalType.cs (working copy) @@ -1,378 +1,388 @@ -#region license -// Copyright (c) 2004, 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 - -namespace Boo.Lang.Compiler.TypeSystem -{ - using System; - using System.Collections; - using System.Reflection; - using Boo.Lang.Compiler.Ast; - using Attribute = Boo.Lang.Compiler.Ast.Attribute; - - public abstract class AbstractInternalType : IInternalEntity, IType, INamespace - { - protected TypeSystemServices _typeSystemServices; - - protected TypeDefinition _typeDefinition; - - protected IType[] _interfaces; - - protected INamespace _parentNamespace; - - protected Type _generatedType; - - protected AbstractInternalType(TypeSystemServices typeSystemServices, TypeDefinition typeDefinition) - { - _typeSystemServices = typeSystemServices; - _typeDefinition = typeDefinition; - } - - public string FullName - { - get - { - return _typeDefinition.FullName; - } - } - - public string Name - { - get - { - return _typeDefinition.Name; - } - } - - public Node Node - { - get - { - return _typeDefinition; - } - } - - public IType NestingType - { - get - { - return _typeDefinition.ParentNode.Entity as IType; - } - } - - public virtual INamespace ParentNamespace - { - get - { - if (null == _parentNamespace) - { - _parentNamespace = (INamespace)TypeSystemServices.GetEntity(_typeDefinition.ParentNode); - } - return _parentNamespace; - } - } - - public virtual bool Resolve(List targetList, string name, EntityType flags) - { - bool found = false; - - foreach (IEntity entity in GetMembers()) - { - if (entity.Name == name && NameResolutionService.IsFlagSet(flags, entity.EntityType)) - { - targetList.AddUnique(entity); - found = true; - } - } - - return found; - } - - public virtual IType BaseType - { - get - { - return null; - } - } - - public TypeDefinition TypeDefinition - { - get - { - return _typeDefinition; - } - } - - public IType Type - { - get - { - return this; - } - } - - public bool IsByRef - { - get - { - return false; - } - } - - public IType GetElementType() - { - return null; - } - - public bool IsClass - { - get - { - return NodeType.ClassDefinition == _typeDefinition.NodeType; - } - } - - public bool IsAbstract - { - get - { - return _typeDefinition.IsAbstract; - } - } - - virtual public bool IsFinal - { - get - { - return _typeDefinition.IsFinal || IsValueType; - } - } - - public bool IsInterface - { - get - { - return NodeType.InterfaceDefinition == _typeDefinition.NodeType; - } - } - - public bool IsEnum - { - get - { - return NodeType.EnumDefinition == _typeDefinition.NodeType; - } - } - - virtual public bool IsValueType - { - get - { - return false; - } - } - - public bool IsArray - { - get - { - return false; - } - } - - public virtual int GetTypeDepth() - { - return 1; - } - - public IEntity GetDefaultMember() - { - IType defaultMemberAttribute = _typeSystemServices.Map(Types.DefaultMemberAttribute); - foreach (Attribute attribute in _typeDefinition.Attributes) - { - IConstructor tag = TypeSystemServices.GetEntity(attribute) as IConstructor; - if (null != tag) - { - if (defaultMemberAttribute == tag.DeclaringType) - { - StringLiteralExpression memberName = attribute.Arguments[0] as StringLiteralExpression; - if (null != memberName) - { - List buffer = new List(); - Resolve(buffer, memberName.Value, EntityType.Any); - return NameResolutionService.GetEntityFromList(buffer); - } - } - } - } - if (_typeDefinition.BaseTypes.Count > 0) - { - List buffer = new List(); - - foreach (TypeReference baseType in _typeDefinition.BaseTypes) - { - IType tag = TypeSystemServices.GetType(baseType); - IEntity defaultMember = tag.GetDefaultMember(); - if (defaultMember != null) - { - if (tag.IsInterface) - { - buffer.AddUnique(defaultMember); - } - else //non-interface base class trumps interfaces - { - return defaultMember; - } - } - } - return NameResolutionService.GetEntityFromList(buffer); - } - return null; - } - - public virtual EntityType EntityType - { - get - { - return EntityType.Type; - } - } - - public virtual bool IsSubclassOf(IType other) - { - return false; - } - - public virtual bool IsAssignableFrom(IType other) - { - return this == other || - (!this.IsValueType && Null.Default == other) || - other.IsSubclassOf(this); - } - - public virtual IConstructor[] GetConstructors() - { - return new IConstructor[0]; - } - - public IType[] GetInterfaces() - { - if (null == _interfaces) - { - List buffer = new List(); - - foreach (TypeReference baseType in _typeDefinition.BaseTypes) - { - IType tag = TypeSystemServices.GetType(baseType); - if (tag.IsInterface) - { - buffer.AddUnique(tag); - } - } - - _interfaces = (IType[])buffer.ToArray(typeof(IType)); - } - return _interfaces; - } - - public virtual IEntity[] GetMembers() - { - ArrayList buffer = new ArrayList(); - foreach (TypeMember member in _typeDefinition.Members) - { - buffer.Add(GetMemberEntity(member)); - } - return (IEntity[])buffer.ToArray(typeof(IEntity)); - } - - private IEntity GetMemberEntity(TypeMember member) - { - if (null == member.Entity) - { - member.Entity = CreateEntity(member); - } - return member.Entity; - } - - private IEntity CreateEntity(TypeMember member) - { - switch (member.NodeType) - { - case NodeType.Field: - { - return new InternalField((Field)member); - } - - case NodeType.EnumMember: - { - return new InternalEnumMember(_typeSystemServices, (EnumMember)member); - } - - case NodeType.Method: - { - return new InternalMethod(_typeSystemServices, (Method)member); - } - - case NodeType.Constructor: - { - return new InternalConstructor(_typeSystemServices, (Constructor)member); - } - - case NodeType.Property: - { - return new InternalProperty(_typeSystemServices, (Property)member); - } - - case NodeType.Event: - { - return new InternalEvent(_typeSystemServices, (Event)member); - } - } - throw new ArgumentException("Member type not supported: " + member); - } - - public Type GeneratedType - { - get - { - return _generatedType; - } - - set - { - _generatedType = value; - } - } - - override public string ToString() - { - return FullName; - } - } - -} +#region license +// Copyright (c) 2004, 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 + +namespace Boo.Lang.Compiler.TypeSystem +{ + using System; + using System.Collections; + using System.Reflection; + using Boo.Lang.Compiler.Ast; + using Attribute = Boo.Lang.Compiler.Ast.Attribute; + + public abstract class AbstractInternalType : IInternalEntity, IType, INamespace + { + protected TypeSystemServices _typeSystemServices; + + protected TypeDefinition _typeDefinition; + + protected IType[] _interfaces; + + protected INamespace _parentNamespace; + + protected Type _generatedType; + + protected AbstractInternalType(TypeSystemServices typeSystemServices, TypeDefinition typeDefinition) + { + _typeSystemServices = typeSystemServices; + _typeDefinition = typeDefinition; + } + + public string FullName + { + get + { + return _typeDefinition.FullName; + } + } + + public string Name + { + get + { + return _typeDefinition.Name; + } + } + + public Node Node + { + get + { + return _typeDefinition; + } + } + + public IType NestingType + { + get + { + return _typeDefinition.ParentNode.Entity as IType; + } + } + + public virtual INamespace ParentNamespace + { + get + { + if (null == _parentNamespace) + { + _parentNamespace = (INamespace)TypeSystemServices.GetEntity(_typeDefinition.ParentNode); + } + return _parentNamespace; + } + } + + public virtual bool Resolve(List targetList, string name, EntityType flags) + { + bool found = false; + + foreach (IEntity entity in GetMembers()) + { + if (entity.Name == name && NameResolutionService.IsFlagSet(flags, entity.EntityType)) + { + targetList.AddUnique(entity); + found = true; + } + } + + return found; + } + + public virtual IType BaseType + { + get + { + return null; + } + } + + public TypeDefinition TypeDefinition + { + get + { + return _typeDefinition; + } + } + + public IType Type + { + get + { + return this; + } + } + + public bool IsByRef + { + get + { + return false; + } + } + + public IType GetElementType() + { + return null; + } + + public bool IsClass + { + get + { + return NodeType.ClassDefinition == _typeDefinition.NodeType; + } + } + + public bool IsAbstract + { + get + { + return _typeDefinition.IsAbstract; + } + } + + virtual public bool IsFinal + { + get + { + return _typeDefinition.IsFinal || IsValueType; + } + } + + public bool IsInterface + { + get + { + return NodeType.InterfaceDefinition == _typeDefinition.NodeType; + } + } + + public bool IsEnum + { + get + { + return NodeType.EnumDefinition == _typeDefinition.NodeType; + } + } + + virtual public bool IsValueType + { + get + { + return false; + } + } + + public bool IsArray + { + get + { + return false; + } + } + + public virtual int GetTypeDepth() + { + return 1; + } + + public IEntity GetDefaultMember() + { + IType defaultMemberAttribute = _typeSystemServices.Map(Types.DefaultMemberAttribute); + foreach (Attribute attribute in _typeDefinition.Attributes) + { + IConstructor tag = TypeSystemServices.GetEntity(attribute) as IConstructor; + if (null != tag) + { + if (defaultMemberAttribute == tag.DeclaringType) + { + StringLiteralExpression memberName = attribute.Arguments[0] as StringLiteralExpression; + if (null != memberName) + { + List buffer = new List(); + Resolve(buffer, memberName.Value, EntityType.Any); + return NameResolutionService.GetEntityFromList(buffer); + } + } + } + } + if (_typeDefinition.BaseTypes.Count > 0) + { + List buffer = new List(); + + foreach (TypeReference baseType in _typeDefinition.BaseTypes) + { + IType tag = TypeSystemServices.GetType(baseType); + IEntity defaultMember = tag.GetDefaultMember(); + if (defaultMember != null) + { + if (tag.IsInterface) + { + buffer.AddUnique(defaultMember); + } + else //non-interface base class trumps interfaces + { + return defaultMember; + } + } + } + return NameResolutionService.GetEntityFromList(buffer); + } + return null; + } + + public virtual EntityType EntityType + { + get + { + return EntityType.Type; + } + } + + public virtual bool IsSubclassOf(IType other) + { + return false; + } + + public virtual bool IsAssignableFrom(IType other) + { + return this == other || + (!this.IsValueType && Null.Default == other) || + other.IsSubclassOf(this); + } + + public virtual IConstructor[] GetConstructors() + { + return new IConstructor[0]; + } + + public IType[] GetInterfaces() + { + if (null == _interfaces) + { + List buffer = new List(); + + foreach (TypeReference baseType in _typeDefinition.BaseTypes) + { + IType tag = TypeSystemServices.GetType(baseType); + if (tag.IsInterface) + { + buffer.AddUnique(tag); + } + } + + _interfaces = (IType[])buffer.ToArray(typeof(IType)); + } + return _interfaces; + } + + public virtual IEntity[] GetMembers() + { + ArrayList buffer = new ArrayList(); + foreach (TypeMember member in _typeDefinition.Members) + { + buffer.Add(GetMemberEntity(member)); + } + return (IEntity[])buffer.ToArray(typeof(IEntity)); + } + + private IEntity GetMemberEntity(TypeMember member) + { + if (null == member.Entity) + { + member.Entity = CreateEntity(member); + } + return member.Entity; + } + + private IEntity CreateEntity(TypeMember member) + { + switch (member.NodeType) + { + case NodeType.Field: + { + return new InternalField((Field)member); + } + + case NodeType.EnumMember: + { + return new InternalEnumMember(_typeSystemServices, (EnumMember)member); + } + + case NodeType.Method: + { + return new InternalMethod(_typeSystemServices, (Method)member); + } + + case NodeType.Constructor: + { + return new InternalConstructor(_typeSystemServices, (Constructor)member); + } + + case NodeType.Property: + { + return new InternalProperty(_typeSystemServices, (Property)member); + } + + case NodeType.Event: + { + return new InternalEvent(_typeSystemServices, (Event)member); + } + } + throw new ArgumentException("Member type not supported: " + member); + } + + public Type GeneratedType + { + get + { + return _generatedType; + } + + set + { + _generatedType = value; + } + } + + override public string ToString() + { + return FullName; + } + + IGenericTypeDefinitionInfo IType.GenericTypeDefinitionInfo + { + get { return null; } + } + + IGenericTypeInfo IType.GenericTypeInfo + { + get { return null; } + } + } + +} Index: src/Boo.Lang.Compiler/TypeSystem/ArrayType.cs =================================================================== --- src/Boo.Lang.Compiler/TypeSystem/ArrayType.cs (revision 2352) +++ src/Boo.Lang.Compiler/TypeSystem/ArrayType.cs (working copy) @@ -1,246 +1,256 @@ -#region license -// Copyright (c) 2004, 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 - -namespace Boo.Lang.Compiler.TypeSystem -{ - public class ArrayType : IArrayType - { - IType _elementType; - - IType _array; - - int _rank; - - public ArrayType(TypeSystemServices tagManager, IType elementType) - { - _array = tagManager.ArrayType; - _elementType = elementType; - _rank = 1; - } - - public ArrayType(TypeSystemServices tagManager, IType elementType, int rank) - { - _array = tagManager.ArrayType; - _elementType = elementType; - _rank = rank; - } - - - public string Name - { - get - { - if (_rank > 1) - { - return "(" + _elementType.ToString() + ", " + _rank + ")"; - } - return "(" + _elementType.ToString() + ")"; - } - } - - public EntityType EntityType - { - get - { - return EntityType.Array; - } - } - - public string FullName - { - get - { - return Name; - } - } - - public IType Type - { - get - { - return this; - } - } - - public bool IsFinal - { - get - { - return true; - } - } - - public bool IsByRef - { - get - { - return false; - } - } - - public bool IsClass - { - get - { - return false; - } - } - - public bool IsInterface - { - get - { - return false; - } - } - - public bool IsAbstract - { - get - { - return false; - } - } - - public bool IsEnum - { - get - { - return false; - } - } - - public bool IsValueType - { - get - { - return false; - } - } - - public bool IsArray - { - get - { - return true; - } - } - - public int GetTypeDepth() - { - return 2; - } - - public int GetArrayRank() - { - return _rank; - } - - public IType GetElementType() - { - return _elementType; - } - - public IType BaseType - { - get - { - return _array; - } - } - - public IEntity GetDefaultMember() - { - return null; - } - - public virtual bool IsSubclassOf(IType other) - { - return other.IsAssignableFrom(_array); - } - - public virtual bool IsAssignableFrom(IType other) - { - if (other == this || other == Null.Default) - { - return true; - } - - if (other.IsArray) - { - IArrayType otherArray = (IArrayType)other; - - if (otherArray.GetArrayRank() != _rank) - { - return false; - } - - IType otherEntityType = otherArray.GetElementType(); - if (_elementType.IsValueType || otherEntityType.IsValueType) - { - return _elementType == otherEntityType; - } - return _elementType.IsAssignableFrom(otherEntityType); - } - return false; - } - - public IConstructor[] GetConstructors() - { - return new IConstructor[0]; - } - - public IType[] GetInterfaces() - { - return null; - } - - public IEntity[] GetMembers() - { - return _array.GetMembers(); - } - - public INamespace ParentNamespace - { - get - { - return _array.ParentNamespace; - } - } - - public bool Resolve(List targetList, string name, EntityType flags) - { - return _array.Resolve(targetList, name, flags); - } - - override public string ToString() - { - return Name; - } - } -} +#region license +// Copyright (c) 2004, 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 + +namespace Boo.Lang.Compiler.TypeSystem +{ + public class ArrayType : IArrayType + { + IType _elementType; + + IType _array; + + int _rank; + + public ArrayType(TypeSystemServices tagManager, IType elementType) + { + _array = tagManager.ArrayType; + _elementType = elementType; + _rank = 1; + } + + public ArrayType(TypeSystemServices tagManager, IType elementType, int rank) + { + _array = tagManager.ArrayType; + _elementType = elementType; + _rank = rank; + } + + + public string Name + { + get + { + if (_rank > 1) + { + return "(" + _elementType.ToString() + ", " + _rank + ")"; + } + return "(" + _elementType.ToString() + ")"; + } + } + + public EntityType EntityType + { + get + { + return EntityType.Array; + } + } + + public string FullName + { + get + { + return Name; + } + } + + public IType Type + { + get + { + return this; + } + } + + public bool IsFinal + { + get + { + return true; + } + } + + public bool IsByRef + { + get + { + return false; + } + } + + public bool IsClass + { + get + { + return false; + } + } + + public bool IsInterface + { + get + { + return false; + } + } + + public bool IsAbstract + { + get + { + return false; + } + } + + public bool IsEnum + { + get + { + return false; + } + } + + public bool IsValueType + { + get + { + return false; + } + } + + public bool IsArray + { + get + { + return true; + } + } + + public int GetTypeDepth() + { + return 2; + } + + public int GetArrayRank() + { + return _rank; + } + + public IType GetElementType() + { + return _elementType; + } + + public IType BaseType + { + get + { + return _array; + } + } + + public IEntity GetDefaultMember() + { + return null; + } + + public virtual bool IsSubclassOf(IType other) + { + return other.IsAssignableFrom(_array); + } + + public virtual bool IsAssignableFrom(IType other) + { + if (other == this || other == Null.Default) + { + return true; + } + + if (other.IsArray) + { + IArrayType otherArray = (IArrayType)other; + + if (otherArray.GetArrayRank() != _rank) + { + return false; + } + + IType otherEntityType = otherArray.GetElementType(); + if (_elementType.IsValueType || otherEntityType.IsValueType) + { + return _elementType == otherEntityType; + } + return _elementType.IsAssignableFrom(otherEntityType); + } + return false; + } + + public IConstructor[] GetConstructors() + { + return new IConstructor[0]; + } + + public IType[] GetInterfaces() + { + return null; + } + + public IEntity[] GetMembers() + { + return _array.GetMembers(); + } + + public INamespace ParentNamespace + { + get + { + return _array.ParentNamespace; + } + } + + public bool Resolve(List targetList, string name, EntityType flags) + { + return _array.Resolve(targetList, name, flags); + } + + override public string ToString() + { + return Name; + } + + IGenericTypeDefinitionInfo IType.GenericTypeDefinitionInfo + { + get { return null; } + } + + IGenericTypeInfo IType.GenericTypeInfo + { + get { return null; } + } + } +} Index: src/Boo.Lang.Compiler/TypeSystem/Error.cs =================================================================== --- src/Boo.Lang.Compiler/TypeSystem/Error.cs (revision 2352) +++ src/Boo.Lang.Compiler/TypeSystem/Error.cs (working copy) @@ -185,6 +185,16 @@ { return Name; } + + IGenericTypeDefinitionInfo IType.GenericTypeDefinitionInfo + { + get { return null; } + } + + IGenericTypeInfo IType.GenericTypeInfo + { + get { return null; } + } } public class Null : AbstractType Index: src/Boo.Lang.Compiler/TypeSystem/ExternalField.cs =================================================================== --- src/Boo.Lang.Compiler/TypeSystem/ExternalField.cs (revision 2352) +++ src/Boo.Lang.Compiler/TypeSystem/ExternalField.cs (working copy) @@ -30,7 +30,7 @@ { public class ExternalField : IField { - TypeSystemServices _typeSystemServices; + protected TypeSystemServices _typeSystemServices; System.Reflection.FieldInfo _field; @@ -40,7 +40,7 @@ _field = field; } - public IType DeclaringType + public virtual IType DeclaringType { get { @@ -60,7 +60,7 @@ { get { - return _field.DeclaringType.FullName + "." + _field.Name; + return DeclaringType.FullName + "." + _field.Name; } } @@ -128,7 +128,7 @@ } } - public IType Type + public virtual IType Type { get { Index: src/Boo.Lang.Compiler/TypeSystem/ExternalGenericType.cs =================================================================== --- src/Boo.Lang.Compiler/TypeSystem/ExternalGenericType.cs (revision 2352) +++ src/Boo.Lang.Compiler/TypeSystem/ExternalGenericType.cs (working copy) @@ -1,89 +0,0 @@ -#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 - -namespace Boo.Lang.Compiler.TypeSystem -{ - using System; - - public class ExternalGenericType : ExternalType, IGenericType - { - IType[] _arguments = null; - bool _constructed; - -#if NET_2_0 - public ExternalGenericType(TypeSystemServices tss, Type type) : base(tss, type) - { - _constructed = !type.ContainsGenericParameters; - } - - public IType[] GetGenericArguments() - { - if (_arguments == null) - { - Type[] actualArguments = ActualType.GetGenericArguments(); - _arguments = new IType[actualArguments.Length]; - - Converter map = _typeSystemServices.Map; - _arguments = Array.ConvertAll(actualArguments, map); - } - - return _arguments; - } - - public IGenericTypeDefinition GetGenericTypeDefinition() - { - return (IGenericTypeDefinition)_typeSystemServices.Map(ActualType.GetGenericTypeDefinition()); - } - - public bool FullyConstructed - { - get { return _constructed; } - } - -#else - public ExternalGenericType(TypeSystemServices tss, Type type) : base(tss, type) - { - } - - IType[] IGenericType.GetGenericArguments() - { - throw new NotImplementedException(); - } - - IGenericTypeDefinition IGenericType.GetGenericTypeDefinition() - { - throw new NotImplementedException(); - } - - bool IGenericType.FullyConstructed - { - get { throw new NotImplementedException(); } - } -#endif - } -} Index: src/Boo.Lang.Compiler/TypeSystem/ExternalGenericTypeDefinition.cs =================================================================== --- src/Boo.Lang.Compiler/TypeSystem/ExternalGenericTypeDefinition.cs (revision 2352) +++ src/Boo.Lang.Compiler/TypeSystem/ExternalGenericTypeDefinition.cs (working copy) @@ -1,121 +0,0 @@ -#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 - - -namespace Boo.Lang.Compiler.TypeSystem -{ - using System; - -#if NET_2_0 - public class ExternalGenericTypeDefinition : ExternalType, IGenericTypeDefinition - { - private IGenericParameter[] _parameters; - - public ExternalGenericTypeDefinition(TypeSystemServices tss, Type type) : base(tss, type) - { - } - - public IGenericParameter[] GetGenericParameters() - { - if (null == _parameters) _parameters = CreateParameters(); - return _parameters; - } - - public IType MakeGenericType(IType[] arguments) - { - return _typeSystemServices.Map(ActualType.MakeGenericType(ToSystemType(arguments))); - } - - private Type[] ToSystemType(IType[] arguments) - { - Type[] externalTypes = new Type[arguments.Length]; - for (int i = 0; i < arguments.Length; ++i) - { - ExternalType externalType = arguments[i] as ExternalType; - if (null == externalType) throw new NotImplementedException("only generics for externally defined types for now"); - externalTypes[i] = externalType.ActualType; - } - return externalTypes; - } - - protected override string BuildFullName() - { - string name = ActualType.FullName; - return name.Substring(0, name.IndexOf('`')); - } - - private IGenericParameter[] CreateParameters() - { - Type[] arguments = this.ActualType.GetGenericArguments(); - IGenericParameter[] parameters = new IGenericParameter[arguments.Length]; - for (int i=0; i _instances; + + public ExternalGenericTypeDefinitionInfo(TypeSystemServices tss, ExternalType type) + { + _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, delegate(IType t) { return t is ExternalType; })) + { + Type[] actualTypes = Array.ConvertAll( + arguments, + delegate(IType t) { return ((ExternalType)t).ActualType; }); + + 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; + } + } + + private IType CreateMixedType(IType[] arguments) + { + ExternalCallableType callable = _type as ExternalCallableType; + if (null != callable) + { + return new MixedGenericCallableType(_tss, callable, arguments); + } + else + { + return new MixedGenericType(_tss, _type, arguments); + } + } + + 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; } + } + } +} + +#endif Index: src/Boo.Lang.Compiler/TypeSystem/ExternalGenericTypeInfo.cs =================================================================== --- src/Boo.Lang.Compiler/TypeSystem/ExternalGenericTypeInfo.cs (revision 2352) +++ src/Boo.Lang.Compiler/TypeSystem/ExternalGenericTypeInfo.cs (working copy) @@ -1,89 +1,79 @@ -#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 - -namespace Boo.Lang.Compiler.TypeSystem -{ - using System; - - public class ExternalGenericType : ExternalType, IGenericType - { - IType[] _arguments = null; - bool _constructed; - -#if NET_2_0 - public ExternalGenericType(TypeSystemServices tss, Type type) : base(tss, type) - { - _constructed = !type.ContainsGenericParameters; - } - - public IType[] GetGenericArguments() - { - if (_arguments == null) - { - Type[] actualArguments = ActualType.GetGenericArguments(); - _arguments = new IType[actualArguments.Length]; - - Converter map = _typeSystemServices.Map; - _arguments = Array.ConvertAll(actualArguments, map); - } - - return _arguments; - } - - public IGenericTypeDefinition GetGenericTypeDefinition() - { - return (IGenericTypeDefinition)_typeSystemServices.Map(ActualType.GetGenericTypeDefinition()); - } - - public bool FullyConstructed - { - get { return _constructed; } - } - -#else - public ExternalGenericType(TypeSystemServices tss, Type type) : base(tss, type) - { - } - - IType[] IGenericType.GetGenericArguments() - { - throw new NotImplementedException(); - } - - IGenericTypeDefinition IGenericType.GetGenericTypeDefinition() - { - throw new NotImplementedException(); - } - - bool IGenericType.FullyConstructed - { - get { throw new NotImplementedException(); } - } -#endif - } -} +#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 ExternalGenericTypeInfo : IGenericTypeInfo + { + TypeSystemServices _tss; + ExternalType _type; + IType[] _arguments = null; + bool _constructed; + + public ExternalGenericTypeInfo(TypeSystemServices tss, ExternalType type) + { + _tss = tss; + _type = type; + _constructed = !_type.ActualType.ContainsGenericParameters; + } + + public IType[] GenericArguments + { + get + { + if (_arguments == null) + { + _arguments = Array.ConvertAll( + _type.ActualType.GetGenericArguments(), + _tss.Map); + } + + return _arguments; + } + } + + public IType GenericDefinition + { + get + { + return _tss.Map(_type.ActualType.GetGenericTypeDefinition()); + } + } + + public bool FullyConstructed + { + get { return _constructed; } + } + } +} + +#endif Index: src/Boo.Lang.Compiler/TypeSystem/ExternalMethod.cs =================================================================== --- src/Boo.Lang.Compiler/TypeSystem/ExternalMethod.cs (revision 2352) +++ src/Boo.Lang.Compiler/TypeSystem/ExternalMethod.cs (working copy) @@ -1,292 +1,292 @@ -#region license -// Copyright (c) 2004, 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 - -namespace Boo.Lang.Compiler.TypeSystem -{ - using System; - using System.Reflection; - - public class ExternalMethod : IMethod - { - protected TypeSystemServices _typeSystemServices; - - MethodBase _mi; - - IParameter[] _parameters; - - ICallableType _type; - - int _acceptVarArgs = -1; - - int _isDuckTyped = -1; - - int _isExtension = -1; - - int _isPInvoke = -1; - - internal ExternalMethod(TypeSystemServices manager, MethodBase mi) - { - _typeSystemServices = manager; - _mi = mi; - } - - public bool IsExtension - { - get - { - if (-1 == _isExtension) - { - _isExtension = IsStatic && MetadataUtil.IsAttributeDefined(_mi, Types.ExtensionAttribute) - ? 1 - : 0; - } - return 1 == _isExtension; - } - } - - public bool IsDuckTyped - { - get - { - if (-1 == _isDuckTyped) - { - _isDuckTyped = - !ReturnType.IsValueType && MetadataUtil.IsAttributeDefined(_mi, Types.DuckTypedAttribute) - ? 1 - : 0; - } - return 1 == _isDuckTyped; - } - } - - public bool IsPInvoke - { - get - { - if (-1 == _isPInvoke) - { - _isPInvoke = IsStatic && MetadataUtil.IsAttributeDefined(_mi, Types.DllImportAttribute) - ? 1 - : 0; - } - return 1 == _isPInvoke; - } - } - - public IType DeclaringType - { - get - { - return _typeSystemServices.Map(_mi.DeclaringType); - } - } - - public bool IsStatic - { - get - { - return _mi.IsStatic; - } - } - - public bool IsPublic - { - get - { - return _mi.IsPublic; - } - } - - public bool IsProtected - { - get - { - return _mi.IsFamily || _mi.IsFamilyOrAssembly; - } - } - - public bool IsPrivate - { - get - { - return _mi.IsPrivate; - } - } - - public bool IsAbstract - { - get - { - return _mi.IsAbstract; - } - } - - public bool IsInternal - { - get - { - return _mi.IsAssembly; - } - } - - public bool IsVirtual - { - get - { - return _mi.IsVirtual; - } - } - - public bool IsSpecialName - { - get - { - return _mi.IsSpecialName; - } - } - - public string Name - { - get - { - return _mi.Name; - } - } - - public string FullName - { - get - { - return this.DeclaringType + "." + _mi.Name; - } - } - - public bool AcceptVarArgs - { - get - { - if (_acceptVarArgs == -1) - { - ParameterInfo[] parameters = _mi.GetParameters(); - - _acceptVarArgs = - parameters.Length > 0 && IsParamArray(parameters[parameters.Length-1]) ? 1 : 0; - } - return _acceptVarArgs == 1; - } - } - - private bool IsParamArray(ParameterInfo parameter) - { - /* Hack to fix problem with mono-1.1.8.* and older */ - return parameter.ParameterType.IsArray - && ( - Attribute.IsDefined(parameter, Types.ParamArrayAttribute) - || parameter.GetCustomAttributes(Types.ParamArrayAttribute, false).Length > 0); - } - - - public virtual EntityType EntityType - { - get - { - return EntityType.Method; - } - } - - public ICallableType CallableType - { - get - { - if (null == _type) - { - _type = _typeSystemServices.GetCallableType(this); - } - return _type; - } - } - - public IType Type - { - get - { - return CallableType; - } - } - - public IParameter[] GetParameters() - { - if (null == _parameters) - { - _parameters = _typeSystemServices.Map(_mi.GetParameters()); - } - return _parameters; - } - - public virtual IType ReturnType - { - get - { - MethodInfo mi = _mi as MethodInfo; - if (null != mi) - { - return _typeSystemServices.Map(mi.ReturnType); - } - return null; - } - } - - public MethodBase MethodInfo - { - get - { - return _mi; - } - } - - override public bool Equals(object other) - { - ExternalMethod rhs = other as ExternalMethod; - if (null == rhs) - { - return false; - } - return _mi.MethodHandle.Value == rhs._mi.MethodHandle.Value; - } - - override public int GetHashCode() - { - return _mi.MethodHandle.Value.GetHashCode(); - } - - override public string ToString() - { - return _typeSystemServices.GetSignature(this); - } - } -} +#region license +// Copyright (c) 2004, 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 + +namespace Boo.Lang.Compiler.TypeSystem +{ + using System; + using System.Reflection; + + public class ExternalMethod : IMethod + { + protected TypeSystemServices _typeSystemServices; + + MethodBase _mi; + + IParameter[] _parameters; + + ICallableType _type; + + int _acceptVarArgs = -1; + + int _isDuckTyped = -1; + + int _isExtension = -1; + + int _isPInvoke = -1; + + internal ExternalMethod(TypeSystemServices manager, MethodBase mi) + { + _typeSystemServices = manager; + _mi = mi; + } + + public bool IsExtension + { + get + { + if (-1 == _isExtension) + { + _isExtension = IsStatic && MetadataUtil.IsAttributeDefined(_mi, Types.ExtensionAttribute) + ? 1 + : 0; + } + return 1 == _isExtension; + } + } + + public bool IsDuckTyped + { + get + { + if (-1 == _isDuckTyped) + { + _isDuckTyped = + !ReturnType.IsValueType && MetadataUtil.IsAttributeDefined(_mi, Types.DuckTypedAttribute) + ? 1 + : 0; + } + return 1 == _isDuckTyped; + } + } + + public bool IsPInvoke + { + get + { + if (-1 == _isPInvoke) + { + _isPInvoke = IsStatic && MetadataUtil.IsAttributeDefined(_mi, Types.DllImportAttribute) + ? 1 + : 0; + } + return 1 == _isPInvoke; + } + } + + public virtual IType DeclaringType + { + get + { + return _typeSystemServices.Map(_mi.DeclaringType); + } + } + + public bool IsStatic + { + get + { + return _mi.IsStatic; + } + } + + public bool IsPublic + { + get + { + return _mi.IsPublic; + } + } + + public bool IsProtected + { + get + { + return _mi.IsFamily || _mi.IsFamilyOrAssembly; + } + } + + public bool IsPrivate + { + get + { + return _mi.IsPrivate; + } + } + + public bool IsAbstract + { + get + { + return _mi.IsAbstract; + } + } + + public bool IsInternal + { + get + { + return _mi.IsAssembly; + } + } + + public bool IsVirtual + { + get + { + return _mi.IsVirtual; + } + } + + public bool IsSpecialName + { + get + { + return _mi.IsSpecialName; + } + } + + public string Name + { + get + { + return _mi.Name; + } + } + + public string FullName + { + get + { + return this.DeclaringType + "." + _mi.Name; + } + } + + public bool AcceptVarArgs + { + get + { + if (_acceptVarArgs == -1) + { + ParameterInfo[] parameters = _mi.GetParameters(); + + _acceptVarArgs = + parameters.Length > 0 && IsParamArray(parameters[parameters.Length-1]) ? 1 : 0; + } + return _acceptVarArgs == 1; + } + } + + private bool IsParamArray(ParameterInfo parameter) + { + /* Hack to fix problem with mono-1.1.8.* and older */ + return parameter.ParameterType.IsArray + && ( + Attribute.IsDefined(parameter, Types.ParamArrayAttribute) + || parameter.GetCustomAttributes(Types.ParamArrayAttribute, false).Length > 0); + } + + + public virtual EntityType EntityType + { + get + { + return EntityType.Method; + } + } + + public ICallableType CallableType + { + get + { + if (null == _type) + { + _type = _typeSystemServices.GetCallableType(this); + } + return _type; + } + } + + public IType Type + { + get + { + return CallableType; + } + } + + public virtual IParameter[] GetParameters() + { + if (null == _parameters) + { + _parameters = _typeSystemServices.Map(_mi.GetParameters()); + } + return _parameters; + } + + public virtual IType ReturnType + { + get + { + MethodInfo mi = _mi as MethodInfo; + if (null != mi) + { + return _typeSystemServices.Map(mi.ReturnType); + } + return null; + } + } + + public MethodBase MethodInfo + { + get + { + return _mi; + } + } + + override public bool Equals(object other) + { + ExternalMethod rhs = other as ExternalMethod; + if (null == rhs) + { + return false; + } + return _mi.MethodHandle.Value == rhs._mi.MethodHandle.Value; + } + + override public int GetHashCode() + { + return _mi.MethodHandle.Value.GetHashCode(); + } + + override public string ToString() + { + return _typeSystemServices.GetSignature(this); + } + } +} Index: src/Boo.Lang.Compiler/TypeSystem/ExternalParameter.cs =================================================================== --- src/Boo.Lang.Compiler/TypeSystem/ExternalParameter.cs (revision 2352) +++ src/Boo.Lang.Compiler/TypeSystem/ExternalParameter.cs (working copy) @@ -1,84 +1,84 @@ -#region license -// Copyright (c) 2004, 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 - -namespace Boo.Lang.Compiler.TypeSystem -{ - using System.Reflection; - - public class ExternalParameter : IParameter - { - TypeSystemServices _typeSystemServices; - ParameterInfo _parameter; - - public ExternalParameter(TypeSystemServices service, ParameterInfo parameter) - { - _typeSystemServices = service; - _parameter = parameter; - } - - public string Name - { - get - { - return _parameter.Name; - } - } - - public string FullName - { - get - { - return _parameter.Name; - } - } - - public EntityType EntityType - { - get - { - return EntityType.Parameter; - } - } - - public IType Type - { - get - { - return _typeSystemServices.Map(_parameter.ParameterType); - } - } - - public bool IsByRef - { - get - { - return Type.IsByRef; - } - } - } -} +#region license +// Copyright (c) 2004, 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 + +namespace Boo.Lang.Compiler.TypeSystem +{ + using System.Reflection; + + public class ExternalParameter : IParameter + { + TypeSystemServices _typeSystemServices; + protected ParameterInfo _parameter; + + public ExternalParameter(TypeSystemServices service, ParameterInfo parameter) + { + _typeSystemServices = service; + _parameter = parameter; + } + + public string Name + { + get + { + return _parameter.Name; + } + } + + public string FullName + { + get + { + return _parameter.Name; + } + } + + public EntityType EntityType + { + get + { + return EntityType.Parameter; + } + } + + public virtual IType Type + { + get + { + return _typeSystemServices.Map(_parameter.ParameterType); + } + } + + public bool IsByRef + { + get + { + return Type.IsByRef; + } + } + } +} Index: src/Boo.Lang.Compiler/TypeSystem/ExternalProperty.cs =================================================================== --- src/Boo.Lang.Compiler/TypeSystem/ExternalProperty.cs (revision 2352) +++ src/Boo.Lang.Compiler/TypeSystem/ExternalProperty.cs (working copy) @@ -30,7 +30,7 @@ { public class ExternalProperty : IProperty { - TypeSystemServices _typeSystemServices; + protected TypeSystemServices _typeSystemServices; System.Reflection.PropertyInfo _property; @@ -60,7 +60,7 @@ } } - public IType DeclaringType + public virtual IType DeclaringType { get { @@ -154,7 +154,7 @@ { get { - return _property.DeclaringType.FullName + "." + _property.Name; + return DeclaringType.FullName + "." + Name; } } @@ -166,7 +166,7 @@ } } - public IType Type + public virtual IType Type { get { @@ -190,7 +190,7 @@ } } - public IParameter[] GetParameters() + public virtual IParameter[] GetParameters() { if (null == _parameters) { @@ -199,7 +199,7 @@ return _parameters; } - public IMethod GetGetMethod() + public virtual IMethod GetGetMethod() { System.Reflection.MethodInfo getter = _property.GetGetMethod(true); if (null != getter) @@ -209,7 +209,7 @@ return null; } - public IMethod GetSetMethod() + public virtual IMethod GetSetMethod() { System.Reflection.MethodInfo setter = _property.GetSetMethod(true); if (null != setter) Index: src/Boo.Lang.Compiler/TypeSystem/ExternalType.cs =================================================================== --- src/Boo.Lang.Compiler/TypeSystem/ExternalType.cs (revision 2352) +++ src/Boo.Lang.Compiler/TypeSystem/ExternalType.cs (working copy) @@ -1,408 +1,455 @@ -#region license -// Copyright (c) 2004, 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 - -namespace Boo.Lang.Compiler.TypeSystem -{ - using System; - using System.Reflection; - - public class ExternalType : IType - { - protected TypeSystemServices _typeSystemServices; - - Type _type; - - IConstructor[] _constructors; - - IType[] _interfaces; - - IEntity[] _members; - - int _typeDepth = -1; - - string _primitiveName; - - string _fullName; - - internal ExternalType(TypeSystemServices tss, Type type) - { - if (null == type) - { - throw new ArgumentException("type"); - } - _typeSystemServices = tss; - _type = type; - } - - public string FullName - { - get - { - if (null == _fullName) - { - _fullName = BuildFullName(); - } - return _fullName; - } - } - - internal string PrimitiveName - { - get - { - return _primitiveName; - } - - set - { - _primitiveName = value; - } - } - - public string Name - { - get - { - return _type.Name; - } - } - - public EntityType EntityType - { - get - { - return EntityType.Type; - } - } - - public IType Type - { - get - { - return this; - } - } - - public virtual bool IsFinal - { - get - { - return _type.IsSealed; - } - } - - public bool IsByRef - { - get - { - return _type.IsByRef; - } - } - - public IType DeclaringType - { - get - { - System.Type declaringType = _type.DeclaringType; - return null != declaringType - ? _typeSystemServices.Map(declaringType) - : null; - } - } - - public IType GetElementType() - { - return _typeSystemServices.Map(_type.GetElementType()); - } - - public bool IsClass - { - get - { - return _type.IsClass; - } - } - - public bool IsAbstract - { - get - { - return _type.IsAbstract; - } - } - - public bool IsInterface - { - get - { - return _type.IsInterface; - } - } - - public bool IsEnum - { - get - { - return _type.IsEnum; - } - } - - public bool IsValueType - { - get - { - return _type.IsValueType; - } - } - - public bool IsArray - { - get - { - return false; - } - } - - public IType BaseType - { - get - { - - Type baseType = _type.BaseType; - return null == baseType - ? null - : _typeSystemServices.Map(baseType); - } - } - - public IEntity GetDefaultMember() - { - return _typeSystemServices.Map(_type.GetDefaultMembers()); - } - - public Type ActualType - { - get - { - return _type; - } - } - - public virtual bool IsSubclassOf(IType other) - { - ExternalType external = other as ExternalType; - if (null == external /*|| _typeSystemServices.VoidType == other*/) - { - return false; - } - - return _type.IsSubclassOf(external._type) || - (external.IsInterface && external._type.IsAssignableFrom(_type)) - ; - } - - public virtual bool IsAssignableFrom(IType other) - { - ExternalType external = other as ExternalType; - if (null == external) - { - if (EntityType.Null == other.EntityType) - { - return !IsValueType; - } - return other.IsSubclassOf(this); - } - if (other == _typeSystemServices.VoidType) - { - return false; - } - return _type.IsAssignableFrom(external._type); - } - - public IConstructor[] GetConstructors() - { - if (null == _constructors) - { - BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; - ConstructorInfo[] ctors = _type.GetConstructors(flags); - _constructors = new IConstructor[ctors.Length]; - for (int i=0; i<_constructors.Length; ++i) - { - _constructors[i] = new ExternalConstructor(_typeSystemServices, ctors[i]); - } - } - return _constructors; - } - - public IType[] GetInterfaces() - { - if (null == _interfaces) - { - Type[] interfaces = _type.GetInterfaces(); - _interfaces = new IType[interfaces.Length]; - for (int i=0; i<_interfaces.Length; ++i) - { - _interfaces[i] = _typeSystemServices.Map(interfaces[i]); - } - } - return _interfaces; - } - - public IEntity[] GetMembers() - { - if (null == _members) - { - BindingFlags flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;// | BindingFlags.FlattenHierarchy; - MemberInfo[] members = _type.GetMembers(flags); - Type[] nested = _type.GetNestedTypes(); - _members = new IEntity[members.Length+nested.Length]; - int i = 0; - for (i=0; i 0) - { - int current = 0; - foreach (Type i in interfaces) - { - int depth = GetInterfaceDepth(i); - if (depth > current) - { - current = depth; - } - } - return 1+current; - } - return 1; - } - - protected virtual string BuildFullName() - { - if (_type.IsByRef) return "ref " + this.GetElementType().ToString(); - if (_type.DeclaringType != null) return this.DeclaringType.ToString() + "." + _type.Name; - return _type.FullName; - } - } -} +#region license +// Copyright (c) 2004, 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 + +namespace Boo.Lang.Compiler.TypeSystem +{ + using System; + using System.Reflection; + + public class ExternalType : IType + { + protected TypeSystemServices _typeSystemServices; + + Type _type; + + IConstructor[] _constructors; + + IType[] _interfaces; + + IEntity[] _members; + + int _typeDepth = -1; + + string _primitiveName; + + string _fullName; + + internal ExternalType(TypeSystemServices tss, Type type) + { + if (null == type) + { + throw new ArgumentException("type"); + } + _typeSystemServices = tss; + _type = type; + } + + public virtual string FullName + { + get + { + if (null == _fullName) + { + _fullName = BuildFullName(); + } + return _fullName; + } + } + + internal string PrimitiveName + { + get + { + return _primitiveName; + } + + set + { + _primitiveName = value; + } + } + + public virtual string Name + { + get + { + return _type.Name; + } + } + + public EntityType EntityType + { + get + { + return EntityType.Type; + } + } + + public IType Type + { + get + { + return this; + } + } + + public virtual bool IsFinal + { + get + { + return _type.IsSealed; + } + } + + public bool IsByRef + { + get + { + return _type.IsByRef; + } + } + + public IType DeclaringType + { + get + { + System.Type declaringType = _type.DeclaringType; + return null != declaringType + ? _typeSystemServices.Map(declaringType) + : null; + } + } + + public virtual IType GetElementType() + { + return _typeSystemServices.Map(_type.GetElementType()); + } + + public bool IsClass + { + get + { + return _type.IsClass; + } + } + + public bool IsAbstract + { + get + { + return _type.IsAbstract; + } + } + + public bool IsInterface + { + get + { + return _type.IsInterface; + } + } + + public bool IsEnum + { + get + { + return _type.IsEnum; + } + } + + public bool IsValueType + { + get + { + return _type.IsValueType; + } + } + + public bool IsArray + { + get + { + return false; + } + } + + public virtual IType BaseType + { + get + { + + Type baseType = _type.BaseType; + return null == baseType + ? null + : _typeSystemServices.Map(baseType); + } + } + + public virtual IEntity GetDefaultMember() + { + return _typeSystemServices.Map(_type.GetDefaultMembers()); + } + + public Type ActualType + { + get + { + return _type; + } + } + + public virtual bool IsSubclassOf(IType other) + { + ExternalType external = other as ExternalType; + if (null == external /*|| _typeSystemServices.VoidType == other*/) + { + return false; + } + + return _type.IsSubclassOf(external._type) || + (external.IsInterface && external._type.IsAssignableFrom(_type)) + ; + } + + public virtual bool IsAssignableFrom(IType other) + { + ExternalType external = other as ExternalType; + if (null == external) + { + if (EntityType.Null == other.EntityType) + { + return !IsValueType; + } + return other.IsSubclassOf(this); + } + if (other == _typeSystemServices.VoidType) + { + return false; + } + return _type.IsAssignableFrom(external._type); + } + + public virtual IConstructor[] GetConstructors() + { + if (null == _constructors) + { + BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; + ConstructorInfo[] ctors = _type.GetConstructors(flags); + _constructors = new IConstructor[ctors.Length]; + for (int i=0; i<_constructors.Length; ++i) + { + _constructors[i] = new ExternalConstructor(_typeSystemServices, ctors[i]); + } + } + return _constructors; + } + + public virtual IType[] GetInterfaces() + { + if (null == _interfaces) + { + Type[] interfaces = _type.GetInterfaces(); + _interfaces = new IType[interfaces.Length]; + for (int i=0; i<_interfaces.Length; ++i) + { + _interfaces[i] = _typeSystemServices.Map(interfaces[i]); + } + } + return _interfaces; + } + + public virtual IEntity[] GetMembers() + { + if (null == _members) + { + BindingFlags flags = BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;// | BindingFlags.FlattenHierarchy; + MemberInfo[] members = _type.GetMembers(flags); + Type[] nested = _type.GetNestedTypes(); + _members = new IEntity[members.Length+nested.Length]; + int i = 0; + for (i=0; i 0) + { + int current = 0; + foreach (Type i in interfaces) + { + int depth = GetInterfaceDepth(i); + if (depth > current) + { + current = depth; + } + } + return 1+current; + } + return 1; + } + + protected virtual string BuildFullName() + { + if (_type.IsByRef) return "ref " + this.GetElementType().ToString(); + if (_type.DeclaringType != null) return this.DeclaringType.ToString() + "." + _type.Name; + return _type.FullName; + } + +#if NET_2_0 + ExternalGenericTypeDefinitionInfo _genericTypeDefinitionInfo = null; + public virtual IGenericTypeDefinitionInfo GenericTypeDefinitionInfo + { + get + { + if (ActualType.IsGenericTypeDefinition) + { + if (_genericTypeDefinitionInfo == null) + { + _genericTypeDefinitionInfo = new ExternalGenericTypeDefinitionInfo(_typeSystemServices, this); + } + return _genericTypeDefinitionInfo; + } + return null; + } + } + + ExternalGenericTypeInfo _genericTypeInfo = null; + public virtual IGenericTypeInfo GenericTypeInfo + { + get + { + if (ActualType.IsGenericType) + { + if (_genericTypeInfo == null) + { + _genericTypeInfo = new ExternalGenericTypeInfo(_typeSystemServices, this); + } + return _genericTypeInfo; + } + return null; + } + } +#else + IGenericTypeDefinitionInfo IType.GenericTypeDefinitionInfo + { + get { return null; } + } + + IGenericTypeInfo IType.GenericTypeInfo + { + get { return null; } + } +#endif + + } +} Index: src/Boo.Lang.Compiler/TypeSystem/IEntity.cs =================================================================== --- src/Boo.Lang.Compiler/TypeSystem/IEntity.cs (revision 2352) +++ src/Boo.Lang.Compiler/TypeSystem/IEntity.cs (working copy) @@ -1,334 +1,339 @@ -#region license -// Copyright (c) 2004, 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 - -namespace Boo.Lang.Compiler.TypeSystem -{ - public interface IEntity - { - string Name - { - get; - } - - string FullName - { - get; - } - - EntityType EntityType - { - get; - } - } - - public interface IInternalEntity : IEntity - { - Boo.Lang.Compiler.Ast.Node Node - { - get; - } - } - - public interface ITypedEntity : IEntity - { - IType Type - { - get; - } - } - - public interface IMember : ITypedEntity - { - bool IsDuckTyped - { - get; - } - - IType DeclaringType - { - get; - } - - bool IsStatic - { - get; - } - - bool IsPublic - { - get; - } - } - - public interface IExtensionEnabled : IEntityWithParameters - { - bool IsExtension { get; } - } - - public interface IEvent : IMember - { - IMethod GetAddMethod(); - IMethod GetRemoveMethod(); - IMethod GetRaiseMethod(); - - bool IsAbstract - { - get; - } - - bool IsVirtual - { - get; - } - } - - public interface IField : IAccessibleMember - { - bool IsInitOnly - { - get; - } - - bool IsLiteral - { - get; - } - - object StaticValue - { - get; - } - } - - public interface IProperty : IAccessibleMember, IEntityWithParameters, IExtensionEnabled - { - IMethod GetGetMethod(); - - IMethod GetSetMethod(); - } - - public interface IType : ITypedEntity, INamespace - { - bool IsClass - { - get; - } - - bool IsAbstract - { - get; - } - - bool IsInterface - { - get; - } - - bool IsEnum - { - get; - } - - bool IsByRef - { - get; - } - - bool IsValueType - { - get; - } - - bool IsFinal - { - get; - } - - bool IsArray - { - get; - } - - int GetTypeDepth(); - - IType GetElementType(); - - IType BaseType - { - get; - } - - IEntity GetDefaultMember(); - - IConstructor[] GetConstructors(); - - IType[] GetInterfaces(); - - bool IsSubclassOf(IType other); - - bool IsAssignableFrom(IType other); - } - - public interface IGenericParameter : IType - { - IGenericTypeDefinition GetDeclaringType(); - bool Constructed { get; } - } - - public interface IGenericTypeDefinition : IType - { - IGenericParameter[] GetGenericParameters(); - IType MakeGenericType(IType[] arguments); - } - - public interface IGenericType : IType - { - IType[] GetGenericArguments(); - IGenericTypeDefinition GetGenericTypeDefinition(); - bool FullyConstructed { get; } - } - - public interface ICallableType : IType - { - CallableSignature GetSignature(); - } - - public interface IArrayType : IType - { - int GetArrayRank(); - } - - public interface ILocalEntity : ITypedEntity - { - bool IsPrivateScope - { - get; - } - - /// - /// Is this variable shared among closures? - /// - bool IsShared - { - get; - set; - } - - /// - /// Is this variable ever used in the body of the method? - /// - bool IsUsed - { - get; - set; - } - } - - public interface IParameter : ITypedEntity - { - /// - /// Is the parameter out or ref? - /// - bool IsByRef - { - get; - } - } - - public interface IAccessibleMember : IMember - { - bool IsProtected - { - get; - } - - bool IsInternal - { - get; - } - - bool IsPrivate - { - get; - } - } - - public interface IEntityWithParameters : IEntity - { - IParameter[] GetParameters(); - - bool AcceptVarArgs - { - get; - } - } - - public interface IMethodBase : IAccessibleMember, IEntityWithParameters - { - ICallableType CallableType - { - get; - } - } - - public interface IMethod : IMethodBase, IExtensionEnabled - { - IType ReturnType - { - get; - } - - bool IsAbstract - { - get; - } - - bool IsVirtual - { - get; - } - - bool IsSpecialName - { - get; - } - - bool IsPInvoke - { - get; - } - } - - public interface IConstructor : IMethodBase - { - } - - public interface IDestructor : IMethodBase - { - } -} +#region license +// Copyright (c) 2004, 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 + +namespace Boo.Lang.Compiler.TypeSystem +{ + public interface IEntity + { + string Name + { + get; + } + + string FullName + { + get; + } + + EntityType EntityType + { + get; + } + } + + public interface IInternalEntity : IEntity + { + Boo.Lang.Compiler.Ast.Node Node + { + get; + } + } + + public interface ITypedEntity : IEntity + { + IType Type + { + get; + } + } + + public interface IMember : ITypedEntity + { + bool IsDuckTyped + { + get; + } + + IType DeclaringType + { + get; + } + + bool IsStatic + { + get; + } + + bool IsPublic + { + get; + } + } + + public interface IExtensionEnabled : IEntityWithParameters + { + bool IsExtension { get; } + } + + public interface IEvent : IMember + { + IMethod GetAddMethod(); + IMethod GetRemoveMethod(); + IMethod GetRaiseMethod(); + + bool IsAbstract + { + get; + } + + bool IsVirtual + { + get; + } + } + + public interface IField : IAccessibleMember + { + bool IsInitOnly + { + get; + } + + bool IsLiteral + { + get; + } + + object StaticValue + { + get; + } + } + + public interface IProperty : IAccessibleMember, IEntityWithParameters, IExtensionEnabled + { + IMethod GetGetMethod(); + + IMethod GetSetMethod(); + } + + public interface IType : ITypedEntity, INamespace + { + bool IsClass + { + get; + } + + bool IsAbstract + { + get; + } + + bool IsInterface + { + get; + } + + bool IsEnum + { + get; + } + + bool IsByRef + { + get; + } + + bool IsValueType + { + get; + } + + bool IsFinal + { + get; + } + + bool IsArray + { + get; + } + + int GetTypeDepth(); + + IType GetElementType(); + + IType BaseType + { + get; + } + + IEntity GetDefaultMember(); + + IConstructor[] GetConstructors(); + + IType[] GetInterfaces(); + + bool IsSubclassOf(IType other); + + bool IsAssignableFrom(IType other); + + IGenericTypeDefinitionInfo GenericTypeDefinitionInfo { get; } + + IGenericTypeInfo GenericTypeInfo { get; } + } + + public interface IGenericTypeDefinitionInfo + { + IGenericParameter[] GenericParameters { get; } + IType MakeGenericType(IType[] arguments); + } + + public interface IGenericTypeInfo + { + IType[] GenericArguments { get; } + IType GenericDefinition { get; } + bool FullyConstructed { get; } + } + + public interface IGenericParameter: IType + { + IType DeclaringType { get; } + int GenericParameterPosition { get; } + // TODO: Constraints { get; } + } + + public interface ICallableType : IType + { + CallableSignature GetSignature(); + } + + public interface IArrayType : IType + { + int GetArrayRank(); + } + + public interface ILocalEntity : ITypedEntity + { + bool IsPrivateScope + { + get; + } + + /// + /// Is this variable shared among closures? + /// + bool IsShared + { + get; + set; + } + + /// + /// Is this variable ever used in the body of the method? + /// + bool IsUsed + { + get; + set; + } + } + + public interface IParameter : ITypedEntity + { + /// + /// Is the parameter out or ref? + /// + bool IsByRef + { + get; + } + } + + public interface IAccessibleMember : IMember + { + bool IsProtected + { + get; + } + + bool IsInternal + { + get; + } + + bool IsPrivate + { + get; + } + } + + public interface IEntityWithParameters : IEntity + { + IParameter[] GetParameters(); + + bool AcceptVarArgs + { + get; + } + } + + public interface IMethodBase : IAccessibleMember, IEntityWithParameters + { + ICallableType CallableType + { + get; + } + } + + public interface IMethod : IMethodBase, IExtensionEnabled + { + IType ReturnType + { + get; + } + + bool IsAbstract + { + get; + } + + bool IsVirtual + { + get; + } + + bool IsSpecialName + { + get; + } + + bool IsPInvoke + { + get; + } + } + + public interface IConstructor : IMethodBase + { + } + + public interface IDestructor : IMethodBase + { + } +} Index: src/Boo.Lang.Compiler/TypeSystem/InternalField.cs =================================================================== --- src/Boo.Lang.Compiler/TypeSystem/InternalField.cs (revision 2352) +++ src/Boo.Lang.Compiler/TypeSystem/InternalField.cs (working copy) @@ -1,181 +1,181 @@ -#region license -// Copyright (c) 2004, 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 - -namespace Boo.Lang.Compiler.TypeSystem +#region license +// Copyright (c) 2004, 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 + +namespace Boo.Lang.Compiler.TypeSystem { using Boo.Lang.Compiler.Ast; - public class InternalField : IInternalEntity, IField - { - Field _field; - object _staticValue; - - public InternalField(Field field) - { - _field = field; - } - - public string Name - { - get - { - return _field.Name; - } - } - - public string FullName - { - get - { - return _field.DeclaringType.FullName + "." + _field.Name; - } - } - - public bool IsStatic - { - get - { - return _field.IsStatic; - } - } - - public bool IsPublic - { - get - { - return _field.IsPublic; - } - } - - public bool IsProtected - { - get - { - return _field.IsProtected; - } - } - + public class InternalField : IInternalEntity, IField + { + Field _field; + object _staticValue; + + public InternalField(Field field) + { + _field = field; + } + + public string Name + { + get + { + return _field.Name; + } + } + + public string FullName + { + get + { + return _field.DeclaringType.FullName + "." + _field.Name; + } + } + + public bool IsStatic + { + get + { + return _field.IsStatic; + } + } + + public bool IsPublic + { + get + { + return _field.IsPublic; + } + } + + public bool IsProtected + { + get + { + return _field.IsProtected; + } + } + public bool IsPrivate { get { return _field.IsPrivate; } - } - + } + public bool IsInternal { get { return _field.IsInternal; } - } - - public EntityType EntityType - { - get - { - return EntityType.Field; - } - } - - public IType Type - { - get - { - return null != _field.Type - ? TypeSystemServices.GetType(_field.Type) - : Unknown.Default; - } - } - - public IType DeclaringType - { - get - { - return (IType)TypeSystemServices.GetEntity(_field.ParentNode); - } - } - - public bool IsLiteral - { - get - { - //return IsStatic && IsInitOnly && TypeSystemServices.IsPrimitiveTypeOrString(Type); - return null != _staticValue; - } - } - - public bool IsInitOnly - { - get - { - return _field.IsFinal; - } - } - - public object StaticValue - { - get - { - return _staticValue; - } - - set - { - _staticValue = value; - } - } - - public Node Node - { - get - { - return _field; - } - } - - public Field Field - { - get - { - return _field; - } - } - - override public string ToString() - { - return FullName; - } - + } + + public EntityType EntityType + { + get + { + return EntityType.Field; + } + } + + public IType Type + { + get + { + return null != _field.Type + ? TypeSystemServices.GetType(_field.Type) + : Unknown.Default; + } + } + + public IType DeclaringType + { + get + { + return (IType)TypeSystemServices.GetEntity(_field.ParentNode); + } + } + + public bool IsLiteral + { + get + { + //return IsStatic && IsInitOnly && TypeSystemServices.IsPrimitiveTypeOrString(Type); + return null != _staticValue; + } + } + + public bool IsInitOnly + { + get + { + return _field.IsFinal; + } + } + + public object StaticValue + { + get + { + return _staticValue; + } + + set + { + _staticValue = value; + } + } + + public Node Node + { + get + { + return _field; + } + } + + public Field Field + { + get + { + return _field; + } + } + + override public string ToString() + { + return FullName; + } + public bool IsDuckTyped { get { return false; } - } - } -} + } + } +} Index: src/Boo.Lang.Compiler/TypeSystem/MixedGenericType.cs =================================================================== --- src/Boo.Lang.Compiler/TypeSystem/MixedGenericType.cs (revision 0) +++ src/Boo.Lang.Compiler/TypeSystem/MixedGenericType.cs (revision 0) @@ -0,0 +1,565 @@ +#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 type constructed from an external definition but involving internal parameters. + /// + public class MixedGenericType : ExternalType, IGenericTypeInfo + { + #region Data Members + + ExternalType _definition; + IType[] _arguments = null; + bool _constructed; + string _name = null; + string _fullName = null; + Dictionary _mappedMembers = new Dictionary(); + + #endregion + + #region Constructor + + public MixedGenericType(TypeSystemServices tss, ExternalType definition, IType[] arguments) : base(tss, definition.ActualType) + { + _definition = definition; + _arguments = arguments; + _constructed = IsConstructed(); + } + + #endregion + + #region IGenericTypeInfo members + + public IType[] GenericArguments + { + get { return _arguments; } + } + + public IType GenericDefinition + { + get { return _definition; } + } + + public bool FullyConstructed + { + get { return _constructed; } + } + + #endregion + + #region Properties + + public override IGenericTypeInfo GenericTypeInfo + { + get { return this; } + } + + public override IType BaseType + { + get { return MapType(_definition.BaseType); } + } + + 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; + } + } + + #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 IType GetElementType() + { + return MapType(_definition.GetElementType()); + } + + public override IEntity GetDefaultMember() + { + return MapMember(_definition.GetDefaultMember()); + } + + public override IConstructor[] GetConstructors() + { + return Array.ConvertAll( + _definition.GetConstructors(), + delegate(IConstructor c) { return (IConstructor)MapMember(c); }); + } + + public override IType[] GetInterfaces() + { + return Array.ConvertAll( + _definition.GetInterfaces(), + MapType); + } + + public override IEntity[] GetMembers() + { + return Array.ConvertAll( + _definition.GetMembers(), + MapMember); + } + + public override bool IsSubclassOf(IType other) + { + if (BaseType != null && (BaseType == other || BaseType.IsSubclassOf(other))) + { + return true; + } + + if (other.IsInterface && Array.Exists( + GetInterfaces(), + delegate(IType i) { return other.IsAssignableFrom(i); })) + { + return true; + } + + return false; + } + + public override bool IsAssignableFrom(IType other) + { + if (other == null) + { + return false; + } + + if (other == this || other.IsSubclassOf(this)) + { + return true; + } + + return false; + } + + #endregion + + #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) + { + if (sourceType == null) + { + return null; + } + + // Map generic parameter to corresponding argument + IGenericParameter gp = sourceType as IGenericParameter; + if (null != gp && gp.DeclaringType == _definition) + { + return GenericArguments[gp.GenericParameterPosition]; + } + + // Map open constructed type using generic parameters to closed constructed type + // using corresponding arguments + if (null != sourceType.GenericTypeInfo && !sourceType.GenericTypeInfo.FullyConstructed) + { + IType[] mappedArguments = Array.ConvertAll( + sourceType.GenericTypeInfo.GenericArguments, + MapType); + + return sourceType.GenericTypeInfo. + GenericDefinition.GenericTypeDefinitionInfo. + MakeGenericType(mappedArguments); + } + + // 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()); + } + + // TODO: Handle ref/out types of generic parameters + + // If source type doesn't require mapping, return it as is + return sourceType; + } + + /// + /// Maps a member from the type's definition to its constructed version. + /// + protected IEntity MapMember(IEntity source) + { + if (source == null) return null; + + if (_mappedMembers.ContainsKey(source)) + { + return _mappedMembers[source]; + } + + IEntity mapped = null; + + switch (source.EntityType) + { + case EntityType.Method: + mapped = new MappedMethod(_typeSystemServices, ((ExternalMethod)source).MethodInfo, this); + break; + + case EntityType.Constructor: + mapped = new MappedConstructor(_typeSystemServices, ((ExternalConstructor)source).ConstructorInfo, this); + break; + + case EntityType.Field: + mapped = new MappedField(_typeSystemServices, ((ExternalField)source).FieldInfo, this); + break; + + case EntityType.Property: + mapped = new MappedProperty(_typeSystemServices, ((ExternalProperty)source).PropertyInfo, this); + break; + + case EntityType.Type: + mapped = MapType((IType)source); + break; + + default: + throw new ArgumentException( + string.Format("Invalid entity type for mapping: {0}.", source.EntityType)); + } + + _mappedMembers[source] = mapped; + return mapped; + } + + #endregion + + #region class MappedMethod + + /// + /// A method in a mixed generic type. + /// + public class MappedMethod : ExternalMethod + { + private MixedGenericType _parentType; + + public MappedMethod(TypeSystemServices tss, MethodBase method, MixedGenericType parentType) : base(tss, method) + { + _parentType = parentType; + } + + public override IType DeclaringType + { + get { return _parentType; } + } + + public override IType ReturnType + { + get + { + return _parentType.MapType(base.ReturnType); + } + } + + public override IParameter[] GetParameters() + { + return Array.ConvertAll( + base.GetParameters(), + delegate(IParameter p) + { + return new MappedParameter(_typeSystemServices, (ExternalParameter)p, _parentType); + }); + } + } + + #endregion + + #region class MappedConstructor + + /// + /// A constructor in a mixed generic type. + /// + public class MappedConstructor : MappedMethod, IConstructor + { + public MappedConstructor(TypeSystemServices tss, ConstructorInfo ci, MixedGenericType parentType) : base(tss, ci, parentType) + { + } + + public override EntityType EntityType + { + get { return EntityType.Constructor; } + } + + public override IType ReturnType + { + get { return _typeSystemServices.VoidType; } + } + + public ConstructorInfo ConstructorInfo + { + get + { + return (ConstructorInfo)MethodInfo; + } + } + } + + #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 + { + private MixedGenericType _parentType; + + public MappedProperty(TypeSystemServices tss, PropertyInfo property, MixedGenericType parentType) : base(tss, property) + { + _parentType = parentType; + } + + public override IType Type + { + get { return _parentType.MapType(base.Type); } + } + + public override IType DeclaringType + { + get { return _parentType.MapType(base.DeclaringType); } + } + + public override IParameter[] GetParameters() + { + IParameter[] baseParams = base.GetParameters(); + return Array.ConvertAll( + baseParams, + delegate(IParameter p) + { + return new MappedParameter(_typeSystemServices, (ExternalParameter)p, _parentType); + }); + } + + public override IMethod GetGetMethod() + { + return (IMethod)_parentType.MapMember(base.GetGetMethod()); + } + + public override IMethod GetSetMethod() + { + return (IMethod)_parentType.MapMember(base.GetSetMethod()); + } + + public override string ToString() + { + IParameter[] parameters = GetParameters(); + if (parameters.Length > 0) + { + string[] parameterNames = Array.ConvertAll( + parameters, + delegate(IParameter p) { return p.Type.Name; }); + + return string.Format( + "{0} {1} [{2}]", + Type.Name, + Name, + string.Join(", ", parameterNames)); + } + + return string.Format("{0} {1}", Type.Name, Name); + } + } + #endregion + + #region class MappedField + + public class MappedField : ExternalField + { + MixedGenericType _parentType; + + public MappedField(TypeSystemServices tss, FieldInfo field, MixedGenericType parentType) : base(tss, field) + { + _parentType = parentType; + } + + public override IType DeclaringType + { + get { return _parentType; } + } + + public override IType Type + { + get { return _parentType.MapType(base.Type); } + } + } + + #endregion + } + + public class MixedGenericCallableType: MixedGenericType, ICallableType + { + ExternalCallableType _definition; + CallableSignature _signature; + + public MixedGenericCallableType(TypeSystemServices tss, ExternalCallableType definition, IType[] arguments): + base(tss, definition, arguments) + { + _definition = definition; + } + + public CallableSignature GetSignature() + { + if (_signature == null) + { + CallableSignature definitionSignature = _definition.GetSignature(); + + IParameter[] parameters = Array.ConvertAll( + definitionSignature.Parameters, + delegate(IParameter p) + { + return new MappedParameter(_typeSystemServices, (ExternalParameter)p, this); + }); + + _signature = new CallableSignature(parameters, MapType(definitionSignature.ReturnType)); + } + + return _signature; + } + + override public bool IsAssignableFrom(IType other) + { + return _typeSystemServices.IsCallableTypeAssignableFrom(this, other); + } + } +} + +#endif Index: src/Boo.Lang.Compiler/TypeSystem/NameResolutionService.cs =================================================================== --- src/Boo.Lang.Compiler/TypeSystem/NameResolutionService.cs (revision 2352) +++ src/Boo.Lang.Compiler/TypeSystem/NameResolutionService.cs (working copy) @@ -274,10 +274,14 @@ } } - private IEntity MakeGenericType(GenericTypeReference node, IGenericTypeDefinition entity) + private IEntity MakeGenericType(GenericTypeReference node, IType entity) { IType[] arguments = ResolveGenericArguments(node); - return entity.MakeGenericType(arguments); + if (entity.GenericTypeDefinitionInfo == null) + { + throw CompilerErrorFactory.NotAGenericDefinition(node, node.Name); + } + return entity.GenericTypeDefinitionInfo.MakeGenericType(arguments); } private IType[] ResolveGenericArguments(GenericTypeReference node) @@ -294,6 +298,7 @@ public void ResolveSimpleTypeReference(SimpleTypeReference node) { + if (null != node.Entity) return; IEntity entity = ResolveTypeName(node); @@ -319,12 +324,14 @@ GenericTypeReference gtr = node as GenericTypeReference; if (null != gtr) { - entity = MakeGenericType(gtr, (IGenericTypeDefinition) entity); + entity = MakeGenericType(gtr, (IType)entity); } #endif + node.Name = entity.FullName; } - node.Entity = entity; + + node.Entity = entity; } private IEntity ResolveTypeName(SimpleTypeReference node) Index: src/Boo.Lang.Compiler/TypeSystem/TypeSystemServices.cs =================================================================== --- src/Boo.Lang.Compiler/TypeSystem/TypeSystemServices.cs (revision 2352) +++ src/Boo.Lang.Compiler/TypeSystem/TypeSystemServices.cs (working copy) @@ -1,1492 +1,1490 @@ -#region license -// Copyright (c) 2004, 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 - -namespace Boo.Lang.Compiler.TypeSystem -{ - using System; - using System.Collections; - using System.Reflection; - using System.Text; - using Boo.Lang.Compiler.Ast; - using Attribute = Boo.Lang.Compiler.Ast.Attribute; - using Module = Boo.Lang.Compiler.Ast.Module; - - public class TypeSystemServices - { - public DuckTypeImpl DuckType; - - public ExternalType IQuackFuType; - - public ExternalType ExceptionType; - - public ExternalType ApplicationExceptionType; - - public ExternalType MulticastDelegateType; - - public ExternalType DelegateType; - - public ExternalType IntPtrType; - - public ExternalType UIntPtrType; - - public ExternalType ObjectType; - - public ExternalType ValueTypeType; - - public ExternalType EnumType; - - public ExternalType RegexType; - - public ExternalType ArrayType; - - public ExternalType TypeType; - - public IArrayType ObjectArrayType; - - public ExternalType VoidType; - - public ExternalType StringType; - - public ExternalType BoolType; - - public ExternalType CharType; - - public ExternalType SByteType; - - public ExternalType ByteType; - - public ExternalType ShortType; - - public ExternalType UShortType; - - public ExternalType IntType; - - public ExternalType UIntType; - - public ExternalType LongType; - - public ExternalType ULongType; - - public ExternalType SingleType; - - public ExternalType DoubleType; - - public ExternalType DecimalType; - - public ExternalType TimeSpanType; - - public ExternalType DateTimeType; - - public ExternalType RuntimeServicesType; - - public ExternalType BuiltinsType; - - public ExternalType ListType; - - public ExternalType HashType; - - public ExternalType ICallableType; - - public ExternalType IEnumerableType; - - public ExternalType IEnumeratorType; - - public ExternalType ICollectionType; - - public ExternalType IListType; - - public ExternalType IDictionaryType; - - public ExternalType SystemAttribute; - - protected Hashtable _primitives = new Hashtable(); - - protected Hashtable _entityCache = new Hashtable(); - - protected Hashtable _arrayCache = new Hashtable(); - - protected Hashtable _anonymousCallableTypes = new Hashtable(); - - public static readonly IType ErrorEntity = Error.Default; - - public readonly BooCodeBuilder CodeBuilder; - - StringBuilder _buffer = new StringBuilder(); - - Module _compilerGeneratedTypesModule; - - Module _compilerGeneratedExtensionsModule; - - ClassDefinition _compilerGeneratedExtensionsClass; - - CompilerContext _context; - - public TypeSystemServices() : this(new CompilerContext()) - { - } - - public TypeSystemServices(CompilerContext context) - { - if (null == context) - { - throw new ArgumentNullException("context"); - } - - _context = context; - - CodeBuilder = new BooCodeBuilder(this); - - Cache(typeof(Builtins.duck), DuckType = new DuckTypeImpl(this)); - Cache(IQuackFuType = new ExternalType(this, typeof(IQuackFu))); - Cache(VoidType = new VoidTypeImpl(this)); - Cache(ObjectType = new ExternalType(this, Types.Object)); - Cache(RegexType = new ExternalType(this, Types.Regex)); - Cache(ValueTypeType = new ExternalType(this, typeof(ValueType))); - Cache(EnumType = new ExternalType(this, typeof(Enum))); - Cache(ArrayType = new ExternalType(this, Types.Array)); - Cache(TypeType = new ExternalType(this, Types.Type)); - Cache(StringType = new ExternalType(this, Types.String)); - Cache(BoolType = new ExternalType(this, Types.Bool)); - Cache(SByteType = new ExternalType(this, Types.SByte)); - Cache(CharType = new ExternalType(this, Types.Char)); - Cache(ShortType = new ExternalType(this, Types.Short)); - Cache(IntType = new ExternalType(this, Types.Int)); - Cache(LongType = new ExternalType(this, Types.Long)); - Cache(ByteType = new ExternalType(this, Types.Byte)); - Cache(UShortType = new ExternalType(this, Types.UShort)); - Cache(UIntType = new ExternalType(this, Types.UInt)); - Cache(ULongType = new ExternalType(this, Types.ULong)); - Cache(SingleType = new ExternalType(this, Types.Single)); - Cache(DoubleType = new ExternalType(this, Types.Double)); - Cache(DecimalType = new ExternalType(this, Types.Decimal)); - Cache(TimeSpanType = new ExternalType(this, Types.TimeSpan)); - Cache(DateTimeType = new ExternalType(this, Types.DateTime)); - Cache(RuntimeServicesType = new ExternalType(this, Types.RuntimeServices)); - Cache(BuiltinsType = new ExternalType(this, Types.Builtins)); - Cache(ListType = new ExternalType(this, Types.List)); - Cache(HashType = new ExternalType(this, Types.Hash)); - Cache(ICallableType = new ExternalType(this, Types.ICallable)); - Cache(IEnumerableType = new ExternalType(this, Types.IEnumerable)); - Cache(IEnumeratorType = new ExternalType(this, typeof(IEnumerator))); - Cache(ICollectionType = new ExternalType(this, Types.ICollection)); - Cache(IListType = new ExternalType(this, Types.IList)); - Cache(IDictionaryType = new ExternalType(this, Types.IDictionary)); - Cache(ApplicationExceptionType = new ExternalType(this, Types.ApplicationException)); - Cache(ExceptionType = new ExternalType(this, Types.Exception)); - Cache(IntPtrType = new ExternalType(this, Types.IntPtr)); - Cache(UIntPtrType = new ExternalType(this, Types.UIntPtr)); - Cache(MulticastDelegateType = new ExternalType(this, Types.MulticastDelegate)); - Cache(DelegateType = new ExternalType(this, Types.Delegate)); - Cache(SystemAttribute = new ExternalType(this, typeof(System.Attribute))); - - ObjectArrayType = GetArrayType(ObjectType, 1); - - PreparePrimitives(); - PrepareBuiltinFunctions(); - } - - public CompilerContext Context - { - get - { - return _context; - } - } - - public IType GetMostGenericType(IType current, IType candidate) - { - if (current.IsAssignableFrom(candidate)) - { - return current; - } - - if (candidate.IsAssignableFrom(current)) - { - return candidate; - } - - if (IsNumberOrBool(current) && IsNumberOrBool(candidate)) - { - return GetPromotedNumberType(current, candidate); - } - - if (IsCallableType(current) && IsCallableType(candidate)) - { - return ICallableType; - } - - if (current.IsClass && candidate.IsClass) - { - if (current == ObjectType || candidate == ObjectType) - { - return ObjectType; - } - if (current.GetTypeDepth() < candidate.GetTypeDepth()) - { - return GetMostGenericType(current.BaseType, candidate); - } - return GetMostGenericType(current, candidate.BaseType); - } - return ObjectType; - } - - public IType GetPromotedNumberType(IType left, IType right) - { - if (left == DecimalType || - right == DecimalType) - { - return DecimalType; - } - if (left == DoubleType || - right == DoubleType) - { - return DoubleType; - } - if (left == SingleType || - right == SingleType) - { - return SingleType; - } - if (left == ULongType) - { - if (right == SByteType || - right == ShortType || - right == IntType || - right == LongType) - { - // This is against the C# spec but allows expressions like: - // ulong x = 4 - // y = x + 1 - // y will be long. - // C# disallows mixing ulongs and signed numbers - // but in the above case it promotes the constant to ulong - // and the result is ulong. - // Since its too late here to promote the constant, - // maybe we should return LongType. I didn't chose ULongType - // because in other cases returns . - return LongType; - } - return ULongType; - } - if (right == ULongType) - { - if (left == SByteType || - left == ShortType || - left == IntType || - left == LongType) - { - // This is against the C# spec but allows expressions like: - // ulong x = 4 - // y = 1 + x - // y will be long. - // C# disallows mixing ulongs and signed numbers - // but in the above case it promotes the constant to ulong - // and the result is ulong. - // Since its too late here to promote the constant, - // maybe we should return LongType. I didn't chose ULongType - // because in other cases returns . - return LongType; - } - return ULongType; - } - if (left == LongType || - right == LongType) - { - return LongType; - } - if (left == UIntType) - { - if (right == SByteType || - right == ShortType || - right == IntType) - { - // This is allowed per C# spec and y is long: - // uint x = 4 - // y = x + 1 - // C# promotes to also - // but in the above case it promotes the constant to uint first - // and the result of "x + 1" is uint. - // Since its too late here to promote the constant, - // "y = x + 1" will be long in boo. - return LongType; - } - return UIntType; - } - if (right == UIntType) - { - if (left == SByteType || - left == ShortType || - left == IntType) - { - // This is allowed per C# spec and y is long: - // uint x = 4 - // y = 1 + x - // C# promotes to also - // but in the above case it promotes the constant to uint first - // and the result of "1 + x" is uint. - // Since its too late here to promote the constant, - // "y = x + 1" will be long in boo. - return LongType; - } - return UIntType; - } - if (left == IntType || - right == IntType || - left == ShortType || - right == ShortType || - left == UShortType || - right == UShortType || - left == ByteType || - right == ByteType || - left == SByteType || - right == SByteType) - { - return IntType; - } - return left; - } - - public static bool IsReadOnlyField(IField field) - { - return field.IsInitOnly || field.IsLiteral; - } - - public bool IsCallable(IType type) - { - return (TypeType == type) || IsCallableType(type) || IsDuckType(type); - } - - public bool IsDuckTyped(Expression expression) - { - IType type = expression.ExpressionType; - return null != type && this.IsDuckType(type); - } - - public bool IsQuackBuiltin(Expression node) - { - return IsQuackBuiltin(GetOptionalEntity(node)); - } - - public bool IsQuackBuiltin(IEntity entity) - { - return BuiltinFunction.Quack == entity; - } - - public bool IsDuckType(IType type) - { - if (null == type) - { - throw new ArgumentNullException("type"); - } - return ( - (type == DuckType) - || KnowsQuackFu(type) - || (_context.Parameters.Ducky - && (type == ObjectType))); +#region license +// Copyright (c) 2004, 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 + +namespace Boo.Lang.Compiler.TypeSystem +{ + using System; + using System.Collections; + using System.Reflection; + using System.Text; + using Boo.Lang.Compiler.Ast; + using Attribute = Boo.Lang.Compiler.Ast.Attribute; + using Module = Boo.Lang.Compiler.Ast.Module; + + public class TypeSystemServices + { + public DuckTypeImpl DuckType; + + public ExternalType IQuackFuType; + + public ExternalType ExceptionType; + + public ExternalType ApplicationExceptionType; + + public ExternalType MulticastDelegateType; + + public ExternalType DelegateType; + + public ExternalType IntPtrType; + + public ExternalType UIntPtrType; + + public ExternalType ObjectType; + + public ExternalType ValueTypeType; + + public ExternalType EnumType; + + public ExternalType RegexType; + + public ExternalType ArrayType; + + public ExternalType TypeType; + + public IArrayType ObjectArrayType; + + public ExternalType VoidType; + + public ExternalType StringType; + + public ExternalType BoolType; + + public ExternalType CharType; + + public ExternalType SByteType; + + public ExternalType ByteType; + + public ExternalType ShortType; + + public ExternalType UShortType; + + public ExternalType IntType; + + public ExternalType UIntType; + + public ExternalType LongType; + + public ExternalType ULongType; + + public ExternalType SingleType; + + public ExternalType DoubleType; + + public ExternalType DecimalType; + + public ExternalType TimeSpanType; + + public ExternalType DateTimeType; + + public ExternalType RuntimeServicesType; + + public ExternalType BuiltinsType; + + public ExternalType ListType; + + public ExternalType HashType; + + public ExternalType ICallableType; + + public ExternalType IEnumerableType; + + public ExternalType IEnumeratorType; + + public ExternalType ICollectionType; + + public ExternalType IListType; + + public ExternalType IDictionaryType; + + public ExternalType SystemAttribute; + + protected Hashtable _primitives = new Hashtable(); + + protected Hashtable _entityCache = new Hashtable(); + + protected Hashtable _arrayCache = new Hashtable(); + + protected Hashtable _anonymousCallableTypes = new Hashtable(); + + public static readonly IType ErrorEntity = Error.Default; + + public readonly BooCodeBuilder CodeBuilder; + + StringBuilder _buffer = new StringBuilder(); + + Module _compilerGeneratedTypesModule; + + Module _compilerGeneratedExtensionsModule; + + ClassDefinition _compilerGeneratedExtensionsClass; + + CompilerContext _context; + + public TypeSystemServices() : this(new CompilerContext()) + { } + + public TypeSystemServices(CompilerContext context) + { + if (null == context) + { + throw new ArgumentNullException("context"); + } + + _context = context; + CodeBuilder = new BooCodeBuilder(this); + + Cache(typeof(Builtins.duck), DuckType = new DuckTypeImpl(this)); + Cache(IQuackFuType = new ExternalType(this, typeof(IQuackFu))); + Cache(VoidType = new VoidTypeImpl(this)); + Cache(ObjectType = new ExternalType(this, Types.Object)); + Cache(RegexType = new ExternalType(this, Types.Regex)); + Cache(ValueTypeType = new ExternalType(this, typeof(ValueType))); + Cache(EnumType = new ExternalType(this, typeof(Enum))); + Cache(ArrayType = new ExternalType(this, Types.Array)); + Cache(TypeType = new ExternalType(this, Types.Type)); + Cache(StringType = new ExternalType(this, Types.String)); + Cache(BoolType = new ExternalType(this, Types.Bool)); + Cache(SByteType = new ExternalType(this, Types.SByte)); + Cache(CharType = new ExternalType(this, Types.Char)); + Cache(ShortType = new ExternalType(this, Types.Short)); + Cache(IntType = new ExternalType(this, Types.Int)); + Cache(LongType = new ExternalType(this, Types.Long)); + Cache(ByteType = new ExternalType(this, Types.Byte)); + Cache(UShortType = new ExternalType(this, Types.UShort)); + Cache(UIntType = new ExternalType(this, Types.UInt)); + Cache(ULongType = new ExternalType(this, Types.ULong)); + Cache(SingleType = new ExternalType(this, Types.Single)); + Cache(DoubleType = new ExternalType(this, Types.Double)); + Cache(DecimalType = new ExternalType(this, Types.Decimal)); + Cache(TimeSpanType = new ExternalType(this, Types.TimeSpan)); + Cache(DateTimeType = new ExternalType(this, Types.DateTime)); + Cache(RuntimeServicesType = new ExternalType(this, Types.RuntimeServices)); + Cache(BuiltinsType = new ExternalType(this, Types.Builtins)); + Cache(ListType = new ExternalType(this, Types.List)); + Cache(HashType = new ExternalType(this, Types.Hash)); + Cache(ICallableType = new ExternalType(this, Types.ICallable)); + Cache(IEnumerableType = new ExternalType(this, Types.IEnumerable)); + Cache(IEnumeratorType = new ExternalType(this, typeof(IEnumerator))); + Cache(ICollectionType = new ExternalType(this, Types.ICollection)); + Cache(IListType = new ExternalType(this, Types.IList)); + Cache(IDictionaryType = new ExternalType(this, Types.IDictionary)); + Cache(ApplicationExceptionType = new ExternalType(this, Types.ApplicationException)); + Cache(ExceptionType = new ExternalType(this, Types.Exception)); + Cache(IntPtrType = new ExternalType(this, Types.IntPtr)); + Cache(UIntPtrType = new ExternalType(this, Types.UIntPtr)); + Cache(MulticastDelegateType = new ExternalType(this, Types.MulticastDelegate)); + Cache(DelegateType = new ExternalType(this, Types.Delegate)); + Cache(SystemAttribute = new ExternalType(this, typeof(System.Attribute))); + + ObjectArrayType = GetArrayType(ObjectType, 1); + + PreparePrimitives(); + PrepareBuiltinFunctions(); + } + + public CompilerContext Context + { + get + { + return _context; + } + } + + public IType GetMostGenericType(IType current, IType candidate) + { + if (current.IsAssignableFrom(candidate)) + { + return current; + } + + if (candidate.IsAssignableFrom(current)) + { + return candidate; + } + + if (IsNumberOrBool(current) && IsNumberOrBool(candidate)) + { + return GetPromotedNumberType(current, candidate); + } + + if (IsCallableType(current) && IsCallableType(candidate)) + { + return ICallableType; + } + + if (current.IsClass && candidate.IsClass) + { + if (current == ObjectType || candidate == ObjectType) + { + return ObjectType; + } + if (current.GetTypeDepth() < candidate.GetTypeDepth()) + { + return GetMostGenericType(current.BaseType, candidate); + } + return GetMostGenericType(current, candidate.BaseType); + } + return ObjectType; + } + + public IType GetPromotedNumberType(IType left, IType right) + { + if (left == DecimalType || + right == DecimalType) + { + return DecimalType; + } + if (left == DoubleType || + right == DoubleType) + { + return DoubleType; + } + if (left == SingleType || + right == SingleType) + { + return SingleType; + } + if (left == ULongType) + { + if (right == SByteType || + right == ShortType || + right == IntType || + right == LongType) + { + // This is against the C# spec but allows expressions like: + // ulong x = 4 + // y = x + 1 + // y will be long. + // C# disallows mixing ulongs and signed numbers + // but in the above case it promotes the constant to ulong + // and the result is ulong. + // Since its too late here to promote the constant, + // maybe we should return LongType. I didn't chose ULongType + // because in other cases returns . + return LongType; + } + return ULongType; + } + if (right == ULongType) + { + if (left == SByteType || + left == ShortType || + left == IntType || + left == LongType) + { + // This is against the C# spec but allows expressions like: + // ulong x = 4 + // y = 1 + x + // y will be long. + // C# disallows mixing ulongs and signed numbers + // but in the above case it promotes the constant to ulong + // and the result is ulong. + // Since its too late here to promote the constant, + // maybe we should return LongType. I didn't chose ULongType + // because in other cases returns . + return LongType; + } + return ULongType; + } + if (left == LongType || + right == LongType) + { + return LongType; + } + if (left == UIntType) + { + if (right == SByteType || + right == ShortType || + right == IntType) + { + // This is allowed per C# spec and y is long: + // uint x = 4 + // y = x + 1 + // C# promotes to also + // but in the above case it promotes the constant to uint first + // and the result of "x + 1" is uint. + // Since its too late here to promote the constant, + // "y = x + 1" will be long in boo. + return LongType; + } + return UIntType; + } + if (right == UIntType) + { + if (left == SByteType || + left == ShortType || + left == IntType) + { + // This is allowed per C# spec and y is long: + // uint x = 4 + // y = 1 + x + // C# promotes to also + // but in the above case it promotes the constant to uint first + // and the result of "1 + x" is uint. + // Since its too late here to promote the constant, + // "y = x + 1" will be long in boo. + return LongType; + } + return UIntType; + } + if (left == IntType || + right == IntType || + left == ShortType || + right == ShortType || + left == UShortType || + right == UShortType || + left == ByteType || + right == ByteType || + left == SByteType || + right == SByteType) + { + return IntType; + } + return left; + } + + public static bool IsReadOnlyField(IField field) + { + return field.IsInitOnly || field.IsLiteral; + } + + public bool IsCallable(IType type) + { + return (TypeType == type) || IsCallableType(type) || IsDuckType(type); + } + + public bool IsDuckTyped(Expression expression) + { + IType type = expression.ExpressionType; + return null != type && this.IsDuckType(type); + } + + public bool IsQuackBuiltin(Expression node) + { + return IsQuackBuiltin(GetOptionalEntity(node)); + } + + public bool IsQuackBuiltin(IEntity entity) + { + return BuiltinFunction.Quack == entity; + } + + public bool IsDuckType(IType type) + { + if (null == type) + { + throw new ArgumentNullException("type"); + } + return ( + (type == DuckType) + || KnowsQuackFu(type) + || (_context.Parameters.Ducky + && (type == ObjectType))); + } + public bool KnowsQuackFu(IType type) { return type.IsSubclassOf(IQuackFuType); - } - - bool IsCallableType(IType type) - { - return (ICallableType.IsAssignableFrom(type)) || - (type is ICallableType); - } - - public AnonymousCallableType GetCallableType(IMethod method) - { - CallableSignature signature = new CallableSignature(method); - return GetCallableType(signature); - } - - public AnonymousCallableType GetCallableType(CallableSignature signature) - { - AnonymousCallableType type = (AnonymousCallableType)_anonymousCallableTypes[signature]; - if (null == type) - { - type = new AnonymousCallableType(this, signature); - _anonymousCallableTypes.Add(signature, type); - } - return type; - } - - public IType GetConcreteCallableType(Node sourceNode, CallableSignature signature) - { - AnonymousCallableType type = GetCallableType(signature); - return GetConcreteCallableType(sourceNode, type); - } - - public IType GetEnumeratorItemType(IType iteratorType) - { - if (iteratorType.IsArray) return ((IArrayType)iteratorType).GetElementType(); - if (StringType == iteratorType) return CharType; - - if (iteratorType.IsClass) - { - IType enumeratorItemType = GetEnumeratorItemTypeFromAttribute(iteratorType); - if (null != enumeratorItemType) - { - return enumeratorItemType; - } - -#if NET_2_0 - enumeratorItemType = GetEnumeratorItemTypeFromGenericEnumerable(iteratorType); - if (null != enumeratorItemType) - { - return enumeratorItemType; - } -#endif - } - return ObjectType; - } - - public IType GetExpressionType(Expression node) - { - IType type = node.ExpressionType; - if (null == type) - { - throw CompilerErrorFactory.InvalidNode(node); - } - return type; - } - - public IType GetConcreteExpressionType(Expression expression) - { - IType type = GetExpressionType(expression); - AnonymousCallableType anonymousType = type as AnonymousCallableType; - if (null != anonymousType) - { - IType concreteType = GetConcreteCallableType(expression, anonymousType); - expression.ExpressionType = concreteType; - return concreteType; - } - return type; - } - - public void MapToConcreteExpressionTypes(ExpressionCollection items) - { - foreach (Expression item in items) - { - GetConcreteExpressionType(item); - } - } - - public ClassDefinition GetCompilerGeneratedExtensionsClass() - { - if (null == _compilerGeneratedExtensionsClass) - { - BooClassBuilder builder = CodeBuilder.CreateClass("CompilerGeneratedExtensions"); - builder.Modifiers = TypeMemberModifiers.Final|TypeMemberModifiers.Transient|TypeMemberModifiers.Public; - builder.AddBaseType(ObjectType); - - BooMethodBuilder ctor = builder.AddConstructor(); - ctor.Modifiers = TypeMemberModifiers.Private; - ctor.Body.Add( - CodeBuilder.CreateSuperConstructorInvocation(ObjectType)); - - ClassDefinition cd = builder.ClassDefinition; - Module module = GetCompilerGeneratedExtensionsModule(); - module.Members.Add(cd); - ((ModuleEntity)module.Entity).InitializeModuleClass(cd); - - _compilerGeneratedExtensionsClass = cd; - } - return _compilerGeneratedExtensionsClass; - } - - public Module GetCompilerGeneratedExtensionsModule() - { - if (null == _compilerGeneratedExtensionsModule) - { - _compilerGeneratedExtensionsModule = NewModule(null); - } - return _compilerGeneratedExtensionsModule; - } - - public void AddCompilerGeneratedType(TypeDefinition type) - { - GetCompilerGeneratedTypesModule().Members.Add(type); - } - - public Module GetCompilerGeneratedTypesModule() - { - if (null == _compilerGeneratedTypesModule) - { - _compilerGeneratedTypesModule = NewModule("CompilerGenerated"); - } - return _compilerGeneratedTypesModule; - } - - private Module NewModule(string ns) - { - Module module = new Module(); - if (null != ns) module.Namespace = new NamespaceDeclaration(ns); - module.Entity = new ModuleEntity(_context.NameResolutionService, this, module); - _context.CompileUnit.Modules.Add(module); - return module; - } - - public ClassDefinition CreateCallableDefinition(string name) - { - ClassDefinition cd = new ClassDefinition(); - cd.BaseTypes.Add(CodeBuilder.CreateTypeReference(this.MulticastDelegateType)); - cd.BaseTypes.Add(CodeBuilder.CreateTypeReference(this.ICallableType)); - cd.Name = name; - cd.Modifiers = TypeMemberModifiers.Final; - cd.Members.Add(CreateCallableConstructor()); - cd.Members.Add(CreateCallMethod()); - cd.Entity = new InternalCallableType(this, cd); - return cd; - } - - Method CreateCallMethod() - { - Method method = new Method("Call"); - method.Modifiers = TypeMemberModifiers.Public|TypeMemberModifiers.Virtual; - method.Parameters.Add(CodeBuilder.CreateParameterDeclaration(1, "args", ObjectArrayType)); - method.ReturnType = CodeBuilder.CreateTypeReference(ObjectType); - method.Entity = new InternalMethod(this, method); - return method; - } - - Constructor CreateCallableConstructor() - { - Constructor constructor = new Constructor(); - constructor.Modifiers = TypeMemberModifiers.Public; - constructor.ImplementationFlags = MethodImplementationFlags.Runtime; - constructor.Parameters.Add( - CodeBuilder.CreateParameterDeclaration(1, "instance", ObjectType)); - constructor.Parameters.Add( - CodeBuilder.CreateParameterDeclaration(2, "method", IntPtrType)); - constructor.Entity = new InternalConstructor(this, constructor); - return constructor; - } - - public bool AreTypesRelated(IType lhs, IType rhs) - { - ICallableType ctype = lhs as ICallableType; - if (null != ctype) - { - return ctype.IsAssignableFrom(rhs) - || ctype.IsSubclassOf(rhs); - } - return lhs.IsAssignableFrom(rhs) - || (lhs.IsInterface && !rhs.IsFinal) - || (rhs.IsInterface && !lhs.IsFinal) - || CanBeReachedByDownCastOrPromotion(lhs, rhs) - || FindImplicitConversionOperator(rhs,lhs) != null; - } - - public IMethod FindExplicitConversionOperator(IType fromType, IType toType) - { - return FindConversionOperator("op_Explicit", fromType, toType); - } - - public IMethod FindImplicitConversionOperator(IType fromType, IType toType) - { - return FindConversionOperator("op_Implicit", fromType, toType); - } - - public IMethod FindConversionOperator(string name, IType fromType, IType toType) - { - while (fromType != this.ObjectType) - { - IMethod method = FindConversionOperator(name, fromType, toType, fromType.GetMembers()); - if (null != method) return method; - method = FindConversionOperator(name, fromType, toType, toType.GetMembers()); - if (null != method) return method; - method = FindConversionOperator(name, fromType, toType, FindExtension(fromType, name)); - if (null != method) return method; - - fromType = fromType.BaseType; - if (null == fromType) break; - } - return null; - } - - private IEntity[] FindExtension(IType fromType, string name) - { - IEntity extension = _context.NameResolutionService.ResolveExtension(fromType, name); - if (null == extension) return Ambiguous.NoEntities; - - Ambiguous a = extension as Ambiguous; - if (null != a) return a.Entities; - return new IEntity[] { extension }; - } - - IMethod FindConversionOperator(string name, IType fromType, IType toType, IEntity[] candidates) - { - foreach (IEntity entity in candidates) - { - if (EntityType.Method != entity.EntityType || name != entity.Name) continue; - IMethod method = (IMethod)entity; - if (IsConversionOperator(method, fromType, toType)) return method; - } - return null; - } - - bool IsConversionOperator(IMethod method, IType fromType, IType toType) - { - if (!method.IsStatic) return false; - if (method.ReturnType != toType) return false; - IParameter[] parameters = method.GetParameters(); - return (1 == parameters.Length && fromType == parameters[0].Type); - } - - public bool IsCallableTypeAssignableFrom(ICallableType lhs, IType rhs) - { - if (lhs == rhs || Null.Default == rhs) - { - return true; - } - - ICallableType other = rhs as ICallableType; - if (null != other) - { - CallableSignature lvalue = lhs.GetSignature(); - CallableSignature rvalue = other.GetSignature(); - if (lvalue == rvalue) - { - return true; - } - - IParameter[] lparams = lvalue.Parameters; - IParameter[] rparams = rvalue.Parameters; - if (lparams.Length >= rparams.Length) - { - for (int i=0; i 1) - { - IEntity[] tags = new IEntity[info.Length]; - for (int i=0; i 0) - { - return Map(info[0]); - } - return null; - } - - public IEntity Map(MemberInfo mi) - { - IEntity tag = (IEntity)_entityCache[GetCacheKey(mi)]; - if (null == tag) - { - switch (mi.MemberType) - { - case MemberTypes.Method: - { - return Map((MethodInfo)mi); - } - - case MemberTypes.Constructor: - { - return Map((ConstructorInfo)mi); - } - - case MemberTypes.Field: - { - tag = new ExternalField(this, (FieldInfo)mi); - break; - } - - case MemberTypes.Property: - { - tag = new ExternalProperty(this, (PropertyInfo)mi); - break; - } - - case MemberTypes.Event: - { - tag = new ExternalEvent(this, (EventInfo)mi); - break; - } - - case MemberTypes.NestedType: - { - return Map((Type)mi); - } - - default: - { - throw new NotImplementedException(mi.ToString()); - } - } - _entityCache.Add(GetCacheKey(mi), tag); - } - return tag; - } - - public string GetSignature(IEntityWithParameters method) - { - return GetSignature(method, true); - } - - public string GetSignature(IEntityWithParameters method, bool includeFullName) - { - _buffer.Length = 0; - if (includeFullName) - { - _buffer.Append(method.FullName); - } - else - { - _buffer.Append(method.Name); - } - _buffer.Append("("); - - IParameter[] parameters = method.GetParameters(); - for (int i=0; i 0) { _buffer.Append(", "); } - if (method.AcceptVarArgs && i == parameters.Length-1) { _buffer.Append('*'); } - _buffer.Append(parameters[i].Type); - } - _buffer.Append(")"); - return _buffer.ToString(); - } - - public object GetCacheKey(MemberInfo mi) - { - return mi; - } - - public IEntity ResolvePrimitive(string name) - { - return (IEntity)_primitives[name]; - } - - public bool IsPrimitive(string name) - { - return _primitives.ContainsKey(name); - } - - /// - /// checks if the passed type will be equivalente to - /// System.Object in runtime (accounting for the presence - /// of duck typing). - /// - public bool IsSystemObject(IType type) - { - return type == ObjectType || type == DuckType; - } - - protected virtual void PreparePrimitives() - { - AddPrimitiveType("duck", DuckType); - AddPrimitiveType("void", VoidType); - AddPrimitiveType("bool", BoolType); - AddPrimitiveType("char", CharType); - AddPrimitiveType("date", DateTimeType); - AddPrimitiveType("timespan", TimeSpanType); - AddPrimitiveType("string", StringType); - AddPrimitiveType("object", ObjectType); - AddPrimitiveType("regex", RegexType); - AddPrimitiveType("sbyte", SByteType); - AddPrimitiveType("byte", ByteType); - AddPrimitiveType("short", ShortType); - AddPrimitiveType("ushort", UShortType); - AddPrimitiveType("int", IntType); - AddPrimitiveType("uint", UIntType); - AddPrimitiveType("long", LongType); - AddPrimitiveType("ulong", ULongType); - AddPrimitiveType("single", SingleType); - AddPrimitiveType("double", DoubleType); - AddPrimitiveType("decimal", DecimalType); - AddPrimitiveType("callable", ICallableType); - } - - protected virtual void PrepareBuiltinFunctions() - { - AddBuiltin(BuiltinFunction.Len); - AddBuiltin(BuiltinFunction.AddressOf); - AddBuiltin(BuiltinFunction.Eval); - AddBuiltin(BuiltinFunction.Switch); - } - - protected void AddPrimitiveType(string name, ExternalType type) - { - _primitives[name] = type; - type.PrimitiveName = name; - } - - protected void AddBuiltin(BuiltinFunction function) - { - _primitives[function.Name] = function; - } - - void Cache(ExternalType tag) - { - _entityCache[tag.ActualType] = tag; - } - - void Cache(object key, IType tag) - { - _entityCache[key] = tag; - } - - Method CreateBeginInvokeMethod(ICallableType anonymousType) - { - Method method = CodeBuilder.CreateRuntimeMethod("BeginInvoke", Map(typeof(IAsyncResult)), - anonymousType.GetSignature().Parameters, false); - - int delta=method.Parameters.Count; - method.Parameters.Add( - CodeBuilder.CreateParameterDeclaration(delta+1, "callback", Map(typeof(AsyncCallback)))); - method.Parameters.Add( - CodeBuilder.CreateParameterDeclaration(delta+1, "asyncState", ObjectType)); - return method; - } - - Method CreateBeginInvokeExtension(ICallableType anonymousType, Method beginInvoke, out MethodInvocationExpression mie) - { - InternalMethod beginInvokeEntity = (InternalMethod)beginInvoke.Entity; - - Method extension = CodeBuilder.CreateMethod("BeginInvoke", Map(typeof(IAsyncResult)), - TypeMemberModifiers.Public|TypeMemberModifiers.Static); - extension.Attributes.Add(CodeBuilder.CreateAttribute(Types.ExtensionAttribute)); - - ParameterDeclaration self = CodeBuilder.CreateParameterDeclaration(0, "self", beginInvokeEntity.DeclaringType); - - extension.Parameters.Add(self); - CodeBuilder.DeclareParameters(extension, 1, anonymousType.GetSignature().Parameters); - - mie = CodeBuilder.CreateMethodInvocation( - CodeBuilder.CreateReference(self), - beginInvokeEntity); - - ParameterDeclarationCollection parameters = extension.Parameters; - for (int i=1; i)); - - IType itemType = null; - foreach (IGenericType type in FindConstructedTypes(iteratorType, genericEnumerable)) - { - IType candidateItemType = type.GetGenericArguments()[0]; - _context.TraceVerbose("Candidate enumerable item type for {0}: {1}", - iteratorType, candidateItemType); - - if (itemType != null) - { - itemType = GetMostGenericType(itemType, candidateItemType); - } - else - { - itemType = candidateItemType; - } - } - - return itemType; - } - - System.Collections.Generic.IEnumerable FindConstructedTypes(IType type, IGenericTypeDefinition genericTypeDef) - { - while (type != null) - { - string typeName = (type is ExternalType ? ((ExternalType)type).ActualType.Name : type.Name); - - IGenericType genericType = type as IGenericType; - - if (genericType != null && - genericType.FullyConstructed && - genericType.GetGenericTypeDefinition() == genericTypeDef) - { - yield return genericType; - } - - foreach (IType interfaceType in type.GetInterfaces()) - { - foreach (IGenericType match in FindConstructedTypes(interfaceType, genericTypeDef)) - { - yield return match; - } - } - - type = type.BaseType; - } - } -#endif - - public virtual IType GetConcreteCallableType(Node sourceNode, AnonymousCallableType anonymousType) - { - if (null == anonymousType.ConcreteType) - { - anonymousType.ConcreteType = CreateConcreteCallableType(sourceNode, anonymousType); - } - return anonymousType.ConcreteType; - } - - protected virtual IType CreateConcreteCallableType(Node sourceNode, AnonymousCallableType anonymousType) - { - Module module = GetCompilerGeneratedTypesModule(); - - string name = string.Format("___callable{0}", module.Members.Count); - ClassDefinition cd = CreateCallableDefinition(name); - cd.Modifiers |= TypeMemberModifiers.Public; - cd.LexicalInfo = sourceNode.LexicalInfo; - - cd.Members.Add(CreateInvokeMethod(anonymousType)); - - Method beginInvoke = CreateBeginInvokeMethod(anonymousType); - cd.Members.Add(beginInvoke); - - cd.Members.Add(CreateEndInvokeMethod(anonymousType)); - _compilerGeneratedTypesModule.Members.Add(cd); - - CreateCallableTypeBeginInvokeExtensions(anonymousType, beginInvoke); - - return (IType)cd.Entity; - } - - private void CreateCallableTypeBeginInvokeExtensions(AnonymousCallableType anonymousType, Method beginInvoke) - { - ClassDefinition extensions = GetCompilerGeneratedExtensionsClass(); - extensions.Members.Add(CreateBeginInvokeCallbackOnlyExtension(anonymousType, beginInvoke)); - extensions.Members.Add(CreateBeginInvokeSimplerExtension(anonymousType, beginInvoke)); - } - - private static void InvalidNode(Node node) - { - throw CompilerErrorFactory.InvalidNode(node); - } - - public class DuckTypeImpl : ExternalType - { - public DuckTypeImpl(TypeSystemServices typeSystemServices) : - base(typeSystemServices, Types.Object) - { - } - } - - #region VoidTypeImpl - class VoidTypeImpl : ExternalType - { - internal VoidTypeImpl(TypeSystemServices typeSystemServices) : base(typeSystemServices, Types.Void) - { - } - - override public bool Resolve(List targetList, string name, EntityType flags) - { - return false; - } - - override public bool IsSubclassOf(IType other) - { - return false; - } - - override public bool IsAssignableFrom(IType other) - { - return false; - } - } - - #endregion - } -} + } + + bool IsCallableType(IType type) + { + return (ICallableType.IsAssignableFrom(type)) || + (type is ICallableType); + } + + public AnonymousCallableType GetCallableType(IMethod method) + { + CallableSignature signature = new CallableSignature(method); + return GetCallableType(signature); + } + + public AnonymousCallableType GetCallableType(CallableSignature signature) + { + AnonymousCallableType type = (AnonymousCallableType)_anonymousCallableTypes[signature]; + if (null == type) + { + type = new AnonymousCallableType(this, signature); + _anonymousCallableTypes.Add(signature, type); + } + return type; + } + + public IType GetConcreteCallableType(Node sourceNode, CallableSignature signature) + { + AnonymousCallableType type = GetCallableType(signature); + return GetConcreteCallableType(sourceNode, type); + } + + public IType GetEnumeratorItemType(IType iteratorType) + { + if (iteratorType.IsArray) return ((IArrayType)iteratorType).GetElementType(); + if (StringType == iteratorType) return CharType; + + if (iteratorType.IsClass) + { + IType enumeratorItemType = GetEnumeratorItemTypeFromAttribute(iteratorType); + if (null != enumeratorItemType) + { + return enumeratorItemType; + } + } +#if NET_2_0 + IType genericItemType = GetEnumeratorItemTypeFromGenericEnumerable(iteratorType); + if (null != genericItemType) + { + return genericItemType; + } +#endif + return ObjectType; + } + + public IType GetExpressionType(Expression node) + { + IType type = node.ExpressionType; + if (null == type) + { + throw CompilerErrorFactory.InvalidNode(node); + } + return type; + } + + public IType GetConcreteExpressionType(Expression expression) + { + IType type = GetExpressionType(expression); + AnonymousCallableType anonymousType = type as AnonymousCallableType; + if (null != anonymousType) + { + IType concreteType = GetConcreteCallableType(expression, anonymousType); + expression.ExpressionType = concreteType; + return concreteType; + } + return type; + } + + public void MapToConcreteExpressionTypes(ExpressionCollection items) + { + foreach (Expression item in items) + { + GetConcreteExpressionType(item); + } + } + + public ClassDefinition GetCompilerGeneratedExtensionsClass() + { + if (null == _compilerGeneratedExtensionsClass) + { + BooClassBuilder builder = CodeBuilder.CreateClass("CompilerGeneratedExtensions"); + builder.Modifiers = TypeMemberModifiers.Final|TypeMemberModifiers.Transient|TypeMemberModifiers.Public; + builder.AddBaseType(ObjectType); + + BooMethodBuilder ctor = builder.AddConstructor(); + ctor.Modifiers = TypeMemberModifiers.Private; + ctor.Body.Add( + CodeBuilder.CreateSuperConstructorInvocation(ObjectType)); + + ClassDefinition cd = builder.ClassDefinition; + Module module = GetCompilerGeneratedExtensionsModule(); + module.Members.Add(cd); + ((ModuleEntity)module.Entity).InitializeModuleClass(cd); + + _compilerGeneratedExtensionsClass = cd; + } + return _compilerGeneratedExtensionsClass; + } + + public Module GetCompilerGeneratedExtensionsModule() + { + if (null == _compilerGeneratedExtensionsModule) + { + _compilerGeneratedExtensionsModule = NewModule(null); + } + return _compilerGeneratedExtensionsModule; + } + + public void AddCompilerGeneratedType(TypeDefinition type) + { + GetCompilerGeneratedTypesModule().Members.Add(type); + } + + public Module GetCompilerGeneratedTypesModule() + { + if (null == _compilerGeneratedTypesModule) + { + _compilerGeneratedTypesModule = NewModule("CompilerGenerated"); + } + return _compilerGeneratedTypesModule; + } + + private Module NewModule(string ns) + { + Module module = new Module(); + if (null != ns) module.Namespace = new NamespaceDeclaration(ns); + module.Entity = new ModuleEntity(_context.NameResolutionService, this, module); + _context.CompileUnit.Modules.Add(module); + return module; + } + + public ClassDefinition CreateCallableDefinition(string name) + { + ClassDefinition cd = new ClassDefinition(); + cd.BaseTypes.Add(CodeBuilder.CreateTypeReference(this.MulticastDelegateType)); + cd.BaseTypes.Add(CodeBuilder.CreateTypeReference(this.ICallableType)); + cd.Name = name; + cd.Modifiers = TypeMemberModifiers.Final; + cd.Members.Add(CreateCallableConstructor()); + cd.Members.Add(CreateCallMethod()); + cd.Entity = new InternalCallableType(this, cd); + return cd; + } + + Method CreateCallMethod() + { + Method method = new Method("Call"); + method.Modifiers = TypeMemberModifiers.Public|TypeMemberModifiers.Virtual; + method.Parameters.Add(CodeBuilder.CreateParameterDeclaration(1, "args", ObjectArrayType)); + method.ReturnType = CodeBuilder.CreateTypeReference(ObjectType); + method.Entity = new InternalMethod(this, method); + return method; + } + + Constructor CreateCallableConstructor() + { + Constructor constructor = new Constructor(); + constructor.Modifiers = TypeMemberModifiers.Public; + constructor.ImplementationFlags = MethodImplementationFlags.Runtime; + constructor.Parameters.Add( + CodeBuilder.CreateParameterDeclaration(1, "instance", ObjectType)); + constructor.Parameters.Add( + CodeBuilder.CreateParameterDeclaration(2, "method", IntPtrType)); + constructor.Entity = new InternalConstructor(this, constructor); + return constructor; + } + + public bool AreTypesRelated(IType lhs, IType rhs) + { + ICallableType ctype = lhs as ICallableType; + if (null != ctype) + { + return ctype.IsAssignableFrom(rhs) + || ctype.IsSubclassOf(rhs); + } + + return lhs.IsAssignableFrom(rhs) + || (lhs.IsInterface && !rhs.IsFinal) + || (rhs.IsInterface && !lhs.IsFinal) + || CanBeReachedByDownCastOrPromotion(lhs, rhs) + || FindImplicitConversionOperator(rhs,lhs) != null; + } + + public IMethod FindExplicitConversionOperator(IType fromType, IType toType) + { + return FindConversionOperator("op_Explicit", fromType, toType); + } + + public IMethod FindImplicitConversionOperator(IType fromType, IType toType) + { + return FindConversionOperator("op_Implicit", fromType, toType); + } + + public IMethod FindConversionOperator(string name, IType fromType, IType toType) + { + while (fromType != this.ObjectType) + { + IMethod method = FindConversionOperator(name, fromType, toType, fromType.GetMembers()); + if (null != method) return method; + method = FindConversionOperator(name, fromType, toType, toType.GetMembers()); + if (null != method) return method; + method = FindConversionOperator(name, fromType, toType, FindExtension(fromType, name)); + if (null != method) return method; + + fromType = fromType.BaseType; + if (null == fromType) break; + } + return null; + } + + private IEntity[] FindExtension(IType fromType, string name) + { + IEntity extension = _context.NameResolutionService.ResolveExtension(fromType, name); + if (null == extension) return Ambiguous.NoEntities; + + Ambiguous a = extension as Ambiguous; + if (null != a) return a.Entities; + return new IEntity[] { extension }; + } + + IMethod FindConversionOperator(string name, IType fromType, IType toType, IEntity[] candidates) + { + foreach (IEntity entity in candidates) + { + if (EntityType.Method != entity.EntityType || name != entity.Name) continue; + IMethod method = (IMethod)entity; + if (IsConversionOperator(method, fromType, toType)) return method; + } + return null; + } + + bool IsConversionOperator(IMethod method, IType fromType, IType toType) + { + if (!method.IsStatic) return false; + if (method.ReturnType != toType) return false; + IParameter[] parameters = method.GetParameters(); + return (1 == parameters.Length && fromType == parameters[0].Type); + } + + public bool IsCallableTypeAssignableFrom(ICallableType lhs, IType rhs) + { + if (lhs == rhs || Null.Default == rhs) + { + return true; + } + + ICallableType other = rhs as ICallableType; + if (null != other) + { + CallableSignature lvalue = lhs.GetSignature(); + CallableSignature rvalue = other.GetSignature(); + if (lvalue == rvalue) + { + return true; + } + + IParameter[] lparams = lvalue.Parameters; + IParameter[] rparams = rvalue.Parameters; + if (lparams.Length >= rparams.Length) + { + for (int i=0; i 1) + { + IEntity[] tags = new IEntity[info.Length]; + for (int i=0; i 0) + { + return Map(info[0]); + } + return null; + } + + public IEntity Map(MemberInfo mi) + { + IEntity tag = (IEntity)_entityCache[GetCacheKey(mi)]; + if (null == tag) + { + switch (mi.MemberType) + { + case MemberTypes.Method: + { + return Map((MethodInfo)mi); + } + + case MemberTypes.Constructor: + { + return Map((ConstructorInfo)mi); + } + + case MemberTypes.Field: + { + tag = new ExternalField(this, (FieldInfo)mi); + break; + } + + case MemberTypes.Property: + { + tag = new ExternalProperty(this, (PropertyInfo)mi); + break; + } + + case MemberTypes.Event: + { + tag = new ExternalEvent(this, (EventInfo)mi); + break; + } + + case MemberTypes.NestedType: + { + return Map((Type)mi); + } + + default: + { + throw new NotImplementedException(mi.ToString()); + } + } + _entityCache.Add(GetCacheKey(mi), tag); + } + return tag; + } + + public string GetSignature(IEntityWithParameters method) + { + return GetSignature(method, true); + } + + public string GetSignature(IEntityWithParameters method, bool includeFullName) + { + _buffer.Length = 0; + if (includeFullName) + { + _buffer.Append(method.FullName); + } + else + { + _buffer.Append(method.Name); + } + _buffer.Append("("); + + IParameter[] parameters = method.GetParameters(); + for (int i=0; i 0) { _buffer.Append(", "); } + if (method.AcceptVarArgs && i == parameters.Length-1) { _buffer.Append('*'); } + _buffer.Append(parameters[i].Type); + } + _buffer.Append(")"); + return _buffer.ToString(); + } + + public object GetCacheKey(MemberInfo mi) + { + return mi; + } + + public IEntity ResolvePrimitive(string name) + { + return (IEntity)_primitives[name]; + } + + public bool IsPrimitive(string name) + { + return _primitives.ContainsKey(name); + } + + /// + /// checks if the passed type will be equivalente to + /// System.Object in runtime (accounting for the presence + /// of duck typing). + /// + public bool IsSystemObject(IType type) + { + return type == ObjectType || type == DuckType; + } + + protected virtual void PreparePrimitives() + { + AddPrimitiveType("duck", DuckType); + AddPrimitiveType("void", VoidType); + AddPrimitiveType("bool", BoolType); + AddPrimitiveType("char", CharType); + AddPrimitiveType("date", DateTimeType); + AddPrimitiveType("timespan", TimeSpanType); + AddPrimitiveType("string", StringType); + AddPrimitiveType("object", ObjectType); + AddPrimitiveType("regex", RegexType); + AddPrimitiveType("sbyte", SByteType); + AddPrimitiveType("byte", ByteType); + AddPrimitiveType("short", ShortType); + AddPrimitiveType("ushort", UShortType); + AddPrimitiveType("int", IntType); + AddPrimitiveType("uint", UIntType); + AddPrimitiveType("long", LongType); + AddPrimitiveType("ulong", ULongType); + AddPrimitiveType("single", SingleType); + AddPrimitiveType("double", DoubleType); + AddPrimitiveType("decimal", DecimalType); + AddPrimitiveType("callable", ICallableType); + } + + protected virtual void PrepareBuiltinFunctions() + { + AddBuiltin(BuiltinFunction.Len); + AddBuiltin(BuiltinFunction.AddressOf); + AddBuiltin(BuiltinFunction.Eval); + AddBuiltin(BuiltinFunction.Switch); + } + + protected void AddPrimitiveType(string name, ExternalType type) + { + _primitives[name] = type; + type.PrimitiveName = name; + } + + protected void AddBuiltin(BuiltinFunction function) + { + _primitives[function.Name] = function; + } + + void Cache(ExternalType tag) + { + _entityCache[tag.ActualType] = tag; + } + + void Cache(object key, IType tag) + { + _entityCache[key] = tag; + } + + Method CreateBeginInvokeMethod(ICallableType anonymousType) + { + Method method = CodeBuilder.CreateRuntimeMethod("BeginInvoke", Map(typeof(IAsyncResult)), + anonymousType.GetSignature().Parameters, false); + + int delta=method.Parameters.Count; + method.Parameters.Add( + CodeBuilder.CreateParameterDeclaration(delta+1, "callback", Map(typeof(AsyncCallback)))); + method.Parameters.Add( + CodeBuilder.CreateParameterDeclaration(delta+1, "asyncState", ObjectType)); + return method; + } + + Method CreateBeginInvokeExtension(ICallableType anonymousType, Method beginInvoke, out MethodInvocationExpression mie) + { + InternalMethod beginInvokeEntity = (InternalMethod)beginInvoke.Entity; + + Method extension = CodeBuilder.CreateMethod("BeginInvoke", Map(typeof(IAsyncResult)), + TypeMemberModifiers.Public|TypeMemberModifiers.Static); + extension.Attributes.Add(CodeBuilder.CreateAttribute(Types.ExtensionAttribute)); + + ParameterDeclaration self = CodeBuilder.CreateParameterDeclaration(0, "self", beginInvokeEntity.DeclaringType); + + extension.Parameters.Add(self); + CodeBuilder.DeclareParameters(extension, 1, anonymousType.GetSignature().Parameters); + + mie = CodeBuilder.CreateMethodInvocation( + CodeBuilder.CreateReference(self), + beginInvokeEntity); + + ParameterDeclarationCollection parameters = extension.Parameters; + for (int i=1; i)); + + IType itemType = null; + foreach (IType type in FindConstructedTypes(iteratorType, genericEnumerable)) + { + IType candidateItemType = type.GenericTypeInfo.GenericArguments[0]; + _context.TraceVerbose("Candidate enumerable item type for {0}: {1}", + iteratorType, candidateItemType); + + if (itemType != null) + { + itemType = GetMostGenericType(itemType, candidateItemType); + } + else + { + itemType = candidateItemType; + } + } + + return itemType; + } + + System.Collections.Generic.IEnumerable FindConstructedTypes(IType type, IType definition) + { + while (type != null) + { + string typeName = (type is ExternalType ? ((ExternalType)type).ActualType.Name : type.Name); + + if (type.GenericTypeInfo != null && + type.GenericTypeInfo.FullyConstructed && + type.GenericTypeInfo.GenericDefinition == definition) + { + yield return type; + } + + foreach (IType interfaceType in type.GetInterfaces()) + { + foreach (IType match in FindConstructedTypes(interfaceType, definition)) + { + yield return match; + } + } + + type = type.BaseType; + } + } +#endif + + public virtual IType GetConcreteCallableType(Node sourceNode, AnonymousCallableType anonymousType) + { + if (null == anonymousType.ConcreteType) + { + anonymousType.ConcreteType = CreateConcreteCallableType(sourceNode, anonymousType); + } + return anonymousType.ConcreteType; + } + + protected virtual IType CreateConcreteCallableType(Node sourceNode, AnonymousCallableType anonymousType) + { + Module module = GetCompilerGeneratedTypesModule(); + + string name = string.Format("___callable{0}", module.Members.Count); + ClassDefinition cd = CreateCallableDefinition(name); + cd.Modifiers |= TypeMemberModifiers.Public; + cd.LexicalInfo = sourceNode.LexicalInfo; + + cd.Members.Add(CreateInvokeMethod(anonymousType)); + + Method beginInvoke = CreateBeginInvokeMethod(anonymousType); + cd.Members.Add(beginInvoke); + + cd.Members.Add(CreateEndInvokeMethod(anonymousType)); + _compilerGeneratedTypesModule.Members.Add(cd); + + CreateCallableTypeBeginInvokeExtensions(anonymousType, beginInvoke); + + return (IType)cd.Entity; + } + + private void CreateCallableTypeBeginInvokeExtensions(AnonymousCallableType anonymousType, Method beginInvoke) + { + ClassDefinition extensions = GetCompilerGeneratedExtensionsClass(); + extensions.Members.Add(CreateBeginInvokeCallbackOnlyExtension(anonymousType, beginInvoke)); + extensions.Members.Add(CreateBeginInvokeSimplerExtension(anonymousType, beginInvoke)); + } + + private static void InvalidNode(Node node) + { + throw CompilerErrorFactory.InvalidNode(node); + } + + public class DuckTypeImpl : ExternalType + { + public DuckTypeImpl(TypeSystemServices typeSystemServices) : + base(typeSystemServices, Types.Object) + { + } + } + + #region VoidTypeImpl + class VoidTypeImpl : ExternalType + { + internal VoidTypeImpl(TypeSystemServices typeSystemServices) : base(typeSystemServices, Types.Void) + { + } + + override public bool Resolve(List targetList, string name, EntityType flags) + { + return false; + } + + override public bool IsSubclassOf(IType other) + { + return false; + } + + override public bool IsAssignableFrom(IType other) + { + return false; + } + } + + #endregion + } +} Index: src/Boo.Lang/Boo.Lang.csproj =================================================================== --- src/Boo.Lang/Boo.Lang.csproj (revision 2352) +++ src/Boo.Lang/Boo.Lang.csproj (working copy) @@ -49,7 +49,6 @@ - Index: src/Boo.sln =================================================================== --- src/Boo.sln (revision 2352) +++ src/Boo.sln (working copy) @@ -1,6 +1,5 @@ - -Microsoft Visual Studio Solution File, Format Version 9.00 -# Visual Studio 2005 +Microsoft Visual Studio Solution File, Format Version 9.00 +# SharpDevelop 2.1.0.1825 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Boo.Lang", "Boo.Lang\Boo.Lang.csproj", "{8F36FEA8-5EC9-46D3-BE8D-39AE484C1266}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Boo.Lang.Parser", "Boo.Lang.Parser\Boo.Lang.Parser.csproj", "{C1943936-DBBD-4331-94C3-BE4F7E6229DA}" @@ -31,6 +30,10 @@ {3D5461D4-F243-41A5-927B-6636CEE2E6B8}.Debug|Any CPU.Build.0 = Debug|Any CPU {3D5461D4-F243-41A5-927B-6636CEE2E6B8}.Release|Any CPU.ActiveCfg = Release|Any CPU {3D5461D4-F243-41A5-927B-6636CEE2E6B8}.Release|Any CPU.Build.0 = Release|Any CPU + {86284E52-4C54-48CB-A286-4E34047AF1EF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {86284E52-4C54-48CB-A286-4E34047AF1EF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {86284E52-4C54-48CB-A286-4E34047AF1EF}.Release|Any CPU.Build.0 = Release|Any CPU + {86284E52-4C54-48CB-A286-4E34047AF1EF}.Release|Any CPU.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE Index: tests/testcases/net2/generics/callable-1.boo =================================================================== --- tests/testcases/net2/generics/callable-1.boo (revision 0) +++ tests/testcases/net2/generics/callable-1.boo (revision 0) @@ -0,0 +1,14 @@ +""" +42 +""" + +import System +import System.Threading +import System.Collections.Generic + +f as Action of int +f = {i as int | print i * 2} + +l = List of int() +l.Add(21) +l.ForEach(f) Index: tests/testcases/net2/generics/callable-2.boo =================================================================== --- tests/testcases/net2/generics/callable-2.boo (revision 0) +++ tests/testcases/net2/generics/callable-2.boo (revision 0) @@ -0,0 +1,18 @@ +""" +Avish +""" + +import System +import System.Collections.Generic + +public class Person: + public Name as string + public def constructor(name as string): + Name = name + +f as Action of Person +f = {p as Person | print p.Name} + +l = List of Person() +l.Add(Person("Avish")) +l.ForEach(f) Index: tests/testcases/net2/generics/collections-2.boo =================================================================== --- tests/testcases/net2/generics/collections-2.boo (revision 0) +++ tests/testcases/net2/generics/collections-2.boo (revision 0) @@ -0,0 +1,14 @@ +""" +Avish +""" + +import System.Collections.Generic + +class Person: + public Name as string + +l = List of Person() +p = Person() +p.Name = "Avish" +l.Add(p) +print l[0].Name Index: tests/testcases/net2/generics/generators-1.boo =================================================================== --- tests/testcases/net2/generics/generators-1.boo (revision 0) +++ tests/testcases/net2/generics/generators-1.boo (revision 0) @@ -0,0 +1,14 @@ +""" +1 +2 +3 +""" + +import System.Collections.Generic + +public def YieldInts() as IEnumerable of int: + yield 1 + yield 2 + yield 3 + +for i in YieldInts(): print i Index: tests/testcases/net2/generics/interface-1.boo =================================================================== --- tests/testcases/net2/generics/interface-1.boo (revision 0) +++ tests/testcases/net2/generics/interface-1.boo (revision 0) @@ -0,0 +1,22 @@ +""" +-1 +""" + +import System +import System.Collections.Generic + +public class Person: + public Name as string + + public def constructor(name as string): + Name = name + +public class PersonComparer(IComparer of Person): + public def Compare(x as Person, y as Person): + return string.Compare(x.Name, y.Name) + +p1 = Person("Avish") +p2 = Person("Bet's On!") +c = PersonComparer() as IComparer of Person +print c.Compare(p1, p2) + Index: tests/testcases/net2/generics/mixed-1.boo =================================================================== --- tests/testcases/net2/generics/mixed-1.boo (revision 0) +++ tests/testcases/net2/generics/mixed-1.boo (revision 0) @@ -0,0 +1,23 @@ +""" +Thingy +""" + +import System.Collections.Generic + +class Thingy: + _thingies = List of Thingy() + + public AsList as List of Thingy: + get: return _thingies + + public AsIList as IList of Thingy: + get: return _thingies + + public AsICollection as ICollection of Thingy: + get: return _thingies + + public AsNonGeneric as System.Collections.ICollection: + get: return _thingies + +t = Thingy() +print t Index: tests/testcases/net2/generics/mixed-2.boo =================================================================== --- tests/testcases/net2/generics/mixed-2.boo (revision 0) +++ tests/testcases/net2/generics/mixed-2.boo (revision 0) @@ -0,0 +1,23 @@ +""" +Avish +Avish +Avish +""" + +import System.Collections.Generic + +class Person: + public Name as string + + public def constructor(name as string): + Name = name + +def MatchName(name as string): + return {p as Person | p.Name == name} + +l = List of Person() +l.Add(Person("Avish")) + +print l[0].Name +print l.Find(MatchName("Avish")).Name +print l.Find({p as Person | p.Name == "Avish"}).Name Index: tests/testcases/net2/generics/override-1.boo =================================================================== --- tests/testcases/net2/generics/override-1.boo (revision 0) +++ tests/testcases/net2/generics/override-1.boo (revision 0) @@ -0,0 +1,19 @@ +""" +Avish added! +""" + +import System.Collections.ObjectModel + +public class Person: + public Name as string + + public def constructor(name as string): + Name = name + +public class PersonList(Collection of Person): + public override def InsertItem(index as int, p as Person): + print "${p.Name} added!" + super.InsertItem(index, p) + +pl = PersonList() +pl.Add(Person("Avish"))