Ejemplo n.º 1
0
        private void ClearBlockData(Instruction I)
        {
            var from = I.NumVal;
            var to = I.NumVal2;

            var array = m_ExecutionStack.Peek().LocalScope;

            if (to >= 0 && from >= 0 && to >= from)
            {
                Array.Clear(array, from, to - from + 1);
            }
        }
		private int ExecIndex(Instruction i, int instructionPtr)
		{
			int nestedMetaOps = 100; // sanity check, to avoid potential infinite loop here

			// stack: base - index
			bool isNameIndex = i.OpCode == OpCode.IndexN;

			bool isMultiIndex = (i.OpCode == OpCode.IndexL);

			DynValue originalIdx = i.Value ?? m_ValueStack.Pop();
			DynValue idx = originalIdx.ToScalar();
			DynValue obj = m_ValueStack.Pop().ToScalar();

			DynValue h = null;


			while (nestedMetaOps > 0)
			{
				--nestedMetaOps;

				if (obj.Type == DataType.Table)
				{
					if (!isMultiIndex)
					{
						var v = obj.Table.Get(idx);

						if (!v.IsNil())
						{
							m_ValueStack.Push(v.AsReadOnly());
							return instructionPtr;
						}
					}

					h = GetMetamethodRaw(obj, "__index");

					if (h == null || h.IsNil())
					{
						if (isMultiIndex) throw new ScriptRuntimeException("cannot multi-index a table. userdata expected");

						m_ValueStack.Push(DynValue.Nil);
						return instructionPtr;
					}
				}
				else if (obj.Type == DataType.UserData)
				{
					UserData ud = obj.UserData;

					var v = ud.Descriptor.Index(this.GetScript(), ud.Object, originalIdx, isNameIndex);

					if (v == null)
					{
						throw ScriptRuntimeException.UserDataMissingField(ud.Descriptor.Name, idx.String);
					}

					m_ValueStack.Push(v.AsReadOnly());
					return instructionPtr;
				}
				else
				{
					h = GetMetamethodRaw(obj, "__index");

					if (h == null || h.IsNil())
						throw ScriptRuntimeException.IndexType(obj);
				}

				if (h.Type == DataType.Function || h.Type == DataType.ClrFunction)
				{
					if (isMultiIndex) throw new ScriptRuntimeException("cannot multi-index through metamethods. userdata expected");
					m_ValueStack.Push(h);
					m_ValueStack.Push(obj);
					m_ValueStack.Push(idx);
					return Internal_ExecCall(2, instructionPtr);
				}
				else
				{
					obj = h;
					h = null;
				}
			}

			throw ScriptRuntimeException.LoopInIndex();
		}
		private void ListenDebugger(Instruction instr, int instructionPtr)
		{
			bool isOnDifferentRef = false;

			if (instr.SourceCodeRef != null && m_Debug.LastHlRef != null)
			{
				if (m_Debug.LineBasedBreakPoints)
				{
					isOnDifferentRef = instr.SourceCodeRef.SourceIdx != m_Debug.LastHlRef.SourceIdx ||
						instr.SourceCodeRef.FromLine != m_Debug.LastHlRef.FromLine;
				}
				else
				{
					isOnDifferentRef = instr.SourceCodeRef != m_Debug.LastHlRef;
				}
			}
			else if (m_Debug.LastHlRef == null)
			{
				isOnDifferentRef = instr.SourceCodeRef != null;
			}


			if (m_Debug.DebuggerAttached.IsPauseRequested() ||
				(instr.SourceCodeRef != null && instr.SourceCodeRef.Breakpoint && isOnDifferentRef))
			{
				m_Debug.DebuggerCurrentAction = DebuggerAction.ActionType.None;
				m_Debug.DebuggerCurrentActionTarget = -1;
			}

			switch (m_Debug.DebuggerCurrentAction)
			{
				case DebuggerAction.ActionType.Run:
					if (m_Debug.LineBasedBreakPoints)
						m_Debug.LastHlRef = instr.SourceCodeRef;
					return;
				case DebuggerAction.ActionType.ByteCodeStepOver:
					if (m_Debug.DebuggerCurrentActionTarget != instructionPtr) return;
					break;
				case DebuggerAction.ActionType.ByteCodeStepOut:
				case DebuggerAction.ActionType.StepOut:
					if (m_ExecutionStack.Count >= m_Debug.ExStackDepthAtStep) return;
					break;
				case DebuggerAction.ActionType.StepIn:
					if ((m_ExecutionStack.Count >= m_Debug.ExStackDepthAtStep) && (instr.SourceCodeRef == null || instr.SourceCodeRef == m_Debug.LastHlRef)) return;
					break;
				case DebuggerAction.ActionType.StepOver:
					if (instr.SourceCodeRef == null || instr.SourceCodeRef == m_Debug.LastHlRef || m_ExecutionStack.Count > m_Debug.ExStackDepthAtStep) return;
					break;
			}


			RefreshDebugger(false, instructionPtr);

			while (true)
			{
				var action = m_Debug.DebuggerAttached.GetAction(instructionPtr, instr.SourceCodeRef);

				switch (action.Action)
				{
					case DebuggerAction.ActionType.StepIn:
					case DebuggerAction.ActionType.StepOver:
					case DebuggerAction.ActionType.StepOut:
					case DebuggerAction.ActionType.ByteCodeStepOut:
						m_Debug.DebuggerCurrentAction = action.Action;
						m_Debug.LastHlRef = instr.SourceCodeRef;
						m_Debug.ExStackDepthAtStep = m_ExecutionStack.Count;
						return;
					case DebuggerAction.ActionType.ByteCodeStepIn:
						m_Debug.DebuggerCurrentAction = DebuggerAction.ActionType.ByteCodeStepIn;
						m_Debug.DebuggerCurrentActionTarget = -1;
						return;
					case DebuggerAction.ActionType.ByteCodeStepOver:
						m_Debug.DebuggerCurrentAction = DebuggerAction.ActionType.ByteCodeStepOver;
						m_Debug.DebuggerCurrentActionTarget = instructionPtr + 1;
						return;
					case DebuggerAction.ActionType.Run:
						m_Debug.DebuggerCurrentAction = DebuggerAction.ActionType.Run;
						m_Debug.LastHlRef = instr.SourceCodeRef;
						m_Debug.DebuggerCurrentActionTarget = -1;
						return;
					case DebuggerAction.ActionType.ToggleBreakpoint:
						ToggleBreakPoint(action, null);
						RefreshDebugger(true, instructionPtr);
						break;
					case DebuggerAction.ActionType.ResetBreakpoints:
						ResetBreakPoints(action);
						RefreshDebugger(true, instructionPtr);
						break;
					case DebuggerAction.ActionType.SetBreakpoint:
						ToggleBreakPoint(action, true);
						RefreshDebugger(true, instructionPtr);
						break;
					case DebuggerAction.ActionType.ClearBreakpoint:
						ToggleBreakPoint(action, false);
						RefreshDebugger(true, instructionPtr);
						break;
					case DebuggerAction.ActionType.Refresh:
						RefreshDebugger(false, instructionPtr);
						break;
					case DebuggerAction.ActionType.HardRefresh:
						RefreshDebugger(true, instructionPtr);
						break;
					case DebuggerAction.ActionType.None:
					default:
						break;
				}
			}
		}
        public int Compile(ByteCode bc, Func<int> afterDecl, string friendlyName)
        {
            using (bc.EnterSource(m_Begin))
            {
                var symbs = m_Closure
                    //.Select((s, idx) => s.CloneLocalAndSetFrame(m_ClosureFrames[idx]))
                    .ToArray();

                m_ClosureInstruction = bc.Emit_Closure(symbs, bc.GetJumpPointForNextInstruction());
                var ops = afterDecl();

                m_ClosureInstruction.NumVal += 2 + ops;
            }

            return CompileBody(bc, friendlyName);
        }
		private int ExecNeg(Instruction i, int instructionPtr)
		{
			DynValue r = m_ValueStack.Pop().ToScalar();
			double? rn = r.CastToNumber();

			if (rn.HasValue)
			{
				m_ValueStack.Push(DynValue.NewNumber(-rn.Value));
				return instructionPtr;
			}
			else
			{
				int ip = Internal_InvokeUnaryMetaMethod(r, "__unm", instructionPtr);
				if (ip >= 0) return ip;
				else throw ScriptRuntimeException.ArithmeticOnNonNumber(r);
			}
		}
		private int ExecMod(Instruction i, int instructionPtr)
		{
			DynValue r = m_ValueStack.Pop().ToScalar();
			DynValue l = m_ValueStack.Pop().ToScalar();

			double? rn = r.CastToNumber();
			double? ln = l.CastToNumber();

			if (ln.HasValue && rn.HasValue)
			{
				double mod = Math.IEEERemainder(ln.Value, rn.Value);
				if (mod < 0) mod += rn.Value;
				m_ValueStack.Push(DynValue.NewNumber(mod));
				return instructionPtr;
			}
			else
			{
				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__mod", instructionPtr);
				if (ip >= 0) return ip;
				else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r);
			}
		}
		private int JumpBool(Instruction i, bool expectedValueForJump, int instructionPtr)
		{
			DynValue op = m_ValueStack.Pop().ToScalar();

			if (op.CastToBool() == expectedValueForJump)
				return i.NumVal;

			return instructionPtr;
		}
		private int ExecRet(Instruction i)
		{
			CallStackItem csi;
			int retpoint = 0;

			if (i.NumVal == 0)
			{
				csi = PopToBasePointer();
				retpoint = csi.ReturnAddress;
				var argscnt = (int)(m_ValueStack.Pop().Number);
				m_ValueStack.RemoveLast(argscnt + 1);
				m_ValueStack.Push(DynValue.Void);
			}
			else if (i.NumVal == 1)
			{
				var retval = m_ValueStack.Pop();
				csi = PopToBasePointer();
				retpoint = csi.ReturnAddress;
				var argscnt = (int)(m_ValueStack.Pop().Number);
				m_ValueStack.RemoveLast(argscnt + 1);
				m_ValueStack.Push(retval);
				retpoint = Internal_CheckForTailRequests(i, retpoint);
			}
			else
			{
				throw new InternalErrorException("RET supports only 0 and 1 ret val scenarios");
			}

			if (csi.Continuation != null)
				m_ValueStack.Push(csi.Continuation.Invoke(new ScriptExecutionContext(this, csi.Continuation, i.SourceCodeRef),
					new DynValue[1] { m_ValueStack.Pop() }));

			return retpoint;
		}
		private void ExecToNum(Instruction i)
		{
			double? v = m_ValueStack.Pop().ToScalar().CastToNumber();
			if (v.HasValue)
				m_ValueStack.Push(DynValue.NewNumber(v.Value));
			else
				throw ScriptRuntimeException.ConvertToNumberFailed(i.NumVal);
		}
		private void ExecMkTuple(Instruction i)
		{
			Slice<DynValue> slice = new Slice<DynValue>(m_ValueStack, m_ValueStack.Count - i.NumVal, i.NumVal, false);

			var v = Internal_AdjustTuple(slice);

			m_ValueStack.RemoveLast(i.NumVal);

			m_ValueStack.Push(DynValue.NewTuple(v));
		}
		private void ExecClosure(Instruction i)
		{
			Closure c = new Closure(this.m_Script, i.NumVal, i.SymbolList,
				i.SymbolList.Select(s => this.GetUpvalueSymbol(s)).ToList());

			m_ValueStack.Push(DynValue.NewClosure(c));
		}
		private DynValue GetStoreValue(Instruction i)
		{
			int stackofs = i.NumVal;
			int tupleidx = i.NumVal2;

			DynValue v = m_ValueStack.Peek(stackofs);

			if (v.Type == DataType.Tuple)
			{
				return (tupleidx < v.Tuple.Length) ? v.Tuple[tupleidx] : DynValue.NewNil();
			}
			else
			{
				return (tupleidx == 0) ? v : DynValue.NewNil();
			}
		}
		private void ExecSwap(Instruction i)
		{
			DynValue v1 = m_ValueStack.Peek(i.NumVal);
			DynValue v2 = m_ValueStack.Peek(i.NumVal2);

			m_ValueStack.Set(i.NumVal, v2);
			m_ValueStack.Set(i.NumVal2, v1);
		}
		private void ExecStoreUpv(Instruction i)
		{
			DynValue value = GetStoreValue(i);
			SymbolRef symref = i.Symbol;

			var stackframe = m_ExecutionStack.Peek();

			DynValue v = stackframe.ClosureScope[symref.i_Index];
			if (v == null)
				stackframe.ClosureScope[symref.i_Index] = v = DynValue.NewNil();

			v.Assign(value);
		}
		private void ExecStoreLcl(Instruction i)
		{
			DynValue value = GetStoreValue(i);
			SymbolRef symref = i.Symbol;

			AssignLocal(symref, value);
		}
		private void ExecBeginFn(Instruction i)
		{
			CallStackItem cur = m_ExecutionStack.Peek();

			cur.Debug_Symbols = i.SymbolList;
			cur.LocalScope = new DynValue[i.NumVal];

			ClearBlockData(i);
		}
		private void ExecArgs(Instruction I)
		{
			int numargs = (int)m_ValueStack.Peek(0).Number;

			// unpacks last tuple arguments to simplify a lot of code down under
			var argsList = CreateArgsListForFunctionCall(numargs, 1);

			for (int i = 0; i < I.SymbolList.Length; i++)
			{
				if (i >= argsList.Count)
				{
					this.AssignLocal(I.SymbolList[i], DynValue.NewNil());
				}
				else if ((i == I.SymbolList.Length - 1) && (I.SymbolList[i].i_Name == WellKnownSymbols.VARARGS))
				{
					int len = argsList.Count - i;
					DynValue[] varargs = new DynValue[len];

					for (int ii = 0; ii < len; ii++, i++)
					{
						varargs[ii] = argsList[i].ToScalar().CloneAsWritable();
					}

					this.AssignLocal(I.SymbolList[I.SymbolList.Length - 1], DynValue.NewTuple(Internal_AdjustTuple(varargs)));
				}
				else
				{
					this.AssignLocal(I.SymbolList[i], argsList[i].ToScalar().CloneAsWritable());
				}
			}
		}
		private void ExecIterUpd(Instruction i)
		{
			DynValue v = m_ValueStack.Peek(0);
			DynValue t = m_ValueStack.Peek(1);
			t.Tuple[2] = v;
		}
		private int Internal_CheckForTailRequests(Instruction i, int instructionPtr)
		{
			DynValue tail = m_ValueStack.Peek(0);

			if (tail.Type == DataType.TailCallRequest)
			{
				m_ValueStack.Pop(); // discard tail call request

				TailCallData tcd = tail.TailCallData;

				m_ValueStack.Push(tcd.Function);

				for (int ii = 0; ii < tcd.Args.Length; ii++)
					m_ValueStack.Push(tcd.Args[ii]);

				return Internal_ExecCall(tcd.Args.Length, instructionPtr, tcd.ErrorHandler, tcd.Continuation, false, null, tcd.ErrorHandlerBeforeUnwind);
			}
			else if (tail.Type == DataType.YieldRequest)
			{
				m_SavedInstructionPtr = instructionPtr;
				return YIELD_SPECIAL_TRAP;
			}


			return instructionPtr;
		}
		private void ExecExpTuple(Instruction i)
		{
			DynValue t = m_ValueStack.Peek(i.NumVal);

			if (t.Type == DataType.Tuple)
			{
				for (int idx = 0; idx < t.Tuple.Length; idx++)
					m_ValueStack.Push(t.Tuple[idx]);
			}
			else
			{
				m_ValueStack.Push(t);
			}

		}
		private int ExecShortCircuitingOperator(Instruction i, int instructionPtr)
		{
			bool expectedValToShortCircuit = i.OpCode == OpCode.JtOrPop;

			DynValue op = m_ValueStack.Peek().ToScalar();

			if (op.CastToBool() == expectedValToShortCircuit)
			{
				return i.NumVal;
			}
			else
			{
				m_ValueStack.Pop();
				return instructionPtr;
			}
		}
		private void ExecIterPrep(Instruction i)
		{
			DynValue v = m_ValueStack.Pop();

			if (v.Type != DataType.Tuple)
			{
				v = DynValue.NewTuple(v, DynValue.Nil, DynValue.Nil);
			}

			DynValue f = v.Tuple.Length >= 1 ? v.Tuple[0] : DynValue.Nil;
			DynValue s = v.Tuple.Length >= 2 ? v.Tuple[1] : DynValue.Nil;
			DynValue var = v.Tuple.Length >= 3 ? v.Tuple[2] : DynValue.Nil;

			// MoonSharp additions - given f, s, var
			// 1) if f is not a function and has a __iterator metamethod, call __iterator to get the triplet
			// 2) if f is a table with no __call metamethod, use a default table iterator

			if (f.Type != DataType.Function && f.Type != DataType.ClrFunction)
			{
				DynValue meta = this.GetMetamethod(f, "__iterator");

				if (meta != null && !meta.IsNil())
				{
					if (meta.Type != DataType.Tuple)
						v = this.GetScript().Call(meta, f, s, var);
					else
						v = meta;

					f = v.Tuple.Length >= 1 ? v.Tuple[0] : DynValue.Nil;
					s = v.Tuple.Length >= 2 ? v.Tuple[1] : DynValue.Nil;
					var = v.Tuple.Length >= 3 ? v.Tuple[2] : DynValue.Nil;

					m_ValueStack.Push(DynValue.NewTuple(f, s, var));
				}
				else if (f.Type == DataType.Table)
				{
					DynValue callmeta = this.GetMetamethod(f, "__call");

					if (callmeta == null || callmeta.IsNil())
					{
						m_ValueStack.Push(EnumerableWrapper.ConvertTable(f.Table));
					}
				}
			}

			m_ValueStack.Push(DynValue.NewTuple(f, s, var));
		}
		private int ExecPower(Instruction i, int instructionPtr)
		{
			DynValue r = m_ValueStack.Pop().ToScalar();
			DynValue l = m_ValueStack.Pop().ToScalar();

			double? rn = r.CastToNumber();
			double? ln = l.CastToNumber();

			if (ln.HasValue && rn.HasValue)
			{
				m_ValueStack.Push(DynValue.NewNumber(Math.Pow(ln.Value, rn.Value)));
				return instructionPtr;
			}
			else
			{
				int ip = Internal_InvokeBinaryMetaMethod(l, r, "__pow", instructionPtr);
				if (ip >= 0) return ip;
				else throw ScriptRuntimeException.ArithmeticOnNonNumber(l, r);
			}

		}
		private int ExecJFor(Instruction i, int instructionPtr)
		{
			double val = m_ValueStack.Peek(0).Number;
			double step = m_ValueStack.Peek(1).Number;
			double stop = m_ValueStack.Peek(2).Number;

			bool whileCond = (step > 0) ? val <= stop : val >= stop;

			if (!whileCond)
				return i.NumVal;
			else
				return instructionPtr;
		}
Ejemplo n.º 25
0
 public override void Compile(ByteCode bc)
 {
     m_Jump = bc.Emit_Jump(OpCode.Jump, m_LabelAddress);
 }
		private void ExecIncr(Instruction i)
		{
			DynValue top = m_ValueStack.Peek(0);
			DynValue btm = m_ValueStack.Peek(i.NumVal);

			if (top.ReadOnly)
			{
				m_ValueStack.Pop();

				if (top.ReadOnly)
					top = top.CloneAsWritable();

				m_ValueStack.Push(top);
			}

			top.AssignNumber(top.Number + btm.Number);
		}
		private void RemoveBreakpointStop(Instruction instruction)
		{
			instruction.SourceCodeRef = null;
		}
		private void ExecCNot(Instruction i)
		{
			DynValue v = m_ValueStack.Pop().ToScalar();
			DynValue not = m_ValueStack.Pop().ToScalar();

			if (not.Type != DataType.Boolean)
				throw new InternalErrorException("CNOT had non-bool arg");

			if (not.CastToBool())
				m_ValueStack.Push(DynValue.NewBoolean(!(v.CastToBool())));
			else
				m_ValueStack.Push(DynValue.NewBoolean(v.CastToBool()));
		}
Ejemplo n.º 29
0
 private Instruction AppendInstruction(Instruction c)
 {
     Code.Add(c);
     return c;
 }
		private void ExecNot(Instruction i)
		{
			DynValue v = m_ValueStack.Pop().ToScalar();
			m_ValueStack.Push(DynValue.NewBoolean(!(v.CastToBool())));
		}