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