learnings, nerdisms, bicycles
Jump directly to "how to setup debugging in Gleam"
Gleam is nice little programming language. Perhaps common of functional programming languages, there is no debugger.
...or is there?
Why care? I code a lot. I code at work, I code outside of work, I listen to code podcasts, I read about coding design, I teach coding. Although like to think I'm somewhat competent, I write garbage code. Even worse, I constantly make bad assumptions. Sure, I write tests, but I make bad assumptions there too. Interactive & introspecting debuggers are the best cure for my coding ailments.
So, back to Gleam. Gleam can compile to JavaScript runtimes. Alis has a branch of the gleam compiler to add JavaScript sourcemaps. Hopefully that gets merged soon!
If one can compile Gleam to JavaScript with sourcemaps, one can use existing JavaScript debugging tools.
git clone
the
sourcemap enabled version of the compiler.
Hopefully you will not need to do this long term!rustup toolchain install stable
should do the trick, presuming you've
installed rustup
.cargo build
. cargo
is distributed with rust
.echo $PWD/target/debug/gleam
for me.
GLEAM_BIN=/path/to/target/debug/gleam
, as I'll be using it a lot going
forwardgleam.toml
with the
following patches:# gleam.toml
name = "my=project"
+ target = "javascript"
+ [javascript]
+ sourcemaps = true
.vscode/settings.json
:// .vscode/settings.json
{
"debug.javascript.terminalOptions": {
env: {
NODE_OPTIONS: "${env:NODE_OPTIONS} --import ./monkey-patch-gleam-custom-properties-for-debugging.mjs",
},
skipFiles: [
"<node_internals>/**",
"${workspaceFolder}/build/**/*.mjs",
"!**/MY_LIB_NAME/**/*.mjs",
],
customPropertiesGenerator: "this.customProperties ? this.customProperties() : this",
},
}
This file does some work.
It sets NODE_OPTIONS
to add an import statement to a module we will use to
monkey-patch the gleam runtime. This is an optional step, but makes your
output much more human friendly.
Setup skipFiles
. You probably do not want to be stepping into the gleam
javascript implementation of the standard libraries, as it's somewhat
obnoxious and disruptive. Tinker as you see fit.
Sets up customPropertiesGenerator
. This goes hand-in-hand additionally with
the monkey patching above. Gleam isnt javascript, but we're using a
javascript debugger. This field helps give VSCode better hints at how to
present gleam data-structures in-editor. There's more work to be done here.
If you are interested in this topic, please follow along @
microsoft/vscode-js-debug#2140
Next, setup your monkey-patching file. Adjust as you see fit.
// ./monkey-patch-gleam-custom-properties-for-debugging.mjs
/**
* These methods are used by VSCode JS debugger to display better representation
* of Gleam data structures in the debugger.
* @warn This feature is reliant the debug launch settings--see .vscode/{settings,launch}.json
*/
import Dict from "./build/dev/javascript/gleam_stdlib/dict.mjs";
import { List, NonEmpty } from "./build/dev/javascript/prelude.mjs";
import { new$ as newSet } from "./build/dev/javascript/gleam_stdlib/gleam/set.mjs";
List.prototype.customProperties = function () {
return this.toArray();
};
// aSet.constructor.prototype.customProperties = function () {
// if (this.dict) {
// return Object.values(this.dict.customProperties());
// }
// }
NonEmpty.prototype.customProperties = function () {
return [this.head, ...this.tail.toArray()];
};
Dict.prototype.customProperties = function () {
var out = {};
this.forEach((v, k) => {
out[k] = v;
});
return out;
};
Object.getPrototypeOf(newSet()).customProperties = function () {
return this.dict.entries().map(([k, _v]) => k);
};
gleam clean
cmd+shift+p Debug Terminal
.$GLEAM_BIN run