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; }
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); } }
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; }
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; }
public override Statement VisitIf(If If) { WriteStart("if ("); this.VisitExpression(If.Condition); WriteFinish(")"); this.VisitBlock(If.TrueBlock); if (If.FalseBlock != null) { WriteLine("else"); this.VisitBlock(If.FalseBlock); } return If; }
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)); } } }
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)); }
public override Statement VisitIf(If If) { if (If == null) return null; return base.VisitIf((If)If.Clone()); }
public virtual Statement VisitIf(If If) { if (If == null) return null; If.Condition = this.VisitExpression(If.Condition); If.TrueBlock = this.VisitBlock(If.TrueBlock); If.FalseBlock = this.VisitBlock(If.FalseBlock); return If; }
private If ParseIf(TokenSet followers){ If If = new If(); If.SourceContext = this.scanner.CurrentSourceContext; Debug.Assert(this.currentToken == Token.If); this.GetNextToken(); If.Condition = this.ParseParenthesizedExpression(followers|Parser.StatementStart); if (If.Condition != null) If.ConditionContext = If.Condition.SourceContext; Block b = this.ParseStatementAsBlock(followers|Token.Else); If.TrueBlock = b; if (b != null){ if (b.SourceContext.EndPos > If.SourceContext.EndPos) If.SourceContext.EndPos = b.SourceContext.EndPos; if (b.Statements == null && !(b is LabeledStatement)) this.HandleError(b.SourceContext, Error.PossibleMistakenNullStatement); } if (this.currentToken == Token.Else){ If.ElseContext = this.scanner.CurrentSourceContext; this.GetNextToken(); b = this.ParseStatementAsBlock(followers); If.FalseBlock = b; if (b != null){ if (b.SourceContext.EndPos > If.SourceContext.EndPos) If.SourceContext.EndPos = b.SourceContext.EndPos; if (b.Statements == null) this.HandleError(b.SourceContext, Error.PossibleMistakenNullStatement); } } If.EndIfContext = If.SourceContext; If.EndIfContext.StartPos = If.EndIfContext.EndPos-1; if (b != null){ string text = b.SourceContext.SourceText; if (text != null && text.EndsWith("}")) If.EndIfContext = this.scanner.CurrentSourceContext; } return If; }
private bool IsCoalescableIfStmt(If s) { return (IsCoalescableExpr(s.Condition) && IsCoalescableBlock(s.TrueBlock) && IsCoalescableBlock(s.FalseBlock)); }
public override Statement VisitIf(If If) { if (insideAtomicBlock && IsCoalescableIfStmt(If)) { CurrentContinuation = AddBlock(new BasicBlock(If, CurrentContinuation)); return If; } PushContinuationStack(); this.Visit(If.TrueBlock); BasicBlock trueBlock = PopContinuationStack(); PushContinuationStack(); this.Visit(If.FalseBlock); BasicBlock falseBlock = PopContinuationStack(); SourceContext savedConditionalContext = If.SourceContext; if (If.Condition != null) savedConditionalContext = If.Condition.SourceContext; // We normalize all of the conditional expressions here to make life // easier for "select" Normalizer normalizer = new Normalizer(splicer, null, false); CurrentContinuation = AddBlock(new BasicBlock(null, normalizer.VisitExpression(If.Condition), trueBlock, falseBlock)); CurrentContinuation.SourceContext = savedConditionalContext; if (CurrentContinuation.ConditionalExpression != null) CurrentContinuation.ConditionalExpression.SourceContext = savedConditionalContext; return If; }
//================= 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 AddReadRequiredChild(Block scope, StatementList statements, Identifier name, TypeNode type, Expression target, Identifier reader, Expression result, Expression required, bool unwrapChild, bool ignoreNamespace) { Block elseBlock = AddReadChild(scope, statements, name, type, target, reader, result, unwrapChild, ignoreNamespace).FalseBlock; If notFoundButRequired = new If(new BinaryExpression(required,Literal.True,NodeType.Eq), new Block(new StatementList()), null); InvalidContent(notFoundButRequired.TrueBlock.Statements, reader, name.Name.ToString()); elseBlock.Statements.Add(notFoundButRequired); }
If AddEmptyElementCheck(StatementList statements, Identifier reader) { // make sure the element is not empty. If isEmpty = new If(new BinaryExpression(new QualifiedIdentifier(reader, Identifier.For("IsEmptyElement")), Literal.True, NodeType.Eq), new Block(new StatementList()), new Block(new StatementList())); statements.Add(isEmpty); statements = isEmpty.TrueBlock.Statements; // consume empty start tag and just return. statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("Read")), new ExpressionList()))); return isEmpty; }
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 Statement VisitIf(If If) { WriteStart("if "); this.VisitParenthesizedExpression(If.Condition); Write(""); this.VisitBlock(If.TrueBlock); if (If.FalseBlock != null) { WriteStart("else"); this.VisitBlock(If.FalseBlock); } return If; }
public EventingVisitor(Action<If> visitIf) { VisitedIf += visitIf; } public event Action<If> VisitedIf; public override Statement VisitIf(If If) { if (VisitedIf != null) VisitedIf(If); return base.VisitIf(If); }