Exemplo n.º 1
0
        Allocation Push(Expression e)
        {
            Allocation allocation = function.Top();

            Move(allocation, e);
            allocation.Allocate();
            return(allocation);
        }
        public void Should_allocate_user()
        {
            const int MINUTES = 5;

            _allocation.Allocate(MINUTES);
            _allocation.Allocated.Should().BeTrue();
            _allocation.ExpiresAt.Should().BeCloseTo(DateTime.UtcNow.AddMinutes(MINUTES), TimeSpan.FromSeconds(5));
            _allocation.IsAllocated().Should().BeTrue();
        }
Exemplo n.º 3
0
        public void Visit(ReturnList s)
        {
            // Check for tailcall.
            if (s.Results.Count == 0)
            {
                if (s.ResultList is Call)
                {
                    Call call = (Call)s.ResultList;
                    BuildCall(TailCallC, call.Function, null, call.Arguments, call.ArgumentValues);
                    return;
                }
                else if (s.ResultList is CallSelf)
                {
                    CallSelf call = (CallSelf)s.ResultList;
                    BuildCall(TailCallC, call.Object, call.MethodName, call.Arguments, call.ArgumentValues);
                    return;
                }
            }

            // Push results onto the stack.
            Allocation allocation = function.Top();

            foreach (Expression result in s.Results)
            {
                Allocation allocResult = Push(result);
                allocResult.Release();
                allocation.Allocate();
            }

            // Push result values onto the stack.
            int B;

            if (s.ResultList != null)
            {
                Allocation allocValues = SetTop(s.ResultList);
                allocValues.Release();
                allocation.SetTop();
                B = 0;
            }
            else
            {
                B = s.Results.Count + 1;
            }

            // Return.
            function.InstructionABC(s.SourceSpan, Opcode.Return, allocation, B, 0);
            allocation.Release();
        }
Exemplo n.º 4
0
            // RK values.

            public Allocation ConstantRK(SourceSpan s, object constant)
            {
                int k = Constant(constant);

                if (Instruction.InRangeRK(k))
                {
                    return(new Allocation(Instruction.ConstantToRK(k)));
                }
                else
                {
                    Allocation r = Top();
                    InstructionABx(s, Opcode.LoadK, r, k);
                    r.Allocate();
                    return(r);
                }
            }
Exemplo n.º 5
0
        public void Visit(Concatenate e)
        {
            // Get operand list.
            Allocation allocation = function.Top();

            foreach (Expression operand in e.Operands)
            {
                Allocation allocOperand = Push(operand);
                allocOperand.Release();
                allocation.Allocate();
            }

            // Instruction.
            function.InstructionABC(e.SourceSpan, Opcode.Concat, target, allocation, allocation + e.Operands.Count - 1);
            allocation.Release();
        }
Exemplo n.º 6
0
        public void Visit(AssignList s)
        {
            // Evaluate subexpressions for index targets.
            Allocation allocTargets = function.Top();

            Expression[] targets = new Expression[s.Targets.Count];
            for (int target = 0; target < s.Targets.Count; ++target)
            {
                Expression e     = s.Targets[target];
                Index      index = e as Index;
                if (index != null)
                {
                    Allocation table = R(index.Table);
                    Allocation key   = RK(index.Key);

                    targets[target] = new IndexRef(index.SourceSpan, table, key);

                    key.Release();
                    table.Release();
                    allocTargets.Allocate(2);
                }
                else
                {
                    targets[target] = e;
                }
            }

            // Evaluate all values.
            Allocation allocValues = function.Top();

            for (int value = 0; value < s.Values.Count; ++value)
            {
                Allocation allocValue = Push(s.Values[value]);
                allocValue.Release();
                allocValues.Allocate();
            }
            if (s.ValueList != null)
            {
                if (s.Targets.Count <= s.Values.Count)
                {
                    throw new ArgumentException();
                }

                Allocation allocValueList = PushList(s.ValueList, s.Targets.Count - s.Values.Count);
                allocValueList.Release();
                allocValues.Allocate(s.Targets.Count - s.Values.Count);
            }

            // Assign each value.
            for (int target = 0; target < targets.Length; ++target)
            {
                if (targets[target] is GlobalRef)
                {
                    GlobalRef global = (GlobalRef)targets[target];
                    function.InstructionABx(s.SourceSpan, Opcode.SetGlobal,
                                            allocValues + target, function.Constant(global.Name));
                }
                else if (targets[target] is IndexRef)
                {
                    IndexRef index = (IndexRef)targets[target];
                    function.InstructionABC(s.SourceSpan, Opcode.SetTable,
                                            index.Table, index.Key, allocValues + target);
                }
                else if (targets[target] is LocalRef)
                {
                    LocalRef local = (LocalRef)targets[target];
                    function.InstructionABC(s.SourceSpan, Opcode.Move,
                                            function.Local(local.Variable), allocValues + target, 0);
                }
                else if (targets[target] is UpValRef)
                {
                    UpValRef upval = (UpValRef)targets[target];
                    function.InstructionABC(s.SourceSpan, Opcode.SetUpVal,
                                            allocValues + target, function.UpVal(upval.Variable), 0);
                }
                else
                {
                    throw new InvalidOperationException();
                }
            }

            // Release.
            allocValues.Release();
            allocTargets.Release();
        }
Exemplo n.º 7
0
        public void Visit(Constructor e)
        {
            // Construct.
            Allocation table = function.Top();

            function.InstructionABC(e.SourceSpan, Opcode.NewTable, table, e.ArrayCount, e.HashCount);
            table.Allocate();

            // Initialize.
            Allocation pending      = function.Top();
            int        pendingCount = 0;
            int        batchCount   = 0;

            foreach (ConstructorElement element in e.Elements)
            {
                if (element.HashKey == null)
                {
                    Move(pending, element.Value);
                    pending.Allocate();
                    pendingCount += 1;

                    if (pendingCount == Instruction.FieldsPerFlush)
                    {
                        function.InstructionSetList(e.SourceSpan, table, pendingCount, batchCount + 1);
                        pending.Release();
                        pending      = function.Top();
                        pendingCount = 0;
                        batchCount  += 1;
                    }
                }
                else
                {
                    Allocation key   = RK(element.HashKey);
                    Allocation value = RK(element.Value);
                    function.InstructionABC(e.SourceSpan, Opcode.SetTable, table, key, value);
                    value.Release();
                    key.Release();
                }
            }

            if (e.ElementList != null)
            {
                Allocation allocList = SetTop(e.ElementList);
                allocList.Release();
                pending.SetTop();

                function.InstructionSetList(e.SourceSpan, table, 0, batchCount + 1);
                pending.Release();
                pendingCount = 0;
            }

            if (pendingCount > 0)
            {
                function.InstructionSetList(e.SourceSpan, table, pendingCount, batchCount + 1);
                pending.Release();
                pendingCount = 0;
            }

            // Move table.
            if ((int)target != (int)table)
            {
                function.InstructionABC(e.SourceSpan, Opcode.Move, target, table, 0);
            }
            table.Release();
        }
Exemplo n.º 8
0
        Allocation BuildCall(int C,
                             Expression functionOrObject, string methodName,
                             IList <Expression> arguments, Expression argumentValues)
        {
            // Push function (or method) onto the stack.
            Allocation allocation = function.Top();

            if (methodName == null)
            {
                Allocation allocFunction = Push(functionOrObject);
                allocFunction.Release();
                allocation.Allocate();
            }
            else
            {
                Allocation allocObject = R(functionOrObject);
                Allocation allocMethod = function.ConstantRK(functionOrObject.SourceSpan, methodName);
                function.InstructionABC(functionOrObject.SourceSpan, Opcode.Self, allocation, allocObject, allocMethod);
                allocMethod.Release();
                allocObject.Release();
                allocation.Allocate();
            }

            // Push arguments onto the stack.
            foreach (Expression argument in arguments)
            {
                Allocation allocArgument = Push(argument);
                allocArgument.Release();
                allocation.Allocate();
            }

            // Push variable arguments onto the stack.
            int B;

            if (argumentValues != null)
            {
                Allocation allocValues = SetTop(argumentValues);
                allocValues.Release();
                allocation.SetTop();
                B = 0;
            }
            else
            {
                B = arguments.Count + 1;
            }

            if (C != TailCallC)
            {
                // Call.
                function.InstructionABC(functionOrObject.SourceSpan, Opcode.Call, allocation, B, C);
                allocation.Release();

                // Return appropriate number of values.
                Allocation results = function.Top();
                if (C > 0)
                {
                    results.Allocate(C - 1);
                }
                else
                {
                    results.SetTop();
                }
                return(results);
            }
            else
            {
                // Tail call.
                function.InstructionABC(functionOrObject.SourceSpan, Opcode.TailCall, allocation, B, 0);
                allocation.Release();
                return(function.Top());
            }
        }