diff options
| author | Cliff Click <cliffc@acm.org> | 2024-11-13 13:41:18 -0800 |
|---|---|---|
| committer | Cliff Click <cliffc@acm.org> | 2024-11-23 09:03:20 -0800 |
| commit | 68cd11f31dd4ba7f089d1a15de5a36ec67043da6 (patch) | |
| tree | 19adb6cee02232eba346c6aed2d56081556302f2 /chapter17/README.md | |
| parent | 82fb275502f84e17228fc587385eeb76f195a09e (diff) | |
| download | Simple-68cd11f31dd4ba7f089d1a15de5a36ec67043da6.tar.gz Simple-68cd11f31dd4ba7f089d1a15de5a36ec67043da6.zip | |
Final? pass of finals
Add a least-upper-bound to set Phis to their respective Top while preserving final fields.
Requires a ReadOnly node to "cast-away-writable".
Series of isFinal/makeRO in all Types.
Changes tests to match r/w intent.
Diffstat (limited to 'chapter17/README.md')
| -rw-r--r-- | chapter17/README.md | 103 |
1 files changed, 46 insertions, 57 deletions
diff --git a/chapter17/README.md b/chapter17/README.md index b7a1afd6..bf998ab8 100644 --- a/chapter17/README.md +++ b/chapter17/README.md @@ -15,7 +15,7 @@ Allow pre-increment for identifiers only, for now: `--pc`. ## var & val `var` can be used in the `type` position to indicate a "variable" (mutable -value), whose type will be inferred from the initalizing expression. +value), whose type will be inferred from the required initalizing expression. `val` is the same as `var`, except it is a "value" (not mutable). @@ -30,78 +30,68 @@ infers as `S s? = new S;` -## Initialized fields are immutable by default +## Mutability -Typed field declarations with an initializer are immutable by default, and can -be made mutable with a leading `!`. `var` and `val` keep their current sense. -Fields are immutable at the end of either constructor, but can be changed -during construction. +Typed primitive fields are always mutable. Typed reference fields without an +initializer must be mutable to get a value. References with an initializer are +immutable by default and can be made mutable with a leading `!`. `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` -Examples: +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` -```java -struct Point { int x,y; }; // Fields x and y are not initialized, mutable -Point p = new Point; -p.x++; // Mutate is ok -return p.x; -``` +Leading `!` makes mutable: +`S !s = new S; s.x++; // Ok, has '!' so mutable` -```java -struct Point { int x=3,y=4; }; // Fields x and y are initialized, immutable -Point p = new Point; -p.x++; // Error! -return p.x; -``` +'var' is variable: +`var s = new S; s.x++; // Ok, has var so mutable` -```java -struct Point { int x=3,y=4; }; // Fields x and y are initialized, immutable -Point p = new Point { x=x*x; y=y*y; }; // Ok to mutate in the constructor -p.x++; // Error! -return p.x; -``` +'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` -```java -struct Point { int !x=3, !y=4; }; // Fields x and y are initialized, mutable -Point p = new Point; -p.x++; // Mutate is OK -return p.x; -``` -```java -struct Point { var x,y; }; // Error, var and val require an initializer -Point p = new Point; -p.x++; -return p.x; -``` -```java -struct Point { var x=3,y=4; }; // Fields x and y are mutable -Point p = new Point; -p.x++; // Mutate is OK -return p.x; -``` +### References with an initializer are deeply immutable -```java -struct Point { val x=3,y=4; }; // Fields x and y are immutable -Point p = new Point; -p.x++; // Error! -return p.x; -``` +References with an initializer are deeply immutable, but a mutable version of +the same reference can exist. This works for `var` and normal type +declarations: `var s = new S;` and `S s = new S` both make `s` an +immutable reference to a `struct S`. -## Deep Immutability (proposal) - ```cpp -struct Bar { int x; }; -Bar b = new Bar; /* b = new Bar; *//* b.x++; */ // immutable & deep immutable -Bar !b = new Bar; b = new Bar; b.x++; // mutable & deep mutable -val b = new Bar; /* b = new Bar; *//* b.x++; */ // immutable & deep immutable -var b = new Bar; b = new Bar; b.x++; // mutable & inherits deep mutability from RHS +struct Bar { int x; } +Bar !bar = new Bar; +bar.x = 3; // Ok, bar is mutable + +struct Foo { Bar !bar; int y; } +Foo !foo = new Foo; +foo.bar = barl // Ok bar is mutable +foo.bar.x++; // Ok foo and foo.bar and foo.bar.x are all mutable + +val xfoo = foo; // Throw away mutability +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 @@ -138,7 +128,6 @@ return i; // ERROR: Undefined name 'i' finalize final oper-assign +=, -= TODO -for-interator switch |
