// Perform a function call private FuncFrame func_call(WFunction func) { ASSERT_ERR(this.state.func_depth > MAX_RECURSION, CoreErrorType.MAX_RECURSION, "Maxmimum recursion depth achieved!"); this.state.func_depth++; // Set the size of the locals to the args count & locals count this.locals = new WItem[func.args_size + func.locals_size]; // Then define the function arguments passed in that were on the exec stack for (int i = 0; i < func.args_size; i++) { this.locals[i] = exec_stack.pop(); } // First create a new FuncFrame to push to the function stack FuncFrame frame = new FuncFrame(this, func.name, this.pc, this.locals, this.exec_stack, this.bytecode); // Then push the frame to the FuncStack this.func_stack.push(frame); // Check if the function is native if (func.is_native) { // Natively call the func push_exec(this.native_interface.call_native_func(VM.state.current_file, func.name, this.locals)); // Becuase native functions can't implement Opcode.RETURN, we need to manually return & advance func_return(); goto_next(); } else { this.pc = 0; this.exec_stack = new ExecStack(this); this.bytecode = func.bytecode; this.state.opcode_count = this.bytecode.Length; } return(frame); }
// Perform a function call with a trace private Trace func_call_trace(WFunction func) { // Then create a new Trace instance referencing that frame Trace trace = new Trace(func_call(func)); // Push the trace to the traceback this.traceback.push_call_trace(trace); return(trace); }
public WindowFunction(string Caption, WFunction function) { Act = function; caption = Caption; }
// Main fde cycle public void evaluate_sequence() { // Initialise the state of the multi_core_state this.state.multi_core_state = MultiCoreState.RUNNING; // Check we have not reached the end while (!end()) { // Only execute if the core has not been suspended if (this.state.multi_core_state != MultiCoreState.SUSPENDED) { Int32 op = get_next(); #if CORE_INSTR_DEBUG Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine("op: " + (Opcode)op); Console.ForegroundColor = ConsoleColor.Yellow; #endif // Surround the execute phase in a try catch, this is so the vm can return safely to the error handling // without breaking other vm components try { switch ((Opcode)op) { case Opcode.PRINT: { Console.ForegroundColor = ConsoleColor.Green; #if VM_MULTI_CORE Console.WriteLine("{core " + this.state.id + "} " + peek_exec()); #else Console.WriteLine(peek_exec()); #endif Console.ForegroundColor = ConsoleColor.Yellow; goto_next(); break; } case Opcode.END: { // Return an END state this.state.currently_interpreting = false; break; } case Opcode.NOP: { goto_next(); break; } case Opcode.POP_EXEC: { pop_exec(); goto_next(); break; } case Opcode.LD_CONST: { Int32 id = get_arg(); push_exec(this.vm.bank_manager.request_c_item(this, id)); this.vm.bank_manager.release_c_item(this, id); goto_next(); break; } case Opcode.LD_VAR: { Int32 id = get_arg(); push_exec(this.vm.bank_manager.request_m_item(this, id)); this.vm.bank_manager.release_m_item(this, id); goto_next(); break; } case Opcode.LD_LOC: { // Check if we are actually in a function ASSERT_ERR(this.state.func_depth > 0, CoreErrorType.INVALID_LOCAL, "Cannot load local from non-function state!"); Int32 index = get_arg(); // Check if we have a valid local index ASSERT_ERR(index > this.locals.Length - 1, CoreErrorType.INVALID_LOCAL, "Local index is larger than locals size!"); push_exec(this.locals[index]); goto_next(); break; } case Opcode.BANK_VAR: { Int32 id = get_arg(); this.vm.bank_manager.request_m_item(this, id); this.vm.bank_manager.assign_item(this, id, pop_exec()); this.vm.bank_manager.request_m_item(this, id); goto_next(); break; } case Opcode.BANK_ASSIGN: { goto_next(); break; } case Opcode.LOCAL_ASSIGN: { goto_next(); break; } case Opcode.MAKE_CLASS: { break; } case Opcode.MAKE_FUNC: { break; } case Opcode.NEW: { break; } case Opcode.INVOKE_FUNC: { WFunction func = expect_wfunc(pop_exec()); #if CORE_TRACE_DEBUG func_call_trace(func); #else func_call(func); #endif break; } case Opcode.RETURN: { func_return(); goto_next(); break; } case Opcode.GOTO: { this.pc += get_arg(); break; } case Opcode.IF_ZERO: { Int32 arg = get_arg(); if (expect_numeric(pop_exec()) == 0) { goto_next(); break; } this.pc += arg; break; } case Opcode.IF_NZERO: { Int32 arg = get_arg(); if (expect_numeric(pop_exec()) != 0) { goto_next(); break; } this.pc += arg; break; } case Opcode.IF_GRT: { Int32 arg = get_arg(); if (expect_numeric(pop_exec()) > expect_numeric(pop_exec())) { goto_next(); break; } this.pc += arg; break; } case Opcode.IF_GRTE: { Int32 arg = get_arg(); if (expect_numeric(pop_exec()) >= expect_numeric(pop_exec())) { goto_next(); break; } this.pc += arg; break; } case Opcode.IF_LT: { Int32 arg = get_arg(); if (expect_numeric(pop_exec()) < expect_numeric(pop_exec())) { goto_next(); break; } this.pc += arg; break; } case Opcode.IF_LTE: { Int32 arg = get_arg(); if (expect_numeric(pop_exec()) <= expect_numeric(pop_exec())) { goto_next(); break; } this.pc += arg; break; } case Opcode.INCREMENT: { WItem num = expect_numeric(peek_exec()); num.value = num.value + 1; goto_next(); break; } case Opcode.DECREMENT: { WItem num = expect_numeric(peek_exec()); num.value = num.value - 1; goto_next(); break; } case Opcode.PSH_ZERO: { push_exec((Wint)0); goto_next(); break; } case Opcode.PSH_NULL: { push_exec((Wnull)null); goto_next(); break; } default: { // We have an invalid opcode push_err(CoreErrorType.INVALID_OP, "op: " + op); break; } } // Program counter is out of range ASSERT_ERR(pc <0 || pc> MAX_PC, CoreErrorType.INVALID_PC_RANGE); } catch (CoreErrException e) { if (e.err.is_fatal()) { this.vm.core_manager.isolate(this.state.id); } this.state.err_handler.say_latest(); break; } } } close(); }