The temporary and the reference to it come back together, so they cannot drift
This commit is contained in:
parent
f7009fcd34
commit
0b8564828b
30
lib/parse.ml
30
lib/parse.ml
@ -375,6 +375,15 @@ and bindings f (items : Form.t list) : Ast.binding list =
|
|||||||
|
|
||||||
(* ── Destructuring ─────────────────────────────────────────────────── *)
|
(* ── Destructuring ─────────────────────────────────────────────────── *)
|
||||||
|
|
||||||
|
(* The temporary every pattern binds its value to before anything reads it, so
|
||||||
|
that the value is evaluated once however many names come out of it. Returning
|
||||||
|
the reference as well as the binding is what makes the two impossible to
|
||||||
|
separate by accident. *)
|
||||||
|
and temp (p : Form.t) (v : Ast.expr) : Ast.expr * Ast.binding =
|
||||||
|
let t = fresh_temp () in
|
||||||
|
({ Ast.e = Ast.Var t; loc = p.loc },
|
||||||
|
{ Ast.bname = t; bty = None; bval = v; bloc = p.loc })
|
||||||
|
|
||||||
(* Clojure's destructuring, desugared here into the bindings and field accesses
|
(* Clojure's destructuring, desugared here into the bindings and field accesses
|
||||||
the language already has. [Ast.binding] carries a name and nothing else, and
|
the language already has. [Ast.binding] carries a name and nothing else, and
|
||||||
deliberately so: nothing downstream — not [Load]'s renaming, not [Check], not
|
deliberately so: nothing downstream — not [Load]'s renaming, not [Check], not
|
||||||
@ -393,12 +402,8 @@ and destructure (p : Form.t) (v : Ast.expr) : Ast.binding list =
|
|||||||
(* The value goes into a temporary first, so it is evaluated once however
|
(* The value goes into a temporary first, so it is evaluated once however
|
||||||
many names the pattern binds, and so that [(let [{:keys [p]} p] ...)]
|
many names the pattern binds, and so that [(let [{:keys [p]} p] ...)]
|
||||||
reads the old [p] rather than the one it is in the middle of rebinding. *)
|
reads the old [p] rather than the one it is in the middle of rebinding. *)
|
||||||
| Map items ->
|
| Map items -> let t, bind = temp p v in bind :: dmap p t items
|
||||||
let t = fresh_temp () in
|
| Vec items -> let t, bind = temp p v in bind :: dvec p t items
|
||||||
{ Ast.bname = t; bty = None; bval = v; bloc = p.loc } :: dmap p t items
|
|
||||||
| Vec items ->
|
|
||||||
let t = fresh_temp () in
|
|
||||||
{ Ast.bname = t; bty = None; bval = v; bloc = p.loc } :: dvec p t items
|
|
||||||
| _ ->
|
| _ ->
|
||||||
fail p
|
fail p
|
||||||
"expected a name or a destructuring pattern, found %s — a pattern is \
|
"expected a name or a destructuring pattern, found %s — a pattern is \
|
||||||
@ -410,9 +415,9 @@ and destructure (p : Form.t) (v : Ast.expr) : Ast.binding list =
|
|||||||
the pair form is what nests, since a [:keys] entry is a name and never a
|
the pair form is what nests, since a [:keys] entry is a name and never a
|
||||||
pattern. Everything else Clojure puts in this position — [:as], [:or],
|
pattern. Everything else Clojure puts in this position — [:as], [:or],
|
||||||
[:strs], [:syms] — is refused by name where it is written. *)
|
[:strs], [:syms] — is refused by name where it is written. *)
|
||||||
and dmap (p : Form.t) (t : string) (items : Form.t list) : Ast.binding list =
|
and dmap (p : Form.t) (t : Ast.expr) (items : Form.t list) : Ast.binding list =
|
||||||
let ex loc e : Ast.expr = { Ast.e; loc } in
|
let ex loc e : Ast.expr = { Ast.e; loc } in
|
||||||
let field loc name = ex loc (Ast.Field (ex loc (Ast.Var t), name)) in
|
let field loc name = ex loc (Ast.Field (t, name)) in
|
||||||
let rec go = function
|
let rec go = function
|
||||||
| [] -> []
|
| [] -> []
|
||||||
| { v = Kw "keys"; _ } :: names :: rest ->
|
| { v = Kw "keys"; _ } :: names :: rest ->
|
||||||
@ -460,7 +465,7 @@ and dmap (p : Form.t) (t : string) (items : Form.t list) : Ast.binding list =
|
|||||||
else go items
|
else go items
|
||||||
|
|
||||||
(* [a b] and [a b & rest], over a fixed array. Not over a slice: see [Check]. *)
|
(* [a b] and [a b & rest], over a fixed array. Not over a slice: see [Check]. *)
|
||||||
and dvec (p : Form.t) (t : string) (items : Form.t list) : Ast.binding list =
|
and dvec (p : Form.t) (t : Ast.expr) (items : Form.t list) : Ast.binding list =
|
||||||
let ex loc e : Ast.expr = { Ast.e; loc } in
|
let ex loc e : Ast.expr = { Ast.e; loc } in
|
||||||
let var loc n = ex loc (Ast.Var n) in
|
let var loc n = ex loc (Ast.Var n) in
|
||||||
let rec split acc = function
|
let rec split acc = function
|
||||||
@ -491,7 +496,7 @@ and dvec (p : Form.t) (t : string) (items : Form.t list) : Ast.binding list =
|
|||||||
let nth i =
|
let nth i =
|
||||||
ex p.loc
|
ex p.loc
|
||||||
(Ast.Call (var p.loc "destructure~nth",
|
(Ast.Call (var p.loc "destructure~nth",
|
||||||
[ var p.loc t;
|
[ t;
|
||||||
ex p.loc (Ast.Int (Int64.of_int i));
|
ex p.loc (Ast.Int (Int64.of_int i));
|
||||||
ex p.loc (Ast.Int (Int64.of_int n));
|
ex p.loc (Ast.Int (Int64.of_int n));
|
||||||
ex p.loc (Ast.Int exact) ]))
|
ex p.loc (Ast.Int exact) ]))
|
||||||
@ -518,10 +523,9 @@ and dvec (p : Form.t) (t : string) (items : Form.t list) : Ast.binding list =
|
|||||||
bval =
|
bval =
|
||||||
ex r.loc
|
ex r.loc
|
||||||
(Ast.Call (var r.loc "slice",
|
(Ast.Call (var r.loc "slice",
|
||||||
[ var r.loc t;
|
[ t;
|
||||||
ex r.loc (Ast.Int (Int64.of_int n));
|
ex r.loc (Ast.Int (Int64.of_int n));
|
||||||
ex r.loc (Ast.Call (var r.loc "len",
|
ex r.loc (Ast.Call (var r.loc "len", [ t ])) ])) } ]
|
||||||
[ var r.loc t ])) ])) } ]
|
|
||||||
in
|
in
|
||||||
each 0 elems @ rest_binding
|
each 0 elems @ rest_binding
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user