Implement the following plan:
Plan: Support ALT Replicators (Issue #45)
Context
The transpiler supports replicated SEQ, PAR, and IF but not replicated ALT (ALT i = 0 FOR n). This blocks 5 out of 16 course example files. The replicated ALT dynamically creates N channel alternatives and selects whichever is ready first. Since Go's select requires statically-known cases, the codegen must use reflect.Select for runtime-variable case counts.
Changes
1. AST (ast/ast.go)
Add Replicator field to AltBlock and Declarations field to AltCase:
type AltBlock struct {
Token lexer.Token
Cases []AltCase
Replicator *Replicator // NEW: optional ALT i = start FOR count
}
type AltCase struct {
// ... existing fields ...
Declarations []Statement // NEW: scoped declarations before channel input (e.g., BYTE ch:)
}
The Declarations field is needed because replicated ALT cases commonly have scoped variable declarations before the channel input (e.g., BYTE ch: / VAL INT X IS (j \ s):).
2. Parser (parser/parser.go)
parseAltBlock() (~line 1568): Add replicator detection after consuming ALT token, using the same pattern as parseSeqBlock()/parseParBlock()/parseIfStatement():
// Check for replicator: ALT i = start FOR count
if p.peekTokenIs(lexer.IDENT) {
// Save state, peek ahead for =
p.nextToken()
if p.peekTokenIs(lexer.EQ) {
block.Replicator = p.parseReplicator()
} else {
// Not a replicator — error (ALT doesn't take bare IDENT after keyword)
p.addError("unexpected identifier after ALT")
}
}
parseAltCase() (~line 1640): Handle scoped declarations before the channel input. When the current token is a type keyword (INT_TYPE, BYTE_TYPE, etc.) or VAL or LBRACKET (for array decls), parse it as a declaration and store in altCase.Declarations. Loop until we hit an identifier that starts a channel input.
3. Codegen (codegen/codegen.go)
Generator struct: Add needReflect bool field.
Import scanning (~line 106): Add containsAltReplicator() scanner that walks the AST checking for AltBlock nodes with non-nil Replicator. Set g.needReflect = true.
Import block (~line 204): Add "reflect" to import list when needReflect is true.
generateAltBlock() (~line 1604): When alt.Replicator != nil, generate reflect.Select code:
// Generated pattern for: ALT i = 0 FOR n / BYTE ch: / in[i] ? ch / body
{
_count := <count>
_cases := make([]reflect.SelectCase, _count)
for _i := 0; _i < _count; _i++ {
_cases[_i] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(in[_i])}
}
_chosen, _value, _ := reflect.Select(_cases)
i := <start> + _chosen
var ch byte // from scoped declaration
ch = _value.Interface().(byte) // type from declaration
// ... body ...
}
Key details:
- Build reflect.SelectCase slice with Dir: reflect.SelectRecv and Chan: reflect.ValueOf(channelArray[index])
- The start expression is added to _chosen to compute the replicator variable
- Scoped declarations are generated as local var statements
- The receive variable is assigned from _value.Interface().(goType) where goType comes from occamTypeToGo() on the declaration type
- STEP support: use counter-based pattern like PAR replicator
- Handle scoped abbreviations (like VAL INT X IS (j \ s):) by generating them after the replicator variable is set
4. Tests
Parser test (parser/parser_test.go): Test that ALT i = 0 FOR n parses correctly with replicator, scoped declarations, indexed channel input, and body.
E2e test (codegen/e2e_test.go or codegen/e2e_replicator_test.go): Test replicated ALT with channel arrays — spawn N goroutines sending on channels, use replicated ALT to receive, verify correct value received.
5. Documentation (TODO.md, CLAUDE.md)
Update to reflect ALT replicator support.
Verification
go test ./... # all tests pass
go test ./parser -run TestAlt # parser tests for replicated ALT
go test ./codegen -run TestE2E # e2e tests including replicated ALT
# Real-world validation:
./occam2go -I kroc/modules/course/libsrc -D TARGET.BITS.PER.WORD=32 \
-o /tmp/sort_pump.go kroc/modules/course/examples/sort_pump.occ
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/1826a3f0-b019-499a-abc6-72315cb03f4c.jsonl