Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[bug fix] jsimp: tail call optimization was broken for local functions
  • Loading branch information
Valentin Gatien-Baron committed Jun 22, 2011
1 parent e00f7b0 commit b49c2c1
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 6 deletions.
23 changes: 18 additions & 5 deletions qmljsimp/imp_Code.ml
Expand Up @@ -427,17 +427,30 @@ let analyse_tail_recursion bindings =
| Q.Match (_, _, pel) -> List.iter (fun (_,e) -> aux myself e) pel | Q.Match (_, _, pel) -> List.iter (fun (_,e) -> aux myself e) pel
| Q.Apply (_, Q.Directive (_, `partial_apply _, [Q.Apply (_, Q.Ident (_, f), _)], _), _) | Q.Apply (_, Q.Directive (_, `partial_apply _, [Q.Apply (_, Q.Ident (_, f), _)], _), _)
| Q.Apply (_, Q.Ident (_, f), _) when IdentTable.mem env f -> | Q.Apply (_, Q.Ident (_, f), _) when IdentTable.mem env f ->
#<If:JS_IMP$contains "tailcall">
Format.printf " %s\n%!" (Ident.to_string f)
#<End>;
let set1 = IdentTable.find env f in let set1 = IdentTable.find env f in
let set2 = IdentTable.find env myself in let set2 = IdentTable.find env myself in
let full_set = IdentSet.add myself (IdentSet.add f (IdentSet.union set1 set2)) in let full_set = IdentSet.add myself (IdentSet.add f (IdentSet.union set1 set2)) in
IdentSet.iter (fun i -> IdentTable.replace env i full_set) full_set IdentSet.iter (fun i -> IdentTable.replace env i full_set) full_set
| _ -> () in | e ->
#<If:JS_IMP$contains "fulltailcall">
Format.printf "@\nstopped on %a" QmlPrint.pp#expr e
#<End>;
() in
List.iter List.iter
(fun (i,expr) -> (fun (i,expr) ->
match expr with #<If:JS_IMP$contains "tailcall">
| Q.Lambda (_, _, Q.Lambda (_, _, e)) Format.printf ">> analysing tail calls of %s: " (Ident.to_string i)
| Q.Lambda (_, _, e) -> aux i e #<End>;
| _ -> assert false (match expr with
| Q.Lambda (_, _, Q.Lambda (_, _, e))
| Q.Lambda (_, _, e) -> aux i e
| _ -> assert false);
#<If:JS_IMP$contains "tailcall">
Format.printf "@."
#<End>
) bindings; ) bindings;
let binding_of_ident i = let binding_of_ident i =
List.find (fun (j,_e) -> Ident.equal i j) bindings in List.find (fun (j,_e) -> Ident.equal i j) bindings in
Expand Down
11 changes: 10 additions & 1 deletion qmljsimp/imp_Compiler.ml
Expand Up @@ -83,7 +83,16 @@ let compile ?(val_=fun _ -> assert false) ?bsl ?(closure_map=IdentMap.empty) ~re
if env = 0 then sub else if env = 0 then sub else
let env_args, args = List.split_at env args in let env_args, args = List.split_at env args in
(* same here *) (* same here *)
QmlAst.Apply (label, QmlAst.Apply (label2, fun_, env_args), args) (* BEWARE duplicating the annotation [label] is bad, but the
* backend doesn't care about that and then they are lost *)
QmlAst.Apply (
label,
QmlAst.Directive
(label,
`partial_apply None,
[QmlAst.Apply (label2, fun_, env_args)],
[]),
args)
| QmlAst.Directive (_,(`lifted_lambda _ | `full_apply _),_,_) -> assert false | QmlAst.Directive (_,(`lifted_lambda _ | `full_apply _),_,_) -> assert false
| e -> e) | e -> e)
) code in ) code in
Expand Down

0 comments on commit b49c2c1

Please sign in to comment.