-
Notifications
You must be signed in to change notification settings - Fork 287
Improve the output of the debugger #4365
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: development
Are you sure you want to change the base?
Changes from all commits
884e9f9
796a834
2775f47
4ac672d
49a2121
6125ed2
320b92e
a9a874a
1689c85
fc67e55
ab696cb
6c0774f
bc7e3a8
37ddad9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -7,6 +7,13 @@ needs "lists.m2" | |||||
| needs "methods.m2" | ||||||
| needs "nets.m2" | ||||||
|
|
||||||
| ----------------------------------------------------------------------------- | ||||||
| -- Global variables | ||||||
| ----------------------------------------------------------------------------- | ||||||
|
|
||||||
| debugPrintCarets = true | ||||||
| debugPrintLineNumbers = true | ||||||
|
|
||||||
| ----------------------------------------------------------------------------- | ||||||
| -- code | ||||||
| ----------------------------------------------------------------------------- | ||||||
|
|
@@ -37,7 +44,81 @@ codeFunction := (key, func, level) -> if level <= limit then ( | |||||
| previousMethodsFound = null | ||||||
|
|
||||||
| codeAddress = pos -> ( pos, ": --source code:" ) -- [addr]:[line]:[char]-[line]:[char]: | ||||||
| codeContent = (s, e, filelines) -> PRE M2CODE stack filelines_{s-1 .. e-1} | ||||||
|
|
||||||
|
|
||||||
| protect PrintCaret | ||||||
| protect PrintLineNum | ||||||
| codeContent = method( | ||||||
| Options => { | ||||||
| PrintCaret => true, | ||||||
| PrintLineNum => true | ||||||
| } | ||||||
| ) | ||||||
| ----------------------------------------------------------------------------- | ||||||
| -- Updates to codeContent developed by Bryson Kagy, Adam LaClair, Olalekan Ogunmefun, Jay Yang | ||||||
| -- as part of the 2026 workshop "Building the Future of Macaulay2" at Georgia Tech. | ||||||
| -- Changed the code to print carets and line numbers in the debugger, and added options to toggle these features on and off with the global variables debugPrintLineNumbers and debugPrintCarets. | ||||||
| -- Also made it clearer when the user is in the debugger by adding a sentence to the documentation and by printing "ENTERING DEBUGGER" when the user enters the debugger and adding "<M2 debugger>" to the input line while in the debugger. | ||||||
| -- In codeContent, pos is the FilePosition of the error, s and e are the starting and ending line numbers of the error, and filelines is the list of lines in the file of the error. | ||||||
| ----------------------------------------------------------------------------- | ||||||
|
|
||||||
| codeContent (FilePosition,ZZ,ZZ,List) := opt -> (pos, s, e, filelines) -> ( | ||||||
| posL := {}; --List, containing the information associated to the error message. | ||||||
| strList := {}; --List, used for storing the line numbers as strings. | ||||||
| str := ""; -- String, temporary variable used for creating output. | ||||||
| leftPadding := 0; --Integer, which we initialize below to 3, spaces printed to the left of line number. | ||||||
| rightPadding := 0; --Integer, which we initialize below to 3, spaces printed to the right of line number. | ||||||
| outputList := {}; --List, which contains each line error as a string. | ||||||
| maxLen := 0; --Integer, maximum length that an integer takes up as a string. | ||||||
|
|
||||||
|
|
||||||
| --Initializing variables. | ||||||
| posL = toList(pos); | ||||||
| leftPadding = 3; | ||||||
| rightPadding = 3; | ||||||
|
|
||||||
|
|
||||||
| --Get max length of the integer that will be printed as a string. | ||||||
| if (opt.PrintLineNum === true) then ( | ||||||
| strList = for i from s-1 to e-1 list toString((posL#1+(i-s+1))); | ||||||
| maxLen = max(length\strList) | ||||||
| ); | ||||||
|
|
||||||
| --Create the first line of output. | ||||||
| if (s != e and opt.PrintCaret === true) then ( | ||||||
| outputList = outputList | { concatenate( ((leftPadding + maxLen + rightPadding + posL#2:" ")), "v") }; | ||||||
| ); | ||||||
|
|
||||||
| --Create the middle lines of output, where print out the code. | ||||||
| if (opt.PrintLineNum === true) then ( | ||||||
| outputList = outputList | for i from s-1 to e-1 list ( | ||||||
| concatenate( ((leftPadding + (maxLen - length strList#(i-s+1))):" "), strList#(i-s+1), ((rightPadding):" "), filelines_i ) | ||||||
| ); | ||||||
| ) else ( | ||||||
| outputList = outputList | filelines_{s-1..e-1}; | ||||||
| ); | ||||||
|
|
||||||
|
|
||||||
| --Check whether there are carets to print. | ||||||
| if (opt.PrintCaret === true) then ( | ||||||
| str = ""; | ||||||
| --Append the padding associated to the line numbers. | ||||||
| if (opt.PrintLineNum === true) then ( | ||||||
| str = concatenate(str, ((leftPadding + (maxLen) + rightPadding):" ")); | ||||||
| ); | ||||||
|
|
||||||
| if (s != e) then ( --For multiple lines add a single caret. | ||||||
| str = concatenate(str, (posL#4-1):" ", "^"); | ||||||
| ) else if (#posL == 3) then ( --Add a single caret. | ||||||
| str = concatenate(str,"^"); | ||||||
| ) else if (#posL == 5 or #posL == 7) then ( --Add a line of carets. | ||||||
| str = concatenate(str, (posL#2):" ", (posL#4 - posL#2):"^"); | ||||||
| ); | ||||||
| outputList = outputList | { str }; | ||||||
| ); | ||||||
|
|
||||||
| PRE M2CODE stack( outputList ) | ||||||
| ); | ||||||
|
|
||||||
| -- e.g. see code methods(map, Module, List) | ||||||
| dedupMethods = L -> ( | ||||||
|
|
@@ -50,11 +131,17 @@ dedupMethods = L -> ( | |||||
| L#i = join(tag, L#i))); | ||||||
| toList L) | ||||||
|
|
||||||
| code = method(Dispatch => Thing) | ||||||
| code Nothing := identity | ||||||
| code FilePosition := x -> ( | ||||||
| code = method( | ||||||
| Dispatch => Thing, | ||||||
| Options => { | ||||||
| PrintCaret => true, | ||||||
| PrintLineNum => true | ||||||
| } | ||||||
| ) | ||||||
| code Nothing := opt -> identity | ||||||
| code FilePosition := opt -> x -> ( | ||||||
| filename := x#0; start := x#1; stop := x#3 ?? x#1; | ||||||
| ( | ||||||
| ( | ||||||
| wp := set characters " \t\r);"; | ||||||
| file := ( | ||||||
| if match("startup\\.m2\\.in$", filename) then startupString | ||||||
|
|
@@ -74,11 +161,11 @@ code FilePosition := x -> ( | |||||
| ); | ||||||
| file = lines file; | ||||||
| if #file < stop then error("line number ",toString stop, " not found in file ", filename); | ||||||
| DIV splice { codeAddress(x), codeContent(start, stop, file) } | ||||||
| DIV splice { codeAddress(x), codeContent(PrintCaret => debugPrintCarets, PrintLineNum => debugPrintLineNumbers, x, start, stop, file) } | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems like we should use Either that or just drop options entirely and use the global variables inside |
||||||
| )) | ||||||
| code Symbol := | ||||||
| code Pseudocode := s -> code locate s | ||||||
| code Sequence := s -> ( | ||||||
| code Symbol := | ||||||
| code Pseudocode := opt -> s -> code locate s | ||||||
| code Sequence := opt -> s -> ( | ||||||
| key := select(s, x -> not instance(x, Option)); | ||||||
| -- handle strategies | ||||||
| mesg := "-- code for method: "; | ||||||
|
|
@@ -95,10 +182,10 @@ code Sequence := s -> ( | |||||
| if func =!= null or (func = lookup key) =!= null | ||||||
| then DIV { DIV { mesg, formatDocumentTag s }, codeFunction(s, func, 0) } | ||||||
| else "-- no method function found: " | formatDocumentTag key) | ||||||
| code Function := f -> codeFunction(null, f, 0) | ||||||
| code Command := C -> code C#0 | ||||||
| code List := L -> DIV between_(HR{}) dedupMethods apply(L, code) | ||||||
| code ZZ := i -> code previousMethodsFound#i | ||||||
| code Function := opt -> f -> codeFunction(null, f, 0) | ||||||
| code Command := opt -> C -> code C#0 | ||||||
| code List := opt -> L -> DIV between_(HR{}) dedupMethods apply(L, code) | ||||||
| code ZZ := opt -> i -> code previousMethodsFound#i | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
|
|
||||||
| ----------------------------------------------------------------------------- | ||||||
| -- edit | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
|
|
||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Was adding this file just a git oopsie? |
||
| --Global variables affecting printing | ||
| --debugPrintCarets = false | ||
| --debugPrintLineNumbers = true | ||
|
|
||
|
|
||
| needs "some | ||
| fi | ||
| le" | ||
|
|
||
| if (a == 3) then ( | ||
| << a << endl; | ||
| ); | ||
|
|
||
| value("error 1") | ||
|
|
||
| 1_1 | ||
|
|
||
|
|
||
|
|
||
| (error (1)) +15 | ||
| end-- | ||
|
|
||
| 1_1 | ||
|
|
||
|
|
||
|
|
||
| load "~/Code/M2/Workshop-2026-Atlanta/test.m2" | ||
| breakpoint() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering if we should export these, too, so users can pass them to
code? If so, then I'd considering usingPrintCaretsandPrintLineNumbersto match the correspondingdebug-prefixed global variables.We'd also need to update the
codedocs accordingly.