// // We add an implicit conversion from "object" to any of our heap-allocated // types. // // We also permit implicit conversions between "int" and "byte". // // TODO: We may need to construct a more elaborate expression here for the // conversion to permit the runtime to make the appropriate checks. // public override bool ImplicitCoercionFromTo(Expression source, TypeNode t1, TypeNode t2) { if (t1 == SystemTypes.Object) { if (t2 is Chan || t2 is Set || t2 is ZArray || t2 is Class) return true; else return false; } if (t2 == SystemTypes.Object) { if (t1 is Chan || t1 is Set || t1 is ZArray || t1 is Class) return true; else return false; } if (t1 == SystemTypes.Int32 && t2 == SystemTypes.UInt8) return true; if (t1 == SystemTypes.UInt8 && t2 == SystemTypes.Int32) return true; return base.ImplicitCoercionFromTo(source, t1, t2); }
public void CheckMethodSpecAdmissibility(Expression exp, Method method, bool reportWFonly, bool dontReport) { DeclaringMethod = method; ReportWFErrorOnly = reportWFonly; // true for Pure methods: we only want to enforce well-foundedness on them DontReportError = dontReport; StateStack = new System.Collections.Stack(); ResetCurrentState(); this.VisitExpression(exp); }
public override void VisitExpression(Expression expression) { if (expression == null) return; if (expression.NodeType == NodeType.Pop) PopOccurrences++; base.VisitExpression(expression); }
public AbbreviationDuplicator(Method sourceMethod, Method targetMethod, ContractNodes contractNodes, Method abbreviation, Expression targetObject, ExpressionList actuals) : base(targetMethod.DeclaringType.DeclaringModule, sourceMethod, targetMethod, contractNodes, false) { this.targetObject = targetObject; this.abbreviation = abbreviation; this.actuals = actuals; this.localsInActuals = new TrivialHashtable(); PopulateLocalsInActuals(); }
public override Expression ImplicitCoercion(Expression source, TypeNode targetType, TypeViewer typeViewer) { // LJW: added third parameter "typeViewer" so we override the correct thing if (source == null || source.Type == null || targetType == null) return null; if (source.Type is EnumNode && targetType == SystemTypes.Int32) { return source; } if (source.Type == SystemTypes.Object) { if (targetType is Chan || targetType is Set || targetType is ZArray || targetType is Class) return source; else { this.HandleError(source, System.Compiler.Error.NoImplicitCoercion, "object", targetType.FullName); return null; } } if (targetType == SystemTypes.Object) { if (!(source.Type is Chan || source.Type is Set || source.Type is ZArray || source.Type is Class)) { this.HandleError(source, System.Compiler.Error.NoImplicitCoercion, source.Type.FullName, "object"); return null; } } if (source.Type == SystemTypes.Int32 && targetType == SystemTypes.UInt8) { BinaryExpression binExpr = new BinaryExpression(source, new MemberBinding(null, SystemTypes.UInt8), NodeType.Castclass, source.SourceContext); binExpr.Type = SystemTypes.UInt8; return binExpr; } if (source.Type == SystemTypes.UInt8 && targetType == SystemTypes.Int32) { BinaryExpression binExpr = new BinaryExpression(source, new MemberBinding(null, SystemTypes.Int32), NodeType.Castclass, source.SourceContext); binExpr.Type = SystemTypes.Int32; return binExpr; } return base.ImplicitCoercion(source, targetType, typeViewer); }
internal static Statement GenerateForLoop(Variable loopVariable, Expression lowerBound, Expression upperBound, Statement body) { Block bodyAsBlock = body as Block ?? new Block(new StatementList(body)); Block init = new Block(new StatementList(2)); Block increment = new Block(new StatementList(1)); Block test = new Block(new StatementList(new Branch( new BinaryExpression(loopVariable, upperBound, NodeType.Lt), bodyAsBlock))); //, false, true, false))); init.Statements.Add(new AssignmentStatement(loopVariable, lowerBound)); init.Statements.Add(new Branch(null, test)); increment.Statements.Add(new AssignmentStatement(loopVariable, new BinaryExpression(loopVariable, Literal.Int32One, NodeType.Add))); Block forLoop = new Block(new StatementList(4)); forLoop.Statements.Add(init); forLoop.Statements.Add(bodyAsBlock); forLoop.Statements.Add(increment); forLoop.Statements.Add(test); return forLoop; }
public void VisitPop(Expression expression) { if (expression == null) { VisitPop(); return; } // a pop where we know what we pop. this.VisitPop(); }
public override Expression VisitExpression(Expression expression) { Expression result = base.VisitExpression(expression); return 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 AddReadContent(Class serializer, Block block, TypeNode type, StatementList statements, Identifier reader, Expression target, Expression required, Expression result, SchemaValidator validator) { // position us in the content. statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("MoveToContent")), new ExpressionList()))); Local elementName = new Local(Identifier.Empty,SystemTypes.String); statements.Add(new AssignmentStatement(elementName, new QualifiedIdentifier(reader, Identifier.For("LocalName")))); // make sure the element is not empty. If isEmpty = AddEmptyElementCheck(statements, reader); // Read the contents. statements = isEmpty.FalseBlock.Statements; statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("Read")), new ExpressionList()))); statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("MoveToContent")), new ExpressionList()))); ValidationState context = new ValidationState(); context.ErrorHandler = this.errorHandler; validator.validator.InitValidation(context); ArrayList members = null; if (validator.validator is AllElementsContentValidator) { members = validator.validator.ExpectedElements(context, false, false); AddReadAllGroup(serializer, block, type, statements, reader, target, required, result, members, validator.validator.MixedMember); } else { // There should be one root level anonymous Item0 member. SequenceNode seq = (SequenceNode)validator.RootNode; // this is a wrapper node. if (seq == null) { // perhaps it is ContentType.Empty or Mixed. if (validator.validator.ContentType == XmlSchemaContentType.Mixed || validator.validator.ContentType == XmlSchemaContentType.TextOnly){ Debug.Assert(validator.validator.MixedMember != null); statements.Add(new AssignmentStatement(GetMemberBinding(target, validator.validator.MixedMember), new MethodCall(new QualifiedIdentifier(reader, Identifier.For("ReadStringElement")), new ExpressionList()))); } return; } else { ContentNode n = seq.LeftChild; AddReadContentNode(n, block, statements, reader, target, required, result, validator); } } // consume final end tag statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("ReadEndTag")), new ExpressionList(elementName)))); }
void GetNameAndNamespace(TypeNode type, out Expression name, out Expression ns) { name = Literal.Null; ns = Literal.Null; if (!IsStructuralType(type)) { Identifier id = Checker.GetDefaultElementName(type); name = new Literal(id.Name, SystemTypes.String); if (id.Prefix != null) { ns = new Literal(id.Prefix.Name, SystemTypes.String); } } }
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 AddWriteAttributes(StatementList statements, TypeNode referringType, Identifier writer, Expression source, SchemaValidator validator) { if (validator.Attributes != null) { foreach (SchemaAttDef ad in validator.Attributes) { Identifier name = ad.Name; Expression src = GetMemberBinding(source, ad.Member); if (src.Type == null) continue; // type resolution error. if (!AddWriteSimpleAttribute(src.Type, name, statements, referringType, writer, src)) { // throw exception, attribute has complex type! } } } }
StatementList AddCheckForNull(StatementList statements, Expression src, TypeNode type) { if (type.Template == SystemTypes.GenericBoxed) { If checknull = new If(new BinaryExpression( new MethodCall(new MemberBinding(src, type.GetMethod(Identifier.For("IsNull"),null)), new ExpressionList()), Literal.True, NodeType.Ne), new Block(new StatementList()), null); statements.Add(checknull); return checknull.TrueBlock.Statements; } else if (type is TypeAlias) { // cast to underlying type and check that for null. TypeNode atype = ((TypeAlias)type).AliasedType; return AddCheckForNull(statements, CastTo(src, atype), atype); } else if (type is ConstrainedType) { // cast to underlying type and check that for null. TypeNode atype = ((ConstrainedType)type).UnderlyingType; return AddCheckForNull(statements, CastTo(src, atype), atype); } else if (!IsStream(type) && !type.IsValueType) { //stream types are doing weird things to the null check? if (type == SystemTypes.String || IsStream(type)) src = CastTo(src, SystemTypes.Object); If checknull = new If(new BinaryExpression(src, Literal.Null, NodeType.Ne), new Block(new StatementList()), null); statements.Add(checknull); return checknull.TrueBlock.Statements; } return statements; }
Expression Duplicate(Expression e, TypeNode referringType) { Duplicator dup = new Duplicator(this.module, referringType); return dup.VisitExpression(e); }
void AddWriteMember(Member child, Identifier name, StatementList statements, TypeNode referringType, Expression src, Identifier writer, bool emptyElementOnNull) { src = GetMemberBinding(src, child); TypeNode type = src.Type; if (type == null) return; if (type.Template == SystemTypes.GenericBoxed) { statements = AddCheckForNull(statements, Duplicate(src, referringType), type); type = Checker.GetCollectionElementType(type); src = CastTo(src, type);//unbox it } if (child.IsAnonymous) { if (type is TypeAlias) { TypeAlias alias = (TypeAlias)type; src = CastTo(src, alias.AliasedType); //unbox it AddWriteElement(statements, referringType, writer, alias.Name, src, alias.AliasedType, emptyElementOnNull); } else if (!AddWriteSimpleType(type, statements, referringType, writer, src, Literal.Null, Literal.Null)) { if (type is TupleType || type is TypeUnion || IsStream(type)) { AddCallSerializer(type, statements, src, writer, Literal.Null, Literal.Null); } else { AddWriteElement(statements, referringType, writer, type.Name, src, type, emptyElementOnNull); } } } else if (type is TypeAlias) { TypeAlias alias = (TypeAlias)type; src = CastTo(src, alias.AliasedType); //unbox it AddWriteElement(statements, referringType, writer, name, src, alias.AliasedType, emptyElementOnNull); } else { AddWriteElement(statements, referringType, writer, name, src, type, emptyElementOnNull); } }
void AddWriteTuple(TupleType tuple, StatementList statements, TypeNode referringType, Expression src, Identifier writer) { TypeNode singleton = UnwrapSingletonTuple(tuple, true); if (singleton != null && singleton == SystemTypes.String) { // special case which looks like mixed content. // happens a lot when XML Schema contains SimpleTypes that extend xsd:string. AddWriteSimpleType(singleton, statements, referringType, writer, src, null, null); } else { for (int i = 0, n = tuple.Members.Length; i < n; i++) { Member child = tuple.Members[i]; if (child is Field) { Field f = (Field)child; if (f.Type == null) continue; // type resolution error. // bugbug - what about [XmlElement] custom attributes? AddWriteMember(f, f.Name, statements, referringType, src, writer, true); } } } }
MemberBinding GetMemberBinding(Expression source, Member m) { MemberBinding src = new MemberBinding(source, m); src.Type = Checker.GetMemberType(m); return src; }
void AddWriteStream(TypeNode type, StatementList statements, TypeNode referringType, Expression src, Identifier writer) { // Generate the following code: // XxxxSerializer s = new XxxxSerializer(); // foreach (Xxxx x in src) { // s.Serialize(x,writer); // } // Where Xxxx is the element type for the given stream type. if (type.Template == SystemTypes.GenericNonEmptyIEnumerable) { type = Checker.GetIEnumerableTypeFromNonEmptyIEnumerableStruct(this.module, type); } else { statements = AddCheckForNull(statements, Duplicate(src, referringType), type); } TypeNode ceType = Checker.GetCollectionElementType(type); //todo: should check that type has an IEnumerator. Identifier loopVariable = Identifier.For("e"); loopVariable.Type = ceType; Block body = new Block(); body.Statements = new StatementList(); Expression name, ns; GetNameAndNamespace(ceType, out name, out ns); // call the Serialize method on it, passing the member we're serializing. if (!AddWriteSimpleType(ceType, body.Statements, referringType, writer, loopVariable, name, ns)) { AddCallSerializer(ceType, body.Statements, loopVariable, writer, name, ns); } ForEach fe = new ForEach(ceType, loopVariable, src, body); statements.Add(fe); }
MemberBinding GetMemberBinding(Expression source, Member m, TypeNode t) { MemberBinding src = new MemberBinding(source, m); src.Type = t; return src; }
//================= 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 AddWriteContent(TypeNode type, StatementList statements, TypeNode referringType, Identifier writer, Expression source, SchemaValidator validator) { if (validator.validator is AllElementsContentValidator) { ValidationState context = new ValidationState(); context.ErrorHandler = this.errorHandler; validator.validator.InitValidation(context); ArrayList members = validator.validator.ExpectedElements(context, false, false); foreach (NamedNode childNode in members) { if (childNode.TypeNode == null) continue; // type resolution error. Expression src = GetMemberBinding(source, childNode.Member, childNode.TypeNode); AddWriteElement(statements, referringType, writer, childNode.Name, src, childNode.TypeNode, false); } } else { // Note: there is a SequenceNode wrapper we need to remove and throw away. SequenceNode seq = validator.RootNode as SequenceNode; if (seq != null) { // if seq is null then it's ContentType.Empty or Mixed and mixed is handled at the end. ContentNode n = seq.LeftChild; AddWriteContentNode(n, statements, referringType, writer, source); } } Member mixed = validator.validator.MixedMember; if (mixed != null) { MemberBinding mb = GetMemberBinding(source, mixed); if (mb.Type != null) AddWriteString(statements, referringType, writer, mb); } }
void AddReadContentNode(ContentNode n, Block block, StatementList statements, Identifier reader, Expression target, Expression required, Expression result, SchemaValidator validator) { if (n.TypeNode == null) { Debug.Assert(n is SequenceNode); // In the class inheritance case we have two independent left and right children inside // a parent sequence that has no unified type or member. SequenceNode s = (SequenceNode)n; AddReadContentNode(s.LeftChild, block, statements, reader, target, required, result, validator); AddReadContentNode(s.RightChild, block, statements, reader, target, required, result, validator); return; } TypeNode ct = n.TypeNode; Debug.Assert(ct != null); if (n.Member != null && !(n.Member is Method)) { target = GetMemberBinding(target, n.Member); ct = target.Type; } // todo: might be content model AND mixed, in which case we have to pass the MixedMember // to AddReadTuple, AddReadChoice and AddReadStream. if (ct.Template == SystemTypes.GenericBoxed){ ct = Checker.GetCollectionElementType(ct); } if (ct is TupleType) { AddReadTuple(block, ct as TupleType, statements, reader, target, required, result); } else if (ct is TypeUnion) { AddReadChoice(block, ct as TypeUnion, statements, reader, target, required, result); } else if (IsStream(ct)) { AddReadStream(block, ct, statements, reader, target, result); } else if (ct is TypeAlias) { AddReadAlias(block, ct as TypeAlias, statements, reader, target, required, result); } else { Identifier name = Checker.GetDefaultElementName(ct); AddReadRequiredChild(block, statements, name, ct, target, reader, result, required, true, false); } }
void AddWriteContentNode(ContentNode n, StatementList statements, TypeNode referringType, Identifier writer, Expression source) { if (n.TypeNode == null) { Debug.Assert(n is SequenceNode); // In the class inheritance case we have two independent left and right children inside // a parent sequence that has no unified type or member. SequenceNode s = (SequenceNode)n; AddWriteContentNode(s.LeftChild, statements, referringType, writer, source); AddWriteContentNode(s.RightChild, statements, referringType, writer, source); return; } TypeNode ct = n.TypeNode; Expression src = source; if (n.Member != null && !(n.Member is Method)) { src = GetMemberBinding(source, n.Member, ct); } if (ct.Template == SystemTypes.GenericBoxed) { statements = AddCheckForNull(statements, Duplicate(src, referringType), ct); ct = Checker.GetCollectionElementType(ct); src = CastTo(src, ct);//unbox it } if (ct is TupleType) { AddWriteTuple(ct as TupleType, statements, referringType, src, writer); } else if (ct is TypeUnion) { AddWriteChoice(ct as TypeUnion, statements, referringType, src, writer); } else if (IsStream(ct)) { AddWriteStream(ct, statements, referringType, src, writer); } else if (ct is TypeAlias) { TypeAlias alias = (TypeAlias)ct; src = CastTo(src, alias.AliasedType); //unbox it AddWriteElement(statements, referringType, writer, alias.Name, src, alias.AliasedType, true); } else { AddWriteElement(statements, referringType, writer, ct.Name, src, ct, true); } }
/// <summary> /// This method is called in contexts where surrounding parentheses /// are required, but we wish to avoid extraneous ones. If the /// expression is a BinaryExpression or UnaryExpression, then we /// need not supply our own parens here. /// </summary> /// <param name="expr"></param> /// <returns></returns> private Expression VisitParenthesizedExpression(Expression expr) { if (expr is BinaryExpression) this.VisitExpression(expr); else { Write("("); this.VisitExpression(expr); Write(")"); } return expr; }
void AddWriteElement(StatementList statements, TypeNode referringType, Identifier writer, Identifier name, Expression src, TypeNode mt, bool emptyElementOnNull) { if (mt.Template == SystemTypes.GenericBoxed) { statements = AddCheckForNull(statements, Duplicate(src, referringType), mt); mt = Checker.GetCollectionElementType(mt); // check for null and unbox src = CastTo(src, mt); //unbox it } Literal nameLit = new Literal(name.ToString(), SystemTypes.String); Literal nsLit = (name.Prefix != null) ? new Literal(name.Prefix.Name, SystemTypes.String) : Literal.Null; if (!emptyElementOnNull) { statements = AddCheckForNull(statements, Duplicate(src, referringType), mt); } if (!AddWriteSimpleType(mt, statements, referringType, writer, src, nameLit, nsLit)) { AddCallSerializer(mt, statements, src, writer, nameLit, nsLit); } }
// Make sure we don't skip Pop, Dup, Arglist nodes which the standard Inspector does. public override void VisitExpression(Expression expression) { if (expression == null) return; switch (expression.NodeType) { case NodeType.Dup: seenDup = true; break; case NodeType.Arglist: return; case NodeType.Pop: UnaryExpression uex = expression as UnaryExpression; if (uex != null) { this.VisitPop(uex.Operand); return; } return; default: this.Visit(expression); return; } }
void AddWriteString(StatementList statements, TypeNode referringType, Identifier writer, Expression src) { statements = AddCheckForNull(statements, Duplicate(src, referringType), SystemTypes.String); statements.Add( new ExpressionStatement( new MethodCall(new QualifiedIdentifier(writer,Identifier.For("WriteString")), new ExpressionList(src)))); }
public virtual Expression VisitTypeExpression(Expression expr) { TypeNodeList pars = this.pars; TypeNodeList args = this.args; Identifier id = expr as Identifier; if (id != null) { int key = id.UniqueIdKey; for (int i = 0, n = pars == null ? 0 : pars.Count, m = args == null ? 0 : args.Count; i < n && i < m; i++) { //^ assert pars != null && args != null; TypeNode par = pars[i]; if (par == null || par.Name == null) continue; if (par.Name.UniqueIdKey == key) return new Literal(args[i], CoreSystemTypes.Type); } return id; } Debug.Assert(expr is QualifiedIdentifier || expr is Literal); return expr; }
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 ) ); }