Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,12 @@ Six packages, one pipeline:
| `[arr FOR m]` | `arr[0 : m]` (shorthand slice, FROM 0 implied) |
| `[arr FROM n FOR m] := src` | `copy(arr[n:n+m], src)` (slice assignment) |
| Nested `PROC`/`FUNCTION` | `name := func(...) { ... }` (Go closure) |
| `VAL x IS 42:` (untyped) | `var x = 42` (Go type inference) |
| `[1, 2, 3]` (array literal) | `[]int{1, 2, 3}` |
| `VAL INT X RETYPES X :` | `X := int(int32(math.Float32bits(float32(X))))` |
| `VAL [2]INT X RETYPES X :` | `X := []int{lo, hi}` via `math.Float64bits` |
| `CAUSEERROR()` | `panic("CAUSEERROR")` |
| `LONGPROD` / `LONGDIV` etc. | Go helper functions using `uint64`/`math/bits` |

## Key Parser Patterns

Expand Down Expand Up @@ -164,20 +170,20 @@ Typical workflow for a new language construct:

## What's Implemented

Preprocessor (`#IF`/`#ELSE`/`#ENDIF`/`#DEFINE`/`#INCLUDE` with search paths, include guards, include-once deduplication, `#COMMENT`/`#PRAGMA`/`#USE` ignored), module file generation from SConscript (`gen-module` subcommand), SEQ, PAR, IF, WHILE, CASE, ALT (with guards, timer timeouts, and multi-statement bodies with scoped declarations), SKIP, STOP, variable/array/channel/timer declarations, abbreviations (`VAL INT x IS 42:`, `INT y IS z:`, `VAL []BYTE s IS "hi":`), assignments (simple and indexed), channel send/receive, channel arrays (`[n]CHAN OF TYPE` with indexed send/receive and `[]CHAN OF TYPE` proc params), PROC (with VAL, RESULT, reference, CHAN, []CHAN, open array `[]TYPE`, fixed-size array `[n]TYPE`, and shared-type params), channel direction restrictions (`CHAN OF INT c?` → `<-chan int`, `CHAN OF INT c!` → `chan<- int`, call-site annotations `out!`/`in?` accepted), multi-line parameter lists (lexer suppresses INDENT/DEDENT/NEWLINE inside parens), FUNCTION (IS and VALOF forms with multi-statement bodies, including multi-result `INT, INT FUNCTION` with `RESULT a, b`), multi-assignment (`a, b := func(...)` including indexed targets like `x[0], x[1] := x[1], x[0]`), KRoC-style colon terminators on PROC/FUNCTION (optional), replicators on SEQ/PAR/IF (with optional STEP), arithmetic/comparison/logical/AFTER/bitwise operators, type conversions (`INT expr`, `BYTE expr`, `REAL32 expr`, `REAL64 expr`, etc.), REAL32/REAL64 types, hex integer literals (`#FF`, `#80000000`), string literals, byte literals (`'A'`, `'*n'` with occam escape sequences), built-in print procedures, protocols (simple, sequential, and variant), record types (with field access via bracket syntax), SIZE operator, array slices (`[arr FROM n FOR m]` and shorthand `[arr FOR m]` with slice assignment), nested PROCs/FUNCTIONs (local definitions as Go closures), MOSTNEG/MOSTPOS (type min/max constants for INT, BYTE, REAL32, REAL64), INITIAL declarations (`INITIAL INT x IS 42:` — mutable variable with initial value), checked (modular) arithmetic (`PLUS`, `MINUS`, `TIMES` — wrapping operators).
Preprocessor (`#IF`/`#ELSE`/`#ENDIF`/`#DEFINE`/`#INCLUDE` with search paths, include guards, include-once deduplication, `#COMMENT`/`#PRAGMA`/`#USE` ignored), module file generation from SConscript (`gen-module` subcommand), SEQ, PAR, IF, WHILE, CASE, ALT (with guards, timer timeouts, and multi-statement bodies with scoped declarations), SKIP, STOP, variable/array/channel/timer declarations, abbreviations (`VAL INT x IS 42:`, `INT y IS z:`, `VAL []BYTE s IS "hi":`, untyped `VAL x IS expr:`), assignments (simple and indexed), channel send/receive, channel arrays (`[n]CHAN OF TYPE` with indexed send/receive and `[]CHAN OF TYPE` proc params), PROC (with VAL, RESULT, reference, CHAN, []CHAN, open array `[]TYPE`, fixed-size array `[n]TYPE`, and shared-type params), channel direction restrictions (`CHAN OF INT c?` → `<-chan int`, `CHAN OF INT c!` → `chan<- int`, call-site annotations `out!`/`in?` accepted), multi-line parameter lists and expressions (lexer suppresses INDENT/DEDENT/NEWLINE inside parens/brackets and after continuation operators), FUNCTION (IS and VALOF forms with multi-statement bodies, including multi-result `INT, INT FUNCTION` with `RESULT a, b`), multi-assignment (`a, b := func(...)` including indexed targets like `x[0], x[1] := x[1], x[0]`), KRoC-style colon terminators on PROC/FUNCTION (optional), replicators on SEQ/PAR/IF (with optional STEP), arithmetic/comparison/logical/AFTER/bitwise operators, type conversions (`INT expr`, `BYTE expr`, `REAL32 expr`, `REAL64 expr`, etc.), REAL32/REAL64 types, hex integer literals (`#FF`, `#80000000`), string literals, byte literals (`'A'`, `'*n'` with occam escape sequences), built-in print procedures, protocols (simple, sequential, and variant), record types (with field access via bracket syntax), SIZE operator, array slices (`[arr FROM n FOR m]` and shorthand `[arr FOR m]` with slice assignment), array literals (`[1, 2, 3]`), nested PROCs/FUNCTIONs (local definitions as Go closures), MOSTNEG/MOSTPOS (type min/max constants for INT, BYTE, REAL32, REAL64), INITIAL declarations (`INITIAL INT x IS 42:` — mutable variable with initial value), checked (modular) arithmetic (`PLUS`, `MINUS`, `TIMES` — wrapping operators), RETYPES (bit-level type reinterpretation: `VAL INT X RETYPES X :` for float32→int, `VAL [2]INT X RETYPES X :` for float64→int pair), transputer intrinsics (LONGPROD, LONGDIV, LONGSUM, LONGDIFF, NORMALISE, SHIFTRIGHT, SHIFTLEFT — implemented as Go helper functions), CAUSEERROR (maps to `panic("CAUSEERROR")`).

## Course Module Testing

The KRoC course module (`kroc/modules/course/libsrc/course.module`) is a real-world integration test. A reduced version excluding `float_io.occ` is provided:
The KRoC course module (`kroc/modules/course/libsrc/course.module`) is a real-world integration test:

```bash
# Transpile course module (without float_io.occ)
./occam2go -I kroc/modules/course/libsrc -D TARGET.BITS.PER.WORD=32 -o /tmp/course_out.go course_nofloat.module
# Transpile full course module (including float_io.occ)
./occam2go -I kroc/modules/course/libsrc -D TARGET.BITS.PER.WORD=32 -o /tmp/course_out.go kroc/modules/course/libsrc/course.module

# Verify Go output compiles (will only fail with "no main" since it's a library)
go vet /tmp/course_out.go
```

## Not Yet Implemented

RETYPES (bit-level type reinterpretation), transputer intrinsics (LONGPROD, LONGDIV, LONGSUM, LONGDIFF, NORMALISE, SHIFTRIGHT, SHIFTLEFT), CAUSEERROR, PRI ALT/PRI PAR, PLACED PAR, PORT OF. These are needed to transpile `float_io.occ` (Phase 2). See `TODO.md` for the full list with priorities.
PRI ALT/PRI PAR, PLACED PAR, PORT OF. See `TODO.md` for the full list with priorities.
12 changes: 8 additions & 4 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
- **Channel arrays** — `[n]CHAN OF TYPE cs:` with indexed send/receive and `[]CHAN OF TYPE` proc params
- **Channel direction** — `CHAN OF INT c?` (receive-only) and `CHAN OF INT c!` (send-only); direction annotations at call sites (`out!`, `in?`) accepted and ignored
- **Timers** — `TIMER tim:` with reads and `AFTER` expressions
- **Abbreviations** — `VAL INT x IS 1:`, `INT y IS z:` — named constants and aliases
- **Abbreviations** — `VAL INT x IS 1:`, `INT y IS z:`, untyped `VAL x IS expr:` — named constants and aliases
- **INITIAL declarations** — `INITIAL INT x IS 42:` — mutable variables with initial values
- **Byte literals** — `'A'`, `'0'` with occam escape sequences (`*n`, `*c`, `*t`)
- **Hex integer literals** — `#FF`, `#80000000`
Expand Down Expand Up @@ -49,7 +49,9 @@
- **MOSTNEG/MOSTPOS** — Type min/max constants for INT, BYTE, REAL32, REAL64
- **SIZE operator** — `SIZE arr`, `SIZE "str"` maps to `len()`
- **Array slices** — `[arr FROM n FOR m]` with slice assignment
- **Array literals** — `[1, 2, 3]` — inline array/table expressions
- **Multi-assignment** — `a, b := f(...)` including indexed targets like `x[0], x[1] := x[1], x[0]`
- **Multi-line expression continuation** — Binary operators and `:=` at end of line continue expression on next line

### Protocols
- **Simple** — `PROTOCOL SIG IS INT` (type alias)
Expand All @@ -59,6 +61,11 @@
### Records
- **RECORD** — Struct types with field access via bracket syntax (`p[x]`)

### Type Reinterpretation & Intrinsics
- **RETYPES** — Bit-level type reinterpretation (`VAL INT X RETYPES X :` for float32→int, `VAL [2]INT X RETYPES X :` for float64→int pair)
- **Transputer intrinsics** — `LONGPROD`, `LONGDIV`, `LONGSUM`, `LONGDIFF`, `NORMALISE`, `SHIFTLEFT`, `SHIFTRIGHT` — extended-precision arithmetic as Go helper functions
- **CAUSEERROR** — Error-raising primitive, maps to `panic("CAUSEERROR")`

### Preprocessor
- **`#IF` / `#ELSE` / `#ENDIF`** — Conditional compilation with `TRUE`, `FALSE`, `DEFINED()`, `NOT`, equality
- **`#DEFINE`** — Symbol definition
Expand Down Expand Up @@ -89,8 +96,5 @@
| **PRI ALT / PRI PAR** | Priority variants of ALT and PAR. |
| **PLACED PAR** | Assigning processes to specific hardware. |
| **PORT OF** | Hardware port mapping. |
| **`RETYPES`** | Type punning / reinterpret cast (`VAL INT X RETYPES X :`). Used in float_io.occ. |
| **`CAUSEERROR ()`** | Built-in error-raising primitive. Used in float_io.occ. |
| **Transputer intrinsics** | `LONGPROD`, `LONGDIV`, `LONGSUM`, `LONGDIFF`, `NORMALISE`, `SHIFTLEFT`, `SHIFTRIGHT`. Used in float_io.occ. |
| **`VAL []BYTE` abbreviations** | `VAL []BYTE cmap IS "0123456789ABCDEF":` — named string constants. |
| **`#PRAGMA DEFINED`** | Compiler hint to suppress definedness warnings. Can be ignored. |
24 changes: 24 additions & 0 deletions ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -494,3 +494,27 @@ type Abbreviation struct {

func (a *Abbreviation) statementNode() {}
func (a *Abbreviation) TokenLiteral() string { return a.Token.Literal }

// ArrayLiteral represents an array literal expression: [expr1, expr2, ...]
type ArrayLiteral struct {
Token lexer.Token // the [ token
Elements []Expression // the elements
}

func (al *ArrayLiteral) expressionNode() {}
func (al *ArrayLiteral) TokenLiteral() string { return al.Token.Literal }

// RetypesDecl represents a RETYPES declaration:
// VAL INT X RETYPES X : or VAL [2]INT X RETYPES X :
type RetypesDecl struct {
Token lexer.Token // the VAL token
IsVal bool // always true for now (VAL ... RETYPES ...)
TargetType string // "INT", "REAL32", etc.
IsArray bool // true for [n]TYPE
ArraySize Expression // array size when IsArray
Name string // target variable name
Source string // source variable name
}

func (r *RetypesDecl) statementNode() {}
func (r *RetypesDecl) TokenLiteral() string { return r.Token.Literal }
Loading
Loading