Have let ... in evaluate right hand side first during multi-bind
This commit is contained in:
parent
2d9de2aef0
commit
e1ecb36e61
@ -181,7 +181,7 @@ let rec patterns_to_typed_vars : Raw.pattern nseq -> _ = fun ps ->
|
|||||||
| Raw.PPar pp -> patterns_to_typed_vars (pp.value.inside, [])
|
| Raw.PPar pp -> patterns_to_typed_vars (pp.value.inside, [])
|
||||||
| Raw.PTuple pt -> bind_map_list pattern_to_typed_var (npseq_to_list pt.value)
|
| Raw.PTuple pt -> bind_map_list pattern_to_typed_var (npseq_to_list pt.value)
|
||||||
| Raw.PVar _ -> bind_list [pattern_to_typed_var pattern]
|
| Raw.PVar _ -> bind_list [pattern_to_typed_var pattern]
|
||||||
| other -> (fail @@ wrong_pattern "bla bla" other)
|
| other -> (fail @@ wrong_pattern "parenthetical, tuple, or variable" other)
|
||||||
end
|
end
|
||||||
| _ -> fail @@ multiple_patterns "let" (nseq_to_list ps)
|
| _ -> fail @@ multiple_patterns "let" (nseq_to_list ps)
|
||||||
|
|
||||||
@ -278,10 +278,11 @@ let rec simpl_expression :
|
|||||||
let%bind ty_opt =
|
let%bind ty_opt =
|
||||||
bind_map_option (fun (_,te) -> simpl_type_expression te) lhs_type in
|
bind_map_option (fun (_,te) -> simpl_type_expression te) lhs_type in
|
||||||
let%bind rhs = simpl_expression let_rhs in
|
let%bind rhs = simpl_expression let_rhs in
|
||||||
let rhs' =
|
let rhs_b = Var.fresh ~name: "rhs" () in
|
||||||
|
let rhs',rhs_b_expr =
|
||||||
match ty_opt with
|
match ty_opt with
|
||||||
None -> rhs
|
None -> rhs, e_variable rhs_b
|
||||||
| Some ty -> e_annotation rhs ty in
|
| Some ty -> (e_annotation rhs ty), e_annotation (e_variable rhs_b) ty in
|
||||||
let%bind body = simpl_expression body in
|
let%bind body = simpl_expression body in
|
||||||
let prepare_variable (ty_var: Raw.variable * Raw.type_expr option) =
|
let prepare_variable (ty_var: Raw.variable * Raw.type_expr option) =
|
||||||
let variable, ty_opt = ty_var in
|
let variable, ty_opt = ty_var in
|
||||||
@ -298,18 +299,26 @@ let rec simpl_expression :
|
|||||||
then fail @@ corner_case "let ... in without variables passed parsing stage"
|
then fail @@ corner_case "let ... in without variables passed parsing stage"
|
||||||
else ok ()
|
else ok ()
|
||||||
in
|
in
|
||||||
|
let rhs_b_expr = (* We only want to evaluate the rhs first if multi-bind *)
|
||||||
|
if List.length prep_vars = 1
|
||||||
|
then rhs' else rhs_b_expr
|
||||||
|
in
|
||||||
let rec chain_let_in variables body : expression =
|
let rec chain_let_in variables body : expression =
|
||||||
match variables with
|
match variables with
|
||||||
| hd :: [] ->
|
| hd :: [] ->
|
||||||
if (List.length prep_vars = 1)
|
if (List.length prep_vars = 1)
|
||||||
then e_let_in hd rhs' body
|
then e_let_in hd rhs_b_expr body
|
||||||
else e_let_in hd (e_accessor rhs' [Access_tuple ((List.length prep_vars) - 1)]) body
|
else e_let_in hd (e_accessor rhs_b_expr [Access_tuple ((List.length prep_vars) - 1)]) body
|
||||||
| hd :: tl ->
|
| hd :: tl ->
|
||||||
e_let_in hd
|
e_let_in hd
|
||||||
(e_accessor rhs' [Access_tuple ((List.length prep_vars) - (List.length tl) - 1)])
|
(e_accessor rhs_b_expr [Access_tuple ((List.length prep_vars) - (List.length tl) - 1)])
|
||||||
(chain_let_in tl body)
|
(chain_let_in tl body)
|
||||||
| [] -> body (* Precluded by corner case assertion above *)
|
| [] -> body (* Precluded by corner case assertion above *)
|
||||||
in ok (chain_let_in prep_vars body)
|
in
|
||||||
|
if List.length prep_vars = 1
|
||||||
|
then ok (chain_let_in prep_vars body)
|
||||||
|
(* Bind the right hand side so we only evaluate it once *)
|
||||||
|
else ok (e_let_in (rhs_b, ty_opt) rhs' (chain_let_in prep_vars body))
|
||||||
| Raw.EAnnot a ->
|
| Raw.EAnnot a ->
|
||||||
let Raw.{inside=expr, _, type_expr; _}, loc = r_split a in
|
let Raw.{inside=expr, _, type_expr; _}, loc = r_split a in
|
||||||
let%bind expr' = simpl_expression expr in
|
let%bind expr' = simpl_expression expr in
|
||||||
|
Loading…
Reference in New Issue
Block a user