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(); }
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(); }
// 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); } }
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(); }
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(); }
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(); }
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()); } }