There are two breakpoint keywords in Mochaccino, ok and notok, which are used for debugging.
ok
The ok keyword logs its line number and column position when reached.
notok
The notok keyword prints its position, the result of the preceding statement to the console, and exits the program. Furthermore, their functionality can be extended through the use of debug flags, discussed later.
if (someVar.someMethod()==null) {
notok;
} else {
ok;
}
This is the console log for the above code:
exit[0]: notok
line: 3, column: 3
Debug Flags
Debug flags are preceded by a #, and are inbuilt features that aid in debugging.
Label
You can label your notok keywords for a slightly richer debug message.
if (someVar.someMethod()==null) {
#label: someVar is null
notok;
} else {
ok;
}
Resulting in a log like this:
exit[0]: abc is null
line: 3, column: 3
And that’s not it. You can use the #label flag to label different sections of your code, just like with comments, except when a certain part of the code fails, it prints the label directly above it, if there is one.
#label: doing X things
SomeModule.someOkStuff();
#label: doing more X things
SomeModule.someOkStuff();
#label: doing a Y thing
SomeModule.someNotOkStuff();
#label: and finally some more X things
SomeModule.someOkStuff();
The part highlighted in red causes an error, which results in the following log:
exit[1]: doing a Y thing
line: 6, column: 11
Antinull
The #antinull flag ensures that the succeeding statement does not contain null values in any part. If a null value is detected, the program exits gracefully, and the variable containing the null value gets printed, along with a few details.
exit[0]: abc is null
line: 3, column: 3
abc is null because:
variable abc is not initialised
Rich Error Messages
Aside from pointing out the location and type of errors, Mochaccino can also suggest personalised troubleshooting tips. For exampe:
exit[1]: 1 errors
PackageResolution: package 'B' not found.
3| include B;
Try:
- ensuring the package has the "package B;" and "partof A" directives at the top.
- ensuring the package is within the project scope, by running "moc scope add "path/to/file.moc" from the same directory as your mochaccino.configs.json file.
Variable Debugging
Built-In onChange Property
Variables in Mochaccino come with a special onChange property that can be configured with a callback whenever said variable is changed.
var a<string> = "hello";
a.onChange =(newValue<dynamic>) {
if (newValue==null) {
throw"newValue for 'a' cannot be null";
}
}
Built-In history Property
Variables in Mochaccino also come with a special history property that contains an array of variable modification details, from the time it was initialised, to the last change that occurred. You can use this property to find out which functions or statements affected the lifetime of the variable.
var a<string>;
a = "hello";
a = null;
Console.log(a.history);
Would give:
[...]
exit[0]
Used with other debugging tools, you’ll no longer have to spend hours pulling your hair out wondering where that null value is coming from.
Note
The history property is updated first and then the onChange callback, if specified, is triggered. To access an up-to-date list of a variable’s history, you can access the history property from the onChange callback.