public virtual void BuildAxisClosureSequence(Expression source, AxisBuildState state, SequenceAccessor sqa, Block block, BlockScope scope) { if (!this.IsLocal(source)) { Expression loc = this.NewClosureLocal(source.Type, scope); block.Statements.Add(new AssignmentStatement(loc, source)); source = loc; } foreach( Accessor acc in sqa.Accessors ) { block.Statements.Add(this.BuildAxisClosureBlock(source, state, acc, scope)); } }
public virtual void BuildAxisClosureUnion(Expression source, AxisBuildState state, SwitchAccessor swa, bool yieldResult, Block block, BlockScope scope) { TypeUnion tu = source.Type as TypeUnion; Debug.Assert(tu != null, "Switch accessor must have type union"); if (!this.IsLocal(source)) { Expression loc = this.NewClosureLocal(source.Type, scope); block.Statements.Add(new AssignmentStatement(loc, source)); source = loc; } // determine type union tag and value Method mgetvalue = this.GetTypeView(tu).GetMethod(StandardIds.GetValue); MethodCall mcgetvalue = new MethodCall(new MemberBinding(source, mgetvalue), null); mcgetvalue.Type = mgetvalue.ReturnType; Local locValue = new Local(SystemTypes.Object); block.Statements.Add(new AssignmentStatement(locValue, mcgetvalue)); Method mgettag = this.GetTypeView(tu).GetMethod(StandardIds.GetTag); MethodCall mcgettag = new MethodCall(new MemberBinding(source, mgettag), null); mcgettag.Type = mgettag.ReturnType; Local locTag = new Local(SystemTypes.UInt32); block.Statements.Add(new AssignmentStatement(locTag, mcgettag)); // switch on type union tag BlockList blocks = new BlockList(swa.Accessors.Count); Block endBlock = new Block(null); foreach( int id in swa.Accessors.Keys ) { Accessor acc = (Accessor) swa.Accessors[id]; Block caseBlock = new Block(new StatementList(3)); blocks.Add(caseBlock); block.Statements.Add(new Branch(new BinaryExpression(locTag, new Literal(id, SystemTypes.Int32), NodeType.Eq), caseBlock)); Expression locvar = this.NewClosureLocal(swa.Type.Types[id], scope); caseBlock.Statements.Add(new AssignmentStatement(locvar, this.Unbox(locValue, locvar.Type))); this.BuildAxisClosureExpression(locvar, state, acc, yieldResult, caseBlock, scope); caseBlock.Statements.Add(new Branch(null, endBlock)); } block.Statements.Add(new Branch(null, endBlock)); for( int i = 0, n = blocks.Count; i < n; i++ ) { block.Statements.Add(blocks[i]); } block.Statements.Add(endBlock); }
public virtual void BuildAxisClosureExpression(Expression source, AxisBuildState state, Accessor next, bool yieldResult, Block inner, BlockScope scope) { Cardinality tcard = this.typeSystem.GetCardinality(state.YieldType, this.TypeViewer); Cardinality scard = this.typeSystem.GetCardinality(source, this.TypeViewer); // lift over collections while (true) { if (this.typeSystem.IsStructural(source.Type)) goto lift_done; if (yieldResult && scard == tcard) goto lift_done; switch (scard) { case Cardinality.ZeroOrOne: Block b = new Block(new StatementList(3)); inner.Statements.Add(this.IfNotNull(source, b)); inner = b; source = this.GetNonNull(source, inner, scope); break; case Cardinality.ZeroOrMore: case Cardinality.OneOrMore: TypeNode elementType = this.typeSystem.GetStreamElementType(source, this.TypeViewer); Expression target = null; Block newInner = null; inner.Statements.Add(this.BuildClosureForEach(source, ref target, out newInner, scope)); inner = newInner; source = target; break; default: goto lift_done; } scard = this.typeSystem.GetCardinality(source, this.TypeViewer); } lift_done: if (yieldResult) { if (scard == Cardinality.None) { Block b = new Block(new StatementList(1)); inner.Statements.Add(this.IfNotNull(source, b)); inner = b; source = this.GetNonNull(source, inner, scope); } if (state.YieldTarget != null && state.YieldBlock != null) { inner.Statements.Add(new AssignmentStatement(state.YieldTarget, this.typeSystem.ExplicitCoercion(source, state.YieldType, this.TypeViewer))); inner.Statements.Add(new Branch(Literal.True, state.YieldBlock)); } else { inner.Statements.Add(new Yield(this.typeSystem.ExplicitCoercion(source, state.YieldType, this.TypeViewer))); } } if (next != null) { inner.Statements.Add(this.BuildAxisClosure(source, state, next, scope)); } }
public virtual void BuildAxisClosureMember(Expression source, AxisBuildState state, MemberAccessor ma, Block block, BlockScope scope) { Block inner = block; bool isStatic = (source is Literal) && (source.Type == SystemTypes.Type); if (!this.IsLocal(source)) { Expression loc = this.NewClosureLocal(source.Type, scope); inner.Statements.Add(new AssignmentStatement(loc, source)); source = loc; } // sanity check for member/type mismatch caused by aliases if (!isStatic && source.Type != ma.Member.DeclaringType) { Expression loc = this.NewClosureLocal(ma.Member.DeclaringType, scope); inner.Statements.Add(new AssignmentStatement(loc, this.typeSystem.ExplicitCoercion(source, loc.Type, this.TypeViewer))); source = loc; } Cardinality tcard = this.typeSystem.GetCardinality(state.YieldType, this.TypeViewer); Cardinality scard = this.typeSystem.GetCardinality(source, this.TypeViewer); if (scard != Cardinality.One) { Block b = new Block(new StatementList(3)); inner.Statements.Add(this.IfNotNull(source, b)); inner = b; source = this.GetNonNull(source, inner, scope); } TypeNode memberType = this.typeSystem.GetMemberType(ma.Member); MemberBinding mb = null; if (isStatic) { mb = new MemberBinding(null, ma.Member); } else { mb = new MemberBinding(source, ma.Member); } mb.Type = memberType; this.BuildAxisClosureExpression(mb, state, ma.Next, ma.Yield, inner, scope); }
public virtual Block BuildAxisClosureBlock(Expression source, AxisBuildState state, Accessor accessor, BlockScope scope) { if (accessor == null || source == null || state == null || state.YieldType == null || scope == null) return null; MemberAccessor ma = accessor as MemberAccessor; if (ma != null) { Block block = new Block(new StatementList(3)); this.BuildAxisClosureMember(source, state, ma, block, scope); return block; } SequenceAccessor sqa = accessor as SequenceAccessor; if (sqa != null) { Block block = new Block(new StatementList(sqa.Accessors.Count + 1)); this.BuildAxisClosureSequence(source, state, sqa, block, scope); return block; } SwitchAccessor swa = accessor as SwitchAccessor; if (swa != null) { Block block = new Block(new StatementList()); this.BuildAxisClosureUnion(source, state, swa, false, block, scope); return block; } // todo: add error message here return null; }
public virtual Block BuildAxisClosure(Expression source, AxisBuildState state, Accessor acc, BlockScope scope) { if (state.TypeClosures != null) { TypeNode tn = source.Type; CurrentClosure cc = (CurrentClosure) state.TypeClosures[tn.UniqueKey]; if (cc == null) { cc = this.BeginCurrentClosure(state.YieldType, "axis"); Parameter p = new Parameter(Identifier.For("source"), tn); cc.Method.Parameters = new ParameterList(1); cc.Method.Parameters.Add(p); state.TypeClosures[tn.UniqueKey] = cc; ParameterField pf = new ParameterField(cc.Method.Scope, null, FieldFlags.Public, p.Name, p.Type, null); pf.Parameter = p; cc.Method.Scope.Members.Add(pf); MemberBinding mb = new MemberBinding(new ImplicitThis(), pf); mb.Type = pf.Type; cc.Method.Body.Statements.Add(this.BuildAxisClosureBlock(mb, state, acc, cc.Method.Body.Scope)); this.EndCurrentClosure(cc); } Block block = new Block(new StatementList(1)); ImplicitThis it = new ImplicitThis(); it.Type = cc.Method.DeclaringType; MethodCall mc = new MethodCall(new MemberBinding(it, cc.Method), new ExpressionList(source)); mc.Type = cc.Method.ReturnType; if (cc.Method.IsVirtual) mc.NodeType = NodeType.Callvirt; Expression target = null; Block inner = null; block.Statements.Add(this.BuildClosureForEach(mc, ref target, out inner, scope)); inner.Statements.Add(new Yield(target)); return block; } return this.BuildAxisClosureBlock(source, state, acc, scope); }
public override Node VisitQueryAxis(QueryAxis axis) { if (axis.Type == null) return null; // error handling. Cardinality tcard = this.typeSystem.GetCardinality(axis, this.TypeViewer); switch( tcard ) { case Cardinality.None: case Cardinality.One: case Cardinality.ZeroOrOne: { BlockScope scope = this.currentMethod.Body.Scope; Block block = new Block(new StatementList(4)); AxisBuildState state = new AxisBuildState(axis.Type); state.YieldBlock = new Block(); state.YieldTarget = this.NewClosureLocal(axis.Type, scope); if (tcard == Cardinality.ZeroOrOne) { block.Statements.Add(new AssignmentStatement(state.YieldTarget, this.typeSystem.ImplicitCoercion(Literal.Null, state.YieldType, this.TypeViewer))); } block.Statements.Add(this.BuildAxisClosure(axis.Source, state, axis.AccessPlan, scope)); block.Statements.Add(state.YieldBlock); block.Statements.Add(new ExpressionStatement(state.YieldTarget)); BlockExpression be = new BlockExpression(block, state.YieldType); return this.VisitBlockExpression(be); } default: case Cardinality.OneOrMore: case Cardinality.ZeroOrMore: { TypeNode targetType = this.typeSystem.GetStreamElementType(axis, this.TypeViewer); Block body = null; Node closure = this.StartQueryClosure(targetType, "axis", out body); BlockScope scope = body.Scope; AxisBuildState state = new AxisBuildState(targetType); if (axis.IsCyclic) state.TypeClosures = new Hashtable(); Cardinality scard = this.typeSystem.GetCardinality(axis.Source, this.TypeViewer); switch( scard ) { case Cardinality.None: case Cardinality.One: case Cardinality.ZeroOrOne: body.Statements.Add(this.BuildAxisClosure(axis.Source, state, axis.AccessPlan, scope)); break; case Cardinality.OneOrMore: case Cardinality.ZeroOrMore: Expression feTarget = null; Block inner = null; body.Statements.Add(this.BuildClosureForEach(axis.Source, ref feTarget, out inner, scope)); inner.Statements.Add(this.BuildAxisClosure(feTarget, state, axis.AccessPlan, scope)); break; } return this.EndQueryClosure(closure, axis.Type); } } }