예제 #1
0
        /// <summary>
        /// Visit the nodes of the tree (right then left) and populate some data structures
        /// </summary>
        /// <param name="info"></param>
        private void PopulateData(ShortCircuitInfo info)
        {
            // Is our right child a leaf or another And/Or expression?
            AndOrElement andOrChild = MyRightChild as AndOrElement;

            if (andOrChild == null)
            {
                // Leaf so push it on the stack
                info.Operands.Push(MyRightChild);
            }
            else
            {
                // Another And/Or expression so recurse
                andOrChild.PopulateData(info);
            }

            // Add ourselves as an operator
            info.Operators.Push(this);

            // Do the same thing for the left child
            andOrChild = MyLeftChild as AndOrElement;

            if (andOrChild == null)
            {
                info.Operands.Push(MyLeftChild);
            }
            else
            {
                andOrChild.PopulateData(info);
            }
        }
예제 #2
0
 /// <summary>
 /// Emit a short/long branch for an And/Or element
 /// </summary>
 /// <param name="op"></param>
 /// <param name="longBranch"></param>
 /// <returns></returns>
 private static OpCode GetBranchOpcode(AndOrElement op, bool longBranch)
 {
     if (op._myOperation == AndOrOperation.And)
     {
         if (longBranch == true)
         {
             return(OpCodes.Brfalse);
         }
         else
         {
             return(OpCodes.Brfalse_S);
         }
     }
     else
     {
         if (longBranch == true)
         {
             return(OpCodes.Brtrue);
         }
         else
         {
             return(OpCodes.Brtrue_S);
         }
     }
 }
예제 #3
0
        /// <summary>
        /// Recursively pop operators and operands
        /// </summary>
        /// <param name="operands"></param>
        /// <param name="operators"></param>
        private void Pop(Stack operands, Stack operators)
        {
            operators.Pop();

            AndOrElement andOrChild = MyLeftChild as AndOrElement;

            if (andOrChild == null)
            {
                operands.Pop();
            }
            else
            {
                andOrChild.Pop(operands, operators);
            }

            andOrChild = (AndOrElement)MyRightChild;

            if (andOrChild == null)
            {
                operands.Pop();
            }
            else
            {
                andOrChild.Pop(operands, operators);
            }
        }
예제 #4
0
 private static void EmitBranch(AndOrElement op, FleeILGenerator ilg, Label target, ShortCircuitInfo info)
 {
     // Get the branch opcode
     if (op._myOperation == AndOrOperation.And)
     {
         ilg.EmitBranchFalse(target);
     }
     else
     {
         ilg.EmitBranchTrue(target);
     }
 }
예제 #5
0
        private void PopRightChild(Stack operands, Stack operators)
        {
            AndOrElement andOrChild = MyRightChild as AndOrElement;

            // What kind of child do we have?
            if ((andOrChild != null))
            {
                // Another and/or expression so recurse
                andOrChild.Pop(operands, operators);
            }
            else
            {
                // A terminal so pop it off the operands stack
                operands.Pop();
            }
        }
예제 #6
0
        /// <summary>
        /// Emit a sequence of and/or expressions with short-circuiting
        /// </summary>
        /// <param name="ilg"></param>
        /// <param name="info"></param>
        /// <param name="services"></param>
        private static void EmitLogicalShortCircuit(FleeILGenerator ilg, ShortCircuitInfo info, IServiceProvider services)
        {
            while (info.Operators.Count != 0)
            {
                // Get the operator
                AndOrElement op = (AndOrElement)info.Operators.Pop();
                // Get the left operand
                ExpressionElement leftOperand = (ExpressionElement)info.Operands.Pop();

                // Emit the left
                EmitOperand(leftOperand, info, ilg, services);

                // Get the label for the short-circuit case
                Label l = GetShortCircuitLabel(op, info, ilg);
                // Emit the branch
                EmitBranch(op, ilg, l, info);
            }
        }
예제 #7
0
        /// <summary>
        /// Get the label for a short-circuit
        /// </summary>
        /// <param name="current"></param>
        /// <param name="info"></param>
        /// <param name="ilg"></param>
        /// <returns></returns>
        private static Label GetShortCircuitLabel(AndOrElement current, ShortCircuitInfo info, FleeILGenerator ilg)
        {
            // We modify the given stacks so we need to clone them
            Stack cloneOperands  = (Stack)info.Operands.Clone();
            Stack 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
                AndOrElement top = (AndOrElement)cloneOperators.Pop();

                // Is is a different operation?
                if (top._myOperation != current._myOperation)
                {
                    // Yes, so return a label to its right operand
                    object nextOperand = cloneOperands.Pop();
                    return(GetLabel(nextOperand, ilg, info));
                }
                else
                {
                    // 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));
            }
            else
            {
                return(GetLabel(OurTrueTerminalKey, ilg, info));
            }
        }
예제 #8
0
        private static void EmitBranch(AndOrElement op, FleeILGenerator ilg, Label target, ShortCircuitInfo info)
        {
            if (ilg.IsTemp == true)
            {
                info.Branches.AddBranch(ilg, target);

                // Temp mode; just emit a short branch and return
                OpCode shortBranch = GetBranchOpcode(op, false);
                ilg.Emit(shortBranch, target);

                return;
            }

            // Emit the proper branch opcode

            // Determine if it is a long branch
            bool longBranch = info.Branches.IsLongBranch(ilg, target);

            // Get the branch opcode
            OpCode brOpcode = GetBranchOpcode(op, longBranch);

            // Emit the branch
            ilg.Emit(brOpcode, target);
        }