Appendix D — Build and Debug
The toolchain in one place: the CLI's two commands and their options, the four files a build writes, the conventions that let Debug80 treat a .glim file as a runnable target, and the diagnostics the compiler reports. Every usage line, output line and message here is copied from real runs of Glimmer 0.6.
Getting the command line
Debug80 carries the compiler inside the extension, so the CLI is optional for the normal edit-build-debug workflow. It is useful for dependency reports, scripts, automation and work outside VS Code. The CLI installs with Node 20 or newer:
npm install -g @jhlagado/glimmerThat provides the glimmer command, with the assembler included as a dependency.
The command line
glimmer -h prints the complete command interface:
Usage: glimmer [options] <entry.glim>
glimmer build [options] <entry.glim>
The default command compiles .glim to a generated AZM source file
and register-contract checks it with AZM. build also assembles it
with AZM (.hex, .bin, .d8.json) and rewrites the Debug80 map so
block-body lines step in the .glim source.
Options:
-o, --output <file> Output AZM path (default: <entry>.main.asm, the Debug80 entry-point convention)
--org <addr> Assembly origin, e.g. $4000 (default: $4000)
--no-check Generate only; skip the AZM register-contract check (not with build)
--deps Print the dependency report (writers/readers per cell) and exit
-V, --version Print package version
-h, --help Print this helpTwo commands share that surface:
| Invocation | Work performed |
|---|---|
glimmer game.glim | Generates game.main.asm and register-contract checks it with the assembler. Stops there. |
glimmer build game.glim | The same generation and check, then the assembler assembles the file and the Debug80 map is rewritten so block bodies step in .glim source. |
Each prints what it wrote:
glimmer demo.glimWrote demo.main.asm (register contracts checked by AZM)glimmer build demo.glimWrote demo.main.asm (register contracts checked by AZM)
Wrote demo.main.d8.json (11 block segments attributed to .glim source)build's messages name the two files Debug80 reads; the .hex and .bin land beside them in the same pass.
Options
| Flag | Effect |
|---|---|
-o, --output <file> | Where the generated assembly goes. The default, <entry>.main.asm, is the name Debug80 discovers as an entry point; another name requires explicit integration. |
--org <addr> | Assembly origin. The default $4000 is where MON-3 expects user code; --org $6000 moves the generated .org line and everything after it. |
--no-check | Generate only; the register-contract check is skipped. Generation-only runs print Wrote demo.main.asm without the check note. |
--deps | Print the dependency report and exit. Nothing is written. |
-V, --version | Print the installed Glimmer package version. |
-h, --help | The usage text above. |
--no-check applies to the default command. Combining it with build stops immediately:
build always runs the AZM check; --no-check is not supported with build.--deps prints one stanza per cell, writers above readers:
program Demo
DotX : state byte
raised by: MoveRight
triggers: DrawDot (render)
Right : pulse
raised by: key KEY_6 (held)
triggers: MoveRight (logic)The four artifacts
A build of demo.glim leaves four files beside the source:
| File | Holds |
|---|---|
demo.main.asm | The generated assembly program: your block bodies wrapped in the runtime (loop, dispatch, change flags, profile library) as one readable file. The other three files are derived from this one. |
demo.main.hex | The assembled bytes as Intel HEX records, the transfer format for loading onto hardware. |
demo.main.bin | The same bytes as a raw binary image, starting at the origin. |
demo.main.d8.json | The Debug80 map: address segments attributed to source files, the symbol table (DotX, Glim_MoveRight, every label with its address), and a generator record naming the assembler version and inputs. |
The map's file list names both sources: demo.main.asm for the generated glue and demo.glim for the block bodies. The eleven "block segments" in the build message are the address ranges that point back into the .glim file.
Debug80 targets
Debug80 finds Glimmer programs two ways.
By convention. A file named main.glim, or ending in .main.glim, whose first declaration is program, is discovered as a target. The Run action makes Debug80 build it through Glimmer and launch the result. Part files open directly with declarations (effect, state), so the program check keeps them out of the target list.
By explicit entry. A debug80.json target names any .glim file directly by pointing sourceFile at it. The Glimmer repository project file carries this entry for Tetro, trimmed here to the shape that matters:
{
"targets": {
"tetro-glim": {
"outputDir": "build",
"platform": "tec1g",
"profile": "mon3",
"sourceFile": "examples/tetro.glim",
"artifactBase": "tetro",
"sourceRoots": ["examples"]
}
}
}sourceFile ending in .glim is what routes the build through Glimmer; the artifacts land in outputDir under artifactBase names. The full entry in the repository adds a tec1g section mapping the memory regions (ROM to $07FF, RAM to $7FFF, ROM from $C000) and the $4000 application start.
Debugger source mapping
The rewritten map splits the program along the begin/end boundary:
| Code | Steps in |
|---|---|
Block bodies (begin to end) | The .glim file. Breakpoints on body lines resolve; stepping walks your source line by line. |
| Generated glue (dispatch, wrappers, timers, profile library) | The .main.asm file. Stepping into a call FbPlot or past an end drops into readable generated assembly. |
Build errors follow the same split. A bad instruction inside a body is reported against the .glim line it sits on, at column precision:
badbody.glim:17:5: [AZMN_PARSE] error: inc expects one operandLine 17 is the inc a,b inside the block body in the source file, so the diagnostic points directly to the edit.
Diagnostics
Diagnostics can come from two stages. A [GLIM] compiler error stops before Glimmer writes new generated artifacts. An [AZMN] assembler error occurs after Glimmer has written the new .main.asm, but before HEX, binary and debug-map output is produced. Artifacts from an earlier successful build may still remain on disk. Warnings print and the build continues.
Duplicate name. Two declarations named Score (states, pulses and blocks all draw from one pool of names):
dup.glim:7: [GLIM] error: Duplicate name "Score": all declared names share one namespace.Reserved name. A state named GlimScore collides with the generated runtime's namespace:
reserved.glim:6: [GLIM] error: Reserved name "GlimScore": it belongs to the generated runtime (states cannot use Glim*/Snd_*/Curve_*/Shape_*/CHG_* or runtime symbols).Undeclared cell. A block triggers on Points with no Points anywhere in the program, a typo for Score, reported at the header:
undeclared.glim:8: [GLIM] error: Effect DrawScore triggers on undeclared cell "Points".Render with updates. A render block declares updates Score, claiming a write that the phase forbids:
renderupd.glim:8: [GLIM] error: render DrawScore cannot update state cells: render blocks depict state. Use effect or compute.Missing program declaration. A file of declarations with no program line at the top; the message carries the file alone, since the gap has no line to point at:
noprog.glim: [GLIM] error: Missing program declaration.Missing updates (warning). An effect stores to Score while its header declares no updates Score. The build finishes (both Wrote lines follow the warning) and the program runs with the consequence the message spells out:
warn.glim:12: [GLIM] warning: AddPoint writes Score but does not declare "updates Score": the change flag will not be raised and dependent blocks will not run.
Wrote warn.main.asm (register contracts checked by AZM)
Wrote warn.main.d8.json (4 block segments attributed to .glim source)In a running program, the store still executes and the cell changes in memory, but the change flag stays down, and a block runs only when its flag rises.