-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Distinguished lambda constructors for ref variables #10090
Changes from all commits
c351119
6f0765e
7038524
f53c21b
28d3196
423a96c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -495,6 +495,8 @@ let apply_specialised_attribute ppf = function | |
let rec lam ppf = function | ||
| Lvar id -> | ||
Ident.print ppf id | ||
| Lmutvar id -> | ||
fprintf ppf "*%a" Ident.print id | ||
| Lconst cst -> | ||
struct_const ppf cst | ||
| Lapply ap -> | ||
|
@@ -522,18 +524,26 @@ let rec lam ppf = function | |
fprintf ppf ")" in | ||
fprintf ppf "@[<2>(function%a@ %a%a%a)@]" pr_params params | ||
function_attribute attr return_kind return lam body | ||
| Llet(str, k, id, arg, body) -> | ||
let kind = function | ||
Alias -> "a" | Strict -> "" | StrictOpt -> "o" | Variable -> "v" | ||
| Llet(_, k, id, arg, body) | ||
| Lmutlet(k, id, arg, body) as l -> | ||
let let_kind = begin function | ||
| Llet(str,_,_,_,_) -> | ||
begin match str with | ||
Alias -> "a" | Strict -> "" | StrictOpt -> "o" | ||
end | ||
| Lmutlet _ -> "mut" | ||
| _ -> assert false | ||
end | ||
in | ||
let rec letbody = function | ||
| Llet(str, k, id, arg, body) -> | ||
fprintf ppf "@ @[<2>%a =%s%a@ %a@]" | ||
Ident.print id (kind str) value_kind k lam arg; | ||
letbody body | ||
| Llet(_, k, id, arg, body) | ||
| Lmutlet(k, id, arg, body) as l -> | ||
fprintf ppf "@ @[<2>%a =%s%a@ %a@]" | ||
Ident.print id (let_kind l) value_kind k lam arg; | ||
letbody body | ||
| expr -> expr in | ||
fprintf ppf "@[<2>(let@ @[<hv 1>(@[<2>%a =%s%a@ %a@]" | ||
Ident.print id (kind str) value_kind k lam arg; | ||
Ident.print id (let_kind l) value_kind k lam arg; | ||
let expr = letbody body in | ||
fprintf ppf ")@]@ %a)@]" lam expr | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note: here I think the duplication is cumbersome, and could be avoided with a refactoring of the code (an auxiliary function or something). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You are right, I addressed that in 4600d47. |
||
| Lletrec(id_arg_list, body) -> | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,7 +27,7 @@ exception Real_reference | |
let rec eliminate_ref id = function | ||
Lvar v as lam -> | ||
if Ident.same v id then raise Real_reference else lam | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe that |
||
| Lconst _ as lam -> lam | ||
| Lmutvar _ | Lconst _ as lam -> lam | ||
| Lapply ap -> | ||
Lapply{ap with ap_func = eliminate_ref id ap.ap_func; | ||
ap_args = List.map (eliminate_ref id) ap.ap_args} | ||
|
@@ -37,15 +37,17 @@ let rec eliminate_ref id = function | |
else lam | ||
| Llet(str, kind, v, e1, e2) -> | ||
Llet(str, kind, v, eliminate_ref id e1, eliminate_ref id e2) | ||
| Lmutlet(kind, v, e1, e2) -> | ||
Lmutlet(kind, v, eliminate_ref id e1, eliminate_ref id e2) | ||
| Lletrec(idel, e2) -> | ||
Lletrec(List.map (fun (v, e) -> (v, eliminate_ref id e)) idel, | ||
eliminate_ref id e2) | ||
| Lprim(Pfield 0, [Lvar v], _) when Ident.same v id -> | ||
Lvar id | ||
Lmutvar id | ||
| Lprim(Psetfield(0, _, _), [Lvar v; e], _) when Ident.same v id -> | ||
Lassign(id, eliminate_ref id e) | ||
| Lprim(Poffsetref delta, [Lvar v], loc) when Ident.same v id -> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's a subtle bug remaining here (on the line below, but I can't put a comment there directly): |
||
Lassign(id, Lprim(Poffsetint delta, [Lvar id], loc)) | ||
Lassign(id, Lprim(Poffsetint delta, [Lmutvar id], loc)) | ||
| Lprim(p, el, loc) -> | ||
Lprim(p, List.map (eliminate_ref id) el, loc) | ||
| Lswitch(e, sw, loc) -> | ||
|
@@ -120,10 +122,11 @@ let simplify_exits lam = | |
in | ||
|
||
let rec count = function | ||
| (Lvar _| Lconst _) -> () | ||
| (Lvar _ | Lmutvar _ | Lconst _) -> () | ||
| Lapply ap -> count ap.ap_func; List.iter count ap.ap_args | ||
| Lfunction {body} -> count body | ||
| Llet(_str, _kind, _v, l1, l2) -> | ||
| Llet(_, _kind, _v, l1, l2) | ||
| Lmutlet(_kind, _v, l1, l2) -> | ||
count l2; count l1 | ||
| Lletrec(bindings, body) -> | ||
List.iter (fun (_v, l) -> count l) bindings; | ||
|
@@ -203,13 +206,14 @@ let simplify_exits lam = | |
let subst = Hashtbl.create 17 in | ||
|
||
let rec simplif = function | ||
| (Lvar _|Lconst _) as l -> l | ||
| (Lvar _ | Lmutvar _ | Lconst _) as l -> l | ||
| Lapply ap -> | ||
Lapply{ap with ap_func = simplif ap.ap_func; | ||
ap_args = List.map simplif ap.ap_args} | ||
| Lfunction{kind; params; return; body = l; attr; loc} -> | ||
Lfunction{kind; params; return; body = simplif l; attr; loc} | ||
| Llet(str, kind, v, l1, l2) -> Llet(str, kind, v, simplif l1, simplif l2) | ||
| Lmutlet(kind, v, l1, l2) -> Lmutlet(kind, v, simplif l1, simplif l2) | ||
| Lletrec(bindings, body) -> | ||
Lletrec(List.map (fun (v, l) -> (v, simplif l)) bindings, simplif body) | ||
| Lprim(p, ll, loc) -> begin | ||
|
@@ -407,7 +411,8 @@ let simplify_lets lam = | |
let rec count bv = function | ||
| Lconst _ -> () | ||
| Lvar v -> | ||
use_var bv v 1 | ||
use_var bv v 1 | ||
| Lmutvar _ -> () | ||
| Lapply{ap_func = ll; ap_args = args} -> | ||
let no_opt () = count bv ll; List.iter (count bv) args in | ||
begin match ll with | ||
|
@@ -430,6 +435,9 @@ let simplify_lets lam = | |
count (bind_var bv v) l2; | ||
(* If v is unused, l1 will be removed, so don't count its variables *) | ||
if str = Strict || count_var v > 0 then count bv l1 | ||
| Lmutlet(_kind, _v, l1, l2) -> | ||
count bv l1; | ||
count bv l2 | ||
| Lletrec(bindings, body) -> | ||
List.iter (fun (_v, l) -> count bv l) bindings; | ||
count bv body | ||
|
@@ -491,10 +499,17 @@ let simplify_lets lam = | |
(* This (small) optimisation is always legal, it may uncover some | ||
tail call later on. *) | ||
|
||
let mklet str kind v e1 e2 = match e2 with | ||
| Lvar w when optimize && Ident.same v w -> e1 | ||
| _ -> Llet (str, kind,v,e1,e2) in | ||
let mklet str kind v e1 e2 = | ||
match e2 with | ||
| Lvar w when optimize && Ident.same v w -> e1 | ||
| _ -> Llet (str, kind,v,e1,e2) | ||
in | ||
|
||
let mkmutlet kind v e1 e2 = | ||
match e2 with | ||
| Lmutvar w when optimize && Ident.same v w -> e1 | ||
| _ -> Lmutlet (kind,v,e1,e2) | ||
in | ||
gasche marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
let rec simplif = function | ||
Lvar v as l -> | ||
|
@@ -503,7 +518,7 @@ let simplify_lets lam = | |
with Not_found -> | ||
l | ||
end | ||
| Lconst _ as l -> l | ||
| Lmutvar _ | Lconst _ as l -> l | ||
| Lapply ({ap_func = ll; ap_args = args} as ap) -> | ||
let no_opt () = | ||
Lapply {ap with ap_func = simplif ap.ap_func; | ||
|
@@ -545,7 +560,7 @@ let simplify_lets lam = | |
| Some [field_kind] -> field_kind | ||
| Some _ -> assert false | ||
in | ||
mklet Variable kind v slinit (eliminate_ref v slbody) | ||
mkmutlet kind v slinit (eliminate_ref v slbody) | ||
with Real_reference -> | ||
mklet Strict kind v (Lprim(prim, [slinit], loc)) slbody | ||
end | ||
|
@@ -561,6 +576,7 @@ let simplify_lets lam = | |
| _ -> mklet StrictOpt kind v (simplif l1) (simplif l2) | ||
end | ||
| Llet(str, kind, v, l1, l2) -> mklet str kind v (simplif l1) (simplif l2) | ||
| Lmutlet(kind, v, l1, l2) -> mkmutlet kind v (simplif l1) (simplif l2) | ||
| Lletrec(bindings, body) -> | ||
Lletrec(List.map (fun (v, l) -> (v, simplif l)) bindings, simplif body) | ||
| Lprim(p, ll, loc) -> Lprim(p, List.map simplif ll, loc) | ||
|
@@ -606,6 +622,7 @@ let simplify_lets lam = | |
let rec emit_tail_infos is_tail lambda = | ||
match lambda with | ||
| Lvar _ -> () | ||
| Lmutvar _ -> () | ||
| Lconst _ -> () | ||
| Lapply ap -> | ||
begin | ||
|
@@ -629,7 +646,8 @@ let rec emit_tail_infos is_tail lambda = | |
list_emit_tail_infos false ap.ap_args | ||
| Lfunction {body = lam} -> | ||
emit_tail_infos true lam | ||
| Llet (_str, _k, _, lam, body) -> | ||
| Llet (_, _k, _, lam, body) | ||
| Lmutlet (_k, _, lam, body) -> | ||
emit_tail_infos false lam; | ||
emit_tail_infos is_tail body | ||
| Lletrec (bindings, body) -> | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it should be an error for a mutable variable to appear in
s
. Could you leave a comment here so that we remember about it ? For this PR keeping the old behaviour is probably best.