private NamespaceTypeDefinition CreateContractReferenceAssemblyAttribute(IRootUnitNamespace rootNs) { var internFactory = this.host.InternFactory; var nameTable = this.host.NameTable; var contractReferenceAssemblyAttributeName = nameTable.GetNameFor("ContractReferenceAssemblyAttribute"); var contractNamespaceName = nameTable.GetNameFor("System.Diagnostics.Contracts"); #region Define type CustomAttribute compilerGeneratedAttribute = new CustomAttribute() { Constructor = new Microsoft.Cci.MethodReference( this.host, this.compilerGeneratedAttributeType, CallingConvention.HasThis, this.systemVoidType, this.host.NameTable.Ctor, 0) }; var contractsNs = new NestedUnitNamespace() { ContainingUnitNamespace = rootNs, Name = contractNamespaceName, }; NamespaceTypeDefinition result = new NamespaceTypeDefinition() { Name = contractReferenceAssemblyAttributeName, Attributes = new List<ICustomAttribute>{ compilerGeneratedAttribute }, BaseClasses = new List<ITypeReference>{ this.systemAttributeType }, ContainingUnitNamespace = contractsNs, //unitNamespace, InternFactory = internFactory, IsBeforeFieldInit = true, IsClass = true, IsSealed = true, Methods = new List<IMethodDefinition>(), Layout = LayoutKind.Auto, StringFormat = StringFormatKind.Ansi, }; contractsNs.Members.Add(result); this.allTypes.Add(result); #endregion Define type #region Define the ctor List<IStatement> statements = new List<IStatement>(); SourceMethodBody body = new SourceMethodBody(this.host) { LocalsAreZeroed = true, Block = new BlockStatement() { Statements = statements }, }; MethodDefinition ctor = new MethodDefinition() { Body = body, CallingConvention = CallingConvention.HasThis, ContainingTypeDefinition = result, InternFactory = internFactory, IsRuntimeSpecial = true, IsStatic = false, IsSpecialName = true, Name = nameTable.Ctor, Type = this.systemVoidType, Visibility = TypeMemberVisibility.Public, }; body.MethodDefinition = ctor; var thisRef = new ThisReference() { Type = result, }; // base(); foreach (var baseClass in result.BaseClasses) { var baseCtor = new Microsoft.Cci.MutableCodeModel.MethodReference() { CallingConvention = CallingConvention.HasThis, ContainingType = baseClass, GenericParameterCount = 0, InternFactory = this.host.InternFactory, Name = nameTable.Ctor, Type = this.systemVoidType, }; statements.Add( new ExpressionStatement() { Expression = new MethodCall() { MethodToCall = baseCtor, IsStaticCall = false, // REVIEW: Is this needed in addition to setting the ThisArgument? ThisArgument = new ThisReference() { Type = result, }, Type = this.systemVoidType, // REVIEW: Is this the right way to do this? Arguments = new List<IExpression>(), } } ); break; } // return; statements.Add(new ReturnStatement()); result.Methods.Add(ctor); #endregion Define the ctor return result; }
/// <summary> /// Returns an expression that results in a closure object instance that contains the given field. /// If the expression will be evaluated in the body of this.method, the result is a bound expression /// that references the local that contains the object. Otherwise it is the "this" argument of the /// anonymous delegate method, possibly with a number of field accesses to chase down the outer closure chain. /// </summary> /// <param name="closureField">A reference to a field from the "self instance" of a closure class.</param> private IExpression GetClosureObjectInstanceContaining(IFieldReference closureField) { if (this.isInsideAnonymousMethod) { IExpression result = new ThisReference() { Type = this.currentClosureSelfInstance }; while (result.Type != closureField.ContainingType) { var outerClosureField = this.fieldReferencesForUseInsideAnonymousMethods[result.Type]; result = new BoundExpression() { Instance = result, Definition = outerClosureField, Type = outerClosureField.Type }; } return result; } else { foreach (var instance in this.closureLocalInstances) { if (instance.Type == closureField.ContainingType) return instance; } return this.currentClosureObject; } }
/// <summary> /// Visits the specified this reference. /// </summary> /// <param name="thisReference">The this reference.</param> public override void Visit(IThisReference thisReference) { ThisReference mutableThisReference = new ThisReference(thisReference); this.resultExpression = this.myCodeCopier.DeepCopy(mutableThisReference); }
/// <summary> /// Returns a method whose body is empty, but which can be replaced with the real body when it is /// available. /// </summary> /// <remarks> /// Public because it needs to get called when an anonymous delegate is encountered /// while translating a method body. Just mapping the anonymous delegate doesn't /// provide the information needed. The parameters of a method reference are not /// IParameterDefinitions. /// </remarks> public MethodDefinition TranslateMetadata(R.IMethodSymbol methodSymbol) { Contract.Requires(methodSymbol != null); Contract.Ensures(Contract.Result<MethodDefinition>() != null); var containingType = (ITypeDefinition)this.typeSymbolCache[methodSymbol.ContainingType]; var isConstructor = methodSymbol.MethodKind == R.CommonMethodKind.Constructor; List<IParameterDefinition> parameters = new List<IParameterDefinition>(); var m = new MethodDefinition() { CallingConvention = methodSymbol.IsStatic ? CallingConvention.Default : CallingConvention.HasThis, ContainingTypeDefinition = containingType, InternFactory = this.host.InternFactory, IsHiddenBySignature = true, // REVIEW IsNewSlot = containingType.IsInterface, // REVIEW IsRuntimeSpecial = isConstructor, IsSpecialName = isConstructor, IsStatic = methodSymbol.IsStatic, IsVirtual = containingType.IsInterface, // REVIEW: Why doesn't using methodSymbol.Virtual work for interface methods? Locations = Helper.WrapLocations(methodSymbol.Locations), Name = this.nameTable.GetNameFor(methodSymbol.Name), Parameters = parameters, Type = this.Map(methodSymbol.ReturnType), Visibility = this.Map(methodSymbol.DeclaredAccessibility), }; // IMPORTANT: Have to add it to the cache before doing anything else because it may // get looked up if it is generic and a parameter's type involves the generic // method parameter. this.methodSymbolCache.Add(methodSymbol, m); #region Define the generic parameters if (methodSymbol.IsGenericMethod) { var genericParameters = new List<IGenericMethodParameter>(); foreach (var gp in methodSymbol.TypeParameters) { var gp2 = this.CreateTypeDefinition(gp); genericParameters.Add((IGenericMethodParameter) gp2); } m.GenericParameters = genericParameters; } #endregion #region Define the parameters ushort i = 0; foreach (var p in methodSymbol.Parameters) { var p_prime = new ParameterDefinition() { ContainingSignature = m, IsByReference = p.RefKind == RefKind.Ref, IsIn = p.RefKind == RefKind.None, IsOut = p.RefKind == RefKind.Out, Name = nameTable.GetNameFor(p.Name), Type = this.Map(p.Type), Index = i++, }; parameters.Add(p_prime); } #endregion Define the parameters #region Define default ctor, if needed if (/*methodSymbol.IsSynthesized &&*/ isConstructor) { // BUGBUG!! m.IsHiddenBySignature = true; m.IsRuntimeSpecial = true; m.IsSpecialName = true; var statements = new List<IStatement>(); var body = new SourceMethodBody(this.host, null, null) { LocalsAreZeroed = true, Block = new BlockStatement() { Statements = statements }, }; var thisRef = new ThisReference() { Type = containingType, }; // base(); foreach (var baseClass in containingType.BaseClasses) { var baseCtor = new Microsoft.Cci.MutableCodeModel.MethodReference() { CallingConvention = CallingConvention.HasThis, ContainingType = baseClass, GenericParameterCount = 0, InternFactory = this.host.InternFactory, Name = nameTable.Ctor, Type = this.host.PlatformType.SystemVoid, }; statements.Add( new ExpressionStatement() { Expression = new MethodCall() { MethodToCall = baseCtor, IsStaticCall = false, // REVIEW: Is this needed in addition to setting the ThisArgument? ThisArgument = thisRef, Type = this.host.PlatformType.SystemVoid, // REVIEW: Is this the right way to do this? Arguments = new List<IExpression>(), } } ); break; } // return; statements.Add(new ReturnStatement()); body.MethodDefinition = m; m.Body = body; } #endregion return m; }
public static IExpression GenerateExpressionFromString(string strExpr, IMetadataHost host, IMethodDefinition method) { strExpr = Normalize(strExpr); string rpn = GetRPN(strExpr); Stack<IExpression> stVals = new Stack<IExpression>(); RPNEnumerator rpnEnum = new RPNEnumerator(rpn); var int32Type = host.PlatformType.SystemInt32; var boolType = host.PlatformType.SystemBoolean; while (rpnEnum.MoveNext()) { RPNValue rpnVal = (RPNValue)rpnEnum.Current; if (rpnVal.type == RPNValueType.OPERAND) { if (reNum.IsMatch(rpnVal.val)) { stVals.Push(new CompileTimeConstant() { Type = int32Type, Value = int.Parse(rpnVal.val.Replace(':', '-')) }); } else { IExpression expr = null; var exprParts = rpnVal.val.Split('.'); if (exprParts[0] == "this") { expr = new ThisReference() { Type = method.ContainingType.ResolvedType }; } else { foreach (var arg in method.Parameters) { if (arg.Name.Value == exprParts[0]) { expr = new BoundExpression() { Type = arg.Type.ResolvedType, Definition = arg }; break; } } } if (expr != null && exprParts.Length > 1) { for (int i = 1; i < exprParts.Length; i++) { expr = GetExprWithAccesor(expr, exprParts[i], host); } } if (expr == null || expr.Type.ResolvedType != int32Type.ResolvedType) { return null; } stVals.Push(expr); } } else { var v1 = stVals.Pop(); var v2 = stVals.Pop(); if (rpnVal.val == "+") stVals.Push(new Addition() { Type = int32Type, LeftOperand = v2, RightOperand = v1 }); else if (rpnVal.val == "-") stVals.Push(new Subtraction() { Type = int32Type, LeftOperand = v2, RightOperand = v1 }); else if (rpnVal.val == "*") stVals.Push(new Multiplication() { Type = int32Type, LeftOperand = v2, RightOperand = v1 }); else if (rpnVal.val == "/") stVals.Push(new Division() { Type = int32Type, LeftOperand = v2, RightOperand = v1 }); else if (rpnVal.val == "=") stVals.Push(new Equality() { Type = int32Type, LeftOperand = v2, RightOperand = v1 }); else if (rpnVal.val == "&") stVals.Push(new Conditional() { Type = boolType, Condition = v2, ResultIfTrue = v1, ResultIfFalse = new CompileTimeConstant() { Type = int32Type, Value = 0 } }); else if (rpnVal.val == "|") stVals.Push(new Conditional() { Type = boolType, Condition = v2, ResultIfTrue = new CompileTimeConstant() { Type = int32Type, Value = 1 }, ResultIfFalse = v1 }); else if (rpnVal.val == ">") stVals.Push(new GreaterThan() { Type = boolType, LeftOperand = v2, RightOperand = v1 }); else if (rpnVal.val == "<") stVals.Push(new LessThan() { Type = boolType, LeftOperand = v2, RightOperand = v1 }); else if (rpnVal.val == "%") stVals.Push(new GreaterThanOrEqual() { Type = boolType, LeftOperand = v2, RightOperand = v1 }); else if (rpnVal.val == "#") stVals.Push(new LessThanOrEqual() { Type = boolType, LeftOperand = v2, RightOperand = v1 }); else return null; } } if (stVals.Count > 0) { return stVals.Pop(); } return null; }
/// <summary> /// Visits the specified this reference. /// </summary> /// <param name="thisReference">The this reference.</param> /// <returns></returns> protected virtual IExpression DeepCopy(ThisReference thisReference) { thisReference.Type = this.Substitute(thisReference.Type); return thisReference; }
private static List<IStatement> InitializeFieldsInConstructor(IMethodDefinition method) { Contract.Ensures(Contract.Result<List<IStatement>>() != null); var inits = new List<IStatement>(); if (method.IsConstructor || method.IsStaticConstructor) { var smb = method.Body as ISourceMethodBody; if (method.IsStaticConstructor || (smb != null && !FindCtorCall.IsDeferringCtor(method, smb.Block))) { var thisExp = new ThisReference() { Type = method.ContainingTypeDefinition, }; foreach (var f in method.ContainingTypeDefinition.Fields) { if (f.IsStatic == method.IsStatic) { var a = new Assignment() { Source = new DefaultValue() { DefaultValueType = f.Type, Type = f.Type, }, Target = new TargetExpression() { Definition = f, Instance = method.IsConstructor ? thisExp : null, Type = f.Type }, Type = f.Type, }; inits.Add(new ExpressionStatement() { Expression = a, }); } } } } return inits; }
private static NamespaceTypeDefinition DefineMethodHashAttributeType(HostEnvironment host, RootUnitNamespace rootUnitNamespace) { Contract.Requires(host != null); var internFactory = host.InternFactory; #region Define the type var methodHashAttributeType = new NamespaceTypeDefinition() { BaseClasses = new List<ITypeReference> { host.PlatformType.SystemAttribute, }, ContainingUnitNamespace = rootUnitNamespace, InternFactory = internFactory, //IsBeforeFieldInit = true, IsClass = true, IsPublic = true, //IsSealed = true, Methods = new List<IMethodDefinition>(1), Name = host.NameTable.GetNameFor("MethodHashAttribute"), //Layout = LayoutKind.Auto, //StringFormat = StringFormatKind.Ansi, }; #endregion #region Define the ctor var systemVoidType = host.PlatformType.SystemVoid; List<IStatement> statements = new List<IStatement>(); SourceMethodBody body = new SourceMethodBody(host) { LocalsAreZeroed = true, Block = new BlockStatement() { Statements = statements }, }; var ctor = new MethodDefinition() { Body = body, CallingConvention = CallingConvention.HasThis, ContainingTypeDefinition = methodHashAttributeType, InternFactory = internFactory, IsRuntimeSpecial = true, IsStatic = false, IsSpecialName = true, Name = host.NameTable.Ctor, Type = systemVoidType, Visibility = TypeMemberVisibility.Public, }; var systemStringType = host.PlatformType.SystemString; var systemIntType = host.PlatformType.SystemInt32; ctor.Parameters = new List<IParameterDefinition>(){ new ParameterDefinition() { ContainingSignature = ctor, Name = host.NameTable.GetNameFor("a"), Type = systemStringType, Index = 0, }, new ParameterDefinition() { ContainingSignature = ctor, Name = host.NameTable.GetNameFor("b"), Type = systemIntType, Index = 1, } }; body.MethodDefinition = ctor; var thisRef = new ThisReference() { Type = methodHashAttributeType, }; // base(); foreach (var baseClass in methodHashAttributeType.BaseClasses) { var baseCtor = new Microsoft.Cci.MutableCodeModel.MethodReference() { CallingConvention = CallingConvention.HasThis, ContainingType = baseClass, GenericParameterCount = 0, InternFactory = internFactory, Name = host.NameTable.Ctor, Type = systemVoidType, }; statements.Add( new ExpressionStatement() { Expression = new MethodCall() { MethodToCall = baseCtor, IsStaticCall = false, // REVIEW: Is this needed in addition to setting the ThisArgument? ThisArgument = new ThisReference() { Type = methodHashAttributeType, }, Type = systemVoidType, // REVIEW: Is this the right way to do this? Arguments = new List<IExpression>(), } } ); break; } // return; statements.Add(new ReturnStatement()); methodHashAttributeType.Methods.Add(ctor); #endregion Define the ctor return methodHashAttributeType; }
/// <summary> /// Create the new body of the iterator method. /// </summary> /// <remarks> /// Pseudo code: /// iteratorClosureLocal = new Closure(0); /// iteratorClosureLocal.field = parameter; // for each parameter including this. /// return iteratorClosureLocal; /// </remarks> private BlockStatement CreateNewIteratorMethodBody(IteratorClosureInformation iteratorClosure) { BlockStatement result = new BlockStatement(); // iteratorClosureLocal = new IteratorClosure(0); LocalDefinition localDefinition = new LocalDefinition() { Name = this.host.NameTable.GetNameFor("iteratorClosureLocal"), Type = GetClosureTypeReferenceFromIterator(iteratorClosure), }; CreateObjectInstance createObjectInstance = new CreateObjectInstance() { MethodToCall = GetMethodReference(iteratorClosure, iteratorClosure.Constructor), Type = localDefinition.Type }; // the start state depends on whether the iterator is an IEnumerable or an IEnumerator. For the former, // it must be created in state -2. Then it is the GetEnumerator method that puts it into its // "start" state, i.e., state 0. var startState = this.isEnumerable ? -2 : 0; createObjectInstance.Arguments.Add(new CompileTimeConstant() { Value = startState, Type = this.host.PlatformType.SystemInt32 }); LocalDeclarationStatement localDeclarationStatement = new LocalDeclarationStatement() { InitialValue = createObjectInstance, LocalVariable = localDefinition }; result.Statements.Add(localDeclarationStatement); // Generate assignments to closure instance's fields for each of the parameters captured by the closure. foreach (object capturedLocalOrParameter in FieldForCapturedLocalOrParameter.Keys) { BoundField boundField = FieldForCapturedLocalOrParameter[capturedLocalOrParameter]; Assignment assignment; ITypeReference localOrParameterType = GetLocalOrParameterType(capturedLocalOrParameter); if (capturedLocalOrParameter is ILocalDefinition) continue; if (capturedLocalOrParameter is IThisReference) { var thisR = new ThisReference(); IExpression thisValue = thisR; if (!this.method.ContainingTypeDefinition.IsClass) { thisValue = new AddressDereference() { Address = thisR, Type = this.method.ContainingTypeDefinition.IsGeneric ? (ITypeReference)this.method.ContainingTypeDefinition.InstanceType : (ITypeReference)this.method.ContainingTypeDefinition }; } assignment = new Assignment { Source = thisValue, Type = this.method.ContainingType, Target = new TargetExpression() { Definition = GetFieldReference(iteratorClosure, boundField.Field), Type = this.method.ContainingType, Instance = new BoundExpression() { Type = localDefinition.Type, Instance = null, Definition = localDefinition, IsVolatile = false } }, }; } else { assignment = new Assignment { Source = new BoundExpression() { Definition = capturedLocalOrParameter, Instance = null, IsVolatile = false, Type = localOrParameterType }, Type = localOrParameterType, Target = new TargetExpression() { Definition = GetFieldReference(iteratorClosure, boundField.Field), Type = localOrParameterType, Instance = new BoundExpression() { Type = localDefinition.Type, Instance = null, Definition = localDefinition, IsVolatile = false } }, }; } ExpressionStatement expressionStatement = new ExpressionStatement() { Expression = assignment }; result.Statements.Add(expressionStatement); } // Generate: return iteratorClosureLocal; result.Statements.Add(new ReturnStatement() { Expression = new BoundExpression() { Definition = localDeclarationStatement.LocalVariable, Instance = null, Type = localDeclarationStatement.LocalVariable.Type } }); return result; }
public override void RewriteChildren(ThisReference thisReference) { if (TypeHelper.TypesAreEquivalent(thisReference.Type, this.sourceType)) thisReference.Type = this.targetType; }
/// <summary> /// Rewrites the children of the given this reference expression. /// </summary> public virtual void RewriteChildren(ThisReference thisReference) { this.RewriteChildren((Expression)thisReference); }
/// <summary> /// Visits the specified this reference. /// </summary> /// <param name="thisReference">The this reference.</param> public override void Visit(IThisReference thisReference) { ThisReference mutableThisReference = thisReference as ThisReference; if (alwaysMakeACopy || mutableThisReference == null) mutableThisReference = new ThisReference(thisReference); this.resultExpression = this.myCodeMutator.Visit(mutableThisReference); }
/// <summary> /// Visits the specified this reference. /// </summary> /// <param name="thisReference">The this reference.</param> /// <returns></returns> public virtual IExpression Visit(ThisReference thisReference) { thisReference.Type = this.Visit(thisReference.Type); return thisReference; }