diff --git a/compiler/src/CODE-LOGIC.md b/compiler/src/CODE-LOGIC.md index 00bebbe..4f8549e 100644 --- a/compiler/src/CODE-LOGIC.md +++ b/compiler/src/CODE-LOGIC.md @@ -260,3 +260,38 @@ a keyword, and visibility is name resolution at compile time. - **Exit-code bands stay split**: WO-E108 is a diagnostic through the normal collector path (exit 1); WO-E106/E107/E109 are manifest errors printed directly (exit 2). + +## Operator parity (iteration 36 — `.wob` v6) + +- **Precedence went INTO existing rungs, not new ones.** `|`/`^` joined + `parse_additive`, `&`/`<<`/`>>` joined `parse_multiplicative` — exactly + Go's table (`token.go` Precedence), which exists to fix C's trap: + `x & mask == 0` groups the AND first here. The ladder doc in `parser.ml` + carries the worked examples. +- **`not` is a keyword at the unary level (Lua placement).** `not a == b` + groups `(not a) == b`. Chosen over Python's looser placement because the + grammar's ordering is already anchored to Lua by name and because + Bool-only typing turns almost every misread into a compile error. It + lowers on the existing EQ against a zero constant — no new opcode, the + same doctrine as and/or's JZ lowering. +- **Compound assigns are parse-time sugar via rewind-and-reparse.** + `x += e` IS `x = x + e`, the documented contract — including an index + expression evaluating twice, exactly as the written-out form would. The + parser re-parses the place by resetting `st.pos` (no expression rung + consumes a compound token, so the second parse stops where the first + did); every re-parsed node draws a fresh id, so owner/emit see two + honest reads, never one node in two roles. `+=`/`-=` had been lexed + since haxe-parity Task 2 but no rule consumed them — dead tokens, + `x += 1` died as a generic WO-E101 until this iteration. +- **Bitwise is Int-only on BOTH sides (WO-E201 family)** — no F-twin + exists, so a Float operand would have become a garbage word operation + with no diagnostic. A LITERAL shift count outside 0..63 is WO-E223 at + the operand's position (a negative literal arrives as + `Unary(Neg, IntLit)` — both shapes are caught); a variable count is the + VM's WO_T_SHIFT. +- **Hex/binary literals accumulate in OCaml's native int (63-bit).** A + full-width 64-bit literal like `0xFFFFFFFFFFFFFFFF` is out of reach — + all-ones is spelled `-1` (and complement is `-1 ^ x`; there is no `~`). + The `0x`/`0b` prefix commits only when a real base digit follows, so + `0xg` stays `Int 0` + `Ident` — a parse error at its own position, no + new lexer diagnostic. `_` separators are consumed only BETWEEN digits. diff --git a/docs/00-status.md b/docs/00-status.md index 36d79ad..515a21f 100644 --- a/docs/00-status.md +++ b/docs/00-status.md @@ -193,7 +193,8 @@ that sequences its tasks. Read one, approve, then the next starts. | Track | Item | Where | | -------- | --------------------------------------------------------------------------- | ---------------------------------------------------------- | -| Language | nothing active — the framework v1-polish slice landed 2026-08-20 (branch framework-v1, awaiting merge); next per the order: brainstorm 20/21's forks | [order](#implementation-order-re-sequenced-2026-08-20--code-review-pass) | +| Language | 🔄 [iteration 36 — operator parity](stories/language-runtime-database/in-progress/36-operator-parity.md): `not`, bitwise `& \| ^ << >>`, hex/binary/`_` literals, compound assigns — CODE LANDED 2026-08-22 (branch operator-parity, `.wob` v6, all gates green; reference project `.dev/reference/go` drove the design). Awaiting the developer's MANUAL pass on `docs/examples/operators/` (no test fixtures by directive); unblocks story 34's pure-`.wo` HMAC question | [plan](superpowers/plans/2026-08-22-operator-parity.md) | +| Language | the framework v1-polish slice landed 2026-08-20 (branch framework-v1, awaiting merge); next per the order: brainstorm 20/21's forks | [order](#implementation-order-re-sequenced-2026-08-20--code-review-pass) | Off-goal work is parked; the goal (2026-08-20) is the web framework as a polished micro-framework v1 — iteration 17 (library kind + `internal/`) is diff --git a/docs/examples/operators/README.md b/docs/examples/operators/README.md new file mode 100644 index 0000000..12e890d --- /dev/null +++ b/docs/examples/operators/README.md @@ -0,0 +1,42 @@ +# operators — iteration 36's manual-test workload + +Exercises everything iteration 36 added to the language: boolean `not`, +the five Int bitwise operators (`&` `|` `^` `<<` `>>`), hex/binary/ +underscore integer literals, and the five compound assigns +(`+=` `-=` `*=` `/=` `%=`). + +## Run it + +``` +woc . # from this directory +./target/operators +``` + +Every line prints `ok