title: Course module example doesn't transpile
state: OPEN
author: dboreham
labels:
comments: 0
assignees:
projects:
milestone:
number: 35
--
The commands shown in the readme section "Running Programs with the Course Module" (https://github.com/codeassociates/occam2go/blob/main/README.md#running-programs-with-the-course-module) don't seem to work.
For example, I get this:
```
$ ./occam2go -I kroc/modules/course/libsrc \
-D TARGET.BITS.PER.WORD=32 \
-o hello_world.go kroc/modules/course/examples/hello_world.occ
Preprocessor error: line 1: cannot find included file "course.module"
```
Digging into the code a little, I'm not sure how this can work because the example program references a file "course.module" in this line: https://github.com/codeassociates/occam2go/blob/main/examples/course_hello.occ#L16 and the command specifies an include path: kroc/modules/course/libsrc but there's no module file on that path. Is there a missing step where the module file is created?{
"subagent_type": "Explore",
"prompt": "I need to understand GitHub issue #35 about the course module example not transpiling. The issue is that `#INCLUDE \"course.module\"` fails because there's no `course.module` file at the include path.\n\nPlease investigate:\n\n1. Look at the README.md section about \"Running Programs with the Course Module\" to see the documented commands\n2. Check what example files exist in `examples/` related to course module usage\n3. Check if `course.module` exists anywhere in the repo (especially `kroc/modules/course/libsrc/`)\n4. Look at how `#INCLUDE` resolution works in `preproc/preproc.go`\n5. Check if there's a `gen-module` subcommand that might need to be run first to generate the `.module` file\n6. Look at `modgen/modgen.go` to understand what gen-module does\n7. Check if there's a SConscript file that would be used to generate the module file\n\nProvide a thorough summary of the issue and what the fix should be."
}[
{
"type": "text",
"text": "Interesting! There's a bug - the gen-module command is printing the output even when `-o` is specified. But more importantly, let me now summarize my findings:\n\nBased on my thorough investigation, I can now provide you with a comprehensive analysis of issue #35.\n\n## Summary: GitHub Issue #35 - Course Module Example Not Transpiling\n\n### Issue Description\nThe `examples/course_hello.occ` file attempts to include `course.module`:\n\n```occam\n#INCLUDE \"course.module\"\n\nPROC hello (CHAN BYTE keyboard?, screen!, error!)\n ...\n```\n\nHowever, **there is no `course.module` file in the `examples/` directory**, causing the transpilation to fail with:\n```\nPreprocessor error: line 16: cannot find included file \"course.module\"\n```\n\n### Root Cause Analysis\n\n1. **Missing file in examples/**: The `examples/` directory contains `course_hello.occ` and `mathlib.module`, but NOT `course.module`\n\n2. **File exists elsewhere**: The `course.module` file DOES exist at `/home/david/projects/code-associates/occam2go/kroc/modules/course/libsrc/course.module`\n\n3. **Documentation requirements**: The README correctly documents that you must use `-I kroc/modules/course/libsrc` to resolve the include, but this is not obvious from the `examples/course_hello.occ` file alone\n\n4. **Include resolution logic** (from `preproc/preproc.go:236-255`):\n - First searches relative to the current file's directory\n - Then searches each include path specified with `-I`\n - Returns empty string if file not found in any location\n\n### Why This Is a Problem\n\nA user following the example in `examples/course_hello.occ` might try:\n```bash\n./occam2go examples/course_hello.occ # ❌ FAILS\n```\n\nInstead of:\n```bash\n./occam2go -I kroc/modules/course/libsrc examples/course_hello.occ # ✓ WORKS\n```\n\n### What Should Be Fixed\n\nThere are several possible solutions:\n\n**Option 1 (Simplest): Generate and commit `course.module` in `examples/`**\n- Run: `./occam2go gen-module kroc/modules/course/libsrc/SConscript -o examples/course.module`\n- This would allow `examples/course_hello.occ` to transpile without `-I` flags\n- However, the generated `.module` file still has `#INCLUDE` directives that need `-I kroc/modules/course/libsrc` to resolve (consts.inc, utils.occ, etc.)\n- This is not a complete solution!\n\n**Option 2 (Better): Copy all course module source files to `examples/`**\n- Place `consts.inc`, `utils.occ`, `string.occ`, `demo_cycles.occ`, `demo_nets.occ`, `file_in.occ`, `float_io.occ`, `random.occ` in examples/\n- Also place `course.module`\n- This makes the example truly self-contained\n- Downside: Duplicates large amounts of code\n\n**Option 3 (Recommended): Update `examples/course_hello.occ` comment with correct command**\n- The file already has a comment at the top showing the correct command to run\n- Ensure the comment is visible and accurate (it already is!)\n- This is currently the best approach since the README already documents this\n\n**Option 4: Create a simplified course module for examples**\n- Create `examples/course.module` that includes from the correct path\n- E.g., `#INCLUDE \"../kroc/modules/course/libsrc/consts.inc\"`\n- This allows relative path traversal in includes\n\n### Secondary Issue Found\n\nWhile testing `gen-module`, I discovered a **bug**: when using `-o` flag, the command still prints output to stdout in addition to writing the file. Check `main.go:162-169` - the output is printed before the file is written.\n\n### Recommended Fix\n\n**For Issue #35**: The real fix is **Option 4** — create a symlink or a generated `course.module` file in `examples/` that uses relative paths to the real course module source files. This way:\n\n1. Users can transpile `examples/course_hello.occ` without flags\n2. The actual library code isn't duplicated\n3. It's clear that the example depends on the kroc subtree\n\nAlternatively, the simplest fix is to **commit `examples/course.module`** with relative includes:\n\n```occam\n#IF NOT (DEFINED (COURSE.MODULE))\n#DEFINE COURSE.MODULE\n#INCLUDE \"../kroc/modules/course/libsrc/consts.inc\"\n#INCLUDE \"../kroc/modules/course/libsrc/utils.occ\"\n#INCLUDE \"../kroc/modules/course/libsrc/string.occ\"\n#INCLUDE \"../kroc/modules/course/libsrc/demo_cycles.occ\"\n#INCLUDE \"../kroc/modules/course/libsrc/demo_nets.occ\"\n#INCLUDE \"../kroc/modules/course/libsrc/file_in.occ\"\n#INCLUDE \"../kroc/modules/course/libsrc/float_io.occ\"\n#INCLUDE \"../kroc/modules/course/libsrc/random.occ\"\n#ENDIF\n```\n\nThis would:\n- Allow `./occam2go examples/course_hello.occ` to work\n- Not require `-I` flags\n- Not duplicate code\n- Make the example self-documenting regarding its dependency structure"
},
{
"type": "text",
"text": "agentId: a93b5fcd9a9e309c3 (for resuming to continue this agent's work if needed)\n<usage>total_tokens: 46237\ntool_uses: 31\nduration_ms: 94784</usage>"
}
]The investigation is thorough. Let me summarize the issue for the user.
The core problem is:
1. The README documents commands for running course module examples
2. examples/course_hello.occ includes #INCLUDE "course.module"
3. There's no course.module in examples/ directory
4. The actual course.module exists at kroc/modules/course/libsrc/course.module
5. Users need to pass -I kroc/modules/course/libsrc but this isn't obvious
The issue reporter is right - there seems to be a missing step. Let me also check the README to see exactly what commands are documented and verify the current state.
Here's a summary of issue #35:
The README's "Running Programs with the Course Module" section documents commands like:
./occam2go -I kroc/modules/course/libsrc \
-D TARGET.BITS.PER.WORD=32 \
-o hello_world.go kroc/modules/course/examples/hello_world.occ
But this fails because hello_world.occ does #INCLUDE "course.module", and there's no course.module file in the example's directory. The file does exist at kroc/modules/course/libsrc/course.module, so -I kroc/modules/course/libsrc should make it findable by the preprocessor.
Let me verify this quickly to see if the include path resolution is actually the issue or if the example file path is wrong.
Makefile.am README.txt README_kroc.txt SConscript bar.occ cast.occ casting.occ commstime.occ configure.ac demo.occ double_echo.occ echoing.occ hello_raw_world.occ hello_seq_world.occ hello_world.occ sort_inside.occ sort_inside_2.occ sort_pump.occ sort_pump_2.occ test_bell.occ test_utils.occ
ls kroc/modules/course/libsrc/course.module 2>&1
#INCLUDE "course.module"
PROC hello.world (CHAN BYTE keyboard?, screen!, error!)
--{{{
out.string ("Hello World*c*n", 0, screen!)./occam2go -I kroc/modules/course/libsrc -D TARGET.BITS.PER.WORD=32 -o /tmp/hello_world.go kroc/modules/course/examples/hello_world.occ 2>&1
Interesting — the command actually works for me. Let me check what the issue reporter might have been doing differently.
-- Hello World example using the KRoC course module.
--
-- This demonstrates the standard occam entry point pattern:
-- a PROC with three CHAN BYTE parameters (keyboard, screen, error)
-- wired to stdin, stdout, and stderr by the generated main() harness.
--
-- The course module provides utility PROCs such as out.string, out.int,
-- and out.repeat for character-level I/O on byte channels.
--
-- To transpile and run:
-- ./occam2go -I kroc/modules/course/libsrc \
-- -D TARGET.BITS.PER.WORD=32 \
-- -o hello.go examples/course_hello.occ
-- go run hello.go
#INCLUDE "course.module"
PROC hello (CHAN BYTE keyboard?, screen!, error!)
SEQ
out.string ("Hello from occam2go!*c*n", 0, screen!)./occam2go -I kroc/modules/course/libsrc -D TARGET.BITS.PER.WORD=32 -o /tmp/course_hello.go examples/course_hello.occ 2>&1
{
"pattern": "Running Programs with the Course Module",
"path": "README.md",
"output_mode": "content",
"-A": 40
}432:### Running Programs with the Course Module
433-
434-The KRoC [course module](https://github.com/concurrency/kroc/tree/master/modules/course) is a standard occam library providing I/O utilities (`out.string`, `out.int`, `out.repeat`, etc.) for character-level communication over byte channels. The transpiler fully supports it.
435-
436-Occam programs that follow the standard entry point pattern — a PROC with three `CHAN BYTE` parameters `(keyboard?, screen!, error!)` — automatically get a generated `main()` that wires stdin, stdout, and stderr to channels.
437-
438-```bash
439-# 1. Clone the KRoC repository (one-time setup)
440-./scripts/clone-kroc.sh
441-
442-# 2. Build the transpiler
443-go build -o occam2go
444-
445-# 3. Transpile an example that uses the course module
446-./occam2go -I kroc/modules/course/libsrc \
447- -D TARGET.BITS.PER.WORD=32 \
448- -o hello.go examples/course_hello.occ
449-
450-# 4. Run it
451-go run hello.go
452-```
453-
454-Output:
455-```
456-Hello from occam2go!
457-The answer is: 42
458-------------------------------
459-Counting: 1, 2, 3, 4, 5
460-```
461-
462-The `-I` flag tells the preprocessor where to find the course module source files, and `-D TARGET.BITS.PER.WORD=32` sets the word size expected by the course module (the transpiler defaults to 64).
463-
464-The example program (`examples/course_hello.occ`):
465-```occam
466-#INCLUDE "course.module"
467-
468-PROC hello (CHAN BYTE keyboard?, screen!, error!)
469- SEQ
470- out.string ("Hello from occam2go!*c*n", 0, screen!)
471- out.string ("The answer is: ", 0, screen!)
472- out.int (42, 0, screen!)Both commands work fine. The issue reporter seems to have been trying kroc/modules/course/examples/hello_world.occ — let me check if that specific path also works (it did above). Let me re-read the issue more carefully.
The reporter says they get:
Preprocessor error: line 1: cannot find included file "course.module"
The line 1 is key — examples/course_hello.occ has the #INCLUDE on line 16, and kroc/modules/course/examples/hello_world.occ has it on line 1. So they were trying to transpile hello_world.occ from the KRoC examples. Let me check if the kroc/ directory might not be present for them.
ls scripts/clone-kroc.sh 2>&1 && head -20 scripts/clone-kroc.sh
scripts/clone-kroc.sh
#!/bin/bash
# Clone the KRoC (Kent Retargetable occam Compiler) repository.
# This provides the occam "course" standard library source code
# needed for transpiling programs that use it.
set -e
REPO_URL="https://github.com/concurrency/kroc.git"
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
TARGET_DIR="$PROJECT_DIR/kroc"
if [ -d "$TARGET_DIR" ]; then
echo "kroc/ already exists. To re-clone, remove it first:"
echo " rm -rf $TARGET_DIR"
exit 1
fi
echo "Cloning KRoC repository into kroc/..."
git clone "$REPO_URL" "$TARGET_DIR"cat .gitignore 2>/dev/null | head -20; echo "---"; git ls-files kroc/ 2>/dev/null | head -5
# Binaries occam2go *.exe *.exe~ *.dll *.so *.dylib # Test binaries *.test # Output of go coverage *.out # Go workspace file go.work # Dependency directories vendor/ ---
Now I have the full picture. Here's my analysis of issue #35:
The reporter ran the README command and got cannot find included file "course.module". The error says line 1, which matches kroc/modules/course/examples/hello_world.occ (has #INCLUDE on line 1), not examples/course_hello.occ (line 16).
The commands do work when the kroc/ directory is present — I just verified both the README example and the KRoC hello_world.occ transpile successfully with -I kroc/modules/course/libsrc.
The most likely cause is that the reporter didn't run ./scripts/clone-kroc.sh first. The kroc/ directory is not checked into the repo (not in .gitignore either, but it's a separate git clone). Without it, there's no course.module file to find.
Documentation clarity — The README does show ./scripts/clone-kroc.sh as step 1, but the section title "Running Programs with the Course Module" might lead people to skip straight to the transpile command. Making the dependency on the clone step more prominent would help.
Better error message — The preprocessor could suggest checking include paths or running the clone script when a .module file isn't found.
Add kroc/ to .gitignore — Since it's a cloned external repo, it should probably be in .gitignore for cleanliness (it currently isn't).
Would you like me to work on any of these fixes?
gh issue comment 35 --body "$(cat <<'EOF' I investigated this and the documented commands do work correctly when the `kroc/` directory is present. I verified both `examples/course_hello.occ` and `kroc/modules/course/examples/hello_world.occ` transpile successfully with `-I kroc/modules/course/libsrc`. The error message says `line 1`, which matches `kroc/modules/course/examples/hello_world.occ` (has `#INCLUDE` on line 1). The most likely cause is that `./scripts/clone-kroc.sh` wasn't run first — the `kroc/` directory is a separate git clone that isn't checked into this repo, so without running that script there's no `course.module` file to find. The README does show the clone script as step 1 in the "Running Programs with the Course Module" section, but it's easy to skip past. Some possible improvements: 1. **Documentation clarity** — Make the dependency on the clone step more prominent (e.g., a note/warning box) 2. **Better error message** — The preprocessor could suggest checking include paths or running the clone script when a `.module` file isn't found 3. **Add `kroc/` to `.gitignore`** — It's a cloned external repo but isn't currently gitignored EOF )"
Comment posted: https://github.com/codeassociates/occam2go/issues/35#issuecomment-3941244850
Thank you. Can you re-check the issue to see if there have been any comments in response to yours?
author: associate-1 association: member edited: false status: none -- I investigated this and the documented commands do work correctly when the `kroc/` directory is present. I verified both `examples/course_hello.occ` and `kroc/modules/course/examples/hello_world.occ` transpile successfully with `-I kroc/modules/course/libsrc`. The error message says `line 1`, which matches `kroc/modules/course/examples/hello_world.occ` (has `#INCLUDE` on line 1). The most likely cause is that `./scripts/clone-kroc.sh` wasn't run first — the `kroc/` directory is a separate git clone that isn't checked into this repo, so without running that script there's no `course.module` file to find. The README does show the clone script as step 1 in the "Running Programs with the Course Module" section, but it's easy to skip past. Some possible improvements: 1. **Documentation clarity** — Make the dependency on the clone step more prominent (e.g., a note/warning box) 2. **Better error message** — The preprocessor could suggest checking include paths or running the clone script when a `.module` file isn't found 3. **Add `kroc/` to `.gitignore`** — It's a cloned external repo but isn't currently gitignored -- author: dboreham association: member edited: false status: none -- Hmm, interesting. I don't have the course.module file at that directory in kroc. You can see in the github repo that file is not present: https://github.com/concurrency/kroc/tree/master/modules/course/libsrc Is it possible the file is present for you because it has been generated locally at some point in the past? --
There's a response from @dboreham. They point out that course.module isn't actually in the upstream KRoC repo at that path — you can see it's not listed at https://github.com/concurrency/kroc/tree/master/modules/course/libsrc. They're suggesting the file may be present locally because it was generated at some point.
They're likely right. The gen-module subcommand generates .module files from SConscript files, and there is a SConscript in that directory. Let me verify.
ls -la kroc/modules/course/libsrc/course.module && git -C kroc log --oneline -1 -- modules/course/libsrc/course.module 2>&1; echo "---"; head -20 kroc/modules/course/libsrc/course.module
-rw-r--r-- 1 david david 249 Feb 18 22:12 kroc/modules/course/libsrc/course.module --- #IF NOT (DEFINED (COURSE.MODULE)) #DEFINE COURSE.MODULE #INCLUDE "consts.inc" #INCLUDE "utils.occ" #INCLUDE "string.occ" #INCLUDE "demo_cycles.occ" #INCLUDE "demo_nets.occ" #INCLUDE "file_in.occ" #INCLUDE "float_io.occ" #INCLUDE "random.occ" #ENDIF
git -C kroc status modules/course/libsrc/course.module 2>&1
On branch master Your branch is up to date with 'origin/master'. nothing to commit, working tree clean
git -C kroc log --oneline --all -- modules/course/libsrc/course.module 2>&1
git -C kroc ls-files modules/course/libsrc/course.module 2>&1
Confirmed — course.module is not tracked in the KRoC git repo. It's an untracked local file that must have been generated previously (likely via gen-module). @dboreham is correct.
The README's instructions are missing a step: after cloning KRoC, you need to run gen-module to create the course.module file. Want me to add a follow-up comment on the issue acknowledging this?
gh issue comment 35 --body "$(cat <<'EOF' You're right — `course.module` is not tracked in the KRoC repo. It's an untracked local file that was generated previously via the `gen-module` subcommand. The README instructions are missing this step. After cloning KRoC, you need to generate the module file: ```bash ./occam2go gen-module -o kroc/modules/course/libsrc/course.module kroc/modules/course/libsrc/SConscript ``` I'll put together a fix that adds this step to the README and also adds `kroc/` to `.gitignore`. EOF )"
{
"file_path": "/home/david/projects/code-associates/occam2go/README.md",
"offset": 430,
"limit": 50
} 430→```
431→
432→### Running Programs with the Course Module
433→
434→The KRoC [course module](https://github.com/concurrency/kroc/tree/master/modules/course) is a standard occam library providing I/O utilities (`out.string`, `out.int`, `out.repeat`, etc.) for character-level communication over byte channels. The transpiler fully supports it.
435→
436→Occam programs that follow the standard entry point pattern — a PROC with three `CHAN BYTE` parameters `(keyboard?, screen!, error!)` — automatically get a generated `main()` that wires stdin, stdout, and stderr to channels.
437→
438→```bash
439→# 1. Clone the KRoC repository (one-time setup)
440→./scripts/clone-kroc.sh
441→
442→# 2. Build the transpiler
443→go build -o occam2go
444→
445→# 3. Transpile an example that uses the course module
446→./occam2go -I kroc/modules/course/libsrc \
447→ -D TARGET.BITS.PER.WORD=32 \
448→ -o hello.go examples/course_hello.occ
449→
450→# 4. Run it
451→go run hello.go
452→```
453→
454→Output:
455→```
456→Hello from occam2go!
457→The answer is: 42
458→------------------------------
459→Counting: 1, 2, 3, 4, 5
460→```
461→
462→The `-I` flag tells the preprocessor where to find the course module source files, and `-D TARGET.BITS.PER.WORD=32` sets the word size expected by the course module (the transpiler defaults to 64).
463→
464→The example program (`examples/course_hello.occ`):
465→```occam
466→#INCLUDE "course.module"
467→
468→PROC hello (CHAN BYTE keyboard?, screen!, error!)
469→ SEQ
470→ out.string ("Hello from occam2go!*c*n", 0, screen!)
471→ out.string ("The answer is: ", 0, screen!)
472→ out.int (42, 0, screen!)
473→ out.string ("*c*n", 0, screen!)
474→ out.repeat ('-', 30, screen!)
475→ out.string ("*c*n", 0, screen!)
476→ out.string ("Counting: ", 0, screen!)
477→ SEQ i = 1 FOR 5
478→ SEQ
479→ IF 1→# Binaries
2→occam2go
3→*.exe
4→*.exe~
5→*.dll
6→*.so
7→*.dylib
8→
9→# Test binaries
10→*.test
11→
12→# Output of go coverage
13→*.out
14→
15→# Go workspace file
16→go.work
17→
18→# Dependency directories
19→vendor/
20→
21→# IDE
22→.idea/
23→.vscode/
24→*.swp
25→*.swo
26→
27→# OS
28→.DS_Store
29→Thumbs.db
30→
31→# Generated Go files from examples
32→examples/*.go
33→
34→# External repositories
35→kroc/
36→kroc/ is already in .gitignore (line 35). Just need to add the gen-module step to the README.
# 1. Clone the KRoC repository (one-time setup) ./scripts/clone-kroc.sh # 2. Build the transpiler go build -o occam2go # 3. Transpile an example that uses the course module
# 1. Clone the KRoC repository (one-time setup)
./scripts/clone-kroc.sh
# 2. Build the transpiler
go build -o occam2go
# 3. Generate the course module file from the KRoC SConscript (one-time setup)
./occam2go gen-module -o kroc/modules/course/libsrc/course.module \
kroc/modules/course/libsrc/SConscript
# 4. Transpile an example that uses the course moduleThe file /home/david/projects/code-associates/occam2go/README.md has been updated successfully.
# 4. Run it go run hello.go
# 5. Run it go run hello.go
The file /home/david/projects/code-associates/occam2go/README.md has been updated successfully.
{
"file_path": "/home/david/projects/code-associates/occam2go/README.md",
"offset": 438,
"limit": 20
}438→```bash 439→# 1. Clone the KRoC repository (one-time setup) 440→./scripts/clone-kroc.sh 441→ 442→# 2. Build the transpiler 443→go build -o occam2go 444→ 445→# 3. Generate the course module file from the KRoC SConscript (one-time setup) 446→./occam2go gen-module -o kroc/modules/course/libsrc/course.module \ 447→ kroc/modules/course/libsrc/SConscript 448→ 449→# 4. Transpile an example that uses the course module 450→./occam2go -I kroc/modules/course/libsrc \ 451→ -D TARGET.BITS.PER.WORD=32 \ 452→ -o hello.go examples/course_hello.occ 453→ 454→# 5. Run it 455→go run hello.go 456→``` 457→
Now let me also check if there's a similar section in the CLAUDE.md that documents the course module testing.
177:The KRoC course module (`kroc/modules/course/libsrc/course.module`) is a real-world integration test: 180:# Transpile full course module (including float_io.occ) 181:./occam2go -I kroc/modules/course/libsrc -D TARGET.BITS.PER.WORD=32 -o /tmp/course_out.go kroc/modules/course/libsrc/course.module
The CLAUDE.md section assumes course.module already exists, which is fine — it's developer-facing context. The README fix is the important one.
That looks good. The fix adds step 3 (gen-module) to the README instructions and renumbers the subsequent steps. This is the missing step the issue reporter identified — course.module isn't in the upstream KRoC repo and needs to be generated from the SConscript before transpiling examples that include it.
Want me to commit this and open a PR?
Yes but first would it be possible for you to test the new instructions, as if you were another user reading them?
The user wants me to test the instructions end-to-end as if I were a fresh user. I should simulate following the README steps. Since the kroc/ directory already exists with a potentially stale course.module, I should remove it first to start clean.
Good idea. I'll start from scratch by removing the existing kroc/ directory and the generated course.module, then follow the README steps exactly.
rm -rf /home/david/projects/code-associates/occam2go/kroc
Cloning KRoC repository into kroc/... Cloning into '/home/david/projects/code-associates/occam2go/kroc'... Done.
./occam2go gen-module -o kroc/modules/course/libsrc/course.module kroc/modules/course/libsrc/SConscript
./occam2go -I kroc/modules/course/libsrc -D TARGET.BITS.PER.WORD=32 -o hello.go examples/course_hello.occ
Hello from occam2go! The answer is: 42 ------------------------------ Counting: 1, 2, 3, 4, 5
All 5 steps work end-to-end from a clean state. Output matches the README exactly. Let me clean up the generated file.