Ejemplo n.º 1
0
        /// <summary>
        /// Emit the end cases for a short-circuit
        /// </summary>
        /// <param name="info"></param>
        /// <param name="ilg"></param>
        /// <param name="endLabel"></param>
        private static void EmitTerminals(ShortCircuitInfo info, FleeILGenerator ilg, Label endLabel)
        {
            // Emit the false case if it was used
            if (info.Branches.HasLabel(OurFalseTerminalKey) == true)
            {
                Label falseLabel = info.Branches.FindLabel(OurFalseTerminalKey);

                // Mark the label and note its position
                ilg.MarkLabel(falseLabel);
                MarkBranchTarget(info, falseLabel, ilg);

                ilg.Emit(OpCodes.Ldc_I4_0);

                // If we also have a true terminal, then skip over it
                if (info.Branches.HasLabel(OurTrueTerminalKey) == true)
                {
                    ilg.Emit(OpCodes.Br_S, endLabel);
                }
            }

            // Emit the true case if it was used
            if (info.Branches.HasLabel(OurTrueTerminalKey) == true)
            {
                Label trueLabel = info.Branches.FindLabel(OurTrueTerminalKey);

                // Mark the label and note its position
                ilg.MarkLabel(trueLabel);
                MarkBranchTarget(info, trueLabel, ilg);

                ilg.Emit(OpCodes.Ldc_I4_1);
            }
        }
Ejemplo n.º 2
0
        /// <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));
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Emit a short-circuited logical operation sequence
        /// The idea: Store all the leaf operands in a stack with the leftmost at the top and rightmost at the bottom.
        /// For each operand, emit it and try to find an end point for when it short-circuits.  This means we go up through
        /// the stack of operators (ignoring siblings) until we find a different operation (then emit a branch to its right operand)
        /// or we reach the root (emit a branch to a true/false).
        /// Repeat the process for all operands and then emit the true/false/last operand end cases.
        /// </summary>
        private void EmitLogical(YaleIlGenerator ilg, ShortCircuitInfo info, ExpressionContext context)
        {
            // We always have an end label
            info.Branches.GetLabel(OurEndLabelKey, ilg);

            // Populate our data structures
            PopulateData(info);

            // Emit the sequence
            EmitLogicalShortCircuit(ilg, info, context);

            // Get the last operand
            var terminalOperand = (BaseExpressionElement)info.Operands.Pop();

            // Emit it
            EmitOperand(terminalOperand, info, ilg, context);
            // And jump to the end
            var endLabel = info.Branches.FindLabel(OurEndLabelKey);

            ilg.Emit(OpCodes.Br_S, endLabel);

            // Emit our true/false terminals
            EmitTerminals(info, ilg, endLabel);

            // Mark the end
            ilg.MarkLabel(endLabel);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Emit a short-circuited logical operation sequence
        /// The idea: Store all the leaf operands in a stack with the leftmost at the top and rightmost at the bottom.
        /// For each operand, emit it and try to find an end point for when it short-circuits.  This means we go up through
        /// the stack of operators (ignoring siblings) until we find a different operation (then emit a branch to its right operand)
        /// or we reach the root (emit a branch to a true/false).
        /// Repeat the process for all operands and then emit the true/false/last operand end cases.
        /// </summary>
        /// <param name="ilg"></param>
        /// <param name="info"></param>
        /// <param name="services"></param>
        private void EmitLogical(FleeILGenerator ilg, ShortCircuitInfo info, IServiceProvider services)
        {
            // We always have an end label
            info.Branches.GetLabel(OurEndLabelKey, ilg);

            // Populate our data structures
            this.PopulateData(info);

            // Emit the sequence
            EmitLogicalShortCircuit(ilg, info, services);

            // Get the last operand
            ExpressionElement terminalOperand = (ExpressionElement)info.Operands.Pop();

            // Emit it
            EmitOperand(terminalOperand, info, ilg, services);
            // And jump to the end
            Label endLabel = info.Branches.FindLabel(OurEndLabelKey);

            ilg.Emit(OpCodes.Br_S, endLabel);

            // Emit our true/false terminals
            EmitTerminals(info, ilg, endLabel);

            // Mark the end
            ilg.MarkLabel(endLabel);
        }
Ejemplo n.º 5
0
 /// <summary>
 /// Note a label's position if we are in mark mode
 /// </summary>
 /// <param name="info"></param>
 /// <param name="target"></param>
 /// <param name="ilg"></param>
 private static void MarkBranchTarget(ShortCircuitInfo info, Label target, FleeILGenerator ilg)
 {
     if (ilg.IsTemp == true)
     {
         info.Branches.MarkLabel(ilg, target);
     }
 }
Ejemplo n.º 6
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);
            }
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Emit a short-circuited logical operation sequence
        /// The idea: Store all the leaf operands in a stack with the leftmost at the top and rightmost at the bottom.
        /// For each operand, emit it and try to find an end point for when it short-circuits.  This means we go up through
        /// the stack of operators (ignoring siblings) until we find a different operation (then emit a branch to its right operand)
        /// or we reach the root (emit a branch to a true/false).
        /// Repeat the process for all operands and then emit the true/false/last operand end cases.
        /// </summary>
        /// <param name="ilg"></param>
        /// <param name="info"></param>
        /// <param name="services"></param>
        private void EmitLogical(FleeILGenerator ilg, ShortCircuitInfo info, IServiceProvider services)
        {
            // We always have an end label
            Label endLabel = ilg.DefineLabel();

            // Populate our data structures
            this.PopulateData(info);

            // Emit the sequence
            EmitLogicalShortCircuit(ilg, info, services);

            // Get the last operand
            ExpressionElement terminalOperand = (ExpressionElement)info.Operands.Pop();

            // Emit it
            EmitOperand(terminalOperand, info, ilg, services);

            // only 1-3 opcodes, always a short branch
            ilg.EmitBranch(endLabel);

            // Emit our true/false terminals
            EmitTerminals(info, ilg, endLabel);

            // Mark the end
            ilg.MarkLabel(endLabel);
        }
Ejemplo n.º 8
0
 private static Label GetLabel(object key, FleeILGenerator ilg, ShortCircuitInfo info)
 {
     if (info.HasLabel(key))
     {
         return(info.FindLabel(key));
     }
     return(info.AddLabel(key, ilg.DefineLabel()));
 }
Ejemplo n.º 9
0
        private void DoEmitLogical(FleeILGenerator ilg, IServiceProvider services)
        {
            // We have to do a 'fake' emit so we can get the positions of the labels
            ShortCircuitInfo info = new ShortCircuitInfo();

            // Do the real emit
            this.EmitLogical(ilg, info, services);
        }
Ejemplo n.º 10
0
        private static void EmitOperand(ExpressionElement operand, ShortCircuitInfo info, FleeILGenerator ilg, IServiceProvider services)
        {
            // Is this operand the target of a label?
            if (info.HasLabel(operand) == true)
            {
                // Yes, so mark it
                Label leftLabel = info.FindLabel(operand);
                ilg.MarkLabel(leftLabel);
            }

            // Emit the operand
            operand.Emit(ilg, services);
        }
Ejemplo n.º 11
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(YaleIlGenerator ilg, ShortCircuitInfo info, ExpressionContext context)
        {
            while (info.Operators.Count != 0)
            {
                // Get the operator
                var op = (AndOrElement)info.Operators.Pop();
                // Get the left operand
                var leftOperand = (BaseExpressionElement)info.Operands.Pop();

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

                // Get the label for the short-circuit case
                var label = GetShortCircuitLabel(op, info, ilg);
                // Emit the branch
                EmitBranch(op, ilg, label, info);
            }
        }
Ejemplo n.º 12
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);
            }
        }
Ejemplo n.º 13
0
        private void DoEmitLogical(YaleIlGenerator ilGenerator, ExpressionContext context)
        {
            // We have to do a 'fake' emit so we can get the positions of the labels
            var info = new ShortCircuitInfo();
            // Create a temporary IL generator
            var ilgTemp = CreateTempIlGenerator(ilGenerator);

            // We have to make sure that the label count for the temp YaleIlGenerator matches our real YaleIlGenerator
            Utility.SyncFleeIlGeneratorLabels(ilGenerator, ilgTemp);
            // Do the fake emit
            EmitLogical(ilgTemp, info, context);

            // Clear everything except the label positions
            info.ClearTempState();
            info.Branches.ComputeBranches();

            Utility.SyncFleeIlGeneratorLabels(ilgTemp, ilGenerator);

            // Do the real emit
            EmitLogical(ilGenerator, info, context);
        }
Ejemplo n.º 14
0
        private void DoEmitLogical(FleeILGenerator ilg, IServiceProvider services)
        {
            // We have to do a 'fake' emit so we can get the positions of the labels
            ShortCircuitInfo info = new ShortCircuitInfo();
            // Create a temporary IL generator
            FleeILGenerator ilgTemp = this.CreateTempFleeILGenerator(ilg);

            // We have to make sure that the label count for the temp FleeILGenerator matches our real FleeILGenerator
            Utility.SyncFleeILGeneratorLabels(ilg, ilgTemp);
            // Do the fake emit
            this.EmitLogical(ilgTemp, info, services);

            // Clear everything except the label positions
            info.ClearTempState();

            info.Branches.ComputeBranches();

            Utility.SyncFleeILGeneratorLabels(ilgTemp, ilg);

            // Do the real emit
            this.EmitLogical(ilg, info, services);
        }
Ejemplo n.º 15
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);
    }
Ejemplo n.º 16
0
    // Emit a short-circuited logical operation sequence
    // The idea: Store all the leaf operands in a stack with the leftmost at the top and rightmost at the bottom.
    // For each operand, emit it and try to find an end point for when it short-circuits.  This means we go up through
    // the stack of operators (ignoring siblings) until we find a different operation (then emit a branch to its right operand)
    // or we reach the root (emit a branch to a true/false).
    // Repeat the process for all operands and then emit the true/false/last operand end cases.
    private void EmitLogical(FleeILGenerator ilg, ShortCircuitInfo info, IServiceProvider services)
    {
        // We always have an end label
        info.Branches.GetLabel(OurEndLabelKey, ilg);

        // Populate our data structures
        this.PopulateData(info);

        // Emit the sequence
        EmitLogicalShortCircuit(ilg, info, services);

        // Get the last operand
        ExpressionElement terminalOperand = (ExpressionElement)info.Operands.Pop();
        // Emit it
        EmitOperand(terminalOperand, info, ilg, services);
        // And jump to the end
        Label endLabel = info.Branches.FindLabel(OurEndLabelKey);
        ilg.Emit(OpCodes.Br_S, endLabel);

        // Emit our true/false terminals
        EmitTerminals(info, ilg, endLabel);

        // Mark the end
        ilg.MarkLabel(endLabel);
    }
Ejemplo n.º 17
0
    // Get the label for a short-circuit
    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);
        }
    }
Ejemplo n.º 18
0
 private static Label GetLabel(object key, FleeILGenerator ilg, ShortCircuitInfo info)
 {
     return(info.Branches.GetLabel(key, ilg));
 }
Ejemplo n.º 19
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);
        }
Ejemplo n.º 20
0
    private static void EmitOperand(ExpressionElement operand, ShortCircuitInfo info, FleeILGenerator ilg, IServiceProvider services)
    {
        // Is this operand the target of a label?
        if (info.Branches.HasLabel(operand) == true)
        {
            // Yes, so mark it
            Label leftLabel = info.Branches.FindLabel(operand);
            ilg.MarkLabel(leftLabel);

            // Note the label's position
            MarkBranchTarget(info, leftLabel, ilg);
        }

        // Emit the operand
        operand.Emit(ilg, services);
    }
Ejemplo n.º 21
0
 // Note a label's position if we are in mark mode
 private static void MarkBranchTarget(ShortCircuitInfo info, Label target, FleeILGenerator ilg)
 {
     if (ilg.IsTemp == true)
     {
         info.Branches.MarkLabel(ilg, target);
     }
 }
Ejemplo n.º 22
0
    // Emit the end cases for a short-circuit
    private static void EmitTerminals(ShortCircuitInfo info, FleeILGenerator ilg, Label endLabel)
    {
        // Emit the false case if it was used
        if (info.Branches.HasLabel(OurFalseTerminalKey) == true)
        {
            Label falseLabel = info.Branches.FindLabel(OurFalseTerminalKey);

            // Mark the label and note its position
            ilg.MarkLabel(falseLabel);
            MarkBranchTarget(info, falseLabel, ilg);

            ilg.Emit(OpCodes.Ldc_I4_0);

            // If we also have a true terminal, then skip over it
            if (info.Branches.HasLabel(OurTrueTerminalKey) == true)
            {
                ilg.Emit(OpCodes.Br_S, endLabel);
            }
        }

        // Emit the true case if it was used
        if (info.Branches.HasLabel(OurTrueTerminalKey) == true)
        {
            Label trueLabel = info.Branches.FindLabel(OurTrueTerminalKey);

            // Mark the label and note its position
            ilg.MarkLabel(trueLabel);
            MarkBranchTarget(info, trueLabel, ilg);

            ilg.Emit(OpCodes.Ldc_I4_1);
        }
    }
Ejemplo n.º 23
0
 private static Label GetLabel(object key, FleeILGenerator ilg, ShortCircuitInfo info)
 {
     return info.Branches.GetLabel(key, ilg);
 }
Ejemplo n.º 24
0
    // Visit the nodes of the tree (right then left) and populate some data structures
    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);
        }
    }
Ejemplo n.º 25
0
    private void DoEmitLogical(FleeILGenerator ilg, IServiceProvider services)
    {
        // We have to do a 'fake' emit so we can get the positions of the labels
        ShortCircuitInfo info = new ShortCircuitInfo();
        // Create a temporary IL generator
        FleeILGenerator ilgTemp = this.CreateTempFleeILGenerator(ilg);

        // We have to make sure that the label count for the temp FleeILGenerator matches our real FleeILGenerator
        Utility.SyncFleeILGeneratorLabels(ilg, ilgTemp);
        // Do the fake emit
        this.EmitLogical(ilgTemp, info, services);

        // Clear everything except the label positions
        info.ClearTempState();

        info.Branches.ComputeBranches();

        Utility.SyncFleeILGeneratorLabels(ilgTemp, ilg);

        // Do the real emit
        this.EmitLogical(ilg, info, services);
    }
Ejemplo n.º 26
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);
     }
 }
Ejemplo n.º 27
0
    // Emit a sequence of and/or expressions with short-circuiting
    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);
        }
    }