aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/SPEC.md15
1 files changed, 8 insertions, 7 deletions
diff --git a/docs/SPEC.md b/docs/SPEC.md
index 1c65f42..9d860fe 100644
--- a/docs/SPEC.md
+++ b/docs/SPEC.md
@@ -498,16 +498,17 @@ a[2]; // zy: index 2 out of range (length 2)
### 3.14 constant expressions
-3.14.1 constant expressions are used for array lengths, enum values, `const` initializers, global initializers, `case` labels, `embed` array sizes and asm operands. the grammar is: number | character | named constant | `-` operand | `~` operand | `( constant )` | and the binary operators `+ - * | & << >>` only, evaluated left to right with no precedence.
+3.14.1 constant expressions are used for array lengths, enum values, `const` initializers, global initializers, `case` labels, `embed` array sizes and asm operands. the grammar is: number | character | named constant | `-` operand | `~` operand | `( constant )` | and the binary operators `* / % + - << >> & ^ |`, with the c precedences (3.3): `* / %` bind tightest, then `+ -`, `<< >>`, `&`, `^` and `|`; operators of one level group left to right.
```
-const X = 1 + 2 * 3; // 9, not 7
+const X = 1 + 2 * 3; // 7
const Y = 10 - 2 - 3; // 5
const V = 1 | 2 + 4; // 7
const W = ~0 & 255; // 255
+const Z = 7 - 6 / 2 % 2; // 6
```
-other operators (`/ % ^ < ?:` and so on) are not part of a constant expression: `const Z = 6 / 2;` is error: expected ';', found '/'.
+division truncates toward zero as at run time; a division or remainder by zero is error: division by zero in a constant expression. other operators (`< == && ?:` and so on) are not part of a constant expression: `const Z = 1 < 2;` is a syntax error.
-3.14.2 the names allowed are global constants (`const`, enum members, `Enum.MEMBER`, `Struct.CONST` inside that struct as the bare name), global variables and arrays (their value is their address), and defined functions (their address). a local `const` is not visible to a constant expression: `const n = 5; int[n] a;` inside a function is error: expected a constant.
+3.14.2 the names allowed are global constants (`const`, enum members, `Enum.MEMBER`, `Struct.CONST` inside that struct as the bare name), global variables and arrays (their value is their address), defined functions (their address), and a local `const` whose initializer is itself constant: `const n = 5; const m = n * 2; int[m] a;` inside a function gives `a` 10 elements. a local `const` with a run-time initializer is not a constant: `const n = f(); int[n] a;` is error: expected a constant.
### 3.15 closures
@@ -1145,11 +1146,11 @@ each item gives a minimal program, the expected behavior (per this spec) and the
1. fixed: README ("memory debug") says `memdebug scrub;` also fills a freed payload with 57005; the compiler used to compare the word with `rt.scrub` and reject it. it is accepted now (also b.2.1).
2. README ("zc, the language") says a cast type "has to be a simple type ... `int` or `*node`". the prefix pointer spelling `*node` is not a type (README's own "pointer types" section says so, and `(*int)y` => `int: is a type, not a value`). the postfix form `(node*)x` is the one that works.
-3. README says "operators follow C precedence". this holds for expressions. constant expressions (array lengths, enum values, `const`, `case` labels) have no precedence: `+ - * | & << >>` only, left to right (3.14). `const X = 1 + 2 * 3;` is 9, and `/ % ^` are rejected (`const Z = 6 / 2;` => `expected ';', found '/'`). README does not mention either fact.
+3. fixed (3.14.1): constant expressions now follow c precedence and accept `/ % ^`. it was: constant expressions (array lengths, enum values, `const`, `case` labels) have no precedence: `+ - * | & << >>` only, left to right (3.14). `const X = 1 + 2 * 3;` is 9, and `/ % ^` are rejected (`const Z = 6 / 2;` => `expected ';', found '/'`). README does not mention either fact.
4. README lists `switch` forms `case 1, 2:` and `default:`. the catch-all `case _:` exists in the compiler and is not documented.
5. README ("zc, the language"): "a unit is read whole and scanned for function signatures before it compiles, so calls can come before definitions, tags included, and prototypes are optional". prototypes that are written must name their parameters (`int f(int);` => `expected a name, found ')'`).
6. README/LEARN do not say that an embedded `\0` ends a string literal: `b"hi\n\0x"` has `len` 3 and `"ab\0cd"` is `ab`.
-7. README ("zc, the language") says `const k = 5;` in a function is a local constant. it is not a constant expression: `const n = 5; int[n] a;` in a function => `expected a constant`.
+7. fixed (3.14.2): README ("zc, the language") says `const k = 5;` in a function is a local constant. it is not a constant expression: `const n = 5; int[n] a;` in a function => `expected a constant`.
8. README (reflection) describes `run.tparamtag` as "the u/m/d tag of a parameter"; the code returns 0 untagged, 1 `.m`, 2 `.d` (there is no u at a parameter).
9. README/LEARN do not say that local variables and arrays are not zeroed (4.1.5).
10. zc0 vs compiler, the case that needed a referee: with `||` and `&&` now at c precedence, zc0 and compiler.zc agree on `1 || 0 && 0` => 1, `0 && 0 || 1` => 1, `1 | 2 && 0` => 0, `1 + 2 << 1` => 6, `7 & 3 ^ 1 | 8` => 10, `6 & 3 == 3` => 0 (checked on both).
@@ -1172,7 +1173,7 @@ each item gives a minimal program, the expected behavior (per this spec) and the
13. fixed (5.2.1): a prototype's parameters may be unnamed (`int f(int, int*);`). a lone type name counts as a type only in a prototype; with a body it is still the parameter's name, and an unnamed typed parameter there is `a parameter needs a name`.
14. fixed (3.13.5): `len(s)` on a `char*` used to return word 0 of the string when `typecheck` was off; it is now a compile error.
15. duplicate `case` labels are not diagnosed (4.7.2).
-16. a local `const` cannot be used in a constant expression (b.1.7).
+16. fixed (3.14.2): a local `const` could not be used in a constant expression (b.1.7).
17. fixed: a bad float or character literal in a function's first statement was not reported (1.4).
18. fixed: `u*d` with a visible variable `u` (local or global) was read as a recast; it is a product (1.6.3).
19. fixed: a cast such as `(int*)s` of a `bstr` kept the byte-string flag, so `p[0]` read a byte.