/// <summary> /// Test two conditions, and conditionally branch vs. fall through: /// either branch to target or fall through to subsequent code; /// conditions are and'ed together: both together constitute "true". /// Another way of thinking of this is condition conjunction (both). /// </summary> /// <param name="left"> /// Initial/left test condition. /// </param> /// <param name="right"> /// Initial/right test condition -- possibly short-circuted. /// </param> /// <param name="target"> /// Conditional branch target (or else fall thru). /// </param> /// <param name="reverse"> /// false --> normal case, fall through on both true, otherwise on false: branch to target /// true --> reversed case, fall through at least one false, otherwise on true: branch to target /// </param> public void EvalBoth(AbstractSyntaxTree left, AbstractSyntaxTree right, BranchTargetLabel target, bool reverse) { // NB: "Both" means evaluating left/first and right/second operands in the normal way. // Each operand is evaluated to branch around the then-part or loop-body on condition false, // and fall thru into the then-part or loop-body on condition true (both sub conditions being true). left.GenerateCodeForConditionalBranchWithPrettyPrint(this, target, reverse); right.GenerateCodeForConditionalBranchWithPrettyPrint(this, target, reverse); }
public void PlaceLabelHere(BranchTargetLabel label) { if (_labelList [label.Id]) { throw new AssertionFailedException("label already defined: L" + label.Id); } _labelList [label.Id] = true; OutLine(String.Format("L{0}:", label.Id)); }
/// <summary> /// Test two conditions, and conditionally branch vs. fall through: /// either branch to target or fall through to subsequent code; /// conditions are or'ed together: either one constitutes "true". /// Another way of thinking of this is condition disjunction (i.e. either). /// </summary> /// <param name="left"> /// Initial/left test condition. /// </param> /// <param name="right"> /// Initial/right test condition -- possibly short-circuted. /// </param> /// <param name="target"> /// Conditional branch target (or else fall thru). /// </param> /// <param name="reverse"> /// false --> normal case, fall through to following code on at least one true, otherwise on false: branch to target /// true --> reversed case, fall through both false, otherwise on true: branch to target /// </param> public void EvalEither(AbstractSyntaxTree left, AbstractSyntaxTree right, BranchTargetLabel target, bool reverse) { // NB: "Either" means evaluating left/first operand, and on true, taking branch around the right/second operand // and into the fall thru code of the then-part or loop-body! // This requires use of an intermediate label, and a reversal of the evaluation condition, but only for the left/first operand. // The second operand is evaluated as per normal, take brach around the then-part or loop-body on condition false. var around = CreateLabel(); left.GenerateCodeForConditionalBranchWithPrettyPrint(this, around, !reverse); right.GenerateCodeForConditionalBranchWithPrettyPrint(this, target, reverse); PlaceLabelHere(around); }
public void GenerateBinaryCompareConditionalBranch(Operator op, BranchTargetLabel label, bool reverse) { //Handle the Relational Operators: LessThan,LessOrEqual,GreaterThan,GreaterOrEqual,EqualEqual,NotEqual, var branchOpcode = ""; switch (op) { case Operator.LessThan: branchOpcode = reverse ? "B.LT" : "B.GE"; break; case Operator.LessOrEqual: branchOpcode = reverse ? "B.LE" : "B.GT"; break; case Operator.GreaterThan: branchOpcode = reverse ? "B.GT" : "B.LE"; break; case Operator.GreaterOrEqual: branchOpcode = reverse ? "B.GE" : "B.LT"; break; case Operator.EqualEqual: branchOpcode = reverse ? "B.EQ" : "B.NE"; break; case Operator.NotEqual: branchOpcode = reverse ? "B.NE" : "B.EQ"; break; default: throw new AssertionFailedException("Operator is not one of the relational operators: " + op.ToString()); } OutLine(String.Format(" {0}{2}L{1}", branchOpcode, label.Id, _argumentPosition.Substring(branchOpcode.Length))); }
public void GenerateUnaryTestConditionalBranch(BranchTargetLabel label, bool reverse) { var opcode = reverse ? "B.TRUE" : "B.FALSE"; OutLine(String.Format(" {0}{2}L{1}", opcode, label.Id, _argumentPosition.Substring(opcode.Length))); }
public void GenerateUnconditionalBranch(BranchTargetLabel label) { var opcode = "JUMP"; OutLine(String.Format(" {0}{2}L{1}", opcode, label.Id, _argumentPosition.Substring(opcode.Length))); }
public virtual void GenerateCodeForConditionalBranchWithPrettyPrint(CodeGenContext context, BranchTargetLabel label, bool reverse) { context.PrettyPrint(this); // prints && operator GenerateCodeForConditionalBranch(context, label, reverse); }
/// <summary> /// Generates code for the given tree node, with the purpose of accomplishing a conditional branch to target /// or falling thru to whatever comes after this generated code. /// </summary> /// <param name="context"> /// where the generated code is output to, and some helper functions /// </param> /// <param name="label"> /// the desired target of the conditional branch /// </param> /// <param name="reverse"> /// the reverse parameter's meaning: /// /// false --> use the normal if-then-style evaluation: /// take branch on condition false and fall thru on condition true /// /// true --> use the reverse of the normal sense of if-then evaluation: /// take branch on condition true and fall thru on condition false /// one might use this, if for some reason /// we had choosen to swap the code ordering of the then-part and else-part /// or, we need to evaluate something involving negation /// or, we're evaluating a do ... while instead of while. /// /// NB: The normal approach for an if-then-statement, e.g. in: /// if ( a ) { b=1; } /// is that we evaluate "a" and /// conditionally branch: take branch around the then-part on "a" being false, or else, /// fall thru to then-part (e.g. { b=1; } ) on "a" being true. /// /// *If* statements and *While* statements and *For* statements evaluate their condition to /// take the branch (around the then or the loop) on the expressed condition being false, and /// fall-thru (into the then-part or loop-body) on it being true. /// /// Sometimes we need to reverse things, e.g.: /// To accomplish negation operator as in /// if ( ! a ) { b=1; } /// We would start by evaluating "! a" as with any if-statemetn: for conditional branch with reverse=false, /// (meaning take branch on false, and fall thru on true) /// However, the "!" will be handled by reversing the evaluation condition (for the further evaluation of "a") /// rather than generating any actual negation code. /// /// Also, *do while* statements evaluate the conditional for branch oppositely than regular while: /// take branch (backward, to repeat the loop) on true, and fall-thru (exiting the loop) on false. /// So, *do while* should evaluate its conditional expression using reverse=true. /// /// Further note that the short-circut boolean || operator requires /// evaluation of the left/first operand under reversed conditions: /// this in order to branch around the right/second operand (short-circuting it). /// So, to accomplish the fall thru to the then-part or loop-body, /// the left/first operand is evaluated to take branch (condition true) into the then-part /// and the right/second operand is evaluated to take branch (condition false) around the then-part /// /// Combinations of &&, || and ! will reverse evaluation conditions as needed. /// /// See the overrides: /// ShortCircutAndTreeNode.GenerateCodeForConditionalBranch, and, /// ShortCircutOrTreeNode.GenerateCodeForConditionalBranch /// /// </param> protected virtual void GenerateCodeForConditionalBranch(CodeGenContext context, BranchTargetLabel label, bool reverse) { // // This implementation is used by any operator that does not customize the evaluation for conditional branch: // This default implementation generates the value to be tested, and then does a test & branch on that value. // GenerateCodeForValue/*WithPrettyPrint*/ (context, EvaluationIntention.Value); // pretty print already done at this level context.GenerateUnaryTestConditionalBranch(label, reverse); // Note: ! && || operators can generate substantially better code using custom implementation rather than this generic one. // Negation is discussed above: // rather than generating code to negate a boolean and test & branch on that, // negation simply evaluates the negated expression with reversed branch condition. // The short-circut operators also need not generate a boolean value to be tested & branched on, // and can instead directly branch on the conditions of the left-hand and right-hand side expressions. }