From a1b2bedbc87caad1b09495da2c515bdffc5ed995 Mon Sep 17 00:00:00 2001 From: Thomas Wood <thomas.wood09@imperial.ac.uk> Date: Mon, 28 Sep 2015 13:00:46 +0100 Subject: [PATCH] Match expression: Variable binders and matching constants now fixed. --- generator/js_of_ast.ml | 46 ++++++++++++++++++++++++++++++------------ generator/tests/let.ml | 9 +++++++++ 2 files changed, 42 insertions(+), 13 deletions(-) diff --git a/generator/js_of_ast.ml b/generator/js_of_ast.ml index 94b9018..7ecdb83 100644 --- a/generator/js_of_ast.ml +++ b/generator/js_of_ast.ml @@ -27,6 +27,10 @@ let show_list sep l = let is_sbool x = List.mem x ["true" ; "false"] +let exp_type_is_constant exp = + List.exists (Ctype.matches exp.exp_env exp.exp_type) + [Predef.type_bool; Predef.type_int; Predef.type_char; Predef.type_string; Predef.type_float] + let rec zip l1 l2 = match l1, l2 with | [], x :: xs | x :: xs, [] -> failwith "zip: list must have the same length." | [], [] -> [] @@ -90,12 +94,24 @@ let ppf_apply_infix f arg1 arg2 = Printf.sprintf "%s %s %s" arg1 f arg2 -let ppf_match value cases = - let s = - Printf.sprintf "switch (%s.type) {@,@[<v 0>%s@]@,}" - value cases +let ppf_match value cases const = + let cons_fld = if const then "" else ".type" in + let s = Printf.sprintf "switch (%s%s) {@,@[<v 0>%s@]@,}" + value cons_fld cases in ppf_lambda_wrap s +let ppf_match_case c = + Printf.sprintf "case %s" c + +let ppf_match_binders binders = + let binds = show_list ", " binders in + Printf.sprintf "@[<v 0>var %s;@]" binds + +(* obj is passed as the object variable binding, if we need to deconstruct it *) +let ppf_match_binder var ?obj fld = match obj with + | None -> Printf.sprintf "%s = %s" var fld + | Some obj -> Printf.sprintf "%s = %s.%s" var obj fld + let ppf_array values = Printf.sprintf "[%s]" values @@ -235,7 +251,8 @@ and js_of_expression e = | Texp_match (exp, l, [], Total) -> let se = js_of_expression exp in let sb = String.concat "@," (List.map (fun x -> js_of_branch x se) l) in - ppf_match se sb + let const = exp_type_is_constant exp in + ppf_match se sb const | Texp_tuple (tl) -> ppf_tuple @@ show_list_f (fun exp -> js_of_expression exp) ", " tl @@ -247,7 +264,9 @@ and js_of_expression e = else (* Constructor has parameters *) let fields = extract_attrs cd.cstr_attributes in let expr_strs = List.map (fun exp -> js_of_expression exp) el in - let expand_constructor_list = List.map2 ppf_cstr in + let expand_constructor_list fields exprs = + try List.map2 ppf_cstr fields exprs with + | Invalid_argument _ -> error ~loc ("Insufficient fieldnames for arguments to " ^ name) in let expanded_constructors = expand_constructor_list fields expr_strs in ppf_multiple_cstrs name (show_list ", " expanded_constructors) @@ -314,16 +333,17 @@ and js_of_pattern pat obj = let loc = pat.pat_loc in match pat.pat_desc with | Tpat_any -> "default", "" - | Tpat_constant c -> js_of_constant c, "" - | Tpat_var (id, _) -> Ident.name id, "" + | Tpat_constant c -> ppf_match_case (js_of_constant c), "" + | Tpat_var (id, _) -> "default", (ppf_match_binders [ppf_match_binder (Ident.name id) ""]) | Tpat_construct (_, cd, el) -> let c = cd.cstr_name in - let spat = Printf.sprintf "%s" ("case \"" ^ c ^ "\"") in + let spat = if is_sbool c then ppf_match_case c else ppf_match_case ("\"" ^ c ^ "\"") in let params = extract_attrs cd.cstr_attributes in - let binders = - if List.length el = 0 then "" - else Printf.sprintf "@[<v 0>%s@]" - ("var " ^ show_list ", " (List.map2 (fun x y -> x ^ " = " ^ obj ^ "." ^ y) (List.map (fun x -> fst (js_of_pattern x obj)) el) params) ^ ";") in + let binder var field = (match var.pat_desc with + | Tpat_var (id, _) -> ppf_match_binder (Ident.name id) ~obj field + | Tpat_any -> "" + | _ -> out_of_scope var.pat_loc "Nested pattern matching") in + let binders = if el = [] then "" else ppf_match_binders (List.map2 binder el params) in spat, binders | Tpat_tuple el -> unsupported ~loc "tuple matching" | Tpat_array el -> unsupported ~loc "array-match" diff --git a/generator/tests/let.ml b/generator/tests/let.ml index a27ee5d..b117838 100644 --- a/generator/tests/let.ml +++ b/generator/tests/let.ml @@ -17,3 +17,12 @@ let affiche x = match x with let pet = Petite 5 let cinq = 5 + +let test b = match b with + | true -> () + | false -> () + +let test x = match x with + | 1 -> () + | 2 -> () + | _ -> () -- GitLab