public static Method MethodFactory <T> (Identifier methodName, params TypeNode[] methodParameters) { ArgumentUtility.CheckNotNull("methodName", methodName); ArgumentUtility.CheckNotNull("methodParameters", methodParameters); TypeNode ct = TypeNodeFactory <T>(); return(ct.GetMethod(methodName, methodParameters)); }
public static Method MethodFactory(TypeNode targetTypeNode, string methodName, params TypeNode[] methodParameters) { ArgumentUtility.CheckNotNull("methodName", methodName); ArgumentUtility.CheckNotNull("methodParameters", methodParameters); ArgumentUtility.CheckNotNull("targetTypeNode", targetTypeNode); Identifier methodIdentifier = Identifier.For(methodName); Method targetMethod = targetTypeNode.GetMethod(methodIdentifier, methodParameters); return(targetMethod); }
private Method GetMethod(TypeNode type, string name, params TypeNode[] argTypes) { var res = type.GetMethod(Identifier.For(name), argTypes); if (res == null) { Log(new InvalidInteropMessage(null, "can't load required method: " + name)); throw new ExitException(); } return(res); }
private Method GetMethod(TypeNode type, string name, params TypeNode[] argTypes) { var res = type.GetMethod(Identifier.For(name), argTypes); if (res == null) { Log(new InvalidInteropMessage(null, "can't load required method: " + name)); throw new ExitException(); } return res; }
public virtual Expression ImplicitCoercion(Expression source, TypeNode targetType, TypeViewer typeViewer){ TypeNode originalTargetType = targetType; if (targetType == null || targetType.Name == Looker.NotFound) return source; if (source == null) return null; //HS D if (source is Hole) { source.Type = targetType; return source; } //HS D if (source is LambdaHole) { if (targetType == SystemTypes.Boolean) source = new LambdaHole(source, new Literal(0), NodeType.Ge, source.SourceContext); source.Type = targetType; return source; } Literal sourceLit = source as Literal; if (sourceLit != null && sourceLit.Value is TypeNode){ this.HandleError(source, Error.TypeInVariableContext, this.GetTypeName((TypeNode)sourceLit.Value), "class", "variable"); return null; } //Ignore parentheses if (source.NodeType == NodeType.Parentheses){ UnaryExpression uex = (UnaryExpression)source; uex.Operand = this.ImplicitCoercion(uex.Operand, targetType, typeViewer); if (uex.Operand == null) return null; uex.Type = uex.Operand.Type; return uex; } bool targetIsNonNullType = this.IsNonNullType(targetType); targetType = TypeNode.StripModifier(targetType, SystemTypes.NonNullType); targetType = TypeNode.StripModifier(targetType, SystemTypes.NullableType); //TODO: handle SkipCheck and EnforceCheck //Special case for closure expressions if (source.NodeType == NodeType.AnonymousNestedFunction) return this.CoerceAnonymousNestedFunction((AnonymousNestedFunction)source, targetType, false, typeViewer); TypeNode sourceType = source.Type; if (sourceType == null) sourceType = SystemTypes.Object; bool sourceIsNonNullType = this.IsNonNullType(source.Type); sourceType = TypeNode.StripModifier(sourceType, SystemTypes.NonNullType); sourceType = TypeNode.StripModifier(sourceType, SystemTypes.NullableType); if (sourceType == SystemTypes.String && !sourceIsNonNullType && source is Literal) sourceIsNonNullType = ((Literal)source).Value != null; if (this.currentParameter != null && targetType is Reference){ UnaryExpression uex = source as UnaryExpression; if (uex != null){ if (sourceIsNonNullType && !targetIsNonNullType){ string ttypeName = this.GetTypeName(targetType); string stypeName = this.GetTypeName(source.Type); this.HandleError(source, Error.NoImplicitCoercion, stypeName, ttypeName); return null; } if (!sourceIsNonNullType && targetIsNonNullType){ string ttypeName = this.GetTypeName(targetType); string stypeName = this.GetTypeName(source.Type); this.HandleError(source, Error.NoImplicitCoercion, stypeName, ttypeName); return null; } if (uex.NodeType == NodeType.OutAddress){ if ((this.currentParameter.Flags & ParameterFlags.Out) == 0){ this.currentParameter.Flags |= ParameterFlags.Out; string stypeName = this.GetTypeName(sourceType); this.currentParameter.Flags &= ~ParameterFlags.Out; this.HandleError(source, Error.NoImplicitCoercion, stypeName, this.GetTypeName(targetType)); return null; } }else if (uex.NodeType == NodeType.RefAddress){ if ((this.currentParameter.Flags & ParameterFlags.Out) != 0){ this.currentParameter.Flags &= ~ParameterFlags.Out; string stypeName = this.GetTypeName(sourceType); this.currentParameter.Flags |= ParameterFlags.Out; this.HandleError(source, Error.NoImplicitCoercion, stypeName, this.GetTypeName(targetType)); return null; } } } } Expression result = this.StandardImplicitCoercion(source, sourceIsNonNullType, sourceType, targetIsNonNullType, targetType, originalTargetType, typeViewer); if (result != null) return result; Method coercion = this.UserDefinedImplicitCoercionMethod(source, sourceType, targetType, true, typeViewer); if (coercion != null){ if (this.IsNullableType(targetType) && this.IsNullableType(sourceType) && !this.IsNullableType(coercion.Parameters[0].Type)) return this.CoerceWithLiftedCoercion(source, sourceType, targetType, coercion, false, typeViewer); ExpressionList args = new ExpressionList(1); args.Add(this.ImplicitCoercion(source, coercion.Parameters[0].Type, typeViewer)); return this.ImplicitCoercion(new MethodCall(new MemberBinding(null, coercion), args, NodeType.Call, coercion.ReturnType, source.SourceContext), targetType, typeViewer); } if (sourceType == SystemTypes.Type && source is Literal) this.HandleError(source, Error.TypeInVariableContext, this.GetTypeName((TypeNode)((Literal)source).Value), "class", "variable"); else if (this.IsNullableType(sourceType) && this.IsNullableType(targetType) && this.ImplicitCoercionFromTo(this.RemoveNullableWrapper(sourceType), this.RemoveNullableWrapper(targetType))) { TypeNode usType = this.RemoveNullableWrapper(sourceType); TypeNode utType = this.RemoveNullableWrapper(targetType); Local tempSrc = new Local(sourceType); Local tempTar = new Local(targetType); StatementList statements = new StatementList(); BlockExpression result1 = new BlockExpression(new Block(statements)); statements.Add(new AssignmentStatement(tempSrc, source)); Method hasValue = sourceType.GetMethod(StandardIds.getHasValue); Method getValueOrDefault = sourceType.GetMethod(StandardIds.GetValueOrDefault); Method ctor = targetType.GetMethod(StandardIds.Ctor, utType); Block pushValue = new Block(); Block done = new Block(); Expression tempHasValue = new MethodCall(new MemberBinding(new UnaryExpression(tempSrc, NodeType.AddressOf), hasValue), null); tempHasValue.Type = SystemTypes.Boolean; statements.Add(new Branch(tempHasValue, pushValue)); statements.Add(new AssignmentStatement(new AddressDereference(new UnaryExpression(tempTar, NodeType.AddressOf), targetType), new Literal(null, CoreSystemTypes.Object))); statements.Add(new Branch(null, done)); statements.Add(pushValue); Expression value = new MethodCall(new MemberBinding(new UnaryExpression(tempSrc, NodeType.AddressOf), getValueOrDefault), null); value.Type = usType; value = this.ImplicitCoercion(value, utType); Construct cons = new Construct(new MemberBinding(null, ctor), new ExpressionList(value)); result1.Type = ctor.DeclaringType; statements.Add(new AssignmentStatement(tempTar, cons)); statements.Add(done); statements.Add(new ExpressionStatement(tempTar)); return result1; }else this.HandleError(source, Error.NoImplicitCoercion, this.GetTypeName(sourceType), this.GetTypeName(originalTargetType)); return null; }
public override Expression VisitOldExpression(OldExpression oldExpression) { if (this.topLevelClosureClass != null) { // In Closure ==> Create a field // Since we're within a closure, we can't create a local to hold the value of the old expression // but instead have to create a field for it. That field can be a member of the top-level // closure class since nothing mentioned in the old expression (except possibly for the // bound variables of enclosing quantifications) should be anything captured from // an inner anonymous delegate. // BUT, first we have to know if the old expression depends on any of the bound // variables of the closures in which it is located. If not, then we can implement // it as a scalar and just generate the assignment "closure_class.field := e" for // "Old(e)" to take a snapshot of e's value in the prestate. If it does depend on // any of the bound variables, then we need to generate a set of for-loops that // compute the indices and values of e for each tuple of indices so it can be retrieved // (given the indices) in the post-state. CollectBoundVariables cbv = new CollectBoundVariables(this.stackOfBoundVariables); cbv.VisitExpression(oldExpression.expression); SubstituteClosureClassWithinOldExpressions subst = new SubstituteClosureClassWithinOldExpressions(this.closureLocals); Expression e = subst.VisitExpression(oldExpression.expression); if (cbv.FoundVariables.Count == 0) { // Use a scalar for the old variable Local closureLocal; if (!this.closureLocals.TryGetValue(this.topLevelClosureClass, out closureLocal)) { Contract.Assume(false, "can't find closure local!"); } // Define a scalar var clTemplate = HelperMethods.Unspecialize(this.topLevelClosureClass); Field f = new Field(clTemplate, null, FieldFlags.CompilerControlled | FieldFlags.Public, Identifier.For("_old" + oldExpression.expression.UniqueKey.ToString()), // unique name for this old expr. oldExpression.Type, null); clTemplate.Members.Add(f); // now produce properly instantiated field f = (Field)Rewriter.GetMemberInstanceReference(f, this.topLevelClosureClass); // Generate code to store value in prestate this.prestateValuesOfOldExpressions.Statements.Add( new AssignmentStatement(new MemberBinding(closureLocal, f), e)); // Return expression to be used in poststate // Return an expression that will evaluate in the poststate to the value of the old // expression in the prestate. This will be this.up.f where "up" is the field C# // generated to point to the instance of the top-level closure class. if (this.PointerToTopLevelClosureClass == null) { // then the old expression occurs in the top-level closure class. Just return "this.f" // where "this" refers to the top-level closure class. return(new MemberBinding(new This(this.currentClosureClass), f)); } else { return(new MemberBinding( new MemberBinding(new This(this.currentClosureClass), this.PointerToTopLevelClosureClass), f)); } } else { // the Old expression *does* depend upon at least one of the bound variable // in a ForAll or Exists expression // Use an indexed variable for the old variable TypeNode oldVariableTypeDomain; // Decide if domain is one-dimensional or not bool oneDimensional = cbv.FoundVariables.Count == 1 && cbv.FoundVariables[0].Type.IsValueType; if (oneDimensional) { // a one-dimensional old-expression can use the index variable directly oldVariableTypeDomain = cbv.FoundVariables[0].Type; } else { oldVariableTypeDomain = SystemTypes.GenericList.GetTemplateInstance(this.module, SystemTypes.Int32); } TypeNode oldVariableTypeRange = oldExpression.Type; TypeNode oldVariableType = SystemTypes.GenericDictionary.GetTemplateInstance(this.module, oldVariableTypeDomain, oldVariableTypeRange); Local closureLocal; if (!this.closureLocals.TryGetValue(this.topLevelClosureClass, out closureLocal)) { Contract.Assume(false, "can't find closure local"); } // Define an indexed variable var clTemplate = HelperMethods.Unspecialize(this.topLevelClosureClass); Field f = new Field(clTemplate, null, FieldFlags.CompilerControlled | FieldFlags.Assembly, // can't be private or protected because it needs to be accessed from inner (closure) classes that don't inherit from the class this field is added to. Identifier.For("_old" + oldExpression.expression.UniqueKey.ToString()), // unique name for this old expr. oldVariableType, null); clTemplate.Members.Add(f); // instantiate f f = (Field)Rewriter.GetMemberInstanceReference(f, closureLocal.Type); // Generate code to initialize the indexed variable Statement init = new AssignmentStatement( new MemberBinding(closureLocal, f), new Construct(new MemberBinding(null, oldVariableType.GetConstructor()), null)); this.prestateValuesOfOldExpressions.Statements.Add(init); // Generate code to store values in prestate // Create assignment: this.closure.f[i,j,k,...] = e; Method setItem = oldVariableType.GetMethod(Identifier.For("set_Item"), oldVariableTypeDomain, oldVariableTypeRange); Expression index; if (oneDimensional) { index = cbv.FoundVariables[0]; } else { //InstanceInitializer ctor = // ContractNodes.TupleClass.GetConstructor(SystemTypes.Int32.GetArrayType(1)); //Expression index = new Construct(new MemberBinding(null,ctor),new ExpressionList( index = Literal.Null; } MethodCall mc = new MethodCall(new MemberBinding(new MemberBinding(closureLocal, f), setItem), new ExpressionList(index, e)); Statement stat = new ExpressionStatement(mc); List <Local> locals = new List <Local>(this.stackOfBoundVariables.Count); TrivialHashtable paramMap = new TrivialHashtable(); // Generate a local for each bound variable to use in for-loop foreach (Variable v in this.stackOfBoundVariables) { Local l = new Local(Identifier.Empty, v.Type); paramMap[v.UniqueKey] = l; locals.Add(l); } // Substitute locals for bound variables in old expression *AND* in inner loop bounds SubstituteParameters sps = new SubstituteParameters(paramMap, this.stackOfBoundVariables); sps.Visit(stat); // Create nested for-loops around assignment // keep track of when the first variable is used (from innermost to outermost) // as soon as the first one is needed because the old expression depends on it, // then keep all enclosing loops. It would be possible to keep only those where // the necessary loops have loop bounds that depend on an enclosing loop, but I // haven't calculated that, so just keep them all. For instance, if the old expression // depends on j and the loops are "for i,0,n" and inside that "for j,0,i", then need // both loops. If the inner loop bounds were 0 and n, then wouldn't need the outer // loop. bool usedAVariable = false; for (int i = this.stackOfBoundVariables.Count - 1; 0 <= i; i--) { if (!usedAVariable && !cbv.FoundVariables.Contains(this.stackOfBoundVariables[i])) { continue; } usedAVariable = true; Expression lowerBound = new Duplicator(this.module, this.currentClosureClass).VisitExpression( this.stackOfMethods[i].Operands[0]); lowerBound = subst.VisitExpression(lowerBound); lowerBound = sps.VisitExpression(lowerBound); Expression upperBound = new Duplicator(this.module, this.currentClosureClass).VisitExpression( this.stackOfMethods[i].Operands[1]); upperBound = subst.VisitExpression(upperBound); upperBound = sps.VisitExpression(upperBound); stat = RewriteHelper.GenerateForLoop(locals[i], lowerBound, upperBound, stat); } this.prestateValuesOfOldExpressions.Statements.Add(stat); // Return expression to be used in poststate Method getItem = oldVariableType.GetMethod(Identifier.For("get_Item"), oldVariableTypeDomain); if (oneDimensional) { index = cbv.FoundReferences[0]; } else { //InstanceInitializer ctor = // ContractNodes.TupleClass.GetConstructor(SystemTypes.Int32.GetArrayType(1)); //Expression index = new Construct(new MemberBinding(null,ctor),new ExpressionList( index = Literal.Null; } // Return an expression that will evaluate in the poststate to the value of the old // expression in the prestate. This will be this.up.f[i,j,k,...] where "up" is the field C# // generated to point to the instance of the top-level closure class. MemberBinding thisDotF; if (this.PointerToTopLevelClosureClass == null) { // then the old expression occurs in the top-level closure class. Just return "this.f" // where "this" refers to the top-level closure class. Contract.Assume(f != null); thisDotF = new MemberBinding(new This(clTemplate), HelperMethods.Unspecialize(f)); } else { thisDotF = new MemberBinding( new MemberBinding(new This(clTemplate), this.PointerToTopLevelClosureClass), f); } return(new MethodCall(new MemberBinding(thisDotF, getItem), new ExpressionList(index))); } } else { // Not in closure ==> Create a local variable Local l = GetLocalForOldExpression(oldExpression); // Make sure local can be seen in the debugger (for the entire method, unfortunately) if (currentMethod.LocalList == null) { currentMethod.LocalList = new LocalList(); } currentMethod.LocalList.Add(l); currentMethod.Body.HasLocals = true; this.prestateValuesOfOldExpressions.Statements.Add(new AssignmentStatement(l, oldExpression.expression)); // Return an expression that will evaluate in the poststate to the value of the old // expression in the prestate. When we're not in a closure, this is just the local // itself. return(l); } }
public static Expression BindPseudoMember(Expression qualifier, Identifier identifier) { if (qualifier != null) { SourceContext fullSourceContext = identifier.SourceContext; if (qualifier.SourceContext.Document != null) { fullSourceContext.StartPos = qualifier.SourceContext.StartPos; } TypeNode qualifierType = qualifier.Type; if (identifier.UniqueIdKey == Cci.Runtime.IsConsistentId.UniqueIdKey) { if (qualifier is Base) { if (qualifierType != null) { qualifierType = TypeNode.StripModifiers(qualifierType); return(new MethodCall(new MemberBinding(null, SystemTypes.Guard.GetMethod(Identifier.For("FrameIsExposable"), SystemTypes.Object, SystemTypes.Type)), new ExpressionList(qualifier, new UnaryExpression(new Literal(qualifierType, SystemTypes.Type), NodeType.Typeof, OptionalModifier.For(SystemTypes.NonNullType, SystemTypes.Type))), NodeType.Call, SystemTypes.Boolean, fullSourceContext)); } } else { return(new MethodCall( new MemberBinding(null, SystemTypes.Guard.GetMethod(Cci.Runtime.IsConsistentId, OptionalModifier.For(SystemTypes.NonNullType, SystemTypes.Object))), new ExpressionList(qualifier), NodeType.Call, SystemTypes.Boolean, fullSourceContext)); } } if (identifier.UniqueIdKey == Cci.Runtime.IsPeerConsistentId.UniqueIdKey) { return(new MethodCall( new MemberBinding(null, SystemTypes.Guard.GetMethod(Cci.Runtime.IsPeerConsistentId, OptionalModifier.For(SystemTypes.NonNullType, SystemTypes.Object))), new ExpressionList(qualifier), NodeType.Call, SystemTypes.Boolean, fullSourceContext)); } if (qualifierType != null) { qualifierType = TypeNode.StripModifiers(qualifierType); if (identifier.UniqueIdKey == Cci.Runtime.IsVirtualConsistentId.UniqueIdKey) { if (qualifier is This || qualifier is ImplicitThis) { SourceContext sc = identifier.SourceContext; identifier = Cci.Runtime.IsExposableId; identifier.SourceContext = sc; } } TypeNode guard = SystemTypes.Guard; if (guard != null) { Property property = guard.GetProperty(identifier); if (property != null && property.IsPublic && !property.IsStatic) { Method method = guard.GetMethod(Identifier.For("Frame" + identifier.Name), SystemTypes.Object, SystemTypes.Type); if (method != null && method.IsPublic && method.IsStatic) { return (new MethodCall( new MemberBinding(null, method), new ExpressionList(qualifier, new UnaryExpression(new Literal(qualifierType, SystemTypes.Type), NodeType.Typeof, OptionalModifier.For(SystemTypes.NonNullType, SystemTypes.Type))), NodeType.Call, method.ReturnType, fullSourceContext)); } } } } { Method method = SystemTypes.Guard.GetMethod(identifier, SystemTypes.Object); if (method != null && method.IsPublic && method.IsStatic && method.ReturnType != SystemTypes.Void) { return(new MethodCall(new MemberBinding(null, method), new ExpressionList(qualifier), NodeType.Call, method.ReturnType, fullSourceContext)); } } } return(null); }
public static void Initialize() { TypeNode RuntimeHelpers = SystemTypes.SystemAssembly.GetType(Identifier.For("System.Runtime.CompilerServices"), Identifier.For("RuntimeHelpers")); if (RuntimeHelpers != null) { Runtime.GetOffsetToStringData = RuntimeHelpers.GetMethod(Identifier.For("get_OffsetToStringData")); } Runtime.Combine = SystemTypes.Delegate.GetMethod(StandardIds.Combine, SystemTypes.Delegate, SystemTypes.Delegate); Runtime.CreateInstance = SystemTypes.Activator.GetMethod(StandardIds.CreateInstance, SystemTypes.Type); Runtime.GenericCreateInstance = SystemTypes.Activator.GetMethod(StandardIds.CreateInstance); Runtime.GetCurrent = SystemTypes.IEnumerator.GetMethod(StandardIds.getCurrent); Runtime.GetEnumerator = SystemTypes.IEnumerable.GetMethod(StandardIds.GetEnumerator); Runtime.GetType = SystemTypes.Object.GetMethod(Identifier.For("GetType")); Runtime.GetTypeFromHandle = SystemTypes.Type.GetMethod(Identifier.For("GetTypeFromHandle"), SystemTypes.RuntimeTypeHandle); Runtime.IDisposableDispose = SystemTypes.IDisposable.GetMethod(StandardIds.Dispose); Runtime.IsInterned = SystemTypes.String.GetMethod(StandardIds.IsInterned, SystemTypes.String); Runtime.MemberwiseClone = SystemTypes.Object.GetMethod(StandardIds.MemberwiseClone); Runtime.MonitorEnter = SystemTypes.Monitor.GetMethod(StandardIds.Enter, SystemTypes.Object); Runtime.MonitorExit = SystemTypes.Monitor.GetMethod(StandardIds.Exit, SystemTypes.Object); Runtime.MoveNext = SystemTypes.IEnumerator.GetMethod(StandardIds.MoveNext); Runtime.ObjectToString = SystemTypes.Object.GetMethod(StandardIds.ToString); Runtime.Reset = SystemTypes.IEnumerator.GetMethod(StandardIds.Reset); Runtime.Remove = SystemTypes.Delegate.GetMethod(StandardIds.Remove, SystemTypes.Delegate, SystemTypes.Delegate); Runtime.StringConcatObjects = SystemTypes.String.GetMethod(StandardIds.Concat, SystemTypes.Object, SystemTypes.Object); Runtime.StringConcatStrings = SystemTypes.String.GetMethod(StandardIds.Concat, SystemTypes.String, SystemTypes.String); Runtime.StringEquals = SystemTypes.String.GetMethod(StandardIds.Equals, SystemTypes.String, SystemTypes.String); InstanceInitializer dbgConstr = null; if (SystemTypes.DebuggableAttribute != null) { if (SystemTypes.DebuggingModes != null) { dbgConstr = SystemTypes.DebuggableAttribute.GetConstructor(SystemTypes.DebuggingModes); } else { dbgConstr = SystemTypes.DebuggableAttribute.GetConstructor(SystemTypes.Boolean, SystemTypes.Boolean); } } MemberBinding debuggableAttributeCtor = null; if (dbgConstr != null) { debuggableAttributeCtor = new MemberBinding(null, dbgConstr); } if (debuggableAttributeCtor != null) { Literal trueLit = new Literal(true, SystemTypes.Boolean); Literal falseLit = new Literal(false, SystemTypes.Boolean); Runtime.Debuggable = new AttributeNode(); Runtime.Debuggable.Constructor = debuggableAttributeCtor; //TODO: will need to fix this up in the case where the type is compiled from source Runtime.Debuggable.Expressions = new ExpressionList(2); if (SystemTypes.DebuggingModes != null) { Runtime.Debuggable.Expressions.Add(new Literal(0x107, SystemTypes.DebuggingModes)); } else { Runtime.Debuggable.Expressions.Add(trueLit); Runtime.Debuggable.Expressions.Add(trueLit); } Runtime.OptimizedButDebuggable = new AttributeNode(); Runtime.OptimizedButDebuggable.Constructor = debuggableAttributeCtor; Runtime.OptimizedButDebuggable.Expressions = new ExpressionList(2); if (SystemTypes.DebuggingModes != null) { Runtime.OptimizedButDebuggable.Expressions.Add(new Literal(0x007, SystemTypes.DebuggingModes)); } else { Runtime.OptimizedButDebuggable.Expressions.Add(trueLit); Runtime.OptimizedButDebuggable.Expressions.Add(falseLit); } Runtime.OptimizedWithPDBOnly = new AttributeNode(); Runtime.OptimizedWithPDBOnly.Constructor = debuggableAttributeCtor; Runtime.OptimizedWithPDBOnly.Expressions = new ExpressionList(2); if (SystemTypes.DebuggingModes != null) { Runtime.OptimizedWithPDBOnly.Expressions.Add(new Literal(0x006, SystemTypes.DebuggingModes)); } else { Runtime.OptimizedWithPDBOnly.Expressions.Add(falseLit); Runtime.OptimizedWithPDBOnly.Expressions.Add(falseLit); } } }