From 22df891893d30e9906d0b14fc3ae5d8e67d500b2 Mon Sep 17 00:00:00 2001 From: Cliff Click Date: Sat, 3 Oct 2026 14:03:48 -0700 Subject: Chapter renumber, and split ch 17 Renumber chapters 10a, 10b, 11, 12, 13, 14 -> 10, 11, 13, 12, [11,14]. Split ch 17 into a 17a and 17b; shuffle around im/mutable syntax to be consistent, and present it more slowly. THe new immutable syntax is pushed through all later chapters --- chapter17/README.md | 186 ---------------------------------------------------- 1 file changed, 186 deletions(-) delete mode 100644 chapter17/README.md (limited to 'chapter17/README.md') diff --git a/chapter17/README.md b/chapter17/README.md deleted file mode 100644 index ea1fef28..00000000 --- a/chapter17/README.md +++ /dev/null @@ -1,186 +0,0 @@ -# Chapter 17: Syntax Sugar - -[Previous: Chapter 16](../chapter16/README.md) | -[Next: Chapter 18](../chapter18/README.md) - - -## Table of Contents - -1. [Pre/Post-increment](#prepost-increment) -2. [Operator assignment](#operator-assignment) -3. [var/val](#var--val) -4. [Mutability](#mutability) -5. [Reference immutability](#reference-variables-with-an-initializer-are-deeply-immutable) -6. [Trinary](#trinary) -7. [For Loops](#for-loops) -8. [Memory effects](#memory-effects) - -## Pre/Post-increment - -Allow `arg++` and `arg--` with the usual meanings; the value is updated and the -expression is the pre-update value. Greedy match is used so `arg---arg` parses -as `(arg--)-arg`. - -Also allows `s.fld++` and `ary[idx]++`, and their `--` variants. - -Allow pre-increment for identifiers only, for now: `--pc`. - - -## Operator assignment - -Along the same lines as post-increment, we now allow `op=` assignment -on local variables with semantics similar to other languages. The supported -operators are `+=`, `-=`, `*=`, `/=`, `&=`, `|=`, `^=`, `<<=`, `>>=`, and `>>>=`. -Bitwise and shift assignments require integer operands; `>>=` preserves the sign -while `>>>=` shifts in zeros. The assignment evaluates its right-hand side once, -stores the result narrowed to the variable's type, and yields that stored value. -Assignments associate right-to-left, as in `x |= y <<= 2`. - -`x += y` - - -## var & val - -`var` can be used in the `type` position to indicate a "variable" (mutable -value), whose type will be inferred from the required initializing expression. - -`val` is the same as `var`, except it is a "value" (not mutable). - -The inferred value is the Greatest Lower Bound `glb` type of the peephole type, -which means `var` and `val` will not infer types like `u8` or `f32`, instead -inferring `int` and `flt` respectively. Reference types will always infer as -nullable, so e.g. - -`var s = new S;` - -infers as - -`S? s = new S;` - - -## Mutability - -Typed primitive fields are always mutable. Typed reference fields without an -initializer must be mutable to get a value. Initialized reference variables -are immutable by default and can be made mutable with a leading `!`. Contrast -this with what [Chapter 16](../chapter16/README.md) -did with `!`. `var` and `val` keep their current sense and can be used to make -any field mutable or immutable. Fields are always mutable during construction, -but will become immutable at the end of either constructor. - -`int x; x=3; x++; // OK, primitive so mutable` - -`int x =3; x++; // Ok, primitive so mutable, despite initializer` - -Assume in the next examples this struct exists: -`struct S { int x; };` - -Then: - -`S s; s = new S ; s.x++; // OK, no initializer so s.x is mutable` - -`S s; s = new S{x=3}; s.x++; // OK, no initializer so s.x is mutable` - -`S s = new S ; s.x++; // Error, initializer so s.x is immutable` - -`S s = new S{x=3}; s.x++; // Error, initializer so s.x is immutable` - -Leading `!` makes mutable: - -`S !s = new S; s.x++; // Ok, has '!' so mutable` - -`var` is variable, i.e. mutable: - -`var s = new S; s.x++; // Ok, has var so mutable` - -`val` is a "value": not mutable through this reference, but may be mutable -through other references. - -`val s = new S; s.x++; // Error, val so s.x is immutable` - - -### Reference variables with an initializer are deeply immutable - -Initialized reference variables are deeply immutable, but a mutable version of the same -reference can exist. This works for `val` and normal type declarations: `val s -= new S;` and `S s = new S` both make `s` an immutable reference to a `struct S`. - -```cpp -struct Bar { int x; } -Bar !bar = new Bar; // '!' so bar is mutable -bar.x = 3; // Ok, bar is mutable - -struct Foo { Bar !bar; int y; } -Foo !foo = new Foo; // '!' so foo is mutable -foo.bar = bar; // Ok foo is mutable -foo.bar.x++; // Ok foo and foo.bar and foo.bar.x are all mutable - -val xfoo = foo; // Throw away mutability deeply on foo -xfoo.bar.x++; // Error, cannot mutate through xfoo - -print(xfoo.bar.x); // Ok to read through xfoo, prints 4 -foo.bar.x++; // Bumps to 5 -print(xfoo.bar.x); // Ok to read through xfoo, prints 5 -``` - -## Trinary - -Allow `pred ? e_true : e_false`. Also allow `pred ? e_true`, where the false result -is the zero type version of the true result. - - -## For Loops - -Allow C/C++ style `for` loops: - -`for( init; test; next ) body` - -Example: - -```cpp -int sum=0; -for( int i=0; i