Please take another look at issue #43 since you have implemented some of the missing language features detailed there after it was opened. Re-test the example programs and update the bug report with the latest status on coverage. Thanks.
I'll start by fetching the issue details and then re-test the example programs mentioned in it.
title: Course examples: unimplemented features preventing transpilation state: OPEN author: associate-1 labels: comments: 0 assignees: projects: milestone: number: 43 -- ## Summary Transpiling the 16 example programs in `kroc/modules/course/examples/` reveals that 11 out of 16 fail to parse due to unimplemented language features. Only `hello_world.occ`, `hello_seq_world.occ`, `hello_raw_world.occ`, `echoing.occ`, and `double_echo.occ` transpile successfully. This is a tracking issue for the full set of missing features discovered. Some have their own dedicated issues. ## Unimplemented Features ### Standard occam features | Feature | Description | Affected files | Issue | |---------|-------------|----------------|-------| | `INLINE FUNCTION` | Function qualifier `INT INLINE FUNCTION f(...)` | `bar.occ` | #44 | | `ALT` replicators | `ALT i = 0 FOR n` (like SEQ/PAR/IF replicators) | `sort_pump.occ`, `sort_pump_2.occ`, `sort_inside.occ`, `sort_inside_2.occ`, `bar.occ` | #45 | | `INT16`/`INT32`/`INT64` | Extended integer width types | `cast.occ`, `casting.occ`, `commstime.occ` | #46 | | `tim ? AFTER expr` | Timer AFTER input (wait until time) | `bar.occ`, `demo.occ`, `sort_inside_2.occ` | | | `PRI ALT` | Prioritised alternation | `bar.occ` | | | Guarded ALT (`&`) | `(condition) & chan ? x` boolean pre-conditions | `bar.occ` | | | Multi-value `CASE` labels | `'*n', '*c'` comma-separated case values | `test_bell.occ` | | | `[][]TYPE` / `[][n]TYPE` | Multi-dimensional array declarations | `bar.occ`, `test_utils.occ` | | | Dotted protocol tags | `bar.blank`, `bar.terminate` in PROTOCOL CASE | `bar.occ` | | | `*"` string escape | Escaped quote character inside string literals | `test_utils.occ` | | ### occam-pi extensions | Feature | Description | Affected files | Issue | |---------|-------------|----------------|-------| | `SHARED CHAN` / `CLAIM` | Shared channels and exclusive access blocks | `bar.occ` | #40 | | `MOBILE` types | Dynamically allocated mobile data | `demo.occ` | #40 | ## Error distribution by file | File | Root causes | |------|-------------| | `bar.occ` | INLINE, PRI ALT, ALT replicator, AFTER, SHARED/CLAIM, guarded ALT, multi-dim arrays, dotted protocol tags | | `cast.occ` | INT16/INT32/INT64 | | `casting.occ` | INT16/INT32/INT64 | | `commstime.occ` | INT64 | | `demo.occ` | AFTER, MOBILE | | `sort_inside.occ` | ALT replicator, multi-dim arrays | | `sort_inside_2.occ` | ALT replicator, AFTER | | `sort_pump.occ` | ALT replicator | | `sort_pump_2.occ` | ALT replicator | | `test_bell.occ` | Multi-value CASE labels | | `test_utils.occ` | Multi-dim arrays, string escape |
ls /home/david/projects/code-associates/occam2go/kroc/modules/course/examples/
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
for f in kroc/modules/course/examples/*.occ; do echo "=== $(basename $f) ==="; ./occam2go -I kroc/modules/course/libsrc -D TARGET.BITS.PER.WORD=32 -o /tmp/test_$(basename $f .occ).go "$f" 2>&1; if [ $? -eq 0 ]; then echo "TRANSPILE: OK"; go vet /tmp/test_$(basename $f .occ).go 2>&1; if [ $? -eq 0 ]; then echo "GO VET: OK"; else echo "GO VET: FAIL"; fi; else echo "TRANSPILE: FAIL"; fi; echo ""; done
=== bar.occ === Parse errors: kroc/modules/course/examples/bar.occ:77: expected variant tag name, got : kroc/modules/course/examples/bar.occ:77: unexpected token: : kroc/modules/course/examples/bar.occ:77: unexpected token in expression: ] kroc/modules/course/examples/bar.occ:77: expected ], got BYTE kroc/modules/course/examples/bar.occ:77: expected IDENT, got NEWLINE kroc/modules/course/examples/bar.occ:78: unexpected token: ; kroc/modules/course/examples/bar.occ:78: expected IDENT, got NEWLINE kroc/modules/course/examples/bar.occ:79: unexpected token: ; kroc/modules/course/examples/bar.occ:79: expected IDENT, got NEWLINE kroc/modules/course/examples/bar.occ:80: unexpected token: ; kroc/modules/course/examples/bar.occ:80: expected IDENT, got NEWLINE kroc/modules/course/examples/bar.occ:81: unexpected token: ; kroc/modules/course/examples/bar.occ:81: expected IDENT, got NEWLINE kroc/modules/course/examples/bar.occ:86: unexpected token: : kroc/modules/course/examples/bar.occ:109: expected type after VAL, got [ kroc/modules/course/examples/bar.occ:109: unexpected token: ] kroc/modules/course/examples/bar.occ:110: expected type after VAL, got [ kroc/modules/course/examples/bar.occ:110: unexpected token: ] kroc/modules/course/examples/bar.occ:111: expected type after VAL, got [ kroc/modules/course/examples/bar.occ:111: unexpected token: ] kroc/modules/course/examples/bar.occ:118: expected type in parameter, got IDENT kroc/modules/course/examples/bar.occ:118: expected ), got CHAN kroc/modules/course/examples/bar.occ:118: expected :, got ! kroc/modules/course/examples/bar.occ:118: unexpected token: ! kroc/modules/course/examples/bar.occ:118: unexpected token: ) kroc/modules/course/examples/bar.occ:123: unexpected token in expression: NEWLINE kroc/modules/course/examples/bar.occ:124: unexpected token: ; kroc/modules/course/examples/bar.occ:124: unexpected token: INT kroc/modules/course/examples/bar.occ:125: unexpected token: : kroc/modules/course/examples/bar.occ:125: unexpected token: : kroc/modules/course/examples/bar.occ:128: unexpected token: ; kroc/modules/course/examples/bar.occ:128: expected :, got NEWLINE kroc/modules/course/examples/bar.occ:129: unexpected token: : kroc/modules/course/examples/bar.occ:129: unexpected token: : kroc/modules/course/examples/bar.occ:130: unexpected token: ; kroc/modules/course/examples/bar.occ:130: unexpected token: ( kroc/modules/course/examples/bar.occ:130: expected :, got ) kroc/modules/course/examples/bar.occ:130: unexpected token: ) kroc/modules/course/examples/bar.occ:130: unexpected token: + kroc/modules/course/examples/bar.occ:131: unexpected token: : kroc/modules/course/examples/bar.occ:131: unexpected token: : kroc/modules/course/examples/bar.occ:132: unexpected token: ; kroc/modules/course/examples/bar.occ:133: unexpected token: : kroc/modules/course/examples/bar.occ:133: unexpected token: : kroc/modules/course/examples/bar.occ:134: unexpected token: : kroc/modules/course/examples/bar.occ:138: expected ), got CHAN kroc/modules/course/examples/bar.occ:138: expected :, got ! kroc/modules/course/examples/bar.occ:138: unexpected token: ! kroc/modules/course/examples/bar.occ:138: unexpected token: ) kroc/modules/course/examples/bar.occ:156: unexpected token in expression: NEWLINE kroc/modules/course/examples/bar.occ:157: unexpected token: ; kroc/modules/course/examples/bar.occ:171: unexpected token in expression: NEWLINE kroc/modules/course/examples/bar.occ:172: unexpected token: ; kroc/modules/course/examples/bar.occ:176: expected IDENT, got AFTER kroc/modules/course/examples/bar.occ:176: unexpected token: AFTER kroc/modules/course/examples/bar.occ:176: unexpected token: ( kroc/modules/course/examples/bar.occ:176: unexpected token: PLUS kroc/modules/course/examples/bar.occ:176: unexpected token: ) kroc/modules/course/examples/bar.occ:182: unexpected token in expression: NEWLINE kroc/modules/course/examples/bar.occ:183: unexpected token: ; kroc/modules/course/examples/bar.occ:186: unexpected token: ; kroc/modules/course/examples/bar.occ:189: expected IDENT, got AFTER kroc/modules/course/examples/bar.occ:189: unexpected token: AFTER kroc/modules/course/examples/bar.occ:189: unexpected token: ( kroc/modules/course/examples/bar.occ:189: unexpected token: PLUS kroc/modules/course/examples/bar.occ:189: unexpected token: ) kroc/modules/course/examples/bar.occ:194: unexpected token in expression: NEWLINE kroc/modules/course/examples/bar.occ:195: unexpected token: ; kroc/modules/course/examples/bar.occ:212: unexpected token in expression: NEWLINE kroc/modules/course/examples/bar.occ:213: unexpected token: ; kroc/modules/course/examples/bar.occ:218: unexpected token in expression: NEWLINE kroc/modules/course/examples/bar.occ:219: unexpected token: ; kroc/modules/course/examples/bar.occ:222: unexpected token: ; kroc/modules/course/examples/bar.occ:225: expected IDENT, got AFTER kroc/modules/course/examples/bar.occ:225: unexpected token: AFTER kroc/modules/course/examples/bar.occ:225: unexpected token: ( kroc/modules/course/examples/bar.occ:225: unexpected token: PLUS kroc/modules/course/examples/bar.occ:225: unexpected token: ) kroc/modules/course/examples/bar.occ:228: unexpected token: : kroc/modules/course/examples/bar.occ:232: expected ), got CHAN kroc/modules/course/examples/bar.occ:232: expected :, got ! kroc/modules/course/examples/bar.occ:232: unexpected token: ! kroc/modules/course/examples/bar.occ:232: unexpected token: , kroc/modules/course/examples/bar.occ:233: expected :, got ! kroc/modules/course/examples/bar.occ:233: unexpected token: ! kroc/modules/course/examples/bar.occ:233: unexpected token: , kroc/modules/course/examples/bar.occ:233: unexpected token in expression: ) kroc/modules/course/examples/bar.occ:252: unexpected token in expression: NEWLINE kroc/modules/course/examples/bar.occ:254: unexpected token: : kroc/modules/course/examples/bar.occ:267: expected variant tag name, got BYTE kroc/modules/course/examples/bar.occ:267: expected variant tag name, got , kroc/modules/course/examples/bar.occ:267: expected variant tag name, got : kroc/modules/course/examples/bar.occ:270: expected variant tag name, got INT kroc/modules/course/examples/bar.occ:270: expected variant tag name, got : kroc/modules/course/examples/bar.occ:271: expected variant tag name, got : kroc/modules/course/examples/bar.occ:271: expected variant tag name, got : kroc/modules/course/examples/bar.occ:273: expected variant tag name, got INT kroc/modules/course/examples/bar.occ:273: expected variant tag name, got : kroc/modules/course/examples/bar.occ:278: expected variant tag name, got INT kroc/modules/course/examples/bar.occ:278: expected variant tag name, got : kroc/modules/course/examples/bar.occ:283: expected variant tag name, got INT kroc/modules/course/examples/bar.occ:283: expected variant tag name, got : kroc/modules/course/examples/bar.occ:288: expected variant tag name, got INT kroc/modules/course/examples/bar.occ:288: expected variant tag name, got : kroc/modules/course/examples/bar.occ:327: expected & after guard in ALT case kroc/modules/course/examples/bar.occ:338: expected & after guard in ALT case kroc/modules/course/examples/bar.occ:352: expected & after guard in ALT case kroc/modules/course/examples/bar.occ:363: expected ), got CHAN kroc/modules/course/examples/bar.occ:363: expected :, got ! kroc/modules/course/examples/bar.occ:363: unexpected token: ! kroc/modules/course/examples/bar.occ:363: unexpected token: , kroc/modules/course/examples/bar.occ:364: expected :, got ? kroc/modules/course/examples/bar.occ:364: unexpected token: ? kroc/modules/course/examples/bar.occ:364: unexpected token: ) kroc/modules/course/examples/bar.occ:373: expected IDENT, got AFTER kroc/modules/course/examples/bar.occ:373: unexpected token: AFTER kroc/modules/course/examples/bar.occ:373: unexpected token: ( kroc/modules/course/examples/bar.occ:373: unexpected token: PLUS kroc/modules/course/examples/bar.occ:373: unexpected token: ) kroc/modules/course/examples/bar.occ:375: unexpected token in expression: NEWLINE kroc/modules/course/examples/bar.occ:376: unexpected token: ; kroc/modules/course/examples/bar.occ:378: unexpected token: ; kroc/modules/course/examples/bar.occ:389: unexpected token in expression: NEWLINE kroc/modules/course/examples/bar.occ:390: unexpected token: ; kroc/modules/course/examples/bar.occ:399: expected channel name or guard in ALT case, got ( kroc/modules/course/examples/bar.occ:399: unexpected token: NOT kroc/modules/course/examples/bar.occ:399: unexpected token: ) kroc/modules/course/examples/bar.occ:399: unexpected token: & kroc/modules/course/examples/bar.occ:399: expected IDENT, got AFTER kroc/modules/course/examples/bar.occ:399: unexpected token: AFTER kroc/modules/course/examples/bar.occ:402: unexpected token: & kroc/modules/course/examples/bar.occ:423: unexpected token: : kroc/modules/course/examples/bar.occ:428: expected ), got CHAN kroc/modules/course/examples/bar.occ:428: expected :, got ! kroc/modules/course/examples/bar.occ:428: unexpected token: ! kroc/modules/course/examples/bar.occ:428: unexpected token: , kroc/modules/course/examples/bar.occ:428: expected :, got ? kroc/modules/course/examples/bar.occ:428: unexpected token: ? kroc/modules/course/examples/bar.occ:428: unexpected token: ) kroc/modules/course/examples/bar.occ:441: unexpected token: : kroc/modules/course/examples/bar.occ:471: unexpected token in expression: CHAN kroc/modules/course/examples/bar.occ:471: unexpected token: : TRANSPILE: FAIL === cast.occ === TRANSPILE: OK # command-line-arguments # [command-line-arguments] vet: /tmp/test_cast.go:2694:12: cannot convert a (variable of type bool) to type byte GO VET: FAIL === casting.occ === TRANSPILE: OK # command-line-arguments # [command-line-arguments] vet: /tmp/test_casting.go:2694:12: cannot convert a (variable of type bool) to type byte GO VET: FAIL === commstime.occ === TRANSPILE: OK GO VET: OK === demo.occ === Parse errors: kroc/modules/course/examples/demo.occ:16: expected IDENT, got AFTER kroc/modules/course/examples/demo.occ:16: unexpected token: AFTER kroc/modules/course/examples/demo.occ:16: unexpected token: PLUS kroc/modules/course/examples/demo.occ:27: expected type after INITIAL, got IDENT kroc/modules/course/examples/demo.occ:27: unexpected token in expression: ] kroc/modules/course/examples/demo.occ:27: expected ], got INT kroc/modules/course/examples/demo.occ:27: expected ], got ? kroc/modules/course/examples/demo.occ:27: expected :, got ? kroc/modules/course/examples/demo.occ:27: unexpected token: ? kroc/modules/course/examples/demo.occ:27: unexpected token: ] kroc/modules/course/examples/demo.occ:27: expected IDENT, got : kroc/modules/course/examples/demo.occ:27: unexpected token: : kroc/modules/course/examples/demo.occ:35: expected type after array size, got NEWLINE TRANSPILE: FAIL === double_echo.occ === TRANSPILE: OK GO VET: OK === echoing.occ === TRANSPILE: OK GO VET: OK === hello_raw_world.occ === TRANSPILE: OK GO VET: OK === hello_seq_world.occ === TRANSPILE: OK GO VET: OK === hello_world.occ === TRANSPILE: OK GO VET: OK === sort_inside.occ === Parse errors: kroc/modules/course/examples/sort_inside.occ:309: expected type after array size, got NEWLINE kroc/modules/course/examples/sort_inside.occ:333: expected type after array size, got NEWLINE kroc/modules/course/examples/sort_inside.occ:336: expected type after array size, got NEWLINE TRANSPILE: FAIL === sort_inside_2.occ === Parse errors: kroc/modules/course/examples/sort_inside_2.occ:294: expected indented block after ALT kroc/modules/course/examples/sort_inside_2.occ:294: unexpected token: ? kroc/modules/course/examples/sort_inside_2.occ:323: expected IDENT, got AFTER kroc/modules/course/examples/sort_inside_2.occ:323: unexpected token: AFTER kroc/modules/course/examples/sort_inside_2.occ:323: unexpected token: PLUS TRANSPILE: FAIL === sort_pump.occ === TRANSPILE: OK # command-line-arguments # [command-line-arguments] vet: /tmp/test_sort_pump.go:2845:7: cannot use first_col (variable of type int) as byte value in assignment GO VET: FAIL === sort_pump_2.occ === TRANSPILE: OK # command-line-arguments # [command-line-arguments] vet: /tmp/test_sort_pump_2.go:2845:7: cannot use first_col (variable of type int) as byte value in assignment GO VET: FAIL === test_bell.occ === Parse errors: kroc/modules/course/examples/test_bell.occ:39: unexpected token: , kroc/modules/course/examples/test_bell.occ:39: unexpected token: BYTE_LIT kroc/modules/course/examples/test_bell.occ:41: unexpected token: ELSE kroc/modules/course/examples/test_bell.occ:77: unexpected token: , kroc/modules/course/examples/test_bell.occ:77: unexpected token: BYTE_LIT kroc/modules/course/examples/test_bell.occ:79: unexpected token: ELSE TRANSPILE: FAIL === test_utils.occ === Parse errors: kroc/modules/course/examples/test_utils.occ:19: expected type after VAL, got [ kroc/modules/course/examples/test_utils.occ:19: unexpected token: INT kroc/modules/course/examples/test_utils.occ:19: unexpected token: ] kroc/modules/course/examples/test_utils.occ:75: expected ), got STRING kroc/modules/course/examples/test_utils.occ:75: unexpected token: STRING kroc/modules/course/examples/test_utils.occ:75: unexpected token: * kroc/modules/course/examples/test_utils.occ:75: unexpected token: STRING kroc/modules/course/examples/test_utils.occ:75: unexpected token: , kroc/modules/course/examples/test_utils.occ:75: unexpected token: INT kroc/modules/course/examples/test_utils.occ:75: unexpected token: , kroc/modules/course/examples/test_utils.occ:75: unexpected token in expression: ) TRANSPILE: FAIL
Let me summarize the results:
Previously passing (5): hello_world, hello_seq_world, hello_raw_world, echoing, double_echo
Now also transpiling (but some with go vet issues):
- commstime.occ — TRANSPILE: OK, GO VET: OK ✅ (was failing due to INT64)
- cast.occ — TRANSPILE: OK, GO VET: FAIL (BOOL→BYTE conversion issue)
- casting.occ — TRANSPILE: OK, GO VET: FAIL (BOOL→BYTE conversion issue)
sort_pump.occ — TRANSPILE: OK, GO VET: FAIL (INT→BYTE assignment issue)sort_pump_2.occ — TRANSPILE: OK, GO VET: FAIL (INT→BYTE assignment issue)Still failing to transpile (6): bar.occ has multiple blockers including PRI ALT, SHARED/CLAIM, dotted protocol tags, and multi-dimensional arrays. Demo.occ needs AFTER and MOBILE support, while sort_inside.occ and sort_inside_2 require multi-dimensional array handling.
Let me recount the actual passing status: six files transpile and pass go vet (hello_world, hello_seq_world, hello_raw_world, echoing, double_echo, commstime), four more transpile but fail vet checks due to type assignment issues, and six still can't transpile at all.
The progress is clear — implementing INLINE FUNCTION, ALT replicators, and the integer type variants unlocked ten out of sixteen files to at least transpile, up from five. Now I need to dig into what's blocking the remaining six, particularly that ALT replicator parse error in sort_inside_2 and the type conversion failures in the vet-failing files.
Good, I can see significant progress. Let me examine the specific failures more closely to categorize them accurately.
{
"file_path": "/home/david/projects/code-associates/occam2go/kroc/modules/course/examples/sort_inside_2.occ",
"offset": 290,
"limit": 10
} 290→
291→--{{{ PROC report.plex ([]CHAN BYTE monitor?, CHAN BYTE out!)
292→PROC report.plex.2 ([]CHAN BYTE monitor?, CHAN BYTE out!)
293→ WHILE TRUE
294→ ALT i = 0 FOR SIZE monitor?
295→ BYTE next, largest:
296→ monitor[i] ? next
297→ SEQ
298→ monitor[i] ? largest
299→ cursor.x.y (3 + ((BYTE i)*5), 3, out!){
"file_path": "/home/david/projects/code-associates/occam2go/kroc/modules/course/examples/sort_inside.occ",
"offset": 305,
"limit": 10
} 305→ --{{{ fill buffer
306→ SEQ
307→ SEQ i = 0 FOR nn
308→ in ? buffer[i]
309→ ptr := 0
310→ --}}}
311→ --}}}
312→ --{{{ main cycle
313→ WHILE TRUE
314→ BYTE x:{
"file_path": "/home/david/projects/code-associates/occam2go/kroc/modules/course/examples/demo.occ",
"offset": 13,
"limit": 25
} 13→ INT t:
14→ SEQ
15→ tim ? t
16→ tim ? AFTER t PLUS delay
17→:
18→
19→
20→--* This merges an array of INT input streams to a single text output stream.
21→--* It tabulates one number from each stream across one line of output.
22→--* Then, it pauses for delay microseconds. It repeats this for ever.
23→--*
24→--* @param delay : the length of the pause (in microseconds)
25→--*
26→PROC print.streams (VAL INT delay, []CHAN INT in?, CHAN BYTE out!)
27→ INITIAL MOBILE []INT n IS MOBILE [SIZE in?]INT:
28→ -- Above is the rather complex way we have to declare an array whose size
29→ -- in not known until runtime. This will be made simple in future versions
30→ -- of occam-pi.
31→ WHILE TRUE
32→ SEQ
33→ PAR i = 0 FOR SIZE n
34→ in[i] ? n[i]
35→ SEQ i = 0 FOR SIZE n
36→ out.int (n[i], 15, out!) -- out.int is from "course.lib"
37→ out.string ("*c*n", 0, out!) -- out.string is from "course.lib"{
"file_path": "/home/david/projects/code-associates/occam2go/kroc/modules/course/examples/test_bell.occ",
"offset": 35,
"limit": 10
} 35→ screen ! 'b'
36→ screen ! BELL
37→ screen ! FLUSH -- the 'b' and the effect of the BELL,
38→ -- if any, happens now!
39→ '*n', '*c'
40→ again := FALSE
41→ ELSE
42→ SKIP
43→ out.string ("*c*n", 0, screen!)
44→{
"file_path": "/home/david/projects/code-associates/occam2go/kroc/modules/course/examples/sort_inside.occ",
"offset": 300,
"limit": 15
} 300→ (n < 0)
301→ nn := 0
302→ (TRUE)
303→ nn := n
304→ --}}}
305→ --{{{ fill buffer
306→ SEQ
307→ SEQ i = 0 FOR nn
308→ in ? buffer[i]
309→ ptr := 0
310→ --}}}
311→ --}}}
312→ --{{{ main cycle
313→ WHILE TRUE
314→ BYTE x:{
"file_path": "/home/david/projects/code-associates/occam2go/kroc/modules/course/examples/test_utils.occ",
"offset": 16,
"limit": 8
} 16→ out.string ("*c*n", 0, screen!)
17→ --}}}
18→ --{{{ test screen
19→ VAL [][2]BYTE coord IS [[41, 11], [20, 5], [30, 15], [3, 16], [12, 20],
20→ [58, 7], [6, 9], [54, 18], [45, 1], [5, 3]]:
21→ VAL INT X IS 0:
22→ VAL INT Y IS 1:
23→ SEQ{
"file_path": "/home/david/projects/code-associates/occam2go/kroc/modules/course/examples/test_utils.occ",
"offset": 72,
"limit": 8
} 72→ out.string ("String (up to 10 characters)? ", 0, screen!)
73→ flush (screen!)
74→ in.string (s, length, 10, keyboard?, screen!)
75→ out.string ("*c*n --> *"", 0, screen!)
76→ out.string ([s FOR length], 0, screen!)
77→ out.string ("*" (", 0, screen!)
78→ out.int (length, 0, screen!)
79→ out.string (" characters)*c*nAgain (yes/no)? ", 0, screen!)Now let me check the sort_inside.occ error more carefully. The error is "expected type after array size" at line 309. Let me look at what ptr is:
Looking at line 309: ptr := 0 — this looks like a simple assignment, not a declaration. Let me look at the broader context to see what ptr is.
Actually wait, looking at the error messages again:
- sort_inside.occ:309: expected type after array size, got NEWLINE
But line 309 is ptr := 0 which is an assignment. Let me look for multi-dim arrays in the file.
I need to find where these multi-dimensional arrays are declared in the file.
{
"pattern": "\\]\\[|\\]\\]",
"path": "/home/david/projects/code-associates/occam2go/kroc/modules/course/examples/sort_inside.occ",
"output_mode": "content"
}{
"pattern": "SIZE monitor\\?",
"path": "/home/david/projects/code-associates/occam2go/kroc/modules/course/examples/sort_inside_2.occ",
"output_mode": "content"
}{
"pattern": "\\[\\d+\\]\\[",
"path": "/home/david/projects/code-associates/occam2go/kroc/modules/course/examples/sort_inside.occ",
"output_mode": "content"
}{
"pattern": "\\]BYTE",
"path": "/home/david/projects/code-associates/occam2go/kroc/modules/course/examples/sort_inside.occ",
"output_mode": "content"
}Ah, so sort_inside.occ uses expression-sized arrays like [max.delay]BYTE buffer: where max.delay is not a literal but an expression/identifier. The parser expects a literal number for array sizes. Let me check line 291 more closely.
Actually wait, let me re-read the error:
sort_inside.occ:309: expected type after array size, got NEWLINE
sort_inside.occ:333: expected type after array size, got NEWLINE
sort_inside.occ:336: expected type after array size, got NEWLINE
Line 309 is ptr := 0. That doesn't match... unless the line numbers are off due to preprocessing. Let me check if this file uses #INCLUDE.
The transpiler is pulling in the course module through the include path, so those line numbers might be pointing to the expanded source after includes are processed. I should try removing the include path to see what the actual errors are in the original file.
./occam2go -o /tmp/test.go kroc/modules/course/examples/sort_inside.occ 2>&1 | head -10
./occam2go -I kroc/modules/course/libsrc -D TARGET.BITS.PER.WORD=32 -o /tmp/test.go kroc/modules/course/examples/sort_inside.occ 2>&1
Exit code 1 Parse errors: kroc/modules/course/examples/sort_inside.occ:309: expected type after array size, got NEWLINE kroc/modules/course/examples/sort_inside.occ:333: expected type after array size, got NEWLINE kroc/modules/course/examples/sort_inside.occ:336: expected type after array size, got NEWLINE Parse errors: kroc/modules/course/examples/sort_inside.occ:309: expected type after array size, got NEWLINE kroc/modules/course/examples/sort_inside.occ:333: expected type after array size, got NEWLINE kroc/modules/course/examples/sort_inside.occ:336: expected type after array size, got NEWLINE
{
"file_path": "/home/david/projects/code-associates/occam2go/kroc/modules/course/examples/sort_inside.occ",
"offset": 287,
"limit": 5
}{
"file_path": "/home/david/projects/code-associates/occam2go/kroc/modules/course/examples/sort_inside.occ",
"offset": 323,
"limit": 5
} 323→
324→--{{{ PROC report.plex ([]CHAN BYTE monitor?, CHAN BYTE out!)
325→PROC report.plex ([]CHAN BYTE monitor?, CHAN BYTE out!)
326→ [total - 1]BYTE next, largest:
327→ WHILE TRUE{
"file_path": "/home/david/projects/code-associates/occam2go/kroc/modules/course/examples/sort_inside.occ",
"offset": 330,
"limit": 10
} 330→ PAR i = 0 FOR total - 1
331→ SEQ
332→ monitor[i] ? next[i]
333→ monitor[i] ? largest[i]
334→ --}}}
335→ --{{{ forward message (sequentially)
336→ SEQ
337→ cursor.x.y (3, 3, out!)
338→ SEQ i = 0 FOR total - 1
339→ SEQSo sort_inside.occ uses:
- [max.delay]BYTE buffer: — expression-sized array where max.delay is a constant expression (not a literal number)
- [total - 1]BYTE next, largest: — expression-sized array with arithmetic
These are variable-length array declarations using expressions as sizes. The parser currently only handles literal integer sizes for arrays.
This is NOT multi-dimensional arrays. It's expression-sized arrays (arrays whose size is a non-literal expression).
Now let me also check sort_inside_2.occ — the error is about SIZE monitor? in ALT i = 0 FOR SIZE monitor?.
The ? suffix is a direction annotation on the channel variable. Let me examine the sort_pump.occ and sort_pump_2.occ errors more carefully.
grep -n "first_col" /tmp/test_sort_pump.go | head -5
grep -n "cannot convert a" /tmp/test_cast.go 2>/dev/null; sed -n '2690,2700p' /tmp/test_cast.go
2840: first_col := 1
2841: _ = first_col
2845: xx = first_col
2856: } else if (xx > first_col) {
2857: xx = first_col_ = r32 var r64 float64 _ = r64 a = true b = (byte(a) + 42) i16 = int16(b) i32 = int32(i16) i = int(i32) i64 = int64(i) r32 = float32(ROUND) i16()
2838→ last_line := 23
2839→ _ = last_line
2840→ first_col := 1
2841→ _ = first_col
2842→ var xx, yy byte
2843→ _ = xx
2844→ _ = yy
2845→ xx = first_col
2846→ yy = first_line
2847→ for true {
2848→ var ch byte
2849→ _ = ch
2850→ ch = <-in
2851→ if (ch != end_marker) {
2852→ cursor_x_y(xx, yy, out)
2853→ out <- ch
2854→ out <- end_message
2855→ xx = (xx + 1)
2856→ } else if (xx > first_col) {
2857→ xx = first_col2688→ _ = i 2689→ var r32 float32 2690→ _ = r32 2691→ var r64 float64 2692→ _ = r64 2693→ a = true 2694→ b = (byte(a) + 42) 2695→ i16 = int16(b) 2696→ i32 = int32(i16) 2697→ i = int(i32) 2698→ i64 = int64(i) 2699→ r32 = float32(ROUND) 2700→ i16() 2701→ r32 = float32(TRUNC) 2702→ i16()
Now I have a clear picture. Let me summarize the current status:
Transpile OK + go vet OK (6 files, up from 5):
1. hello_world.occ — OK (unchanged)
2. hello_seq_world.occ — OK (unchanged)
3. hello_raw_world.occ — OK (unchanged)
4. echoing.occ — OK (unchanged)
5. double_echo.occ — OK (unchanged)
6. commstime.occ — NEW (was blocked by INT64, now fixed)
cast.occ — Transpiles now but fails go vet on bool-to-byte casting, and ROUND/TRUNC need proper implementation instead of function callscasting.occ — Same casting and rounding issues as cast.occsort_pump.occ — Transpiles now but has implicit INT-to-BYTE assignment problemssort_pump_2.occ — Mirrors the assignment type mismatch from sort_pump.occFor the remaining failures, I'm seeing a pattern of more complex language features: bar.occ has multiple blocking constructs and protocol issues, demo.occ needs AFTER and MOBILE support, and the sort_inside files require expression-sized arrays and channel introspection. The test files are hitting multi-value case labels and multi-dimensional array syntax that aren't yet handled.
Looking at the overall progress, I've gone from 5 files fully working to 6, and now have 4 that transpile but fail vetting due to codegen issues. The key wins were adding INLINE FUNCTION, ALT replicators, and the integer type variants — that pushed transpilation success from 5 to 10 files. I should update the issue with this breakdown and correct the categorization for sort_inside.occ, which is actually blocked by expression-sized arrays rather than multi-dim arrays as originally noted.
Now I have a complete picture of the current status. Let me also check the sort_pump.occ source to understand the type mismatch.
{
"pattern": "first.col|first_col",
"path": "/home/david/projects/code-associates/occam2go/kroc/modules/course/examples/sort_pump.occ",
"output_mode": "content"
}250: VAL BYTE first.col IS 1: 255: xx := first.col 272: xx > first.col 275: xx := first.col
{
"file_path": "/home/david/projects/code-associates/occam2go/kroc/modules/course/examples/cast.occ",
"offset": 1,
"limit": 80
} 1→#INCLUDE "course.module"
2→
3→PROC cast.occ (CHAN BYTE keyboard?, screen!, error!)
4→
5→ --{{{ COMMENT documentation
6→ -->
7→ --> Infix operators in occam demand the same type (i.e. base type and
8→ --> precision) for both its operands. Assignment, communication and
9→ --> parameter passing are equally strict: the type and precision of the
10→ --> variable (or parameter) receiving the data (or argument) must match
11→ --> what is being supplied. THERE IS NO AUTOMATIC CASTING BETWEEN TYPES.
12→ -->
13→ --> Hence:
14→ -->
15→ --> INT a:
16→ --> REAL32 x:
17→ --> SEQ
18→ --> a := 42 -- this line is OK
19→ --> x := 42.0 -- this line is OK
20→ --> x := 42 -- this line will not compile
21→ --> a := x -- this line will not compile
22→ --> x := a -- this line will not compile
23→ --> x := 2*x -- this line will not compile
24→ --> x := 2.0*x -- this line is OK
25→ -->
26→ --> CASTING BETWEEN TYPES AND PRECISIONS MUST BE EXPLICITLY SPECIFIED.
27→ -->
28→ --> We can cast any primitive type to any other primitive by using
29→ --> the target type name as a prefix operator. For those casts that may
30→ --> lose precision, we must say how the least significant bit is to be
31→ --> resolved (wither by ROUNDing or TRUNCation). This is done by qualifying
32→ --> the type-name-prefix-operator with either ROUND or TRUNC.
33→ -->
34→ --}}}
35→
36→ BOOL a:
37→ BYTE b:
38→ INT16 i16:
39→ INT32 i32:
40→ INT64 i64:
41→ INT i:
42→ REAL32 r32:
43→ REAL64 r64:
44→
45→ SEQ
46→
47→ a := TRUE
48→
49→ b := (BYTE a) + 42
50→ i16 := INT16 b
51→ i32 := INT32 i16
52→ i := INT i32
53→ i64 := INT64 i
54→ r32 := REAL32 ROUND i16 -- rounds least significant bit to nearest
55→ r32 := REAL32 TRUNC i16 -- rounds least significant bit towards zero
56→ r32 := REAL32 ROUND i -- rounds least significant bit to nearest
57→ r32 := REAL32 TRUNC i -- rounds least significant bit towards zero
58→ r64 := REAL64 r32 -- no need for rounding
59→
60→ r32 := REAL32 ROUND r64 -- rounds least significant bit to nearest
61→ r32 := REAL32 TRUNC r64 -- rounds least significant bit towards zero
62→ i64 := INT64 ROUND r32 -- rounds to nearest whole number
63→ i64 := INT64 TRUNC r32 -- rounds towards zero
64→ i := INT i64
65→ i32 := INT32 ROUND r64 -- rounds to nearest whole number
66→ i32 := INT32 TRUNC r64 -- rounds towards zero
67→ i16 := INT16 i
68→ b := BYTE i16
69→ a := BOOL (b - 42)
70→
71→ IF
72→ a
73→ out.string ("OK!*c*n", 0, screen!)
74→ NOT a
75→ out.string ("ERROR!*c*n", 0, screen!)
76→
77→ --{{{ COMMENT Warning
78→ -->
79→ --> Warning: if the result of an attempted cast lies outside the legal
80→ --> range of values for the target type, there will be a run-time error:Now I see the full picture for cast.occ. The issues are:
1. BYTE a where a is BOOL — Go doesn't allow byte(bool_val). Need to convert BOOL→BYTE as func() byte { if a { return 1 } return 0 }() or similar.
2. REAL32 ROUND i16 and REAL32 TRUNC i16 — ROUND/TRUNC qualifiers on type conversions aren't implemented. They're being generated as separate function calls.
3. BOOL (b - 42) — BOOL type conversion isn't implemented.
sort_pump.occ, the abbreviation VAL BYTE first.col IS 1: needs explicit type annotation so Go doesn't infer it as int instead of byte.sort_inside_2.occ, the ALT replicator SIZE monitor? has a direction annotation on the channel that the parser might not be handling correctly.Let me look more closely at that second issue. The parser is failing when it encounters the ? after monitor in the SIZE expression, treating it as an unexpected token rather than part of a direction-annotated identifier. The SIZE operator needs to properly parse direction annotations on channel names.
gh issue comment 43 --body "$(cat <<'EOF' ## Status Update (2026-02-22) Since this issue was opened, three features have been implemented: - **`INLINE FUNCTION`** (#44, closed) - **`ALT` replicators** (#45, closed) - **`INT16`/`INT32`/`INT64`** (#46, closed) ### Current results: 10/16 transpile, 6/16 pass `go vet` | File | Transpile | `go vet` | Remaining blockers | |------|-----------|----------|--------------------| | `hello_world.occ` | OK | OK | — | | `hello_seq_world.occ` | OK | OK | — | | `hello_raw_world.occ` | OK | OK | — | | `echoing.occ` | OK | OK | — | | `double_echo.occ` | OK | OK | — | | `commstime.occ` | **OK** | **OK** | — *(was blocked by INT64)* | | `cast.occ` | **OK** | FAIL | BOOL↔BYTE type conversion (`byte(bool)` invalid in Go); `ROUND`/`TRUNC` qualifiers on type casts | | `casting.occ` | **OK** | FAIL | Same as `cast.occ` | | `sort_pump.occ` | **OK** | FAIL | `VAL BYTE x IS 1:` abbreviation inferred as `int` instead of `byte`, causing INT→BYTE assignment error | | `sort_pump_2.occ` | **OK** | FAIL | Same as `sort_pump.occ` | | `bar.occ` | FAIL | — | PRI ALT, SHARED/CLAIM, dotted protocol tags, `tim ? AFTER`, multi-dim arrays, guarded ALT with boolean expressions | | `demo.occ` | FAIL | — | `tim ? AFTER`, `MOBILE` types | | `sort_inside.occ` | FAIL | — | Expression-sized arrays (`[max.delay]BYTE`, `[total - 1]BYTE`) — *not* multi-dim arrays as originally reported | | `sort_inside_2.occ` | FAIL | — | `SIZE` of direction-annotated channel name (`SIZE monitor?`), `tim ? AFTER` | | `test_bell.occ` | FAIL | — | Multi-value `CASE` labels (`'*n', '*c'`) | | `test_utils.occ` | FAIL | — | Multi-dim arrays (`[][2]BYTE`), `*"` string escape | ### Summary of changes since original report - **Files now fully working:** `commstime.occ` (1 new, 6 total) - **Files now transpiling but with codegen bugs:** `cast.occ`, `casting.occ`, `sort_pump.occ`, `sort_pump_2.occ` (4 new) - **Files still failing to parse:** 6 (down from 11) ### Corrections to original error distribution - **`sort_inside.occ`**: Root cause is **expression-sized arrays** (`[expr]TYPE`), not multi-dim arrays or ALT replicators. ALT replicators are now implemented and are not used in this file. - **`sort_inside_2.occ`**: ALT replicator itself works, but `SIZE monitor?` (SIZE of a direction-annotated channel param) fails to parse. Also blocked by `tim ? AFTER`. ### New codegen bugs discovered 1. **BOOL↔BYTE conversion**: Go does not allow `byte(boolVal)`. Needs a conditional expression or helper. Also `BOOL(expr)` type conversion is unhandled. 2. **ROUND/TRUNC qualifiers**: `REAL32 ROUND expr` and `INT64 TRUNC expr` are not implemented — the qualifier is currently parsed as a separate function call. 3. **Typed abbreviation inference**: `VAL BYTE first.col IS 1:` generates `first_col := 1` (inferred as `int`), should generate `var first_col byte = 1` to preserve the declared type. ### Remaining unimplemented features (updated) | Feature | Affected files | |---------|---------------| | `tim ? AFTER expr` | `bar.occ`, `demo.occ`, `sort_inside_2.occ` | | `PRI ALT` | `bar.occ` | | Guarded ALT with boolean expr `(cond) & chan ? x` | `bar.occ` | | `SHARED CHAN` / `CLAIM` | `bar.occ` | | `MOBILE` types | `demo.occ` | | Multi-value `CASE` labels | `test_bell.occ` | | Multi-dim arrays (`[][n]TYPE`) | `bar.occ`, `test_utils.occ` | | Expression-sized arrays (`[expr]TYPE`) | `sort_inside.occ` | | Dotted protocol tags | `bar.occ` | | `*"` string escape | `test_utils.occ` | | `SIZE` of direction-annotated name | `sort_inside_2.occ` | | `ROUND`/`TRUNC` cast qualifiers | `cast.occ`, `casting.occ` | | BOOL↔BYTE type conversions | `cast.occ`, `casting.occ` | | Typed abbreviation type preservation | `sort_pump.occ`, `sort_pump_2.occ` | EOF )"
Done. Here's the summary of the updated status:
Progress: 5/16 → 10/16 transpile, 5/16 → 6/16 fully pass go vet
Three previously-implemented features made the difference:
- INT16/INT32/INT64 → unblocked commstime.occ (fully working), cast.occ, casting.occ
- ALT replicators → unblocked sort_pump.occ, sort_pump_2.occ
- INLINE FUNCTION → contributed to unblocking bar.occ (still blocked by other features)
4 files now transpile but hit codegen bugs: BOOL↔BYTE conversions, missing ROUND/TRUNC qualifiers, and typed abbreviation inference losing the declared type.
I also corrected the original issue's diagnosis — sort_inside.occ is blocked by expression-sized arrays ([max.delay]BYTE), not multi-dim arrays or ALT replicators as originally reported.
Thank you. Very interesting. Could you please open new issues for the codegen problems you have discovered?
The user wants me to open new issues for the three codegen bugs discovered during the re-test. Let me create them.
byte(boolVal) is invalid in GoVAL BYTE x IS 1: loses the declared typeLet me create all three issues.
gh issue create --title "Codegen: BOOL↔BYTE type conversions produce invalid Go" --body "$(cat <<'EOF'
## Summary
`BYTE expr` where `expr` is a `BOOL`, and `BOOL expr` where `expr` is a numeric type, produce Go code that doesn't compile. Go does not allow direct conversion between `bool` and integer types.
## Reproduction
From `cast.occ`:
```occam
BOOL a:
BYTE b:
SEQ
a := TRUE
b := (BYTE a) + 42 -- BOOL → BYTE
...
a := BOOL (b - 42) -- BYTE → BOOL
```
Generated Go:
```go
b = (byte(a) + 42) // error: cannot convert a (variable of type bool) to type byte
a = bool(b - 42) // error: cannot convert to bool
```
## Expected codegen
BOOL → BYTE:
```go
// one possible approach
func boolToByte(b bool) byte { if b { return 1 }; return 0 }
b = (boolToByte(a) + 42)
```
BYTE → BOOL:
```go
a = ((b - 42) != 0)
```
## Affected files
- `cast.occ`
- `casting.occ`
Discovered during re-test of #43.
EOF
)"gh issue create --title "Codegen: ROUND/TRUNC qualifiers on type casts not implemented" --body "$(cat <<'EOF' ## Summary Occam type casts that require rounding qualification (`REAL32 ROUND expr`, `INT64 TRUNC expr`) are not implemented. The qualifier is currently misinterpreted, producing invalid Go output. ## Reproduction From `cast.occ`: ```occam INT16 i16: INT i: REAL32 r32: REAL64 r64: SEQ r32 := REAL32 ROUND i16 -- rounds least significant bit to nearest r32 := REAL32 TRUNC i16 -- rounds least significant bit towards zero r32 := REAL32 ROUND i -- rounds least significant bit to nearest i64 := INT64 ROUND r32 -- rounds to nearest whole number i64 := INT64 TRUNC r32 -- rounds towards zero i32 := INT32 ROUND r64 i32 := INT32 TRUNC r64 r64 := REAL64 r32 -- no qualifier needed (no precision loss) r32 := REAL32 ROUND r64 -- qualifier needed (precision loss) ``` Currently generates something like: ```go r32 = float32(ROUND) i16() ``` ## Expected codegen For integer → float (ROUND vs TRUNC is irrelevant since integers map exactly to the mantissa range being tested here): ```go r32 = float32(i16) ``` For float → integer: ```go i64 = int64(math.Round(float64(r32))) // ROUND: nearest i64 = int64(r32) // TRUNC: towards zero (Go default) ``` For float → float (precision loss): ```go r32 = float32(r64) // TRUNC: Go default truncation // ROUND would need: float32 with round-to-nearest semantics ``` ## Affected files - `cast.occ` - `casting.occ` Discovered during re-test of #43. EOF )"
gh issue create --title "Codegen: typed abbreviations lose declared type" --body "$(cat <<'EOF' ## Summary When a \`VAL\` abbreviation has an explicit type, the generated Go code uses \`:=\` (short variable declaration) which infers the type from the literal value. This causes type mismatches when the abbreviation is later assigned to a variable of the declared type. ## Reproduction From \`sort_pump.occ\`: ```occam VAL BYTE first.col IS 1: BYTE xx: SEQ xx := first.col ``` Generated Go: ```go first_col := 1 // inferred as int var xx byte xx = first_col // error: cannot use first_col (variable of type int) as byte value in assignment ``` ## Expected codegen ```go var first_col byte = 1 // preserve the declared BYTE type var xx byte xx = first_col // OK: both are byte ``` The abbreviation generator should use \`var name type = expr\` instead of \`name := expr\` when the abbreviation has an explicit type that differs from Go's default inference. ## Affected files - \`sort_pump.occ\` - \`sort_pump_2.occ\` Discovered during re-test of #43. EOF )"
Created three new issues:
cast.occ, casting.occ)cast.occ, casting.occ)sort_pump.occ, sort_pump_2.occ)