Implement the following plan:
Plan: Add source file tracking to parser error messages (Issue #41)
Context
Parser error messages currently show line numbers relative to the preprocessed (expanded) source. When #INCLUDE pulls in a large library like course.module, errors say "line 4335" even though the user's source file is small. This makes errors very hard to diagnose. We need to map expanded line numbers back to original file:line pairs.
Approach
Build a source map in the preprocessor during expansion, then use it in main.go to translate error line numbers before display. This is the least invasive approach — no changes to lexer, parser, or AST.
Changes
1. preproc/preproc.go — Build source map during expansion
- Add
SourceLoc struct: {File string, Line int}
- Add
sourceMap []SourceLoc field to Preprocessor
- Add
SourceMap() []SourceLoc getter method
- Pass filename through
processSource (new parameter) and ProcessFile
ProcessSource passes "<input>" as the filename (no file context)
- For each output line produced, append a
SourceLoc{filename, originalLine} entry
- For
#INCLUDE lines: the recursive ProcessFile → processSource call populates entries for included content; the current line does NOT get an entry
- For directives that emit blank lines (
#DEFINE, #IF, #ELSE, #ENDIF, #COMMENT, etc.): append {filename, lineNum}
- For skipped lines (inactive condStack): append
{filename, lineNum}
- For regular source lines: append
{filename, lineNum}
- Source map is 0-indexed (entry 0 = expanded line 1)
2. main.go — Translate error line numbers using source map
- After parsing, if there are errors, get
pp.SourceMap()
- For each error string matching
"line NNN: ...", look up NNN in the source map
- Replace with
"filename:line: ..." format (standard compiler error format)
- If the file is the top-level input file, can show just
"filename:line:" or the full path
- If lookup fails (out of bounds), fall through to original message
3. preproc/preproc_test.go — Test source map
- Test that
ProcessFile with #INCLUDE produces correct source map entries
- Test that non-included file maps lines 1:1
- Test that
ProcessSource uses "<input>" as filename
Files to modify
preproc/preproc.go — add SourceLoc, sourceMap field, pass filename, build map
main.go — translate error messages using source map
preproc/preproc_test.go — add source map tests
Verification
go test ./... # all tests pass
# Manual test with course module:
./occam2go -I kroc/modules/course/libsrc -D TARGET.BITS.PER.WORD=32 -o test.go kroc/modules/course/examples/test_utils.occ
# Error messages should now show filename:line instead of just line NNN
If you need specific details from before exiting plan mode (like exact code snippets, error messages, or content you generated), read the full transcript at: /home/david/.claude/projects/-home-david-projects-code-associates-occam2go/0d8c6c7b-51c0-4085-94aa-867d3704a672.jsonl