static IImportTypeHandler _Import(VM vm, Type t, string name = null) { var handler = vm.m_import_manager.GetOrCreateHandler(t); if (string.IsNullOrWhiteSpace(name) == false) { var segments = name.Split('.'); var table = vm.m_global; for (int i = 0; i < segments.Length - 1; ++i) { Table tmp = table.Get(segments[i]) as Table; if (tmp == null) { tmp = vm.NewTable(); table.Set(segments[i], tmp); } table = tmp; } table.Set(segments.Last(), handler); } return(handler); }
void ExecuteFrame() { CallInfo call = _calls.Last(); Closure closure = call.closure; Function func = closure.func; int code_size = func.OpCodeSize(); int a, b, c, bx; UpValue upvalue; while (call.pc < code_size) { VM.CallDebugHook(this); Instruction i = func.GetInstruction(call.pc); ++call.pc; a = call.register_idx + i.GetA(); b = call.register_idx + i.GetB(); c = call.register_idx + i.GetC(); bx = i.GetBx(); switch (i.GetOp()) { case OpType.OpType_LoadNil: _stack[a] = null; break; case OpType.OpType_LoadBool: _stack[a] = (bx == 1 ? true : false); break; case OpType.OpType_LoadInt: _stack[a] = (double)bx; break; case OpType.OpType_LoadConst: _stack[a] = func.GetConstValue(bx); break; case OpType.OpType_Move: _stack[a] = _stack[b]; break; case OpType.OpType_Closure: OpGenerateClosure(a, func.GetChildFunction(bx)); break; case OpType.OpType_Call: if (OpCall(a, i.GetB(), i.GetC() == 1)) { // will enter next frame return; } if (_status == ThreadStatus.Stop) { return; // pause } break; case OpType.OpType_AsyncCall: // new thread to run, and return nothing OpAsyncCall(a, i.GetB(), i.GetC() == 1); break; case OpType.OpType_GetUpvalue: upvalue = closure.GetUpvalue(bx); _stack[a] = upvalue.Read(); break; case OpType.OpType_SetUpvalue: upvalue = closure.GetUpvalue(bx); upvalue.Write(_stack[a]); break; case OpType.OpType_GetGlobal: _stack[a] = closure.env_table.Get(func.GetConstValue(bx)); break; case OpType.OpType_SetGlobal: closure.env_table.Set(func.GetConstValue(bx), _stack[a]); break; case OpType.OpType_VarArg: OpCopyVarArg(a, call); break; case OpType.OpType_Ret: OpReturn(call.func_idx, a, i.GetB(), i.GetC() == 1); return; // finish //break; case OpType.OpType_Jmp: call.pc += -1 + bx; break; case OpType.OpType_JmpFalse: if (ValueUtils.IsFalse(_stack[a])) { call.pc += -1 + bx; } break; case OpType.OpType_JmpTrue: if (!ValueUtils.IsFalse(_stack[a])) { call.pc += -1 + bx; } break; case OpType.OpType_JmpNil: if (null == _stack[a]) { call.pc += -1 + bx; } break; case OpType.OpType_Neg: OpNeg(a); break; case OpType.OpType_Not: _stack[a] = ValueUtils.IsFalse(_stack[a]); break; case OpType.OpType_Len: if (_stack[a] is Table) { _stack[a] = (_stack[a] as Table).Count(); } else { throw NewOpTypeError("get length of ", a); } break; case OpType.OpType_Add: CheckArithType(b, c, "add"); _stack[a] = (double)(_stack[b]) + (double)(_stack[c]); break; case OpType.OpType_Sub: CheckArithType(b, c, "sub"); _stack[a] = (double)(_stack[b]) - (double)(_stack[c]); break; case OpType.OpType_Mul: CheckArithType(b, c, "multiply"); _stack[a] = (double)(_stack[b]) * (double)(_stack[c]); break; case OpType.OpType_Div: CheckArithType(b, c, "div"); _stack[a] = (double)(_stack[b]) / (double)(_stack[c]); break; case OpType.OpType_Pow: CheckArithType(b, c, "power"); _stack[a] = Math.Pow((double)(_stack[b]), (double)(_stack[c])); break; case OpType.OpType_Mod: CheckArithType(b, c, "mod"); _stack[a] = (double)(_stack[b]) % (double)(_stack[c]); break; case OpType.OpType_Concat: OpConcat(a, b, c); break; case OpType.OpType_Less: CheckCompareType(b, c, "<"); _stack[a] = ValueUtils.ToNumber(_stack[b]) < ValueUtils.ToNumber(_stack[c]); break; case OpType.OpType_Greater: CheckCompareType(b, c, ">"); _stack[a] = ValueUtils.ToNumber(_stack[b]) > ValueUtils.ToNumber(_stack[c]); break; case OpType.OpType_Equal: _stack[a] = Object.Equals(_stack[b], _stack[c]); break; case OpType.OpType_UnEqual: _stack[a] = !Object.Equals(_stack[b], _stack[c]); break; case OpType.OpType_LessEqual: CheckCompareType(b, c, "<="); _stack[a] = ValueUtils.ToNumber(_stack[b]) <= ValueUtils.ToNumber(_stack[c]); break; case OpType.OpType_GreaterEqual: CheckCompareType(b, c, ">="); _stack[a] = ValueUtils.ToNumber(_stack[b]) >= ValueUtils.ToNumber(_stack[c]); break; case OpType.OpType_NewTable: _stack[a] = _vm.NewTable(); break; case OpType.OpType_AppendTable: OpTableAppend(a, b, _active_top - b); break; case OpType.OpType_SetTable: OpSetTable(a, b, c); break; case OpType.OpType_GetTable: OpGetTable(a, b, c); break; case OpType.OpType_TableIter: if (_stack[b] is IForEach) { _stack[a] = (_stack[b] as IForEach).GetIter(); } else { throw NewOpTypeError("foreach ", a); } break; case OpType.OpType_TableIterNext: Debug.Assert(_stack[a] is INext); (_stack[a] as INext).Next(out _stack[b], out _stack[c]); break; case OpType.OpType_ForInit: if (!(_stack[a] is double)) { throw NewRuntimeError("'for' init need be number"); } if (!(_stack[b] is double)) { throw NewRuntimeError("'for' limit need be number"); } if (!(_stack[c] is double)) { throw NewRuntimeError("'for' step need be number"); } if (((double)_stack[c] == 0)) { throw NewRuntimeError("'for' step should be nozero"); } break; case OpType.OpType_ForCheck: if (OpForCheck(a, b, c)) { ++call.pc; // jump over JumpTail instruction } break; case OpType.OpType_FillNilFromTopToA: while (_active_top < a) { _stack[_active_top++] = null; } break; case OpType.OpType_CloseUpvalue: OpCloseUpvalueTo(a); break; default: Debug.Assert(false); break; } } // return nil OpReturn(call.func_idx, -1, 0, false); }