From 69633451e04fc538b25b9977b311843ca5a71ace Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E7=AB=8B=E5=B8=AE?= <3294713004@qq.com> Date: Fri, 4 Apr 2025 00:16:04 +0800 Subject: [PATCH] =?UTF-8?q?feat(boards):=20=E6=9B=B4=E6=96=B0python=5Fskul?= =?UTF-8?q?pt=20debugger?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../python_skulpt/others/skulpt/debugger.js | 533 +++++++++--------- 1 file changed, 266 insertions(+), 267 deletions(-) diff --git a/boards/default_src/python_skulpt/others/skulpt/debugger.js b/boards/default_src/python_skulpt/others/skulpt/debugger.js index 5a7fb42f..825f833b 100644 --- a/boards/default_src/python_skulpt/others/skulpt/debugger.js +++ b/boards/default_src/python_skulpt/others/skulpt/debugger.js @@ -1,8 +1,7 @@ /** * Debugger support for skulpt module */ - -var Sk = Sk || {}; //jshint ignore:line +import './skulpt.min.js'; function hasOwnProperty(obj, prop) { var proto = obj.constructor.prototype; @@ -10,303 +9,303 @@ function hasOwnProperty(obj, prop) { (!(prop in proto) || proto[prop] !== obj[prop]); } -Sk.Breakpoint = function(filename, lineno, colno) { - this.filename = filename; - this.lineno = lineno; - this.colno = colno; - this.enabled = true; - this.ignore_count = 0; -}; - -Sk.Debugger = function(filename, output_callback) { - this.dbg_breakpoints = {}; - this.tmp_breakpoints = {}; - this.suspension_stack = []; - this.current_suspension = -1; - this.eval_callback = null; - this.suspension = null; - this.output_callback = output_callback; - this.step_mode = false; - this.filename = filename; -}; - -Sk.Debugger.prototype.print = function(txt) { - if (this.output_callback != null) { - this.output_callback.print(txt); +class Breakpoint { + constructor(filename, lineno, colno) { + this.filename = filename; + this.lineno = lineno; + this.colno = colno; + this.enabled = true; + this.ignore_count = 0; } -}; +} -Sk.Debugger.prototype.get_source_line = function(lineno) { - if (this.output_callback != null) { - return this.output_callback.get_source_line(lineno); - } - - return ""; -}; - -Sk.Debugger.prototype.move_up_the_stack = function() { - this.current_suspension = Math.min(this.current_suspension + 1, this.suspension_stack.length - 1); -}; - -Sk.Debugger.prototype.move_down_the_stack = function() { - this.current_suspension = Math.max(this.current_suspension - 1, 0); -}; - -Sk.Debugger.prototype.enable_step_mode = function() { - this.step_mode = true; -}; - -Sk.Debugger.prototype.disable_step_mode = function() { - this.step_mode = false; -}; - -Sk.Debugger.prototype.get_suspension_stack = function() { - return this.suspension_stack; -}; - -Sk.Debugger.prototype.get_active_suspension = function() { - if (this.suspension_stack.length === 0) { - return null; +export default class Debugger { + constructor(filename, output_callback) { + this.dbg_breakpoints = {}; + this.tmp_breakpoints = {}; + this.suspension_stack = []; + this.current_suspension = -1; + this.eval_callback = null; + this.suspension = null; + this.output_callback = output_callback; + this.step_mode = false; + this.filename = filename; } - return this.suspension_stack[this.current_suspension]; -}; - -Sk.Debugger.prototype.generate_breakpoint_key = function(filename, lineno, colno) { - var key = filename + "-" + lineno; - return key; -}; - -Sk.Debugger.prototype.check_breakpoints = function(filename, lineno, colno, globals, locals) { - // If Step mode is enabled then ignore breakpoints since we will just break - // at every line. - if (this.step_mode === true) { - return true; + print(txt) { + if (this.output_callback != null) { + this.output_callback.print(txt); + } } - - var key = this.generate_breakpoint_key(filename, lineno, colno); - if (hasOwnProperty(this.dbg_breakpoints, key) && - this.dbg_breakpoints[key].enabled === true) { - var bp = null; - if (hasOwnProperty(this.tmp_breakpoints, key)) { - delete this.dbg_breakpoints[key]; - delete this.tmp_breakpoints[key]; + + get_source_line(lineno) { + if (this.output_callback != null) { + return this.output_callback.get_source_line(lineno); + } + + return ""; + } + + move_up_the_stack() { + this.current_suspension = Math.min(this.current_suspension + 1, this.suspension_stack.length - 1); + } + + move_down_the_stack() { + this.current_suspension = Math.max(this.current_suspension - 1, 0); + } + + enable_step_mode() { + this.step_mode = true; + } + + disable_step_mode() { + this.step_mode = false; + } + + get_suspension_stack() { + return this.suspension_stack; + } + + get_active_suspension() { + if (this.suspension_stack.length === 0) { + return null; + } + + return this.suspension_stack[this.current_suspension]; + } + + generate_breakpoint_key(filename, lineno) { + var key = filename + "-" + lineno; + return key; + } + + check_breakpoints(filename, lineno, colno) { + // If Step mode is enabled then ignore breakpoints since we will just break + // at every line. + if (this.step_mode === true) { return true; } - - this.dbg_breakpoints[key].ignore_count -= 1; - this.dbg_breakpoints[key].ignore_count = Math.max(0, this.dbg_breakpoints[key].ignore_count); - - bp = this.dbg_breakpoints[key]; - if (bp.ignore_count === 0) { - return true; - } else { + + var key = this.generate_breakpoint_key(filename, lineno, colno); + if (hasOwnProperty(this.dbg_breakpoints, key) && + this.dbg_breakpoints[key].enabled === true) { + var bp = null; + if (hasOwnProperty(this.tmp_breakpoints, key)) { + delete this.dbg_breakpoints[key]; + delete this.tmp_breakpoints[key]; + return true; + } + + this.dbg_breakpoints[key].ignore_count -= 1; + this.dbg_breakpoints[key].ignore_count = Math.max(0, this.dbg_breakpoints[key].ignore_count); + + bp = this.dbg_breakpoints[key]; + if (bp.ignore_count === 0) { + return true; + } return false; } + return false; } - return false; -}; -Sk.Debugger.prototype.get_breakpoints_list = function() { - return this.dbg_breakpoints; -}; - -Sk.Debugger.prototype.disable_breakpoint = function(filename, lineno, colno) { - var key = this.generate_breakpoint_key(filename, lineno, colno); - - if (hasOwnProperty(this.dbg_breakpoints, key)) { - this.dbg_breakpoints[key].enabled = false; + get_breakpoints_list() { + return this.dbg_breakpoints; } -}; -Sk.Debugger.prototype.enable_breakpoint = function(filename, lineno, colno) { - var key = this.generate_breakpoint_key(filename, lineno, colno); - - if (hasOwnProperty(this.dbg_breakpoints, key)) { - this.dbg_breakpoints[key].enabled = true; + disable_breakpoint(filename, lineno, colno) { + var key = this.generate_breakpoint_key(filename, lineno, colno); + + if (hasOwnProperty(this.dbg_breakpoints, key)) { + this.dbg_breakpoints[key].enabled = false; + } } -}; -Sk.Debugger.prototype.clear_breakpoint = function(filename, lineno, colno) { - var key = this.generate_breakpoint_key(filename, lineno, colno); - if (hasOwnProperty(this.dbg_breakpoints, key)) { - delete this.dbg_breakpoints[key]; - return null; - } else { + enable_breakpoint(filename, lineno, colno) { + var key = this.generate_breakpoint_key(filename, lineno, colno); + + if (hasOwnProperty(this.dbg_breakpoints, key)) { + this.dbg_breakpoints[key].enabled = true; + } + } + + clear_breakpoint(filename, lineno, colno) { + var key = this.generate_breakpoint_key(filename, lineno, colno); + if (hasOwnProperty(this.dbg_breakpoints, key)) { + delete this.dbg_breakpoints[key]; + return null; + } return "Invalid breakpoint specified: " + filename + " line: " + lineno; } -}; -Sk.Debugger.prototype.clear_all_breakpoints = function() { - this.dbg_breakpoints = {}; - this.tmp_breakpoints = {}; -}; - -Sk.Debugger.prototype.set_ignore_count = function(filename, lineno, colno, count) { - var key = this.generate_breakpoint_key(filename, lineno, colno); - if (hasOwnProperty(this.dbg_breakpoints, key)) { - var bp = this.dbg_breakpoints[key]; - bp.ignore_count = count; + clear_all_breakpoints() { + this.dbg_breakpoints = {}; + this.tmp_breakpoints = {}; } -}; -Sk.Debugger.prototype.set_condition = function(filename, lineno, colno, lhs, cond, rhs) { - var key = this.generate_breakpoint_key(filename, lineno, colno); - var bp; - if (hasOwnProperty(this.dbg_breakpoints, key)) { - // Set a new condition - bp = this.dbg_breakpoints[key]; - } else { - bp = new Sk.Breakpoint(filename, lineno, colno); + set_ignore_count(filename, lineno, colno, count) { + var key = this.generate_breakpoint_key(filename, lineno, colno); + if (hasOwnProperty(this.dbg_breakpoints, key)) { + var bp = this.dbg_breakpoints[key]; + bp.ignore_count = count; + } } - - bp.condition = new Sk.Condition(lhs, cond, rhs); - this.dbg_breakpoints[key] = bp; -}; -Sk.Debugger.prototype.print_suspension_info = function(suspension) { - var filename = suspension.filename; - var lineno = suspension.lineno; - var colno = suspension.colno; - this.print("Hit Breakpoint at <" + filename + "> at line: " + lineno + " column: " + colno + "\n"); - this.print("----------------------------------------------------------------------------------\n"); - this.print(" ==> " + this.get_source_line(lineno - 1) + "\n"); - this.print("----------------------------------------------------------------------------------\n"); -}; + set_condition(filename, lineno, colno, lhs, cond, rhs) { + var key = this.generate_breakpoint_key(filename, lineno, colno); + var bp; + if (hasOwnProperty(this.dbg_breakpoints, key)) { + // Set a new condition + bp = this.dbg_breakpoints[key]; + } else { + bp = new Breakpoint(filename, lineno, colno); + } -Sk.Debugger.prototype.set_suspension = function(suspension) { - var parent = null; - if (!hasOwnProperty(suspension, "filename") && suspension.child instanceof Sk.misceval.Suspension) { - suspension = suspension.child; + bp.condition = new window.Sk.Condition(lhs, cond, rhs); + this.dbg_breakpoints[key] = bp; } - - // Pop the last suspension of the stack if there is more than 0 - if (this.suspension_stack.length > 0) { + + print_suspension_info(suspension) { + var filename = suspension.filename; + var lineno = suspension.lineno; + var colno = suspension.colno; + this.print("Hit Breakpoint at <" + filename + "> at line: " + lineno + " column: " + colno + "\n"); + this.print("----------------------------------------------------------------------------------\n"); + this.print(" ==> " + this.get_source_line(lineno - 1) + "\n"); + this.print("----------------------------------------------------------------------------------\n"); + } + + set_suspension(suspension) { + var parent = null; + if (!hasOwnProperty(suspension, "filename") && suspension.child instanceof window.Sk.misceval.Suspension) { + suspension = suspension.child; + } + + // Pop the last suspension of the stack if there is more than 0 + if (this.suspension_stack.length > 0) { + this.suspension_stack.pop(); + this.current_suspension -= 1; + } + + // Unroll the stack to get each suspension. + while (suspension instanceof window.Sk.misceval.Suspension) { + parent = suspension; + this.suspension_stack.push(parent); + this.current_suspension += 1; + suspension = suspension.child; + } + + suspension = parent; + + this.print_suspension_info(suspension); + } + + add_breakpoint(filename, lineno, colno, temporary) { + var key = this.generate_breakpoint_key(filename, lineno, colno); + this.dbg_breakpoints[key] = new Breakpoint(filename, lineno, colno); + if (temporary) { + this.tmp_breakpoints[key] = true; + } + } + + suspension_handler(susp) { + return new Promise(function (resolve, reject) { + try { + resolve(susp.resume()); + } catch (e) { + reject(e); + } + }); + } + + resume() { + // Reset the suspension stack to the topmost + this.current_suspension = this.suspension_stack.length - 1; + + if (this.suspension_stack.length === 0) { + this.print("No running program"); + } else { + var promise = this.suspension_handler(this.get_active_suspension()); + promise.then(this.success.bind(this), this.error.bind(this)); + } + } + + pop_suspension_stack() { this.suspension_stack.pop(); this.current_suspension -= 1; } - - // Unroll the stack to get each suspension. - while (suspension instanceof Sk.misceval.Suspension) { - parent = suspension; - this.suspension_stack.push(parent); - this.current_suspension += 1; - suspension = suspension.child; - } - suspension = parent; - - this.print_suspension_info(suspension); -}; - -Sk.Debugger.prototype.add_breakpoint = function(filename, lineno, colno, temporary) { - var key = this.generate_breakpoint_key(filename, lineno, colno); - this.dbg_breakpoints[key] = new Sk.Breakpoint(filename, lineno, colno); - if (temporary) { - this.tmp_breakpoints[key] = true; - } -}; - -Sk.Debugger.prototype.suspension_handler = function(susp) { - return new Promise(function(resolve, reject) { - try { - resolve(susp.resume()); - } catch(e) { - reject(e); - } - }); -}; - -Sk.Debugger.prototype.resume = function() { - // Reset the suspension stack to the topmost - this.current_suspension = this.suspension_stack.length - 1; - - if (this.suspension_stack.length === 0) { - this.print("No running program"); - } else { - var promise = this.suspension_handler(this.get_active_suspension()); - promise.then(this.success.bind(this), this.error.bind(this)); - } -}; - -Sk.Debugger.prototype.pop_suspension_stack = function() { - this.suspension_stack.pop(); - this.current_suspension -= 1; -}; - -Sk.Debugger.prototype.success = function(r) { - if (r instanceof Sk.misceval.Suspension) { - this.set_suspension(r); - } else { - if (this.suspension_stack.length > 0) { - // Current suspension needs to be popped of the stack - this.pop_suspension_stack(); - - if (this.suspension_stack.length === 0) { - this.print("Program execution complete"); - return; - } - - var parent_suspension = this.get_active_suspension(); - // The child has completed the execution. So override the child's resume - // so we can continue the execution. - parent_suspension.child.resume = function() { - return r; - }; - this.resume(); + success(r) { + if (r instanceof window.Sk.misceval.Suspension) { + this.set_suspension(r); } else { - this.print("Program execution complete"); - } - } -}; + if (this.suspension_stack.length > 0) { + // Current suspension needs to be popped of the stack + this.pop_suspension_stack(); -Sk.Debugger.prototype.error = function(e) { - this.print("Traceback (most recent call last):"); - for (var idx = 0; idx < e.traceback.length; ++idx) { - this.print(" File \"" + e.traceback[idx].filename + "\", line " + e.traceback[idx].lineno + ", in "); - var code = this.get_source_line(e.traceback[idx].lineno - 1); - code = code.trim(); - code = " " + code; - this.print(code); - } - - var err_ty = e.constructor.tp$name; - for (idx = 0; idx < e.args.v.length; ++idx) { - this.print(err_ty + ": " + e.args.v[idx].v); - } -}; - -Sk.Debugger.prototype.asyncToPromise = function(suspendablefn, suspHandlers, debugger_obj) { - return new Promise(function(resolve, reject) { - try { - var r = suspendablefn(); - - (function handleResponse (r) { - try { - while (r instanceof Sk.misceval.Suspension) { - debugger_obj.set_suspension(r); - return; - } - - resolve(r); - } catch(e) { - reject(e); + if (this.suspension_stack.length === 0) { + this.print("Program execution complete"); + return; } - })(r); - } catch (e) { - reject(e); + var parent_suspension = this.get_active_suspension(); + // The child has completed the execution. So override the child's resume + // so we can continue the execution. + parent_suspension.child.resume = function () { + return r; + }; + this.resume(); + } else { + this.print("Program execution complete"); + } } - }); -}; - -Sk.Debugger.prototype.execute = function(suspendablefn, suspHandlers) { - var r = suspendablefn(); - - if (r instanceof Sk.misceval.Suspension) { - this.suspensions.concat(r); - this.eval_callback(r); } -}; -goog.exportSymbol("Sk.Debugger", Sk.Debugger); + error(e) { + this.print("Traceback (most recent call last):"); + for (var idx = 0; idx < e.traceback.length; ++idx) { + this.print(" File \"" + e.traceback[idx].filename + "\", line " + e.traceback[idx].lineno + ", in "); + var code = this.get_source_line(e.traceback[idx].lineno - 1); + code = code.trim(); + code = " " + code; + this.print(code); + } + + var err_ty = e.constructor.tp$name; + for (idx = 0; idx < e.args.v.length; ++idx) { + this.print(err_ty + ": " + e.args.v[idx].v); + } + } + + asyncToPromise(suspendablefn, suspHandlers, debugger_obj) { + return new Promise(function (resolve, reject) { + try { + var r = suspendablefn(); + + (function handleResponse(r) { + try { + while (r instanceof window.Sk.misceval.Suspension) { + debugger_obj.set_suspension(r); + return; + } + + resolve(r); + } catch (e) { + reject(e); + } + })(r); + + } catch (e) { + reject(e); + } + }); + } + + execute(suspendablefn) { + var r = suspendablefn(); + + if (r instanceof window.Sk.misceval.Suspension) { + this.suspensions.concat(r); + this.eval_callback(r); + } + } +} \ No newline at end of file