/// <summary> /// Get the label for a short-circuit /// </summary> private static Label GetShortCircuitLabel(AndOrElement current, ShortCircuitInfo info, YaleIlGenerator ilg) { // We modify the given stacks so we need to clone them var cloneOperands = (Stack)info.Operands.Clone(); var cloneOperators = (Stack)info.Operators.Clone(); // Pop all siblings current.PopRightChild(cloneOperands, cloneOperators); // Go until we run out of operators while (cloneOperators.Count > 0) { // Get the top operator var top = (AndOrElement)cloneOperators.Pop(); // Is is a different operation? if (top.myOperation != current.myOperation) { // Yes, so return a label to its right operand var nextOperand = cloneOperands.Pop(); return(GetLabel(nextOperand, ilg, info)); } // No, so keep going up the stack top.PopRightChild(cloneOperands, cloneOperators); } // We've reached the end of the stack so return the label for the appropriate true/false terminal if (current.myOperation == AndOrOperation.And) { return(GetLabel(OurFalseTerminalKey, ilg, info)); } return(GetLabel(OurTrueTerminalKey, ilg, info)); }
/// <summary> /// Emit a short/long branch for an And/Or element /// </summary> private static OpCode GetBranchOpcode(AndOrElement op, bool longBranch) { if (op.myOperation == AndOrOperation.And) { return(longBranch ? OpCodes.Brfalse : OpCodes.Brfalse_S); } return(longBranch ? OpCodes.Brtrue : OpCodes.Brtrue_S); }
private static void EmitBranch(AndOrElement op, YaleIlGenerator ilg, Label target, ShortCircuitInfo info) { if (ilg.IsTemp) { info.Branches.AddBranch(ilg, target); // Temp mode; just emit a short branch and return var shortBranch = GetBranchOpcode(op, false); ilg.Emit(shortBranch, target); return; } // Emit the proper branch opcode // Determine if it is a long branch var longBranch = info.Branches.IsLongBranch(ilg, target); // Get the branch opcode var brOpcode = GetBranchOpcode(op, longBranch); // Emit the branch ilg.Emit(brOpcode, target); }