Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion M2/Macaulay2/d/interp.dd
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ debugger(f:Frame,c:Code):Expr := (
setDebuggingMode(false);
oldDebuggerCode := getGlobalVariable(currentS);
setGlobalVariable(currentS,Expr(PseudocodeClosure(f,c)));
printMessage(codePosition(c), "entering debugger (enter 'help' to see commands)");
printMessage(codePosition(c), "\n"+ "ENTERING DEBUGGER (enter 'help' to see commands, enter 'break' to quit the debugger)");
incrementInterpreterDepth();
if debuggerHook != nullE then (
r := applyEE(debuggerHook,True);
Expand Down
113 changes: 100 additions & 13 deletions M2/Macaulay2/m2/code.m2
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ needs "lists.m2"
needs "methods.m2"
needs "nets.m2"

-----------------------------------------------------------------------------
-- Global variables
-----------------------------------------------------------------------------

debugPrintCarets = true
debugPrintLineNumbers = true

-----------------------------------------------------------------------------
-- code
-----------------------------------------------------------------------------
Expand Down Expand Up @@ -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
Copy link
Copy Markdown
Member

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 using PrintCarets and PrintLineNumbers to match the corresponding debug-prefixed global variables.

We'd also need to update the code docs accordingly.

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 -> (
Expand All @@ -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
Expand All @@ -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) }
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like we should use opt here. Maybe the default values should be null, and if so, use the global variables?

Either that or just drop options entirely and use the global variables inside codeContent?

))
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: ";
Expand All @@ -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
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
code ZZ := opt -> i -> code previousMethodsFound#i
code ZZ := opt -> i -> code(previousMethodsFound#i, opt)

code(TestInput) in testing.m2 also needs updated to use options


-----------------------------------------------------------------------------
-- edit
Expand Down
2 changes: 2 additions & 0 deletions M2/Macaulay2/m2/exports.m2
Original file line number Diff line number Diff line change
Expand Up @@ -1351,6 +1351,8 @@ exportMutable {
"debugError",
"debugLevel",
"debuggingMode",
"debugPrintCarets",
"debugPrintLineNumbers",
"defaultPrecision",
"dictionaryPath",
"engineDebugLevel",
Expand Down
7 changes: 6 additions & 1 deletion M2/Macaulay2/m2/startup.m2.in
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,12 @@ if firstTime then (

normalPrompts = () -> (
lastprompt := "";
ZZ#{Standard,InputPrompt} = lineno -> concatenate(newline, lastprompt = concatenate(interpreterDepth:"i", toString lineno, " : "));
-- ZZ#{Standard,InputPrompt} = lineno -> concatenate(newline, lastprompt = concatenate(interpreterDepth:"i", toString lineno, " : "));

ZZ#{Standard,InputPrompt} = lineno -> concatenate(newline, lastprompt = if (interpreterDepth == 1) then concatenate(interpreterDepth:"i", toString lineno, " : ") else concatenate("<M2 Debugger> ", interpreterDepth:"i", toString lineno, " : "));
-- if interpreterDepth > 0 then (
-- ZZ#{Standard,InputPrompt} = lineno -> concatenate("<M2 Debugger> ",lastprompt);
-- );
ZZ#{Standard,InputContinuationPrompt} = lineno -> #lastprompt; -- will print that many blanks, see interp.d
symbol currentPrompts <- normalPrompts; -- this avoids the warning about redefining a function
);
Expand Down
29 changes: 29 additions & 0 deletions M2/Macaulay2/m2/test.m2
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The 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()
5 changes: 4 additions & 1 deletion M2/Macaulay2/packages/Macaulay2Doc/ov_debugging.m2
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,10 @@ document {
EXAMPLE {"g 4", "g 3"},
"However, the following attempt results in an error, and the debugger starts up automatically.",
EXAMPLE "g 2",
"You may use ", TO "help", ", as instructed, to view the commands available in the debugger.
"Here it says ENTERING DEBUGGER when you enter the deugger. You may use ", TO "help", ", as instructed, to view the commands available in the debugger.
While in the debugger, the input line says \"<M2 debugger>\" and the line numbers of the error are displayed to the right of the code.
In addition there are carets below the specific characters causing the error or below the starting ending characters if the error is multiple lines.
The line numbers and carets can be toggled off by including at the start of your document debugPrintLineNumbers = false; and debugPrintCarets = false; respectively.
As suggested by the help display, we can use ", TO "listLocalSymbols", " to list the local symbols and their values.",
EXAMPLE "listLocalSymbols",
"We see that the value of ", TT "x", " is 0, and that explains the error message about division by zero.
Expand Down
Loading