evincarofautumn / kitten

A statically typed concatenative systems programming language.
http://kittenlang.org/
Other
1.09k stars 39 forks source link

Figure out a syntax for mutation. #146

Open evincarofautumn opened 9 years ago

evincarofautumn commented 9 years ago

The arrow syntax introduces a local variable.

1 -> x;

Introducing another local by the same name doesn’t mutate it in place. Rather, the new variable shadows the original one.

1 -> x;
x + 1 -> x;

I propose a fat-arrow syntax for mutating local variables in place.

1 -> x;
x + 1 => x;

The right hand side of a fat arrow is (ironically) an lvalue, not an expression—it can be extended to mutate fields of structures by index.

data point:
  case point (int, int)

1 2 point -> p;
p.(0) + 1 => p.(0);

Or by name, if we introduce notation for named fields in type definitions.

data point:
  case point:
    x as int;
    y as int;

1 2 point -> p;
p.x + 1 => p.x;

Array indexers should also serve as lvalues.

[1, 0, 3] -> x;
2 => x.[1];
evincarofautumn commented 7 years ago

We can add a mut operator with a special typing rule:

Γ ⊢ e : ∀H. (R… → S… +Mut<H> +P), H ∉ free(R… → S… +P)
------------------------------------------------------
Γ ⊢ e mut : R… → S… +P

This is basically Haskell’s runST, adapted to permissions rather than monads, and without an existential (or rank-2 universal) type. Then { … } mut or do (mut) { … } enables local mutation of non-escaping variables:

type Var<A, H>
define var<A, H> (A -> Var<A, H> +Mut<H>)
define load<A, H> (Var<A, H> -> A +Mut<H>)
define store<A, H> (A, Var<A, H> -> +Mut<H>)

// -> Int32 +IO
do (mut):
  1 var -> x;
  x load say
  2 x store
  x load dup say

// -> Var<Int32, H>
// error: mutable variable would escape its scope
do (mut):
  1 var

With an operator like addr(lvalue), this could let you take the address of a local value or field and safely pass it down the call stack. There would need to be some operators or other sugar for load and store, such as Forth’s @ and !. The aforementioned fat-arrow syntax a => b; could be sugar for a addr(b) store.