/// <summary> /// Predicate determines if a particular call is virtual or non virtual /// </summary> /// <param name="call">The call to test</param> /// <returns>true if virtual.</returns> public static bool IsVirtual(MethodCall call) { Method callee = ((MemberBinding)call.Callee).BoundMember as Method; if (callee != null) { return (callee.IsVirtual && call.NodeType == NodeType.Callvirt); } return false; }
public override Expression VisitMethodCall(MethodCall call) { MemberBinding mb = call.Callee as MemberBinding; if (mb == null) return call; Method calledMethod = mb.BoundMember as Method; if (calledMethod == null) return call; Method template = calledMethod.Template; if (contractNodes.IsOldMethod(template)) { OldExpression oe = new OldExpression(ExtractOldExpression(call)); oe.Type = call.Type; return oe; } if (contractNodes.IsValueAtReturnMethod(template)) { return new AddressDereference(call.Operands[0], calledMethod.TemplateArguments[0], call.SourceContext); } if (contractNodes.IsResultMethod(template)) { // check if we are in an Task returning method if (this.declaringMethod != null && this.declaringMethod.ReturnType != null) { var rt = this.declaringMethod.ReturnType; var templ = rt.Template; if (templ != null && templ.Name.Name == "Task`1" && rt.TemplateArguments != null && rt.TemplateArguments.Count == 1) { var targ = rt.TemplateArguments[0]; if (calledMethod.TemplateArguments[0] == targ) { // use of ReturnValue<T>() instead of ReturnValue<Task<T>>().Result var retExp = new ReturnValue(rt, call.SourceContext); var resultProp = rt.GetProperty(Identifier.For("Result")); if (resultProp != null && resultProp.Getter != null) { return new MethodCall(new MemberBinding(retExp, resultProp.Getter), new ExpressionList()); } } } } return new ReturnValue(calledMethod.ReturnType, call.SourceContext); } return base.VisitMethodCall(call); }
public override void VisitMethodCall(MethodCall call) { MemberBinding mb = call.Callee as MemberBinding; if (mb == null) return; Method calledMethod = mb.BoundMember as Method; if (calledMethod == null) return; Method template = calledMethod.Template; if (template != null && template.Name.Name == "get_Result" && template.DeclaringType.Name.Name == "Task`1") { // check if callee is result var innercall = mb.TargetObject as MethodCall; if (innercall != null) { MemberBinding mb2 = innercall.Callee as MemberBinding; if (mb2 != null) { Method calledMethod2 = mb2.BoundMember as Method; if (calledMethod2 != null) { Method template2 = calledMethod2.Template; if (contractNodes.IsResultMethod(template2)) { this.foundReturnValueTaskResult = true; //return new ReturnValue(calledMethod.DeclaringType.TemplateArguments[0]); return; } } } } } // For async methods calledMethod (Contract.Result) would be called in the generated generic state machine, // and calledMethod.ReturnType would be generic type argument and actualResultType can be generic method argument // (if async postcondition declared in the generic method from non-generic class). // In this case calledMethod.ReturnType would be != this.actualResultType // and different comparison logic should be used (reflected in EquivalentGenercTypes method). if (this.actualResultType != null && contractNodes.IsResultMethod(template) && (calledMethod.ReturnType == this.actualResultType || EquivalentGenericTypes(calledMethod, actualResultType))) { // using Contract.Result<T>() in a Task<T> returning method, this is a shorthand for // Contract.Result<Task<T>>().Result this.foundReturnValueTaskResult = true; return; } base.VisitMethodCall(call); }
public override void VisitMethodCall(MethodCall call) { MemberBinding mb = call.Callee as MemberBinding; if (mb == null) return; Method calledMethod = mb.BoundMember as Method; if (calledMethod == null) return; Method template = calledMethod.Template; if (template != null && template.Name.Name == "get_Result" && template.DeclaringType.Name.Name == "Task`1") { // check if callee is result var innercall = mb.TargetObject as MethodCall; if (innercall != null) { MemberBinding mb2 = innercall.Callee as MemberBinding; if (mb2 != null) { Method calledMethod2 = mb2.BoundMember as Method; if (calledMethod2 != null) { Method template2 = calledMethod2.Template; if (contractNodes.IsResultMethod(template2)) { this.foundReturnValueTaskResult = true; //return new ReturnValue(calledMethod.DeclaringType.TemplateArguments[0]); return; } } } } } if (this.actualResultType != null && contractNodes.IsResultMethod(template) && calledMethod.ReturnType == this.actualResultType) { // using Contract.Result<T>() in a Task<T> returning method, this is a shorthand for // Contract.Result<Task<T>>().Result this.foundReturnValueTaskResult = true; return; } base.VisitMethodCall(call); }
private static void AddInterfaceImplementationWrapper(Class Class, Method intfMethod, Method baseMethod) { var d = new Duplicator(Class.DeclaringModule, Class); d.SkipBodies = true; var copy = d.VisitMethod(baseMethod); copy.Flags = MethodFlags.Private | MethodFlags.HideBySig | MethodFlags.Virtual | MethodFlags.NewSlot | MethodFlags.Final; copy.ImplementedInterfaceMethods = new MethodList(intfMethod); copy.Name = Identifier.For("InheritedInterfaceImplementationContractWrapper$" + intfMethod.Name.Name); copy.ClearBody(); copy.ThisParameter.Type = Class; var bodyBlock = new Block(new StatementList()); copy.Body = new Block(new StatementList(bodyBlock)); // add call to baseMethod var calledMethod = (baseMethod.TemplateParameters != null && baseMethod.TemplateParameters.Count > 0) ? baseMethod.GetTemplateInstance(Class, copy.TemplateParameters) : baseMethod; var argList = new ExpressionList(); for (int i = 0; i < copy.Parameters.Count; i++) { argList.Add(copy.Parameters[i]); } var callExpression = new MethodCall(new MemberBinding(copy.ThisParameter, calledMethod), argList); if (HelperMethods.IsVoidType(intfMethod.ReturnType)) { bodyBlock.Statements.Add(new ExpressionStatement(callExpression)); } else { bodyBlock.Statements.Add(new Return(callExpression)); } Class.Members.Add(copy); }
public override Expression VisitMethodCall(MethodCall call) { // This is a workaround for a bug in the CCI resolver. It can't cope with calls to methods // in which some parameters were nulled out because of an error. We check for that case here // and null out the entire method call. Reported to Herman on 10/23/04. NameBinding nbCallee = call.Callee as NameBinding; if (nbCallee != null && nbCallee.BoundMembers.Count > 0) { ZMethod calleeMethod = (ZMethod)nbCallee.BoundMembers[0]; for (int n = calleeMethod.Parameters.Count, i = 0; i < n; i++) { if (calleeMethod.Parameters[i] == null) return null; } } // end workaround Expression result = base.VisitMethodCall(call); return result; }
//================= reader methods ========================================== void AddReadAttributes(TypeNode type, StatementList statements, Identifier reader, Expression target, SchemaValidator validator) { if (validator.Attributes != null) { Block whileBody = new Block(new StatementList()); Literal trueLit = Literal.True; MethodCall movenext = new MethodCall(new QualifiedIdentifier(reader, Identifier.For("MoveToNextAttribute")), new ExpressionList()); BinaryExpression condition = new BinaryExpression(movenext, trueLit, NodeType.Eq); While w = new While(condition, whileBody); statements.Add(w); Block lastElseBlock = null; Local nameLocal = new Local(SystemTypes.String); whileBody.Statements.Add(new AssignmentStatement(nameLocal, new QualifiedIdentifier(reader, Identifier.For("LocalName")))); Local nsLocal = new Local(SystemTypes.String); whileBody.Statements.Add(new AssignmentStatement(nsLocal, new QualifiedIdentifier(reader, Identifier.For("NamespaceURI")))); foreach (SchemaAttDef ad in validator.Attributes) { // todo: any way to do tokenized compares? BinaryExpression nameEqual = new BinaryExpression(nameLocal, new Literal(ad.Name.Name, SystemTypes.String), NodeType.Eq); BinaryExpression nsEqual = new BinaryExpression(nsLocal, new Literal(ad.Name.Prefix != null ? ad.Name.Prefix.Name : "", SystemTypes.String), NodeType.Eq); Block elseBlock = new Block(new StatementList()); If ifExpr = new If(new BinaryExpression(nameEqual, nsEqual, NodeType.And), new Block(new StatementList()), elseBlock); if (lastElseBlock != null) { lastElseBlock.Statements.Add(ifExpr); } else { whileBody.Statements.Add(ifExpr); } lastElseBlock = elseBlock; // body of if test, parse the attribute value as the specified type. Debug.Assert(ad.Member is Field || ad.Member is Property); AddReadSimpleType(Checker.GetMemberType(ad.Member), ifExpr.TrueBlock.Statements, reader, GetMemberBinding(target, ad.Member), null, true); } //todo: report unknown attributes? } }
void AddCallSerializer(TypeNode srcType, StatementList statements, Expression src, Identifier writer, Expression rootName, Expression rootNamespace ) { TypeNode type = Unwrap(srcType); Class memberSerializer = this.CreateSerializerFor(type); // call the Serialize method on it, passing the member we're serializing. ExpressionList args = new ExpressionList(); args.Add(src); args.Add(writer); args.Add(rootName); args.Add(rootNamespace); MethodCall call = new MethodCall(); Method serialize = memberSerializer.GetMethod(Identifier.For("Serialize"), new TypeNode[4] { type, Runtime.XmlSerializationWriter, SystemTypes.String, SystemTypes.String} ); call.Callee = new MemberBinding(new MemberBinding(null, memberSerializer), serialize); call.Operands = args; statements.Add( new ExpressionStatement( call ) ); }
Expression GetConvertToString(TypeNode srcType, Expression src, bool always) { TypeNode type = Unwrap(srcType); if (type is EnumNode) { Method method = SystemTypes.Enum.GetMethod(Identifier.For("ToString")); return new MethodCall(new MemberBinding(src, method), new ExpressionList(), NodeType.Callvirt, SystemTypes.String); } // See if it has a type converter. Class converterClass = Checker.GetTypeConverter(type); if (converterClass != null) { TypeConverter converter = TypeDescriptor.GetConverter(type.GetRuntimeType()); if (converter != null) { Type converterType = converter.GetType(); AssemblyNode converterAssembly = AssemblyNode.GetAssembly(converterType.Assembly, cache, false, true); converterClass = converterAssembly.GetType(Identifier.For(converterType.Namespace), Identifier.For(converterType.Name)) as Class; Expression e = tempChecker.GetConverterToString(converter, converterClass, type, src); if (e != null) { //Do I need to add namespace and assembly reference for type converter? return e; } } } if (always) { if (this.tempTypeSystem.ImplicitCoercionFromTo(src, src.Type, SystemTypes.String)) { return CastTo(src, SystemTypes.String); } else { Method method = type.GetMethod(Identifier.For("ToString")); if (method != null) { MethodCall call = new MethodCall(new MemberBinding(src, method), new ExpressionList(), NodeType.Call, SystemTypes.String); if (!src.Type.IsValueType) call.NodeType = NodeType.Callvirt; return call; } } } return null; }
bool AddReadSimpleType(TypeNode simpleType, StatementList statements, Identifier reader, Expression mb, Expression result, bool always) { TypeNode type = Unwrap(simpleType); string method = null; Expression conversion = null; if (type == SystemTypes.String) { method = "ReadStringElement"; } else if (type == SystemTypes.Boolean) { method = "ReadBool"; } else if (type == SystemTypes.Int8) { method = "ReadSByte"; } else if (type == SystemTypes.Char) { method = "ReadChar"; } else if (type == SystemTypes.DateTime) { method = "ReadDateTime"; } else if (type == SystemTypes.Decimal) { method = "ReadDecimal"; } else if (type == SystemTypes.Double) { method = "ReadDouble"; } else if (type == SystemTypes.Guid) { method = "ReadGuid"; } else if (type == SystemTypes.Int16) { method = "ReadInt16"; } else if (type == SystemTypes.Int32) { method = "ReadInt32"; } else if (type == SystemTypes.Int64) { method = "ReadInt64"; } else if (type == SystemTypes.UInt8) { method = "ReadInt8"; } else if (type == SystemTypes.Single) { method = "ReadSingle"; } else if (type == SystemTypes.TimeSpan) { method = "ReadTimeSpan"; } else if (type == SystemTypes.UInt16) { method = "ReadUInt16"; } else if (type == SystemTypes.UInt32) { method = "ReadUInt32"; } else if (type == SystemTypes.UInt64) { method = "ReadUInt64"; } else { // see if there's a type converter for it. conversion = GetConvertFromString(type, new MethodCall(new QualifiedIdentifier(reader, Identifier.For("ReadStringElement")), null), always); } if (method != null) { conversion = new MethodCall(new QualifiedIdentifier(reader, Identifier.For(method)), null, NodeType.Callvirt, type); } if (conversion == null) return false; // there is no simple conversion! statements.Add(new AssignmentStatement(mb, CastTo(conversion, simpleType))); if (result != null) statements.Add(new AssignmentStatement(result, Literal.True)); return true; }
private void GenerateMethodReturn(Block block, AssignmentStatement assignmentStatement, MethodCall call) { ZMethod method = (ZMethod)((MemberBinding)call.Callee).BoundMember; // Eventually, this will be checked by an earlier phase. Debug.Assert(method.Parameters.Count == call.Operands.Count); // process output parameters and the return value; for (int i = 0, n = call.Operands.Count; i < n; i++) { Parameter param = method.Parameters[i]; if ((param.Flags & ParameterFlags.Out) != 0 && call.Operands[i] != null && method.Parameters[i] != null) { Statement assignOutParam = Templates.GetStatementTemplate("FetchOutputParameter"); Replacer.Replace(assignOutParam, "_dest", this.VisitExpression(((UnaryExpression)call.Operands[i]).Operand)); Replacer.Replace(assignOutParam, "_paramName", new Identifier("_Lfc_" + method.Parameters[i].Name.Name)); Replacer.Replace(assignOutParam, "_Callee", method.Name); Replacer.Replace(assignOutParam, "_CalleeClass", method.DeclaringType.Name); block.Statements.Add(assignOutParam); } } if (assignmentStatement != null) { Statement assignReturnValue = Templates.GetStatementTemplate("FetchReturnValue"); Replacer.Replace(assignReturnValue, "_dest", this.VisitExpression(assignmentStatement.Target)); Replacer.Replace(assignReturnValue, "_CalleeClass", method.DeclaringType.Name); Replacer.Replace(assignReturnValue, "_Callee", method.Name); block.Statements.Add(assignReturnValue); } Statement stmt = Templates.GetStatementTemplate("InvalidateLastFunctionCompleted"); block.Statements.Add(stmt); }
private void GenerateMethodCall(Block block, MethodCall call, bool callIsAsync) { ZMethod method = (ZMethod)((MemberBinding)call.Callee).BoundMember; // Eventually, this will be checked by an earlier phase. Debug.Assert(method.Parameters.Count == call.Operands.Count); Statement createCallFrame; if (method.DeclaringType is Interface) { createCallFrame = Templates.GetStatementTemplate("CreateCallFrameForInterface"); Replacer.Replace(createCallFrame, "_thisExpr", this.VisitExpression(((MemberBinding)call.Callee).TargetObject)); Replacer.Replace(createCallFrame, "_CreateMethod", new Identifier("Create" + method.Name.Name)); } else { createCallFrame = Templates.GetStatementTemplate("CreateCallFrame"); } Replacer.Replace(createCallFrame, "_calleeClass", new Identifier(method.DeclaringType.FullName)); Replacer.Replace(createCallFrame, "_Callee", method.Name); block.Statements.Add(createCallFrame); // process input parameters for (int i = 0, n = call.Operands.Count; i < n; i++) { Parameter param = method.Parameters[i]; if ((param.Flags & ParameterFlags.Out) == 0 && call.Operands[i] != null && method.Parameters[i] != null) { Statement assignInParam = Templates.GetStatementTemplate("SetInputParameter"); Replacer.Replace(assignInParam, "_src", this.VisitExpression(call.Operands[i])); Replacer.Replace(assignInParam, "_paramName", new Identifier("priv_" + method.Parameters[i].Name.Name)); block.Statements.Add(assignInParam); } } if (!method.IsStatic) { Statement setThis = Templates.GetStatementTemplate("SetThis"); Replacer.Replace(setThis, "_thisExpr", this.VisitExpression(((MemberBinding)call.Callee).TargetObject)); block.Statements.Add(setThis); } if (callIsAsync) { ExpressionStatement asyncInvoke = (ExpressionStatement)Templates.GetStatementTemplate("InvokeAsyncMethod"); Replacer.Replace(asyncInvoke, "_methodName", new Literal(method.DeclaringType.Name.Name + "." + method.Name.Name, SystemTypes.String)); Replacer.Replace(asyncInvoke, "_context", splicer.SourceContextConstructor(call.SourceContext)); Replacer.Replace(asyncInvoke, "_contextAttr", splicer.ContextAttributeConstructor(attributes)); block.Statements.Add(asyncInvoke); } else { block.Statements.Add(Templates.GetStatementTemplate("InvokeMethod")); block.Statements.Add(Templates.GetStatementTemplate("SetIsCall")); } }
public override Expression VisitMethodCall(MethodCall call) { // We only reach this point for calls to predicate methods within "wait" // join conditions. ZMethod method = (ZMethod)((MemberBinding)call.Callee).BoundMember; ExpressionList ctorArgs; QualifiedIdentifier methodClass = new QualifiedIdentifier( new QualifiedIdentifier( new QualifiedIdentifier(Identifier.For("Z"), Identifier.For("Application")), method.DeclaringType.Name), method.Name); MethodCall predCall = new MethodCall( new QualifiedIdentifier(Identifier.For("p"), Identifier.For("CallPredicateMethod")), new ExpressionList( new Construct( new MemberBinding(null, new TypeExpression(methodClass)), ctorArgs = new ExpressionList()))); ctorArgs.Add(Identifier.For("application")); if (!method.IsStatic) ctorArgs.Add(this.VisitExpression(((MemberBinding)call.Callee).TargetObject)); for (int i = 0, n = call.Operands.Count; i < n; i++) ctorArgs.Add(this.VisitExpression(call.Operands[i])); return predCall; }
public override void VisitMethodCall(MethodCall call) { if (call == null) return; base.VisitMethodCall(call); if (call.Operands != null && call.Operands.Count > 0) return; var mb = call.Callee as MemberBinding; if (mb == null) return; if (!(mb.TargetObject is This)) return; var getter = mb.BoundMember as Method; if (getter == null) return; if (HelperMethods.Unspecialize(getter.DeclaringType) != this.containingType) return; if (!getter.IsPropertyGetter) return; if (!HelperMethods.IsAutoPropertyMember(getter)) return; if ((getter.ImplementedInterfaceMethods != null && 0 < getter.ImplementedInterfaceMethods.Count) || (getter.ImplicitlyImplementedInterfaceMethods != null && 0 < getter.ImplicitlyImplementedInterfaceMethods.Count) || getter.OverridesBaseClassMember) // if the property is an override/implementation, then it is going to inherit any contracts there might be from above { return; } // now we have an auto prop // make sure we have a setter too Property prop = getter.DeclaringMember as Property; if (prop == null) return; if (prop.Setter == null) return; if (!HelperMethods.IsAutoPropertyMember(prop.Setter)) return; if (!IsVisibilityOkay(prop)) return; this.foundAutoProperties.Add(prop); }
public override Expression VisitMethodCall(MethodCall call) { var result = base.VisitMethodCall(call); call = result as MethodCall; if (call == null) return result; var mb = call.Callee as MemberBinding; if (IsInvariantCall(mb)) { if (1 < call.Operands.Count) { Member dummy; this.userMessage = SanitizeUserMessageInternal(this.autoProp.Getter, call.Operands[1], out dummy); } if (2 < call.Operands.Count) { this.conditionString = call.Operands[2] as Literal; } return call.Operands[0]; } if (call.Operands.Count != 0) return call; // only nullary properties. if (IsAutoPropGetterCall(mb)) { if (makeRequires) { return this.autoProp.Setter.Parameters[0]; } return new ReturnValue(autoProp.Type); } return result; }
void AddCallDeserializer(TypeNode type, StatementList statements, Identifier reader, Expression target, Expression required, Expression result) { Class memberSerializer = this.CreateSerializerFor(type); // call the Deserialize method on it, and assign result to target object. ExpressionList args = new ExpressionList(); args.Add(reader); args.Add(required); if (result is Local) result = new UnaryExpression(result, NodeType.AddressOf); args.Add(result); MethodCall call = new MethodCall(); Method deserialize = memberSerializer.GetMethod(Identifier.For("Deserialize"), new TypeNode[3] { Runtime.XmlSerializationReader, SystemTypes.Boolean, SystemTypes.Boolean.GetReferenceType() } ); call.Callee = new MemberBinding(new MemberBinding(null, memberSerializer), deserialize); call.Operands = args; statements.Add(new AssignmentStatement(target, call)); }
bool AddWriteSimpleType(TypeNode simpleType, StatementList statements, TypeNode referringType, Identifier writer, Expression src, Expression name, Expression ns) { Identifier method = null; TypeNode type = Unwrap(simpleType); ExpressionList args = new ExpressionList(src); if (type == SystemTypes.String) { method = Identifier.For("WriteString"); } else if( type == SystemTypes.Boolean) { method = Identifier.For("WriteBoolean"); } else if( type == SystemTypes.Int8) { method = Identifier.For("WriteSByte"); } else if( type == SystemTypes.Char) { method = Identifier.For("WriteChar"); } else if( type == SystemTypes.DateTime) { method = Identifier.For("WriteDateTime"); } else if( type == SystemTypes.Decimal) { method = Identifier.For("WriteDecimal"); } else if( type == SystemTypes.Double) { method = Identifier.For("WriteDouble"); } else if( type == SystemTypes.Guid) { method = Identifier.For("WriteGuid"); } else if( type == SystemTypes.Int16) { method = Identifier.For("WriteInt16"); } else if( type == SystemTypes.Int32) { method = Identifier.For("WriteInt32"); } else if( type == SystemTypes.Int64) { method = Identifier.For("WriteInt64"); } else if( type == SystemTypes.UInt8) { method = Identifier.For("WriteByte"); } else if( type == SystemTypes.Single) { method = Identifier.For("WriteSingle"); } else if( type == SystemTypes.TimeSpan) { method = Identifier.For("WriteTimeSpan"); } else if( type == SystemTypes.UInt16 ) { method = Identifier.For("WriteUInt16"); } else if( type == SystemTypes.UInt32) { method = Identifier.For("WriteUInt32"); } else if( type == SystemTypes.UInt64) { method = Identifier.For("WriteUInt64"); } else { Expression conversion = GetConvertToString(type, src, false); if (conversion != null) { statements = AddCheckForNull(statements, Duplicate(src, referringType), type); method = Identifier.For("WriteString"); args = new ExpressionList(conversion); } else { return false; } } if (name != null) { Identifier id = Checker.GetDefaultElementName(type); string defaultName = id.Name; string defaultNamespace = (id.Prefix != null) ? id.Prefix.Name : null; Expression localName = new Local(SystemTypes.String); Expression localNamespace = new Local(SystemTypes.String); Expression safeName = name; if (name is Literal) { if (name == Literal.Null) { localName = new Literal(defaultName, SystemTypes.String); localNamespace = new Literal(defaultNamespace, SystemTypes.String); } else { localName = name; localNamespace = ns; } } else { If nameNull = new If(new BinaryExpression(name, Literal.Null, NodeType.Eq), new Block(new StatementList()), new Block(new StatementList())); nameNull.TrueBlock.Statements.Add(new AssignmentStatement(localName, new Literal(defaultName, SystemTypes.String))); nameNull.TrueBlock.Statements.Add(new AssignmentStatement(localNamespace, new Literal(defaultNamespace, SystemTypes.String))); nameNull.FalseBlock.Statements.Add(new AssignmentStatement(localName, name)); nameNull.FalseBlock.Statements.Add(new AssignmentStatement(localNamespace, ns)); statements.Add(nameNull); } MethodCall call = new MethodCall(); call.Callee = new QualifiedIdentifier(writer,Identifier.For("WriteStartElement")); call.Operands = new ExpressionList(); call.Operands.Add(localName); call.Operands.Add(localNamespace); statements.Add( new ExpressionStatement( call ) ); } StatementList notNull = statements; if (!type.IsValueType) { notNull = AddCheckForNull(statements, Duplicate(src, referringType), type); } notNull.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, method), args))); if (name != null) { MethodCall call = new MethodCall(); call.Callee = new QualifiedIdentifier(writer,Identifier.For("WriteEndElement")); call.Operands = new ExpressionList(); statements.Add( new ExpressionStatement( call ) ); } return true; }
// The method added by Jiri Adamek // It generates NAtiveZOM calls private void GenerateNativeZOMCall(Block block, MethodCall call, bool callIsAsync, AssignmentStatement assignmentStatement) { ZMethod method = (ZMethod)((MemberBinding)call.Callee).BoundMember; // Eventually, this will be checked by an earlier phase. Debug.Assert(method.Parameters.Count == call.Operands.Count); // Asynchronous calls Debug.Assert(!callIsAsync, "async not supporrted for NativeZOM calls"); // Debugging - parameters for (int i = 0, n = call.Operands.Count; i < n; i++) { Parameter param = method.Parameters[i]; Debug.Assert(param != null); // In fact, call.operands[i] MAY BE null due to the error recovery (if the type of the // expression does not match the type in the method definition) // // Debug.Assert(call.Operands[i] != null); Debug.Assert((param.Flags & ParameterFlags.Out) == 0, "out parameters not supported for NativeZOM calls"); } Expression typename = new QualifiedIdentifier(new Identifier("Microsoft.Zing"), method.DeclaringType.Name); Expression callee; if (!method.IsStatic) { callee = Templates.GetExpressionTemplate("NativeZOMCallee"); Replacer.Replace(callee, "_TypeName", typename); Expression pointer = this.VisitExpression(((MemberBinding)call.Callee).TargetObject); Replacer.Replace(callee, "_Pointer", pointer); Replacer.Replace(callee, "_MethodName", method.Name); } else { callee = Templates.GetExpressionTemplate("NativeZOMStaticCall"); Replacer.Replace(callee, "_ClassName", typename); Replacer.Replace(callee, "_MethodName", method.Name); } ExpressionList argumentList = new ExpressionList(); argumentList.Add(Templates.GetExpressionTemplate("NativeZOMCallFirstArgument")); foreach (Expression operand in call.Operands) argumentList.Add(this.VisitExpression(operand)); MethodCall nativeCall = new MethodCall(callee, argumentList); Statement newStatement; if (assignmentStatement != null) { newStatement = Templates.GetStatementTemplate("NativeZOMCallWithAssignment"); Replacer.Replace(newStatement, "_Dest", this.VisitExpression(assignmentStatement.Target)); Replacer.Replace(newStatement, "_Source", nativeCall); } else { newStatement = new ExpressionStatement(nativeCall); } block.Statements.Add(newStatement); }
internal Class CreateSerializerFor(TypeNode type) { // todo: look in the genCache for other serializer assemblies that may have already // created the serializer for this type and make an assembly reference to that // serializer instead of creating a complete duplicate. TypeNode saved = tempChecker.currentType; Class c = (Class)serializers[type]; if (c != null) return c; c = new Class(); c.Flags = TypeFlags.Class | TypeFlags.BeforeFieldInit; // copy the accessibility of the type we are serializing. c.Flags |= (type.Flags & (TypeFlags.Public | TypeFlags.NestedAssembly)); c.Name = Identifier.For(GetSerializerName(type)); c.Namespace = Identifier.For(GetSerializerNamespace(type)); c.DeclaringModule = this.module; c.Members = new MemberList(); c.Attributes = new AttributeList(); c.BaseClass = Runtime.XmlSerializer; tempChecker.currentType = c; InstanceInitializer ii = Runtime.XmlSerializerAttribute.GetConstructor(); MemberBinding mb = new MemberBinding(null, ii); mb.Type = Runtime.XmlSerializerAttribute; c.Attributes.Add(new AttributeNode(mb, null)); if (cunit != null) { cunit.Namespaces[0].Types.Add(c); } this.module.Types.Add(c); Identifier typeId = Identifier.For("type"); // what we are writing to. Identifier rootName = Identifier.For("rootName"); // what we are writing to. Identifier rootNamespace = Identifier.For("rootNamespace"); // what we are writing to. // Constructor Method constructor = new InstanceInitializer(); constructor.Name = StandardIds.Ctor; constructor.DeclaringType = c; constructor.Flags = MethodFlags.Public|MethodFlags.HideBySig|MethodFlags.SpecialName|MethodFlags.RTSpecialName; constructor.Parameters = new ParameterList(); constructor.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, typeId, SystemTypes.Type, null, null)); constructor.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootName, SystemTypes.String, null, null)); constructor.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootNamespace, SystemTypes.String, null, null)); constructor.ReturnType = SystemTypes.Void; c.Members.Add(constructor); // pass args thru to base XmlSerializer constructor. Block b = constructor.Body = new Block(new StatementList()); b.Statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(new Base(), StandardIds.Ctor), new ExpressionList(typeId, rootName, rootNamespace), NodeType.Call))); //AddConsoleWrite(b.Statements, new Literal("Hello!!",SystemTypes.String)); // Serialize(T source, XmlSerializationWriter writer) method Identifier src = Identifier.For("source"); // object being serialized. Identifier writer = Identifier.For("writer"); // what we are writing to. Method serialize = new Method(); serialize.Name = Identifier.For("Serialize"); serialize.DeclaringType = c; serialize.Flags = MethodFlags.Public|MethodFlags.Static|MethodFlags.HideBySig; serialize.Parameters = new ParameterList(); serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, src, type, null, null)); serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, writer, Runtime.XmlSerializationWriter, null, null)); serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootName, SystemTypes.String, null, null)); serialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, rootNamespace, SystemTypes.String, null, null)); serialize.ReturnType = SystemTypes.Void; c.Members.Add(serialize); // T Deserialize(XmlReader reader, bool required, out bool result) method Identifier reader = Identifier.For("reader"); // what we are reading from. Identifier required = Identifier.For("required"); // whether an object is required or not. Identifier result = Identifier.For("result"); // whether we found anything. Method deserialize = new Method(); deserialize.Name = Identifier.For("Deserialize"); deserialize.DeclaringType = c; deserialize.Flags = MethodFlags.Public|MethodFlags.Static|MethodFlags.HideBySig; deserialize.Parameters = new ParameterList(); deserialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, reader, Runtime.XmlSerializationReader, null, null)); deserialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.In, required, SystemTypes.Boolean, null, null)); deserialize.Parameters.Add(new Parameter(new AttributeList(), ParameterFlags.Out, result, SystemTypes.Boolean.GetReferenceType(), null, null)); deserialize.ReturnType = type; c.Members.Add(deserialize); // It is important that we add the serializer to the cache AFTER we create the methods, but // BEFORE we create the method bodies so that we can handle recurrsive calls to AddCallSerializer which // happens in recurrsive structures like "class Foo { public Foo f; }". Otherwise we'd get stuck in an // infinite loop. serializers[type] = c; // Body of serialize method. b = serialize.Body = new Block(new StatementList()); StatementList statements = b.Statements; if (!AddWriteSimpleType(type, statements, c, writer, src, rootName, rootNamespace)) { MethodCall call = new MethodCall(); call.Callee = new QualifiedIdentifier(writer,Identifier.For("WriteStartElement")); call.Operands = new ExpressionList(); call.Operands.Add(rootName); call.Operands.Add(rootNamespace); statements.Add(new If(new BinaryExpression(rootName,Literal.Null,NodeType.Ne), new Block(new StatementList(new ExpressionStatement(call))),null)); Expression source = src; if (type.Template == SystemTypes.GenericBoxed) { statements = AddCheckForNull(statements, Duplicate(src, c), type); type = Checker.GetCollectionElementType(type); source = CastTo(src, type);//unbox it } if (type is TupleType) { AddWriteTuple(type as TupleType, statements, c, source, writer); } else if (type is TypeUnion) { AddWriteChoice(type as TypeUnion, statements, c, source, writer); } else if (IsStream(type)) { AddWriteStream(type, statements, c, source, writer); } else { SchemaElementDecl sd = SchemaElementDecl.Compile(this.module, type, Checker.GetCollectionElementType(type), this.errorHandler, schemaElementDeclCache); SchemaValidator validator = validator = sd.CreateValidator(this.errorHandler); statements = AddCheckForNull(statements, Duplicate(src, c), type); AddWriteAttributes(statements, c, writer, source, validator); AddWriteContent(type, statements, c, writer, source, validator); } call = new MethodCall(); call.Callee = new QualifiedIdentifier(writer,Identifier.For("WriteEndElement")); call.Operands = new ExpressionList(); statements.Add(new If(new BinaryExpression(rootName,Literal.Null,NodeType.Ne), new Block(new StatementList(new ExpressionStatement(call))),null)); } // body of deserialize method. b = deserialize.Body = new Block(new StatementList()); statements = b.Statements; Local target = new Local(Identifier.Empty, type); if (type.Template == SystemTypes.GenericBoxed){ type = Checker.GetCollectionElementType(type); } if (type is TupleType) { AddReadTuple(b, type as TupleType, statements, reader, target, required, result); } else if (type is TypeUnion) { AddReadChoice(b, type as TypeUnion, statements, reader, target, required, result); } else if (IsStream(type)) { AddReadStream(b, type, statements, reader, target, result); } else { if (type is TypeAlias) { type = ((TypeAlias)type).AliasedType; } // Then we are already positioned on the element to be deserialized. statements.Add(new AssignmentStatement(required, Literal.True)); if (!AddReadSimpleType(type, statements, reader, target, result, false)) { if (!type.IsValueType && !type.IsAbstract && type.GetConstructor() != null) { Construct cons = new Construct(new MemberBinding(null, type), new ExpressionList(), type); statements.Add(new AssignmentStatement(target, cons)); } SchemaElementDecl sd = SchemaElementDecl.Compile(this.module, type, Checker.GetCollectionElementType(type), this.errorHandler, schemaElementDeclCache); SchemaValidator validator = validator = sd.CreateValidator(this.errorHandler); AddReadAttributes(type, statements, reader, target, validator); AddReadContent(c, b, type, statements, reader, target, required, result, validator); } } statements.Add(new Return(target)); tempChecker.currentType = saved; return c; }
public override Expression VisitMethodCall(MethodCall mc){ Expression result = base.VisitMethodCall(mc); mc = result as MethodCall; // check for Aggregate types if (mc != null && mc.Operands != null && mc.Operands.Count == 1) { Literal lit = mc.Callee as Literal; if (lit != null && lit.Type == SystemTypes.Type) { TypeNode type = (TypeNode) lit.Value; if (type != null && type.IsAssignableTo(SystemTypes.IAggregateGroup)) { QueryAggregate qa = new QueryAggregate(); qa.Name = type.Name; qa.AggregateType = type; qa.Expression = mc.Operands[0]; qa.SourceContext = mc.SourceContext; if (this.currentGroup != null) { this.currentGroup.AggregateList.Add(qa); qa.Group = this.currentGroup; } return qa; } } } return result; }
Expression GetConvertFromString(TypeNode targetType, Expression src, bool always) { if (targetType == SystemTypes.String) return src;// nothing to do! if (targetType is EnumNode) { // e.g. return (DayOfWeek)Enum.Parse(typeof(DayOfWeek),"Sunday"); Method method = SystemTypes.Enum.GetMethod(Identifier.For("Parse"), new TypeNode[2]{ SystemTypes.Type, SystemTypes.String}); UnaryExpression typeOfEnum = new UnaryExpression(new MemberBinding(null, targetType), NodeType.Typeof); MethodCall call = new MethodCall(new MemberBinding(new MemberBinding(null, targetType), method), new ExpressionList(new Expression[2]{typeOfEnum, src }), NodeType.Call, SystemTypes.Object); return CastTo(call, targetType); } // See if it has a type converter. Class converterClass = Checker.GetTypeConverter(targetType); if (converterClass != null) { TypeConverter converter = TypeDescriptor.GetConverter(targetType.GetRuntimeType()); if (converter != null) { Type converterType = converter.GetType(); AssemblyNode converterAssembly = AssemblyNode.GetAssembly(converterType.Assembly, cache, false, true); converterClass = converterAssembly.GetType(Identifier.For(converterType.Namespace), Identifier.For(converterType.Name)) as Class; Expression e = tempChecker.GetConverterFromString(converter, converterClass, SystemTypes.String, src, SystemTypes.Object); if (e != null) { //Do I need to add namespace and assembly reference for type converter? return CastTo(e, targetType); } } } if (always) { // e.g. return PointArray.Parse("10,20 30,40 50,60"); Method method = targetType.GetImplicitCoercionFromMethod(SystemTypes.String); if (method == null) { method = targetType.GetMethod(Identifier.For("Parse"), new TypeNode[1]{ SystemTypes.String}); } if (method != null) { MemberBinding typeBinding = new MemberBinding(null, targetType); MethodCall call = new MethodCall(new MemberBinding(typeBinding, method), new ExpressionList(new Expression[1]{ src }), NodeType.Call, targetType ); return call; } } return null; }
public override InstanceInitializer InjectDefaultConstructor(TypeNode typeNode) { if (this.DontInjectDefaultConstructors || typeNode.IsNormalized) return null; Class Class = typeNode as Class; if (Class != null && Class.Name != null && !(Class is ClassParameter) && ClassHasNoExplicitConstructors(typeNode)) { if (Class.IsAbstractSealedContainerForStatics) return null; if (Class.PartiallyDefines != null){ this.InjectDefaultConstructor(Class.PartiallyDefines); InstanceInitializer defCons = Class.PartiallyDefines.GetConstructor(); if (defCons != null && !defCons.HasCompilerGeneratedSignature) defCons = null; //Not an orphan if (defCons != null){ //This is an injected default constructor that is an orphan, adopt it defCons.HasCompilerGeneratedSignature = false; //abuse this flag to stop other partial types from adopting it Class.Members.Add(defCons); Class.BaseClass = ((Class)Class.PartiallyDefines).BaseClass; } return defCons; //Ok if defCons null, this type should not show up in inheritance chains }else{ //Inject a default constructor This thisParameter = new This(Class); Class baseClass = Class.BaseClass; StatementList statements = new StatementList(2); statements.Add(new FieldInitializerBlock(typeNode, false)); if (baseClass != null) { MethodCall mcall = new MethodCall(new QualifiedIdentifier(new Base(), StandardIds.Ctor, typeNode.Name.SourceContext), null); mcall.SourceContext = typeNode.Name.SourceContext; ExpressionStatement callSupCons = new ExpressionStatement(mcall); callSupCons.SourceContext = typeNode.Name.SourceContext; statements.Add(callSupCons); } InstanceInitializer defCons = new InstanceInitializer(typeNode, null, null, new Block(statements)); defCons.Name = new Identifier(".ctor", typeNode.Name.SourceContext); defCons.SourceContext = typeNode.Name.SourceContext; defCons.ThisParameter = thisParameter; if (typeNode.IsAbstract) defCons.Flags |= MethodFlags.Family|MethodFlags.HideBySig; else defCons.Flags |= MethodFlags.Public|MethodFlags.HideBySig; defCons.CallingConvention = CallingConventionFlags.HasThis; defCons.IsCompilerGenerated = true; typeNode.Members.Add(defCons); return defCons; } } return null; }
void AddWriteChoice(TypeUnion tu, StatementList statements, TypeNode referringType, Expression src, Identifier writer) { // generate the following code: // Type srcType = src.GetType(); // if (choiceType.IsAssignableFrom(srcType)){ // XxxxSerializer s = new XxxxSerializer(); // s.Serialize((runtimeType)src, writer); // } else if (...) { // // and so on. // } // What we cannot do here is by creating nested XmlSerializers // based on runtime type because this could cause infinite recurrsion. // So we cannot serialize a type union where one of the choices is "object". TypeNodeList choices = tu.Types; MethodCall call = new MethodCall(); call.Callee = new QualifiedIdentifier(src, Identifier.For("GetType")); call.Operands = new ExpressionList(); Local local = new Local(SystemTypes.Type); statements.Add(new AssignmentStatement(local, call)); for (int i = 0, n = choices.Length; i < n; i++) { TypeNode choiceType = choices[i]; if (choiceType == null) continue; // type resolution error. // if (choiceType.IsAssignableFrom(srcType)){ BinaryExpression condition = new BinaryExpression( new MethodCall( new QualifiedIdentifier(new UnaryExpression(new MemberBinding(null, choiceType), NodeType.Typeof), Identifier.For("IsAssignableFrom")), new ExpressionList(new Expression[] { local })), Literal.True, NodeType.Eq); Block block = new Block(); block.Statements = new StatementList(); BinaryExpression cast = CastTo(src, choiceType); Expression name = null, ns = null; GetNameAndNamespace(choiceType, out name, out ns); Expression simplename = name, simplens = ns; // Check for choice of type: [string] and match this with XmlTextNode. TypeNode unwrapped = UnwrapSingletonTuple(choiceType, true); if (unwrapped == null) unwrapped = choiceType; if (unwrapped != null && unwrapped.IsPrimitive) { simplename = simplens = null; choiceType = unwrapped; } if (!AddWriteSimpleType(choiceType, block.Statements, referringType, writer, cast, simplename, simplens)) { AddCallSerializer(choiceType, block.Statements, cast, writer, name, ns); } If ifStatement = new If(condition, block, null); statements.Add(ifStatement); } }
void AddReadOptional(Block block, StatementList statements, Member mem, Expression target, Identifier reader, Expression result) { TypeNode boxed = Checker.GetMemberType(mem); TypeNode type = Checker.GetCollectionElementType(boxed); statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("MoveToContent")), new ExpressionList()))); Local nameLocal = new Local(Identifier.For("name"),SystemTypes.String, block); Local nsLocal = new Local(Identifier.For("ns"),SystemTypes.String, block); statements.Add(new AssignmentStatement(nameLocal, new QualifiedIdentifier(reader, Identifier.For("LocalName")))); statements.Add(new AssignmentStatement(nsLocal, new QualifiedIdentifier(reader, Identifier.For("NamespaceURI")))); StringBuilder expecting = new StringBuilder(); Expression isFound = null; if (mem.IsAnonymous) { isFound = IsStartOf(block, type, statements, nameLocal, nsLocal, expecting); } else { ExpressionList args = new ExpressionList(); args.Add(new Literal(mem.Name.Name, SystemTypes.String)); isFound = new MethodCall(new QualifiedIdentifier(reader, Identifier.For("IsStartElement")), args); } StatementList trueStatements = new StatementList(); If ifIsFound = new If(isFound, new Block(trueStatements), null); statements.Add(ifIsFound); if (!AddReadSimpleType(type, trueStatements, reader, target, result, false)) { Local localRequired = new Local(Identifier.Empty,SystemTypes.Boolean,block); statements.Add(new AssignmentStatement(localRequired, Literal.True)); AddCallDeserializer(type, trueStatements, reader, target, localRequired, result); } }
void AddReadAllGroup(Class serializer, Block block, TypeNode type, StatementList statements, Identifier reader, Expression target, Expression required, Expression result, ArrayList members, Member mixedMember) { // todo: keep track of which members have been read and report error on duplicates MethodCall read = new MethodCall(new QualifiedIdentifier(reader, Identifier.For("Read")), new ExpressionList()); Local sb = new Local(SystemTypes.StringBuilder); bool isMixed = mixedMember != null; if (isMixed) { statements.Add(new AssignmentStatement(sb, new Construct(new MemberBinding(null, SystemTypes.StringBuilder), new ExpressionList(), SystemTypes.StringBuilder))); } Block whileBody = new Block(new StatementList()); BinaryExpression notEndTag = new BinaryExpression( new QualifiedIdentifier(reader, Identifier.For("NodeType")) , new QualifiedIdentifier(Identifier.For("XmlNodeType"), Identifier.For("EndElement")), NodeType.Ne); BinaryExpression notEOF = new BinaryExpression( new QualifiedIdentifier(reader, Identifier.For("EOF")), Literal.True, NodeType.Ne); While w = new While(new BinaryExpression(notEndTag, notEOF, NodeType.And), whileBody); statements.Add(w); Local nameLocal = new Local(Identifier.For("name"),SystemTypes.String,block); Local nsLocal = new Local(Identifier.For("ns"),SystemTypes.String,block); Local nodeType = new Local(Identifier.For("nodeType"),Runtime.XmlNodeType,block); whileBody.Statements.Add(new AssignmentStatement(nameLocal, new QualifiedIdentifier(reader, Identifier.For("LocalName")))); whileBody.Statements.Add(new AssignmentStatement(nsLocal, new QualifiedIdentifier(reader, Identifier.For("NamespaceURI")))); whileBody.Statements.Add(new AssignmentStatement(nodeType, new QualifiedIdentifier(reader, Identifier.For("NodeType")))); Block childBlock = whileBody; if (isMixed) { // Append the text node to the current StringBuilder contents. childBlock = new Block(new StatementList()); If ifText = new If(IsTextNode(nodeType), new Block(new StatementList()), childBlock); whileBody.Statements.Add(ifText); ExpressionList args = new ExpressionList(); args.Add(new QualifiedIdentifier(reader, Identifier.For("Value"))); ifText.TrueBlock.Statements.Add(new ExpressionStatement(new MethodCall( new QualifiedIdentifier(sb, Identifier.For("Append")), args))); ifText.TrueBlock.Statements.Add(new ExpressionStatement(read)); // advance to next node } If ifElement = new If(new BinaryExpression(nodeType, new QualifiedIdentifier(Identifier.For("XmlNodeType"), Identifier.For("Element")), NodeType.Eq), new Block(new StatementList()), new Block(new StatementList())); childBlock.Statements.Add(ifElement); childBlock = ifElement.TrueBlock; //AddConsoleWrite(statements, new Literal("name=",SystemTypes.String)); //AddConsoleWriteLine(statements, nameLocal); //AddConsoleWrite(statements, new Literal("nodeType=",SystemTypes.String)); //AddConsoleWriteLine(statements, nodeType); foreach (NamedNode childNode in members) { if (!(childNode.Member is Field || childNode.Member is Property)) { AddError(statements, reader, RuntimeError.SerializationOfTypeNotSupported, new Literal(childNode.Member.GetType().FullName, SystemTypes.String)); } else { Expression mb = GetMemberBinding(target, childNode.Member); childBlock = AddReadChild(block, childBlock.Statements, childNode.Name, childNode.TypeNode, mb, reader, result, true, false).FalseBlock; // todo: throw error if child is required. (e.g. NonEmptyIEnumerable...) } } // if it isn't any of the expected elements then throw an error. AddError(childBlock.Statements, reader, RuntimeError.NoSuchMember, new Expression[2]{new Literal(tempChecker.GetTypeName(type),SystemTypes.String), nameLocal}); // If it's not an element then consume it anyway to keep the reader advancing. // Probably a comment or PI or something. ifElement.FalseBlock.Statements.Add(new ExpressionStatement(new MethodCall( new QualifiedIdentifier(reader, Identifier.For("Skip")), new ExpressionList()))); if (isMixed) { statements.Add(new AssignmentStatement(GetMemberBinding(target, mixedMember), new MethodCall(new QualifiedIdentifier(sb, Identifier.For("ToString")), new ExpressionList()))); } statements.Add(new AssignmentStatement(result, Literal.True)); }
void AddReadChoice(Block block, TypeUnion tu, StatementList statements, Identifier reader, Expression target, Expression required, Expression result){ // Read next element and figure out which of the choices in the type union it is then read the matching Type. Local nameLocal = new Local(Identifier.For("name"),SystemTypes.String,block); Local nsLocal = new Local(Identifier.For("ns"),SystemTypes.String,block); Local nodeType = new Local(Identifier.For("nodeType"),Runtime.XmlNodeType,block); statements.Add(new AssignmentStatement(nameLocal, new QualifiedIdentifier(reader, Identifier.For("LocalName")))); statements.Add(new AssignmentStatement(nsLocal, new QualifiedIdentifier(reader, Identifier.For("NamespaceURI")))); statements.Add(new AssignmentStatement(nodeType, new QualifiedIdentifier(reader, Identifier.For("NodeType")))); Local localRequired = new Local(Identifier.Empty,SystemTypes.Boolean,block); statements.Add(new AssignmentStatement(localRequired, Literal.True)); Expression readString = new MethodCall(new QualifiedIdentifier(reader, Identifier.For("ReadString")), null, NodeType.Callvirt, SystemTypes.String); If ifIsElement = new If(new BinaryExpression(nodeType, new QualifiedIdentifier(Identifier.For("XmlNodeType"), Identifier.For("Element")), NodeType.Eq), new Block(new StatementList()), new Block(new StatementList())); statements.Add(ifIsElement); StatementList elseList = ifIsElement.TrueBlock.Statements; StringBuilder expecting = new StringBuilder(); Expression bestCoercion = null; TypeNode bestChoice = null; TypeNode bestUnwrappedChoice = null; bool stringCoercionAmbiguous = false; for (int i = 0, n = tu.Types.Length; i < n; i++) { TypeNode choice = tu.Types[i]; if (choice == null) continue; // type resolution error. TypeNode unwrapped = UnwrapSingletonTuple(Unwrap(choice), false); if (unwrapped == null) unwrapped = choice; Expression coercion = GetConvertFromString(unwrapped, readString, false); if (coercion != null) { // Keep track of the best coercion to string and use this to handle text nodes below. if (bestChoice == null){ bestChoice = choice; bestUnwrappedChoice = unwrapped; bestCoercion = coercion; } else if (tempTypeSystem.IsBetterMatch(unwrapped, bestUnwrappedChoice, SystemTypes.String)) { bestChoice = choice; bestUnwrappedChoice = unwrapped; bestCoercion = coercion; } else { stringCoercionAmbiguous = true; } } BinaryExpression be = IsStartOf(block, choice, statements, nameLocal, nsLocal, expecting); StatementList trueStatements = new StatementList(); If ifIsStartOf = new If(be, new Block(trueStatements), new Block(new StatementList())); elseList.Add(ifIsStartOf); Local choiceTarget = new Local(Identifier.Empty, choice, block); if (choice.Template == SystemTypes.GenericBoxed){ choice = Checker.GetCollectionElementType(choice); } if (!AddReadSimpleType(choice, trueStatements, reader, choiceTarget, result, false)) { AddCallDeserializer(choice, trueStatements, reader, choiceTarget, localRequired, result); } trueStatements.Add(new AssignmentStatement(target, CastTo(choiceTarget, target.Type))); elseList = ifIsStartOf.FalseBlock.Statements; } if (bestCoercion != null && !stringCoercionAmbiguous) { // Then we can also accept text nodes StatementList ifTextStatements = new StatementList(); If ifIsText = new If(IsTextNode(nodeType), new Block(ifTextStatements), null); ifIsElement.FalseBlock.Statements.Add(ifIsText); // then we can also handle text nodes in this choice. ifTextStatements.Add(new AssignmentStatement(target, CastTo(CastTo(bestCoercion, bestChoice), tu))); ifTextStatements.Add(new AssignmentStatement(result, Literal.True)); } // If this was a required element, then throw an error. If isRequired = new If(new BinaryExpression(required, Literal.True, NodeType.Eq), new Block(new StatementList()), new Block(new StatementList())); elseList.Add(isRequired); InvalidContent(isRequired.TrueBlock.Statements, reader, expecting.ToString()); isRequired.FalseBlock.Statements.Add(new AssignmentStatement(result, Literal.False)); }
public override Expression VisitMethodCall(MethodCall call) { if (call == null) return null; QualifiedIdentifier id = call.Callee as QualifiedIdentifier; if (id != null) { if (id.Identifier.Name == ".ctor") return call; } this.VisitExpression(call.Callee); Write("("); this.VisitExpressionList(call.Operands); Write(")"); return call; }
void AddReadStream(Block block, TypeNode type, StatementList statements, Identifier reader, Expression target, Expression result){ // Read next element and figure out if it matches the stream element type, if so read it and add it to the list // If not, then return (throw an error if there are no items and the list is the non-empty type). // flexArray = new flexarray(); // while (reader.Read() && read.NodeType != XmlNodeType.EndElement) { // if (reader.NodeType == XmlNodeType.Element) { // readchild(flexarray); // } // } // target = flexArray; Local nameLocal = new Local(Identifier.For("name"),SystemTypes.String, block); Local nsLocal = new Local(Identifier.For("ns"),SystemTypes.String, block); Local nodeType = new Local(Identifier.For("nodeType"),Runtime.XmlNodeType, block); Local optional = new Local(Identifier.Empty, SystemTypes.Boolean, block); Local foundChild = new Local(Identifier.Empty, SystemTypes.Boolean, block); statements.Add(new AssignmentStatement(optional, Literal.False)); TypeNode eType = Checker.GetCollectionElementType(type); Local local = new Local(Identifier.Empty, eType, block); Method addMethod = null; Local localArray = null; if (type.Template == SystemTypes.GenericBoxed) { addMethod = null; // only needs one! } else if (Checker.IsGenericList(type)) { //TODO: this call is invalid if the eType is not public TypeNode flexArrayType = SystemTypes.GenericList.GetTemplateInstance(this.module, eType); localArray = new Local(Identifier.For("stream"+streamCount++), flexArrayType, block); statements.Add(new AssignmentStatement(localArray, new Construct(new MemberBinding(null, flexArrayType), new ExpressionList(), flexArrayType))); addMethod = flexArrayType.GetMethod(Identifier.For("Add"), eType); } else { TypeNode arrayType = SystemTypes.ArrayList; localArray = new Local(Identifier.Empty, arrayType, block); statements.Add(new AssignmentStatement(localArray, new Construct(new MemberBinding(null, arrayType), new ExpressionList(), arrayType))); addMethod = arrayType.GetMethod(Identifier.For("Add"), SystemTypes.Object); } Block whileBody = new Block(new StatementList()); MethodCall moveToContent = new MethodCall(new QualifiedIdentifier(reader, Identifier.For("MoveToContent")), new ExpressionList()); BinaryExpression notAtEnd = new BinaryExpression(moveToContent, new QualifiedIdentifier(Identifier.For("XmlNodeType"), Identifier.For("EndElement")), NodeType.Ne); BinaryExpression notEOF = new BinaryExpression( new QualifiedIdentifier(reader, Identifier.For("EOF")), Literal.True, NodeType.Ne); While w = new While(new BinaryExpression(notAtEnd, notEOF, NodeType.And), whileBody); statements.Add(w); whileBody.Statements.Add(new AssignmentStatement(nameLocal, new QualifiedIdentifier(reader, Identifier.For("LocalName")))); whileBody.Statements.Add(new AssignmentStatement(nsLocal, new QualifiedIdentifier(reader, Identifier.For("NamespaceURI")))); whileBody.Statements.Add(new AssignmentStatement(nodeType, new QualifiedIdentifier(reader, Identifier.For("NodeType")))); StatementList trueStatements = whileBody.Statements; if (type.Template == SystemTypes.GenericBoxed){ type = Checker.GetCollectionElementType(type); } trueStatements.Add(new AssignmentStatement(foundChild, Literal.False)); if (eType is TupleType || eType is TypeUnion || IsStream(eType)) { AddCallDeserializer(eType, trueStatements, reader, local, optional, foundChild); } else { AddReadChild(whileBody, trueStatements, Checker.GetDefaultElementName(eType), eType, local, reader, foundChild, true, false); } If ifFound = new If(new BinaryExpression(foundChild, Literal.True, NodeType.Eq), new Block(new StatementList()), new Block(new StatementList())); ifFound.TrueBlock.Statements.Add(new AssignmentStatement(result, Literal.True)); // set our result to true then. ifFound.FalseBlock.Statements.Add(new Exit()); // break out of loop then. trueStatements.Add(ifFound); if (addMethod == null) { trueStatements.Add(new AssignmentStatement(target, CastTo(local, type))); // box the result. trueStatements.Add(new Exit()); // break out of loop we have it! } else { MemberBinding addCall = new MemberBinding(localArray, addMethod); trueStatements.Add(new ExpressionStatement(new MethodCall(addCall, new ExpressionList(new Expression[1] {local})))); } // clear out the local, it is a struct of some sort. if (local.Type.IsValueType && ! local.Type.IsPrimitive) { trueStatements.Add(new AssignmentStatement(local, new Construct(new MemberBinding(null,local.Type), new ExpressionList(), local.Type))); } // end while // assign resulting array to the target object (if we have anything to assign). If ifResult = new If(new BinaryExpression(result, Literal.True, NodeType.Eq), new Block(new StatementList()), null); statements.Add(ifResult); statements = ifResult.TrueBlock.Statements; if (addMethod != null) { if (type is ArrayType) { // target = (type)localArray.ToArray(etype); Method toArray = SystemTypes.ArrayList.GetMethod(Identifier.For("ToArray"), SystemTypes.Type); ExpressionList args = new ExpressionList(); args.Add(new UnaryExpression(new Literal(eType, SystemTypes.Type), NodeType.Typeof, SystemTypes.Type)); statements.Add(new AssignmentStatement(target, CastTo(new MethodCall(new MemberBinding(localArray, toArray), args, NodeType.Callvirt, SystemTypes.Array), type))); } else if (type.Template == SystemTypes.GenericNonEmptyIEnumerable) { // Explicit coercion of IEnumerable to NonEmptyIEnumerable requires constructing // the NonEmptyIEnumerable object passing in the IEnumerable as an argument. TypeNode ienumtype = Checker.GetIEnumerableTypeFromNonEmptyIEnumerableStruct(this.module, type); Debug.Assert(ienumtype!=null); //TODO: this call is invalid if the eType is not public TypeNode nonEmptyIEnum = SystemTypes.GenericNonEmptyIEnumerable.GetTemplateInstance(this.module, eType); InstanceInitializer ii = nonEmptyIEnum.GetConstructor(ienumtype); Construct c = new Construct(new MemberBinding(null, ii), new ExpressionList(localArray), nonEmptyIEnum); statements.Add(new AssignmentStatement(target, c)); } else { statements.Add(new AssignmentStatement(target, localArray)); } } }
/// <summary> /// Verifies that method calls are to pure methods. /// </summary> /// <param name="call">Call to inspect.</param> /// <returns><paramref name="call"/></returns> public override void VisitMethodCall(MethodCall call) { // F: Should it be a precondition? Contract.Assume(call != null); MemberBinding binding = call.Callee as MemberBinding; Method method = binding != null ? binding.BoundMember as Method : null; bool pure = this.contractNodes.IsPure(method); // F: For some reason the code below relies on method != null, and hence to binding call.Callee <: MemberBinding Contract.Assume(method != null); if (!this.fSharp && !pure && method != this.contractNodes.AssumeMethod) { // F: Contract.Assume(this.CurrentMethod != null); this.errorHandler(new Warning(1036, "Detected call to method '" + method.FullName + "' without [Pure] in contracts of method '" + this.CurrentMethod.FullName + "'.", this.lastSourceContext)); } // make sure we now assume this method is pure for the rest of the analysis if (!pure) { var template = method; while (template.Template != null) template = template.Template; if (template.Contract == null) { template.Contract = new MethodContract(template); } template.Contract.IsPure = true; } base.VisitMethodCall(call); }
If AddReadChild(Block scope, StatementList statements, Identifier name, TypeNode type, Expression target, Identifier reader, Expression result, bool unwrapChild, bool ignoreNamespace) { ExpressionList args = new ExpressionList(); args.Add(new Literal(name.Name, SystemTypes.String)); if (name.Prefix != null) args.Add(new Literal(name.Prefix.Name, SystemTypes.String)); // see if we're on a text node... Local nodeType = new Local(Identifier.For("nodeType"), Runtime.XmlNodeType, scope); statements.Add(new AssignmentStatement(nodeType, new QualifiedIdentifier(reader, Identifier.For("NodeType")))); StatementList ifTextStatements = new StatementList(); If ifIsText = new If( new BinaryExpression(IsTextNode(nodeType), new BinaryExpression(nodeType, new QualifiedIdentifier(Identifier.For("XmlNodeType"), Identifier.For("EndElement")), NodeType.Eq), NodeType.Or), new Block(ifTextStatements), new Block(new StatementList())); statements.Add(ifIsText); // then see if we can force the text into the desired type. TypeNode unwrapped = UnwrapSingletonTuple(Unwrap(type), false); if (unwrapped == null) unwrapped = type; Expression readString = new MethodCall(new QualifiedIdentifier(reader, Identifier.For("ReadString")), null, NodeType.Callvirt, SystemTypes.String); Expression coercion = GetConvertFromString(unwrapped, readString, false); if (coercion != null) { ifTextStatements = ifIsText.TrueBlock.Statements; ifTextStatements.Add(new AssignmentStatement(target, CastTo(CastTo(coercion, unwrapped),type))); ifTextStatements.Add(new AssignmentStatement(result, Literal.True)); } statements = ifIsText.FalseBlock.Statements; If ifFound = null; string method = ignoreNamespace ? "IsStartElementIgnoreNamespace" : "IsStartElement"; MethodCall isStartEle = new MethodCall(new QualifiedIdentifier(reader, Identifier.For(method)), args); ifFound = new If(isStartEle, new Block(new StatementList()), new Block(new StatementList())); statements.Add(ifFound); statements = ifFound.TrueBlock.Statements; statements.Add(new AssignmentStatement(result, Literal.True)); // body of if test, parse the child element as the specified type. MethodCall read = new MethodCall(new QualifiedIdentifier(reader, Identifier.For("Read")), new ExpressionList()); bool isStructuralType = this.IsStructuralType(type); if (isStructuralType && unwrapChild) { // consume member element wrapper. statements.Add(new ExpressionStatement(read)); } if (type.Template == SystemTypes.GenericBoxed){ type = Checker.GetCollectionElementType(type); } if (!AddReadSimpleType(type, statements, reader, target, result, false)) { AddCallDeserializer(type, statements, reader, target, result, result); } if (isStructuralType && unwrapChild) { // consume member element end tag wrapper. statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("ReadEndTag")), new ExpressionList(new Literal(name.Name, SystemTypes.String))))); } return ifFound; }