degory / ghul

compiler for the ghūl programming language
https://ghul.dev
GNU Affero General Public License v3.0
4 stars 0 forks source link

Local constants #1124

Open degory opened 8 months ago

degory commented 8 months ago

Add support for local constants

Rationale

It would be useful for developers to be able to communicate the intent that a local value is not expected to change over its lifetime. Other languages provide this facility with various constructs, for example, by introducing the definition with const.

Local constants

Local constants are analogous to local variables, but they must be initialized at the point of definition, and their values cannot be changed via assignment or by being passed by reference.

What is 'constant'?

For a local constant of a value type, all its fields will be immutable. However, this immutability doesn't extend to any reference type objects pointed to by the value. Similarly, if a local constant is of a reference type, while it cannot be updated to point to a different object, the referenced object itself remains mutable. If in the future we want to express interior immutability for reference types, that would be an attribute of the type, not an attribute of the variable/constant binding to it.

Syntax options

Option 1

Use let for constants and var for variables:

let some_constant = 123;
var some_variable = "hello"

Option 2

Use let for constants and let var for variables:

let some_constant = 123;
let var some_variable = "hello";

Option 3

Introduce let con for constants:

let con some_constant = 123;
let some_variable = "hello";

I prefer the appearance of option 2, but it requires twice as many characters to type for a very common case. Option 3 is probably the least attractive: if either variables or constants are going to be marked with an additional attribute, constants should be the less marked choice since 1. constants are preferred, and 2. they may well be more common. On the plus side, option 3 is not a source-breaking change.

It would be useful to instrument the compiler to report the number of constants vs. the number of variables in the compiler source code to check which is actually more common in practice

Actions

Assuming we went with option 1, we would need to:

  1. [ ] Repurpose let to define local constants, not local variables.
  2. [ ] Reintroduce var for defining local variables.
  3. [ ] To support bootstrapping, make var and let both aliases for var, until all uses of let in the compiler are replaced with var, and create an interim compiler release.
  4. [ ] Split let and var into defining local constants and local variables, respectively.
  5. [ ] Require an initializer for let; initializers remain optional for var.
  6. [ ] Report an error for assignments to constants defined with let.
  7. [ ] Explicit types remain optional for both let and var

Option 2 would need much the same actions, except initially let and let var would both define variables

Option 3 would not require an interim compiler release because introducing let con would not be a source breaking change