internal void RemoveJump(BlockEndOpcode jumpTo) { bool flag = base.IsReachableFromConditional(); if (flag) { base.prev.DelinkFromConditional(this); } if (this.jump.ID == OpcodeID.Branch) { BranchOpcode jump = (BranchOpcode)this.jump; jumpTo.DeLinkJump(this); jump.RemoveChild(jumpTo); if (jump.Branches.Count == 0) { this.jump = null; } } else { jumpTo.DeLinkJump(this); this.jump = null; } if (flag && (this.jump != null)) { base.prev.LinkToConditional(this); } }
private void CompileBoolean(XPathExpr expr, bool testValue) { if (this.compiler.nestingLevel == 1) { this.CompileBasicBoolean(expr, testValue); } else { OpcodeBlock block = new OpcodeBlock(); Opcode jump = new BlockEndOpcode(); block.Append(new PushBooleanOpcode(testValue)); XPathExprList subExpr = expr.SubExpr; XPathExpr expr2 = subExpr[0]; block.Append(this.CompileBlock(expr2)); if (expr2.ReturnType != ValueDataType.Boolean) { block.Append(new TypecastOpcode(ValueDataType.Boolean)); } block.Append(new ApplyBooleanOpcode(jump, testValue)); for (int i = 1; i < subExpr.Count; i++) { expr2 = subExpr[i]; block.Append(new StartBooleanOpcode(testValue)); block.Append(this.CompileBlock(expr2)); if (expr2.ReturnType != ValueDataType.Boolean) { block.Append(new TypecastOpcode(ValueDataType.Boolean)); } block.Append(new EndBooleanOpcode(jump, testValue)); } block.Append(jump); this.codeBlock.Append(block); } }
internal void AddJump(BlockEndOpcode jumpTo) { bool flag = base.IsReachableFromConditional(); if (flag) { base.prev.DelinkFromConditional(this); } if (this.jump == null) { this.jump = jumpTo; } else { BranchOpcode jump; if (this.jump.ID == OpcodeID.Branch) { jump = (BranchOpcode)this.jump; } else { BlockEndOpcode opcode = (BlockEndOpcode)this.jump; jump = new BranchOpcode(); jump.Branches.Add(opcode); this.jump = jump; } jump.Branches.Add(jumpTo); } jumpTo.LinkJump(this); if (flag && (this.jump != null)) { base.prev.LinkToConditional(this); } }
void FixupJumps() { QueryBuffer <Opcode> treePath = this.diverger.TreePath; QueryBuffer <Opcode> insertPath = this.diverger.InsertPath; for (int i = 0; i < insertPath.Count; ++i) { if (insertPath[i].TestFlag(OpcodeFlags.Jump)) { Fx.Assert(treePath[i].ID == insertPath[i].ID, ""); JumpOpcode insertJump = (JumpOpcode)insertPath[i]; // Opcodes in 'insertPath' have equivalent opcodes in the query tree: i.e. the query tree contains an // an equivalent execution path (upto the point of divergence naturally) that will produce in an identical // result. The remainder of the query tree (anything that lies beyond the point of divergence) represents // a distinct execution path and is grafted onto the tree as a new branch. In fact, we simply break off // the remainder from the query being inserted and graft it onto the query tree. // If there are jumps on the insert path that jump to opcodes NOT in the insert path, then the jumps // will reach opcodes in the new branch we will add(see above). However, because the actual jump opcodes // are shared (used as is from the query tree), the actual jump must also be branched. One jump will // continue to jump to the original opcode and the second new one will jump to an opcode in the grafted branch. if (-1 == insertPath.IndexOf(insertJump.Jump, i + 1)) { Fx.Assert(insertJump.Jump.ID == OpcodeID.BlockEnd, ""); BlockEndOpcode jumpTo = (BlockEndOpcode)insertJump.Jump; // no longer jumping from insertJump to jumpTo insertJump.RemoveJump(jumpTo); // Instead, jumping from treePath[i] to jumpTo JumpOpcode treeJump = (JumpOpcode)treePath[i]; treeJump.AddJump(jumpTo); } } } }
// Compiles expressions at nesting level == 1 -> boolean expressions that can be processed // with less complex opcodes because they will never track multiple sequences simultaneously void CompileBasicBoolean(XPathExpr expr, bool testValue) { // Boolean expressions must always have at least 2 sub expressions Fx.Assert(expr.SubExprCount > 1, ""); Fx.Assert(this.compiler.nestingLevel == 1, ""); OpcodeBlock boolBlock = new OpcodeBlock(); // struct Opcode blockEnd = new BlockEndOpcode(); XPathExprList subExprList = expr.SubExpr; // Compile sub-expressions for (int i = 0; i < subExprList.Count; ++i) { XPathExpr subExpr = subExprList[i]; boolBlock.Append(this.CompileBlock(subExpr)); // Make sure each sub-expression can produce a boolean result if (subExpr.ReturnType != ValueDataType.Boolean) { boolBlock.Append(new TypecastOpcode(ValueDataType.Boolean)); } if (i < (subExprList.Count - 1)) { // No point jumping if this is the last expression boolBlock.Append(new JumpIfOpcode(blockEnd, testValue)); } } boolBlock.Append(blockEnd); this.codeBlock.Append(boolBlock); }
internal void RemoveJump(BlockEndOpcode jumpTo) { Fx.Assert(null != this.jump, ""); bool conditional = this.IsReachableFromConditional(); if (conditional) { this.prev.DelinkFromConditional(this); } if (this.jump.ID == OpcodeID.Branch) { BranchOpcode jumpBranch = (BranchOpcode)this.jump; jumpTo.DeLinkJump(this); jumpBranch.RemoveChild(jumpTo); if (0 == jumpBranch.Branches.Count) { this.jump = null; } } else { Fx.Assert(object.ReferenceEquals(jumpTo, this.jump), ""); jumpTo.DeLinkJump(this); this.jump = null; } if (conditional && null != this.jump) { this.prev.LinkToConditional(this); } }
internal void RemoveJump(BlockEndOpcode jumpTo) { bool flag = base.IsReachableFromConditional(); if (flag) { base.prev.DelinkFromConditional(this); } if (this.jump.ID == OpcodeID.Branch) { BranchOpcode jump = (BranchOpcode) this.jump; jumpTo.DeLinkJump(this); jump.RemoveChild(jumpTo); if (jump.Branches.Count == 0) { this.jump = null; } } else { jumpTo.DeLinkJump(this); this.jump = null; } if (flag && (this.jump != null)) { base.prev.LinkToConditional(this); } }
internal void AddJump(BlockEndOpcode jumpTo) { bool flag = base.IsReachableFromConditional(); if (flag) { base.prev.DelinkFromConditional(this); } if (this.jump == null) { this.jump = jumpTo; } else { BranchOpcode jump; if (this.jump.ID == OpcodeID.Branch) { jump = (BranchOpcode) this.jump; } else { BlockEndOpcode opcode = (BlockEndOpcode) this.jump; jump = new BranchOpcode(); jump.Branches.Add(opcode); this.jump = jump; } jump.Branches.Add(jumpTo); } jumpTo.LinkJump(this); if (flag && (this.jump != null)) { base.prev.LinkToConditional(this); } }
void CompileBoolean(XPathExpr expr, bool testValue) { // Boolean expressions must always have at least 2 sub expressions Fx.Assert(expr.SubExprCount > 1, ""); if (this.compiler.nestingLevel == 1) { this.CompileBasicBoolean(expr, testValue); return; } OpcodeBlock boolBlock = new OpcodeBlock(); // struct Opcode blockEnd = new BlockEndOpcode(); // Set up the result mask boolBlock.Append(new PushBooleanOpcode(testValue)); XPathExprList subExprList = expr.SubExpr; XPathExpr subExpr; // the first expression needs the least work.. subExpr = subExprList[0]; boolBlock.Append(this.CompileBlock(subExpr)); if (subExpr.ReturnType != ValueDataType.Boolean) { boolBlock.Append(new TypecastOpcode(ValueDataType.Boolean)); } boolBlock.Append(new ApplyBooleanOpcode(blockEnd, testValue)); // Compile remaining sub-expressions for (int i = 1; i < subExprList.Count; ++i) { subExpr = subExprList[i]; boolBlock.Append(new StartBooleanOpcode(testValue)); boolBlock.Append(this.CompileBlock(subExpr)); // Make sure each sub-expression can produce a boolean result if (subExpr.ReturnType != ValueDataType.Boolean) { boolBlock.Append(new TypecastOpcode(ValueDataType.Boolean)); } boolBlock.Append(new EndBooleanOpcode(blockEnd, testValue)); } boolBlock.Append(blockEnd); this.codeBlock.Append(boolBlock); }
private void FixupJumps() { QueryBuffer <Opcode> treePath = this.diverger.TreePath; QueryBuffer <Opcode> insertPath = this.diverger.InsertPath; for (int i = 0; i < insertPath.Count; i++) { if (insertPath[i].TestFlag(OpcodeFlags.Jump)) { JumpOpcode opcode = (JumpOpcode)insertPath[i]; if (-1 == insertPath.IndexOf(opcode.Jump, i + 1)) { BlockEndOpcode jump = (BlockEndOpcode)opcode.Jump; opcode.RemoveJump(jump); ((JumpOpcode)treePath[i]).AddJump(jump); } } } }
private void CompileBasicBoolean(XPathExpr expr, bool testValue) { OpcodeBlock block = new OpcodeBlock(); Opcode jump = new BlockEndOpcode(); XPathExprList subExpr = expr.SubExpr; for (int i = 0; i < subExpr.Count; i++) { XPathExpr expr2 = subExpr[i]; block.Append(this.CompileBlock(expr2)); if (expr2.ReturnType != ValueDataType.Boolean) { block.Append(new TypecastOpcode(ValueDataType.Boolean)); } if (i < (subExpr.Count - 1)) { block.Append(new JumpIfOpcode(jump, testValue)); } } block.Append(jump); this.codeBlock.Append(block); }
internal void AddJump(BlockEndOpcode jumpTo) { bool conditional = this.IsReachableFromConditional(); if (conditional) { this.prev.DelinkFromConditional(this); } if (null == this.jump) { this.jump = jumpTo; } else { BranchOpcode jumpBranch; if (this.jump.ID == OpcodeID.Branch) { // already a branch jumpBranch = (BranchOpcode)this.jump; } else { BlockEndOpcode currentJump = (BlockEndOpcode)this.jump; jumpBranch = new BranchOpcode(); jumpBranch.Branches.Add(currentJump); this.jump = jumpBranch; } jumpBranch.Branches.Add(jumpTo); } jumpTo.LinkJump(this); if (conditional && null != this.jump) { this.prev.LinkToConditional(this); } }