public override StatementList ReadInstanceField(InstanceFieldAccess instanceFieldAccess, IVariable result) { StatementList stmts = new StatementList(); var boogieType = Helpers.GetBoogieType(result); var readFieldExpr = dispatcher.ReadInstanceField(instanceFieldAccess); if (!Settings.SplitFieldsEnabled()) { if (!Helpers.IsBoogieRefType(Helpers.GetBoogieType(result))) // int, bool, real { var expr = Expression.Union2PrimitiveType(boogieType, readFieldExpr); stmts.Add(bg.VariableAssignment(result, expr)); } else { stmts.Add(bg.VariableAssignment(result, readFieldExpr)); } } else { //p_int:= F$ConsoleApplication3.Holds`1.x[$tmp2]; if (Helpers.IsGenericField(instanceFieldAccess.Field) && !boogieType.Equals(Helpers.BoogieType.Ref)) { stmts.Add(bg.VariableAssignment(result, Expression.Union2PrimitiveType(boogieType, readFieldExpr))); } else { stmts.Add(bg.VariableAssignment(result, readFieldExpr)); } } return(stmts); }
public override Expression VisitReturnValue(ReturnValue returnValue) { // return a default value of the same type as the return value TypeNode returnType = returnValue.Type; ITypeParameter itp = returnType as ITypeParameter; if (itp != null) { Local loc = new Local(returnType); UnaryExpression loca = new UnaryExpression(loc, NodeType.AddressOf, loc.Type.GetReferenceType()); StatementList statements = new StatementList(2); statements.Add(new AssignmentStatement(new AddressDereference(loca, returnType, false, 0), new Literal(null, SystemTypes.Object))); statements.Add(new ExpressionStatement(loc)); return new BlockExpression(new Block(statements), returnType); } if (returnType.IsValueType) return new Literal(0, returnType); return new Literal(null, returnType); }
public override Expression VisitReturnValue(ReturnValue returnValue) { // return a default value of the same type as the return value TypeNode returnType = returnValue.Type; ITypeParameter itp = returnType as ITypeParameter; if (itp != null) { Local loc = new Local(returnType); UnaryExpression loca = new UnaryExpression(loc, NodeType.AddressOf, loc.Type.GetReferenceType()); StatementList statements = new StatementList(2); statements.Add(new AssignmentStatement(new AddressDereference(loca, returnType, false, 0), new Literal(null, SystemTypes.Object))); statements.Add(new ExpressionStatement(loc)); return(new BlockExpression(new Block(statements), returnType)); } if (returnType.IsValueType) { return(new Literal(0, returnType)); } return(new Literal(null, returnType)); }
public override Expression VisitUnaryExpression(UnaryExpression unaryExpression) { var temp = base.VisitUnaryExpression(unaryExpression); if (temp.NodeType == NodeType.AddressOf) { var unary = temp as UnaryExpression; if (unary != null) { if (!IsAddressoffable(unary.Operand.NodeType)) { var newVar = new Local(unary.Operand.Type); var sl = new StatementList(); sl.Add(new AssignmentStatement(newVar, unary.Operand)); unary.Operand = newVar; sl.Add(new ExpressionStatement(unary)); return(new BlockExpression(new Block(sl))); } } } return(temp); }
public override StatementList AllocLocalVariables(IList <IVariable> variables) { StatementList stmts = new StatementList(); // we allocate an address for all local variables // except they are a pointer, we are assuming that you can't take the address of a pointer foreach (var v in variables) { if (!(v.Type is IManagedPointerType)) { stmts.Add(dispatcher.AllocAddr(v)); } } // load values into stack space foreach (var paramVariable in variables.Where(v => v.IsParameter)) { // paramValue are variables in the three address code // however in boogie they are treated as values // those values are loaded into the stack memory space /* * void foo(int x){ * } * * procedure foo(x : int){ * var _x : Addr; // stack space (done in previous loop) * x_ := AllocAddr(); * * data(_x) := x; // we are doing this conceptually * } */ var boogieParamVariable = BoogieParameter.FromDotNetVariable(paramVariable); if (paramVariable.Type is IManagedPointerType) { stmts.Add(BoogieStatement.VariableAssignment(BoogieVariable.AddressVar(paramVariable), boogieParamVariable)); continue; } Addressable paramAddress = dispatcher.AddressOf(paramVariable); // boogie generator knows that must fetch paramVariable's address (_x and not x) stmts.Add(dispatcher.WriteAddr(paramAddress, boogieParamVariable)); if (Helpers.GetBoogieType(paramVariable).Equals(Helpers.BoogieType.Object)) { stmts.Add(BoogieStatement.AllocObjectAxiom(paramVariable)); } else if (Helpers.GetBoogieType(paramVariable).Equals(Helpers.BoogieType.Addr)) { stmts.Add(BoogieStatement.AllocAddrAxiom(paramVariable)); } } return(stmts); }
public override StatementList AllocObject(IVariable var, InstructionTranslator instTranslator) { var freshVariable = instTranslator.GetFreshVariable(Helpers.GetBoogieType(var)); var stmts = new StatementList(); stmts.Add(dispatcher.AllocObject(freshVariable)); stmts.Add(bg.VariableAssignment(var, freshVariable)); return(stmts); }
private Expression ExtractOldExpression(MethodCall call) { var cand = call.Operands[0]; if (this.currentSL != null) { var locs = FindLocals.Get(cand); if (locs.Count > 0) { // find the instructions that set these locals var assignments = new List <Statement>(); for (int i = this.currentSLindex - 1; i >= 0; i--) { var a = this.currentSL[i] as AssignmentStatement; if (a == null) { continue; } var loc = a.Target as Local; if (loc == null) { continue; } if (locs.Contains(loc)) { assignments.Add(a); this.currentSL[i] = null; locs.Remove(loc); } if (locs.Count == 0) { break; } } assignments.Reverse(); var be = new StatementList(); assignments.ForEach(astmt => be.Add(astmt)); be.Add(new ExpressionStatement(cand)); var sc = cand.SourceContext; cand = new BlockExpression(new Block(be)); cand.SourceContext = sc; if (locs.Count > 0) { // warn that we couldn't extract the local } } } return(cand); }
/// <summary> /// Construeix la funcio de transicio. /// </summary> /// <param name="state">El estat.</param> /// <param name="transitionName">El nom de la transicio.</param> /// <returns>La funcio.</returns> /// private FunctionDeclaration MakeOnTransitionFunction(State state, string transitionName, string contextClassName, string ownerClassName) { StatementList bodyStatements = new StatementList(); // Intruccio per recuperar el context. // bodyStatements.Add( new InlineStatement( String.Format("{0}* ctx = static_cast<{0}*>(getContext())", contextClassName))); bodyStatements.Add( new InlineStatement( String.Format("{0}* owner = ctx->getOwner()", ownerClassName))); foreach (Transition transition in state.Transitions) { if (transition.TransitionEvent.Name == transitionName) { StatementList trueBodyStatements = new StatementList(); trueBodyStatements.Add(new InvokeStatement( new InvokeExpression( new IdentifierExpression("ctx->beginTransition")))); // Accio de transicio. // if (transition.Action != null) { trueBodyStatements.AddRange(MakeActionStatements(transition.Action)); } trueBodyStatements.Add(new InvokeStatement( new InvokeExpression( new IdentifierExpression("ctx->endTransition"), new InvokeExpression( new IdentifierExpression("ctx->getStateInstance"), new IdentifierExpression( String.Format("Context::StateID::{0}", transition.NextState.Name)))))); Expression conditionExpr = new InlineExpression(transition.Guard == null ? "true" : transition.Guard.Expression); bodyStatements.Add(new IfThenElseStatement( conditionExpr, new BlockStatement { Statements = trueBodyStatements }, null)); } } return(new FunctionDeclaration { Access = AccessSpecifier.Public, Implementation = ImplementationSpecifier.Override, ReturnType = TypeIdentifier.FromName("void"), Name = String.Format("transition_{0}", transitionName), Body = new BlockStatement(bodyStatements), }); }
private Node EvaluateLoopStatements() { var stmts = new StatementList(); while (firstOfStatement.Contains(CurrentToken) && CurrentToken != TokenCategory.CONTINUE) { stmts.Add(Statement()); } stmts.Add(Continue()); return(stmts); }
public Node StmtList() { var statementList = new StatementList(); while (System.Array.Exists(stmtCategories, category => category == Current)) { switch (Current) { case TokenCategory.IDENTIFIER: var id = Expect(TokenCategory.IDENTIFIER); switch (Current) { case TokenCategory.ASSIGN: statementList.Add(StmtAssign(id)); break; case TokenCategory.INCREMENT: statementList.Add(StmtIncr(id)); break; case TokenCategory.DECREMENT: statementList.Add(StmtDecr(id)); break; case TokenCategory.OPEN_PARENTHESIS: statementList.Add(StmtFunCall(id)); break; default: throw new SyntaxError(String.Format("Syntax Error: Expected operator or open parenthesis, given '{0}' at ({1}, {2})", stream.Current.Value, previous.Row, previous.LastIndex())); } break; case TokenCategory.IF: statementList.Add(StmtIf()); break; case TokenCategory.LOOP: statementList.Add(StmtLoop()); break; case TokenCategory.BREAK: statementList.Add(StmtBreak()); break; case TokenCategory.RETURN: statementList.Add(StmtReturn()); break; case TokenCategory.SEMICOLON: statementList.Add(StmtEmpty()); break; } } return(statementList); }
StatementList TranslateLocalVariables(Dictionary <string, BoogieVariable> temporalVariables) { StatementList localVariablesStmts = new StatementList(); var bg = BoogieGenerator.Instance(); var allVariables = methodBody.Variables.Union(methodBody.Parameters).ToList(); localVariablesStmts.Add(bg.DeclareLocalVariables(allVariables, temporalVariables)); localVariablesStmts.Add(bg.AllocLocalVariables(allVariables)); // replace for class generated by compiler return(localVariablesStmts); }
StatementList ParseStatements() { StatementList statements = new StatementList(); int Scope = 1; while (Scope > 0) { if (tokenReader.Expect(LexKind.BraceOpen)) { Scope++; } else if (tokenReader.Expect(LexKind.BraceClose)) { Scope--; } bool statementParsed = ParseStatement(out Statement statement); if (statementParsed) { statements.Add(statement); } else { tokenReader.Skip(1); } if (tokenReader.Expect(LexKind.EOF)) { Scope = 0; } } return(statements); }
public GeneratedCode Parse(List<Token> _tokens) { Dictionary<string, Function> Functions = new Dictionary<string, Function>(); StatementList TopLevelStatements = new StatementList(); Tokens = _tokens; Position = 0; GetNextToken(); //Initialize first token while (true) { if (CurToken.Type == TokenType.EOF) break; if (CurToken.IsCharacter(";")) GetNextToken(); //eat ; else if (CurToken.IsIdentifier("function")) { Function func = ParseFunction(); Functions[func.Name] = func; } else TopLevelStatements.Add(ParseStatement()); } Function TopLevel = new Function(TopLevelStatements); return new GeneratedCode() { TopLevelStatements = TopLevel, Functions = Functions }; }
public Node Program() { var declList = new DeclarationList(); var stmtList = new StatementList(); while (firstOfDeclaration.Contains(CurrentToken)) { declList.Add(Declaration()); } while (firstOfStatement.Contains(CurrentToken)) { stmtList.Add(Statement()); } Expect(TokenCategory.EOF); // This refers to the class that refers to the 'Program' token, // not this method's name. return(new Program() { declList, stmtList }); }
public Node For() { var idToken = Expect(TokenCategory.FOR); var identifier = new Identifier() { AnchorToken = Expect(TokenCategory.IDENTIFIER) }; Expect(TokenCategory.IN); var expr = Expression(); Expect(TokenCategory.DO); var stmtList = new StatementList(); while (firstOfStatement.Contains(CurrentToken)) { stmtList.Add(Statement()); } Expect(TokenCategory.END); Expect(TokenCategory.ENDLINE); var result = new For() { identifier, expr, stmtList }; result.AnchorToken = idToken; return(result); //Si nos estamos refiriendo a FormatException? }
public static string CreateDefaultValuesStaticVariablesProcedure() { #region Create body of the procedure StatementList body = new StatementList(); foreach (IFieldReference field in FieldTranslator.GetFieldReferences()) { if (field.IsStatic) { BoogieGenerator bg = BoogieGenerator.Instance(); StaticFieldAccess staticFieldAccess = new StaticFieldAccess(field); body.Add(bg.WriteStaticField(staticFieldAccess, GetDefaultConstant(Helpers.GetBoogieType(field.Type)))); } } #endregion string procedureName = "$default_values_static_fields"; string attributes = String.Empty; StatementList localVariables = new StatementList(); String parametersWithTypes = String.Empty; String returnTypeIfAny = String.Empty; BoogieProcedureTemplate temp = new BoogieProcedureTemplate(procedureName, attributes, localVariables, body, parametersWithTypes, returnTypeIfAny, false); return(temp.TransformText()); }
public override StatementList DeclareLocalVariables(IList <IVariable> variables, Dictionary <string, BoogieVariable> temporalVariables) { StatementList stmts = new StatementList(); foreach (var v in variables.Where(v => !v.IsParameter)) { stmts.Add(BoogieStatement.VariableDeclaration(v)); } foreach (var kv in temporalVariables) { stmts.Add(BoogieStatement.VariableDeclaration(kv.Value)); } return(stmts); }
// hides implementation in super class //public new string VariableAssignment(string variableA, string expr) //{ // return string.Format("{0} := {1};", variableA, expr); //} public override StatementList DeclareLocalVariables(IList <IVariable> variables, Dictionary <string, BoogieVariable> temporalVariables) { var stmts = new StatementList(); foreach (var v in variables) { stmts.Add(BoogieStatement.VariableDeclaration(BoogieVariable.AddressVar(v))); } foreach (var kv in temporalVariables) { stmts.Add(BoogieStatement.VariableDeclaration(kv.Value)); } return(stmts); }
public Node For() { var result = new For() { AnchorToken = Expect(TokenCategory.FOR) }; result.Add(new Identifier() { AnchorToken = Expect(TokenCategory.IDENTIFIER) }); Expect(TokenCategory.IN); result.Add(Expression()); Expect(TokenCategory.DO); var statementList = new StatementList(); if (firstOfStatement.Contains(CurrentToken)) { while (firstOfStatement.Contains(CurrentToken)) { statementList.Add(Statement()); } } result.Add(statementList); Expect(TokenCategory.END); Expect(TokenCategory.SEMICOLON); return(result); }
private StatementList ParseChild(Stream stream) { var child = new StatementList(_host); var open = stream.Next(); while (stream.Peek() != null) { var token = stream.Peek(); if (token == null) { break; } switch (token.Type) { default: var statements = ParseStatement(stream); foreach (var statement in statements) { child.Add(statement); } goto doneWithChildren; } } doneWithChildren: return(child); }
public static void CreateAsyncStartMethod(StreamWriter sw) { StatementList stmts = new StatementList(); var boogieGetTypeRes = BoogieVariable.GetTempVar(Helpers.ObjectType(), null /* need dict with used var names*/, prefix: "asyncType"); var stateMachineVar = BoogieVariable.GetTempVar(Helpers.ObjectType(), null /* need dict with used var names*/, prefix: "stateMachineCopy"); stmts.Add(BoogieStatement.VariableDeclaration(stateMachineVar)); stmts.Add(BoogieStatement.VariableDeclaration(boogieGetTypeRes)); stmts.Add(BoogieStatement.FromString($"{stateMachineVar.Expr} := stateMachine;")); foreach (var asyncMethod in Helpers.asyncMoveNexts) { var asyncType = asyncMethod.ContainingTypeDefinition; var bg = BoogieGenerator.Instance(); stmts.Add(bg.ProcedureCall(BoogieMethod.GetTypeMethod, new List <Expression> { stateMachineVar }, boogieGetTypeRes)); StatementList ifStmts = new StatementList(); ifStmts.Add(BoogieGenerator.Instance().ProcedureCall(BoogieMethod.From(asyncMethod), new List <Expression> { stateMachineVar })); stmts.Add(BoogieStatement.If(Expression.Subtype(boogieGetTypeRes, asyncType), ifStmts)); } stmts.Add(BoogieStatement.FromString($"v0$out := {stateMachineVar.Expr};")); sw.WriteLine(@"procedure {:extern} System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.Start``1$``0$(this : Ref,stateMachine : Ref) returns (v0$out : Ref) {"); foreach (var stmt in stmts) { sw.WriteLine(stmt.Stmt); } sw.WriteLine("}"); }
public Node Program() { var decList = new DeclarationList(); var stmtList = new StatementList(); while (firstOfDeclaration.Contains(CurrentToken)) { decList.Add(Declaration()); } var result = new Program() { AnchorToken = Expect(TokenCategory.PROG) }; while (firstOfStatement.Contains(CurrentToken)) { stmtList.Add(Statement()); } Expect(TokenCategory.END); Expect(TokenCategory.SEMICOL); Expect(TokenCategory.EOF); result.Add(decList); result.Add(stmtList); return(result); }
/// <summary> /// Method generates core part of the CheckMethod /// </summary> private void EmitCheckPostMethodCore(TypeNode taskType) { Contract.Requires(taskType != null); this.checkMethodTaskParameter = new Parameter(Identifier.For("task"), taskType); // TODO ST: can I switch to new Local(taskType.Type)?!? In this case this initialization // could be moved outside this method this.originalResultLocal = new Local(new Identifier("taskLocal"), checkMethodTaskParameter.Type); // Generate: public Task<T> CheckPost(Task<T> task) where T is taskType or // public Task CheckPost(Task task) for non-generic task. checkPostMethod = new Method( declaringType: this.closureClass, attributes: null, name: CheckMethodId, parameters: new ParameterList(checkMethodTaskParameter), // was: taskType.TemplateArguments[0] when hasResult was true and SystemTypes.Void otherwise returnType: taskType, body: null); checkPostMethod.CallingConvention = CallingConventionFlags.HasThis; checkPostMethod.Flags |= MethodFlags.Public; this.checkPostBody = new StatementList(); this.closureClass.Members.Add(this.checkPostMethod); if (taskType.IsGeneric) { // Assign taskParameter to originalResultLocal because // this field is used in a postcondition checkPostBody.Add(new AssignmentStatement(this.originalResultLocal, checkMethodTaskParameter)); } }
/// <summary> /// Crea la declaracio del metode 'start' /// </summary> /// <param name="machine">La maquina.</param> /// <returns>La declaracio del metode.</returns> /// private FunctionDeclaration MakeStartFunction(Machine machine) { StatementList bodyStatements = new StatementList(); if (machine.InitializeAction != null) { var statements = MakeActionStatements(machine.InitializeAction); if (statements != null) { bodyStatements.AddRange(statements); } } bodyStatements.Add( new InvokeStatement( new InvokeExpression( new IdentifierExpression("initialize"), new InvokeExpression( new IdentifierExpression("getStateInstance"), new IdentifierExpression( String.Format("StateID::{0}", machine.Start.FullName)))))); return(new FunctionDeclaration( "start", AccessSpecifier.Public, TypeIdentifier.FromName("void"), null, bodyStatements)); }
public override Statement VisitBranch(Branch branch) { if (branch == null) { return(null); } if (branch.Target == null) { return(null); } branch.Condition = this.VisitExpression(branch.Condition); int n = this.localsStack.top + 1; LocalsStack targetStack = (LocalsStack)this.StackLocalsAtEntry[branch.Target.UniqueKey]; if (targetStack == null) { this.StackLocalsAtEntry[branch.Target.UniqueKey] = this.localsStack.Clone(); return(branch); } //Target block has an entry stack that is different from the current stack. Need to copy stack before branching. if (n <= 0) { return(branch); //Empty stack, no need to copy } StatementList statements = new StatementList(n + 1); this.localsStack.Transfer(targetStack, statements); statements.Add(branch); return(new Block(statements)); }
public override StatementList CallReadArrayElement(IVariable resultVariable, Expression array, Expression index, InstructionTranslator instructionTranslator) { StatementList stmts = new StatementList(); BoogieVariable boogieResVar = null; if (resultVariable != null) { boogieResVar = instructionTranslator.GetFreshVariable(Helpers.GetBoogieType(resultVariable)); } stmts.Add(dispatcher.CallReadArrayElement(boogieResVar, array, index)); if (resultVariable != null) { stmts.Add(dispatcher.WriteAddr(dispatcher.AddressOf(resultVariable), boogieResVar)); } return(stmts); }
public override StatementList AllocLocalVariables(IList <IVariable> variables) { StatementList stmts = new StatementList(); // only allocate an address for variables that are referenced foreach (var v in variables) { if (RequiresAllocation(v)) { stmts.Add(AllocAddr(v)); } } foreach (var paramVariable in variables.Where(v => v.IsParameter && (RequiresAllocation(v) || (v.Type is IManagedPointerType)))) { var boogieParamVariable = BoogieParameter.FromDotNetVariable(paramVariable); //if (!RequiresAllocation(paramVariable)) if (paramVariable.Type is IManagedPointerType) { //BoogieVariable target = RequiresAllocation(paramVariable) || (paramVariable.Type is IManagedPointerType) ? // BoogieVariable.AddressVar(paramVariable) : BoogieVariable.FromDotNetVariable(paramVariable); BoogieVariable target = BoogieVariable.AddressVar(paramVariable); stmts.Add(BoogieStatement.VariableAssignment(target, boogieParamVariable)); continue; } Addressable paramAddress = AddressOf(paramVariable); // boogie generator knows that must fetch paramVariable's address (_x and not x) stmts.Add(WriteAddr(paramAddress, boogieParamVariable)); if (Helpers.GetBoogieType(paramVariable).Equals(Helpers.BoogieType.Object)) { stmts.Add(BoogieStatement.AllocObjectAxiom(paramVariable)); } else if (Helpers.GetBoogieType(paramVariable).Equals(Helpers.BoogieType.Addr)) { stmts.Add(BoogieStatement.AllocAddrAxiom(paramVariable)); } } return(stmts); }
public override StatementList WriteInstanceField(InstanceFieldAccess instanceFieldAccess, Expression expr, InstructionTranslator instTranslator) { StatementList stmts = new StatementList(); var boogieType = expr.Type; if (Helpers.IsGenericField(instanceFieldAccess.Field) && !boogieType.Equals(Helpers.BoogieType.Object)) { stmts.Add(Expression.AssumeInverseRelationUnionAndPrimitiveType(expr)); stmts.Add(dispatcher.WriteAddr(dispatcher.AddressOf(instanceFieldAccess), Expression.PrimitiveType2Union(expr, instTranslator.Boogie()))); } else { stmts.Add(dispatcher.WriteAddr(dispatcher.AddressOf(instanceFieldAccess), expr)); } return(stmts); }
public string AsyncStubsScheduleTask(bool genericVersion = false) { StatementList localVars = new StatementList(); localVars.Add(BoogieStatement.FromString("var state : bool;")); StatementList instructions = new StatementList(); var param0 = new BoogieVariable(Helpers.BoogieType.Object, "sm"); var procIsCompleted = genericVersion ? BoogieMethod.AsyncStubsTaskAwaiterIsCompletedGeneric : BoogieMethod.AsyncStubsTaskAwaiterIsCompleted; var awaiterVar = new BoogieVariable(Helpers.BoogieType.Object, "awaiter"); var stateVar = new BoogieVariable(Helpers.BoogieType.Bool, "state"); var argsList = new List <Expression>(); argsList.Add(awaiterVar); var resList = new List <BoogieVariable>(); resList.Add(stateVar); var callIsCompleted = BoogieStatement.ProcedureCall(procIsCompleted, argsList, resList, stateVar); var assume = BoogieStatement.Assume(Expression.BinaryOperationExpression(stateVar, new Expression(Helpers.BoogieType.Bool, "true"), Backend.ThreeAddressCode.Instructions.BinaryOperation.Eq)); var yield = BoogieStatement.FromString("yield;"); // it is crucial to yield before anything else instructions.Add(yield); instructions.Add(callIsCompleted); instructions.Add(assume); var moveNextMethods = stateMachinesTypes.Select(t => t.Members.Where(m => m.Name.Value.Contains("MoveNext")).First()).Cast <IMethodDefinition>(); var ifCases = moveNextMethods.Select(m => Invoke(m, param0)); foreach (var ifCase in ifCases) { instructions.Add(ifCase); } string procedureName = genericVersion ? "$AsyncStubs`1$ScheduleTask" : "$AsyncStubs$ScheduleTask"; var procedureTemplate = new BoogieProcedureTemplate(procedureName, "", localVars, instructions, "awaiter : Object, sm : Object", String.Empty, false); return(procedureTemplate.TransformText()); }
public Node StmtList() { var node = new StatementList(); while (firstOfStmt.Contains(CurrentToken)) { node.Add(Stmt()); } return(node); }
/**************************************************************** * Statements List Node ***************************************************************/ private Node EvaluateStatements() { var stmts = new StatementList(); while (firstOfStatement.Contains(CurrentToken)) { stmts.Add(Statement()); } return(stmts); }
public Node StmtList() { var statementList = new StatementList(); while (firstOfStatement.Contains(CurrentToken)) { statementList.Add(Stmt()); } return(statementList); }
public override Statement VisitBranch(Branch branch){ if (branch == null) return null; if (branch.Target == null) return null; branch.Condition = this.VisitExpression(branch.Condition); int n = this.localsStack.top+1; LocalsStack targetStack = (LocalsStack)this.StackLocalsAtEntry[branch.Target.UniqueKey]; if (targetStack == null){ this.StackLocalsAtEntry[branch.Target.UniqueKey] = this.localsStack.Clone(); return branch; } //Target block has an entry stack that is different from the current stack. Need to copy stack before branching. if (n <= 0) return branch; //Empty stack, no need to copy StatementList statements = new StatementList(n+1); this.localsStack.Transfer(targetStack, statements); statements.Add(branch); return new Block(statements); }
//public override Block VisitBlock(Block block) { // if(block.Statements != null && block.Statements.Count == 1) { // Return r = block.Statements[0] as Return; // if(r != null) { // Statement s = this.VisitReturn(r); // Block retBlock = s as Block; // if(retBlock != null) { // block.Statements = retBlock.Statements; // return block; // } else { // return base.VisitBlock(block); // } // } else { // return base.VisitBlock(block); // } // } else { // return base.VisitBlock(block); // } //} public override Statement VisitReturn(Return Return) { if (Return == null) { return null; } returnCount++; this.lastReturnSourceContext = Return.SourceContext; StatementList stmts = new StatementList(); Return.Expression = this.VisitExpression(Return.Expression); if (Return.Expression != null) { MethodCall mc = Return.Expression as MethodCall; if (mc != null && mc.IsTailCall) { mc.IsTailCall = false; } var assgnmt = new AssignmentStatement(result, Return.Expression); assgnmt.SourceContext = Return.SourceContext; stmts.Add(assgnmt); } // the branch is a "leave" out of the try block that the body will be // in. var branch = new Branch(null, newExit, false, false, this.leaveExceptionBody); branch.SourceContext = Return.SourceContext; stmts.Add(branch); return new Block(stmts); }
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; }
bool AddWriteSimpleAttribute(TypeNode type, Identifier name, StatementList statements, TypeNode referringType, Identifier writer, Expression src) { ExpressionList args = new ExpressionList(); args.Add(GetXmlNameFromId(name)); args.Add(GetXmlNamespaceFromId(name)); args.Add(src); if (type == SystemTypes.String) { statements = AddCheckForNull(statements, Duplicate(src, referringType), type); statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeString")), args))); } else if( type == SystemTypes.Boolean) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeBoolean")), args))); } else if( type == SystemTypes.Int8) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeSByte")), args))); } else if( type == SystemTypes.Char) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeChar")), args))); } else if( type == SystemTypes.DateTime) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeDateTime")), args))); } else if( type == SystemTypes.Decimal) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeDecimal")), args))); } else if( type == SystemTypes.Double) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeDouble")), args))); } else if( type == SystemTypes.Guid) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeGuid")), args))); } else if( type == SystemTypes.Int16) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeInt16")), args))); } else if( type == SystemTypes.Int32) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeInt32")), args))); } else if( type == SystemTypes.Int64) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeInt64")), args))); } else if( type == SystemTypes.UInt8) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeByte")), args))); } else if( type == SystemTypes.Single) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeSingle")), args))); } else if( type == SystemTypes.TimeSpan) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeTimeSpan")), args))); } else if( type == SystemTypes.UInt16 ) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeUInt16")), args))); } else if( type == SystemTypes.UInt32) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeUInt32")), args))); } else if( type == SystemTypes.UInt64) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeUInt64")), args))); } else { Expression conversion = GetConvertToString(type, src, true); if (conversion != null) { statements = AddCheckForNull(statements, Duplicate(src, referringType), type); ExpressionList args2 = new ExpressionList(); args2.Add(args[0]); args2.Add(args[1]); args2.Add(conversion); statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(writer, Identifier.For("WriteAttributeString")), args2))); } else { return false; } } return true; }
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; }
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; }
void InvalidContent(StatementList statements, Identifier reader, string expecting) { statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("InvalidContent")), new ExpressionList(new Expression[1]{ new Literal(expecting, SystemTypes.String)})))); }
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; }
private static int ExtractVB_ENCCallToPreamble(Block firstBlock, int currentIndex, StatementList preamble) { if (firstBlock == null) return currentIndex; while (currentIndex < firstBlock.Statements.Count) { Statement s = firstBlock.Statements[currentIndex]; if (s != null && s.NodeType != NodeType.Nop) { // check for VB literal assignments if (!s.SourceContext.Hidden) break; var es = s as ExpressionStatement; if (es != null) { MethodCall call = es.Expression as MethodCall; if (call != null) { var mb = call.Callee as MemberBinding; if (mb == null) break; var encMethod = mb.BoundMember as Method; if (encMethod == null) break; if (encMethod.Name.Name != "__ENCAddToList") break; // okay, we are calling the VB memory leak, put it into the preamble goto addToPreamble; } } break; // don't skip other stuff } if (s == null) continue; addToPreamble: preamble.Add(s); var oldCount = firstBlock.Statements.Count; var oldStats = firstBlock.Statements; firstBlock.Statements[currentIndex] = null; Contract.Assert(oldStats == firstBlock.Statements); Contract.Assert(oldCount == firstBlock.Statements.Count); currentIndex++; Contract.Assert(currentIndex <= firstBlock.Statements.Count); } return currentIndex; }
void AddError(StatementList statements, Identifier reader, RuntimeError code, params Expression[] args) { ExpressionList list = new ExpressionList(); list.Add(new Literal(code, Runtime.RuntimeError)); foreach (Expression e in args) list.Add(e); statements.Add(new ExpressionStatement(new MethodCall(new QualifiedIdentifier(reader, Identifier.For("Error")), list))); }
internal static StatementList ExtractClump(StatementList blocks, int firstBlockIndex, int firstStmtIndex, int lastBlockIndex, int lastStmtIndex, AssumeBlock assumeBlock = null) { Contract.Requires(blocks != null); Contract.Requires(firstBlockIndex >= 0); Contract.Requires(firstStmtIndex >= 0); Contract.Ensures(Contract.Result<StatementList>().Count == lastBlockIndex - firstBlockIndex + 1); Contract.Ensures(blocks[firstBlockIndex] == Contract.OldValue(blocks[firstBlockIndex])); StatementList clump = new StatementList(); // first extract the tail of the first block into a new block. Block oldFirstBlock = (Block) blocks[firstBlockIndex]; Block newFirstBlock = new Block(new StatementList()); if (oldFirstBlock != null) { var count = firstBlockIndex == lastBlockIndex ? lastStmtIndex + 1 : oldFirstBlock.Statements.Count; for (int stmtIndex = firstStmtIndex; stmtIndex < count; stmtIndex++) { var stmt = oldFirstBlock.Statements[stmtIndex]; newFirstBlock.Statements.Add(stmt); if (stmt == null) continue; oldFirstBlock.Statements[stmtIndex] = assumeBlock; assumeBlock = null; } } clump.Add(newFirstBlock); var currentBlockIndex = firstBlockIndex + 1; if (currentBlockIndex > lastBlockIndex) return clump; // setup info about forwarding branches to new last full block Block newLastBlock = null; var lastFullBlock = lastBlockIndex - 1; var oldLastBlock = (Block) blocks[lastBlockIndex]; if (oldLastBlock != null && lastStmtIndex == oldLastBlock.Statements.Count - 1) { // last block is also fully used. lastFullBlock = lastBlockIndex; } else { newLastBlock = new Block(new StatementList()); // check if first block had a branch if (newFirstBlock != null && newFirstBlock.Statements != null && newFirstBlock.Statements.Count > 0) { // check if we need to adjust branch to last block var branch = newFirstBlock.Statements[newFirstBlock.Statements.Count - 1] as Branch; if (branch != null && branch.Target != null && branch.Target.UniqueKey == oldLastBlock.UniqueKey) { branch.Target = newLastBlock; } } } // Next extract full blocks between currentBlockIndex and including lastFullBlock for (; currentBlockIndex <= lastFullBlock; currentBlockIndex++) { var block = (Block) blocks[currentBlockIndex]; // don't skip null blocks since context relies on number clump.Add(block); if (block == null) continue; blocks[currentBlockIndex] = assumeBlock; assumeBlock = null; if (newLastBlock != null && block.Statements != null && block.Statements.Count > 0) { // check if we need to adjust branch to last block var branch = block.Statements[block.Statements.Count - 1] as Branch; if (branch != null && branch.Target != null && branch.Target.UniqueKey == oldLastBlock.UniqueKey) { branch.Target = newLastBlock; } } } // next, if last block wasn't full, we have a new last block, extract the prefix if (newLastBlock != null) { for (int i = 0; i < lastStmtIndex + 1; i++) { newLastBlock.Statements.Add(oldLastBlock.Statements[i]); oldLastBlock.Statements[i] = assumeBlock; assumeBlock = null; } clump.Add(newLastBlock); } return clump; }
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)))); }
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; }
//================= 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 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); } }
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; }
public virtual Differences VisitStatementList(StatementList list1, StatementList list2, out StatementList changes, out StatementList deletions, out StatementList insertions){ changes = list1 == null ? null : list1.Clone(); deletions = list1 == null ? null : list1.Clone(); insertions = list1 == null ? new StatementList() : list1.Clone(); //^ assert insertions != null; Differences differences = new Differences(); for (int j = 0, n = list2 == null ? 0 : list2.Count; j < n; j++){ //^ assert list2 != null; Statement nd2 = list2[j]; if (nd2 == null) continue; insertions.Add(null); } TrivialHashtable savedDifferencesMapFor = this.differencesMapFor; this.differencesMapFor = null; TrivialHashtable matchedNodes = new TrivialHashtable(); for (int i = 0, k = 0, n = list1 == null ? 0 : list1.Count; i < n; i++){ //^ assert list1 != null && changes != null && deletions != null; Statement nd1 = list1[i]; if (nd1 == null) continue; Differences diff; int j; Statement nd2 = this.GetClosestMatch(nd1, list1, list2, i, ref k, matchedNodes, out diff, out j); if (nd2 == null || diff == null){Debug.Assert(nd2 == null && diff == null); continue;} matchedNodes[nd1.UniqueKey] = nd1; matchedNodes[nd2.UniqueKey] = nd2; changes[i] = diff.Changes as Statement; deletions[i] = diff.Deletions as Statement; insertions[i] = diff.Insertions as Statement; insertions[n+j] = nd1; //Records the position of nd2 in list2 in case the change involved a permutation Debug.Assert(diff.Changes == changes[i] && diff.Deletions == deletions[i] && diff.Insertions == insertions[i]); differences.NumberOfDifferences += diff.NumberOfDifferences; differences.NumberOfSimilarities += diff.NumberOfSimilarities; } //Find deletions for (int i = 0, n = list1 == null ? 0 : list1.Count; i < n; i++){ //^ assert list1 != null && changes != null && deletions != null; Statement nd1 = list1[i]; if (nd1 == null) continue; if (matchedNodes[nd1.UniqueKey] != null) continue; changes[i] = null; deletions[i] = nd1; insertions[i] = null; differences.NumberOfDifferences += 1; } //Find insertions for (int j = 0, n = list1 == null ? 0 : list1.Count, m = list2 == null ? 0 : list2.Count; j < m; j++){ //^ assert list2 != null; Statement nd2 = list2[j]; if (nd2 == null) continue; if (matchedNodes[nd2.UniqueKey] != null) continue; insertions[n+j] = nd2; //Records nd2 as an insertion into list1, along with its position in list2 differences.NumberOfDifferences += 1; //REVIEW: put the size of the tree here? } if (differences.NumberOfDifferences == 0){ changes = null; deletions = null; insertions = null; } this.differencesMapFor = savedDifferencesMapFor; return differences; }
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 ) ); }
void AddReadAlias( Block block, TypeAlias alias, StatementList statements, Identifier reader, Expression target, Expression required, Expression result) { Local local = new Local(Identifier.Empty, alias.AliasedType, block); AddReadRequiredChild(block, statements, alias.Name, alias.AliasedType, local, reader, result, required, true, true); statements.Add(new AssignmentStatement(target, this.tempChecker.typeSystem.ImplicitCoercion(local, target.Type))); }
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); }
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 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 AddConsoleWriteLine(StatementList statements, Expression e) { statements.Add(new ExpressionStatement( new MethodCall(new QualifiedIdentifier(Identifier.For("Console"), Identifier.For("WriteLine")), new ExpressionList(new Expression[1] { e } )))); }
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)); }
/// <summary> /// Visits the ForEachStatement Node and collects information from it. /// </summary> /// <param name="forEachStatement">The ForEachStatement</param> public override Node Visit(ForEachStatement forEachStatement) { if (expandForEachStatements) { // run analysis on collection VisitDynamic(forEachStatement.Collection); var inference = forEachStatement.Collection.TypeInference.Declaration as Variable; if (!(inference != null && inference.Type is ArrayType)) return forEachStatement; if ((inference.Type as ArrayType).Dimensions.Count > 1) { Error(XenkoMessageCode.ErrorMultiDimArray, forEachStatement.Span, inference, forEachStatement, analyzedModuleMixin.MixinName); return forEachStatement; } var dim = (int)((inference.Type as ArrayType).Dimensions.FirstOrDefault() as LiteralExpression).Value; var result = new StatementList(); for (int i = 0; i < dim; ++i) { var cloned = forEachStatement.DeepClone(); var replace = new XenkoReplaceExtern(cloned.Variable, new IndexerExpression(cloned.Collection, new LiteralExpression(i))); replace.Run(cloned.Body); result.Add(cloned.Body); } VisitDynamic(result); return result; } else { base.Visit(forEachStatement); parsingInfo.ForEachStatements.Add(new StatementNodeCouple(forEachStatement, ParentNode)); return forEachStatement; } }
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)); } } }