Index: Boo.Lang.Compiler/Steps/EmitAssembly.cs
===================================================================
--- Boo.Lang.Compiler/Steps/EmitAssembly.cs (revision 2354)
+++ Boo.Lang.Compiler/Steps/EmitAssembly.cs (working copy)
@@ -1,4697 +1,4704 @@
-#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)
- {
- case EntityType.Type:
- {
- EmitGetTypeFromHandle(GetSystemType(node));
- break;
- }
-
- default:
- {
- NotImplemented(node, tag.ToString());
- 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;
- }
- }
-}
+#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)
+