diff --git a/share/man/nit.md b/share/man/nit.md index 7d30a09f0f..d210fcf540 100644 --- a/share/man/nit.md +++ b/share/man/nit.md @@ -86,6 +86,11 @@ Each time a method is invoked for the first time, its information is printed on This option helps the user to have a simplified but humanly readable overview of the behavior of a particular program execution. +### `--break` +Start the program to indicate the breakpoints for the interpretation. + +Print the menu to add or remove some breakpoint + ## DEBUGGER OPTIONS ### `-d` diff --git a/src/interpreter/naive_interpreter.nit b/src/interpreter/naive_interpreter.nit index 7cdceb480f..90bfb3cea7 100644 --- a/src/interpreter/naive_interpreter.nit +++ b/src/interpreter/naive_interpreter.nit @@ -27,11 +27,14 @@ private import frontend::explain_assert_api redef class ToolContext # --discover-call-trace var opt_discover_call_trace = new OptionBool("Trace calls of the first invocation of methods", "--discover-call-trace") + # --stop-at + var opt_stop = new OptionBool("Start the program to indicate the breakpoints for the interpretation","--break") redef init do super self.option_context.add_option(self.opt_discover_call_trace) + self.option_context.add_option(self.opt_stop) end end diff --git a/src/interpreter/step_interpreter.nit b/src/interpreter/step_interpreter.nit index 544db1ffb8..faad462dcb 100644 --- a/src/interpreter/step_interpreter.nit +++ b/src/interpreter/step_interpreter.nit @@ -36,8 +36,19 @@ redef class NaiveInterpreter # This flag is used to launch setp by step interpreter var debug_flag = false + # The breakpoint tool + private var breakpoint : Breakpoints + private var user_entry = "" + init do + super + breakpoint = new Breakpoints(self.modelbuilder) + if modelbuilder.toolcontext.opt_stop.value then + breakpoint.define_breakpoints + end + end + # Print the commands to execute step-by-step execution fun print_instruction_debug do print "────────────────────────────────────────────────────────────────────" @@ -85,6 +96,10 @@ redef class NaiveInterpreter # Main function of the step-by-step execution this method is called after each instruction fun step_execution(recv : nullable Instance) do + if frame isa InterpreterFrame and breakpoint.is_breakpoint(frame.current_node.location) then + self.deep_old_frame = frames.length + self.debug_flag = true + end if self.debug_flag then init_debug_mode if recv != null then @@ -102,6 +117,9 @@ redef class NaiveInterpreter self.object_inspector.print_pin_list_value self.user_entry = stdin.read_line self.step_execution(recv) + else if user_entry == "break" then + self.user_entry = "" + self.breakpoint.define_breakpoints else if user_entry == "continue" then self.user_entry = "" self.debug_flag = false @@ -142,6 +160,101 @@ redef class NaiveInterpreter super end end + +class Breakpoints + + # The map representing the breakpoints with the links of the source file and array of lines + private var breakpoints_list = new ArrayMap[SourceFile,Array[Int]] + + # The modelbuilder is stored to check the module + var modelbuilder: ModelBuilder + + redef fun to_s do + var return_list = "" + for file, lines in breakpoints_list do + return_list += "File : {file.filename} lines : {lines} \n" + end + return return_list + end + + # Is there location is a breakpoint? + fun is_breakpoint(location : Location): Bool do + if breakpoints_list.has_key(location.file) then + return breakpoints_list[location.file].has(location.line_start) + end + return false + end + + # Method to interact with the breakpoints list + fun define_breakpoints do + print "────────────────────────────────────────────────────────────────────" + print "Breakpoints list" + print "{self.to_s}" + print "For add enter" + " 'break [file name] [line number,...]'".yellow + " for remove " + "'clear [file name] [line number,...]'".yellow + print "To leave the breakpoint mode enter " + "leave".yellow + print "────────────────────────────────────────────────────────────────────" + var user_entry = stdin.read_line.split(" ") + if user_entry.length%3 == 0 then + for x in [0 .. user_entry.length[.step(3) do + var action = user_entry[x] + var file = check_file(user_entry[x+1]) + var lines = check_line(user_entry[x+2]) + if file != null then + if action == "break" then + add_breakpoints(file,lines) + else if action == "clear" then + remove_breakpoint(file,lines) + else + print "Command unknown" + end + end + end + else + print "Error on the number of parameters" + end + end + + # Check in the list of modules the source file exists with the name of the parameter. + # If it exists, return this. + fun check_file(name: String) : nullable SourceFile do + for mmodule in modelbuilder.identified_modules do + if mmodule.location.file.filename.search(name) != null then return mmodule.location.file + end + print "File not found" + return null + end + + # Check the user input line. + fun check_line(string_line: String) : Array[Int] do + var lines = string_line.split(",") + var return_array = new Array[Int] + for line in lines do + if line.is_int then + return_array.add(line.to_i) + end + end + return return_array + end + + fun add_breakpoints(file : SourceFile,lines : Array[Int])do + if not lines.is_empty then + if breakpoints_list.has_key(file) then + breakpoints_list[file].add_all(lines) + else + breakpoints_list[file] = lines + end + end + end + + fun remove_breakpoint(file : SourceFile,lines : Array[Int])do + if not lines.is_empty then + for line in lines do + breakpoints_list[file].remove_all(line) + end + end + end +end + # Represents the inspected object with the relationship between the instance and the name of the object (if it exists) class ObjectInspected # The instance of the inspected object. diff --git a/tests/sav/error_class_glob.res b/tests/sav/error_class_glob.res index 46e2b1aed4..504e245e89 100644 --- a/tests/sav/error_class_glob.res +++ b/tests/sav/error_class_glob.res @@ -1,13 +1,13 @@ -../lib/core/kernel.nit:32,1--225,3: Error: `kernel$Object` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? -../lib/core/kernel.nit:227,1--300,3: Error: `kernel$Sys` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? -../lib/core/kernel.nit:313,1--371,3: Error: `kernel$Comparable` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? -../lib/core/kernel.nit:373,1--410,3: Error: `kernel$Discrete` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? -../lib/core/kernel.nit:412,1--429,3: Error: `kernel$Cloneable` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? -../lib/core/kernel.nit:431,1--486,3: Error: `kernel$Numeric` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? -../lib/core/kernel.nit:492,1--515,3: Error: `kernel$Bool` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? -../lib/core/kernel.nit:517,1--599,3: Error: `kernel$Float` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? -../lib/core/kernel.nit:601,1--700,3: Error: `kernel$Byte` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? -../lib/core/kernel.nit:702,1--883,3: Error: `kernel$Int` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? -../lib/core/kernel.nit:885,1--1064,3: Error: `kernel$Char` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? -../lib/core/kernel.nit:1066,1--1083,3: Error: `kernel$Pointer` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? -../lib/core/kernel.nit:1085,1--1094,3: Error: `kernel$Task` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? +../lib/core/kernel.nit:32,1--230,3: Error: `kernel$Object` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? +../lib/core/kernel.nit:232,1--305,3: Error: `kernel$Sys` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? +../lib/core/kernel.nit:318,1--376,3: Error: `kernel$Comparable` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? +../lib/core/kernel.nit:378,1--415,3: Error: `kernel$Discrete` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? +../lib/core/kernel.nit:417,1--434,3: Error: `kernel$Cloneable` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? +../lib/core/kernel.nit:436,1--491,3: Error: `kernel$Numeric` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? +../lib/core/kernel.nit:497,1--520,3: Error: `kernel$Bool` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? +../lib/core/kernel.nit:522,1--604,3: Error: `kernel$Float` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? +../lib/core/kernel.nit:606,1--705,3: Error: `kernel$Byte` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? +../lib/core/kernel.nit:707,1--888,3: Error: `kernel$Int` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? +../lib/core/kernel.nit:890,1--1069,3: Error: `kernel$Char` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? +../lib/core/kernel.nit:1071,1--1088,3: Error: `kernel$Pointer` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? +../lib/core/kernel.nit:1090,1--1099,3: Error: `kernel$Task` does not specialize `module_0$Object`. Possible duplication of the root class `Object`? diff --git a/tests/sav/nitce/fixme/base_gen_reassign_alt4.res b/tests/sav/nitce/fixme/base_gen_reassign_alt4.res index 5bdd4bf614..e131b2ec7a 100644 --- a/tests/sav/nitce/fixme/base_gen_reassign_alt4.res +++ b/tests/sav/nitce/fixme/base_gen_reassign_alt4.res @@ -1,4 +1,4 @@ -Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:723) +Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:728) 11 21 31 diff --git a/tests/sav/nitce/fixme/base_gen_reassign_alt5.res b/tests/sav/nitce/fixme/base_gen_reassign_alt5.res index 5bdd4bf614..e131b2ec7a 100644 --- a/tests/sav/nitce/fixme/base_gen_reassign_alt5.res +++ b/tests/sav/nitce/fixme/base_gen_reassign_alt5.res @@ -1,4 +1,4 @@ -Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:723) +Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:728) 11 21 31 diff --git a/tests/sav/nitce/fixme/base_gen_reassign_alt6.res b/tests/sav/nitce/fixme/base_gen_reassign_alt6.res index 5bdd4bf614..e131b2ec7a 100644 --- a/tests/sav/nitce/fixme/base_gen_reassign_alt6.res +++ b/tests/sav/nitce/fixme/base_gen_reassign_alt6.res @@ -1,4 +1,4 @@ -Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:723) +Runtime error: Cast failed. Expected `OTHER`, got `Float` (../lib/core/kernel.nit:728) 11 21 31 diff --git a/tests/sav/nituml_args3.res b/tests/sav/nituml_args3.res index a5a027f67e..fe264cef63 100644 --- a/tests/sav/nituml_args3.res +++ b/tests/sav/nituml_args3.res @@ -12,7 +12,7 @@ digraph G { fontsize = 8 ] Object [ - label = "{interface\nObject||+ object_id(): Int\l+ is_same_type(other: Object): Bool\l+ is_same_instance(other: nullable Object): Bool\l+ ==(other: nullable Object): Bool\l+ !=(other: nullable Object): Bool\l+ output()\l+ output_class_name()\l+ hash(): Int\l+ sys(): Sys\l+ init()\l}" + label = "{interface\nObject||+ object_id(): Int\l+ is_same_type(other: Object): Bool\l+ is_same_instance(other: nullable Object): Bool\l+ ==(other: nullable Object): Bool\l+ !=(other: nullable Object): Bool\l+ output()\l+ output_class_name()\l+ hash(): Int\l+ inspect_o()\l+ sys(): Sys\l+ init()\l}" ] Sys [ diff --git a/tests/sav/nituml_args4.res b/tests/sav/nituml_args4.res index f03123ae1a..3223febd04 100644 --- a/tests/sav/nituml_args4.res +++ b/tests/sav/nituml_args4.res @@ -12,7 +12,7 @@ digraph G { fontsize = 8 ] Object [ - label = "{interface\nObject||+ object_id(): Int\l+ is_same_type(other: Object): Bool\l+ is_same_instance(other: nullable Object): Bool\l+ ==(other: nullable Object): Bool\l+ !=(other: nullable Object): Bool\l+ output()\l+ output_class_name()\l+ hash(): Int\l+ sys(): Sys\l+ init()\l}" + label = "{interface\nObject||+ object_id(): Int\l+ is_same_type(other: Object): Bool\l+ is_same_instance(other: nullable Object): Bool\l+ ==(other: nullable Object): Bool\l+ !=(other: nullable Object): Bool\l+ output()\l+ output_class_name()\l+ hash(): Int\l+ inspect_o()\l+ sys(): Sys\l+ init()\l}" ] Sys [