From f9a7f229c52110978e624b2c4ea883546e2e6adc Mon Sep 17 00:00:00 2001 From: charguer <arthur@chargueraud.org> Date: Wed, 6 Apr 2016 09:08:33 +0200 Subject: [PATCH] convert --- generator/parse_type.ml | 2 + generator/tests/jsref/JsInterpreter.ml | 94 ++++---- generator/tests/jsref/JsInterpreterMonads.ml | 7 + .../tests/jsref/convert_monads_to_ppx.php | 224 ++++++++++++++++++ 4 files changed, 284 insertions(+), 43 deletions(-) create mode 100644 generator/tests/jsref/convert_monads_to_ppx.php diff --git a/generator/parse_type.ml b/generator/parse_type.ml index 71a81c9..96beaf6 100644 --- a/generator/parse_type.ml +++ b/generator/parse_type.ml @@ -59,6 +59,8 @@ exception Outdated_version (** Parse a file or get a dumped syntax tree in it *) let parse_file inputfile parse_fun ast_magic = +(* TODO new version is: + let (ic, is_ast_file) = open_and_check_magic inputfile ast_magic in *) let ic = open_in_bin inputfile in let is_ast_file = try diff --git a/generator/tests/jsref/JsInterpreter.ml b/generator/tests/jsref/JsInterpreter.ml index 153775e..458c6c0 100644 --- a/generator/tests/jsref/JsInterpreter.ml +++ b/generator/tests/jsref/JsInterpreter.ml @@ -364,7 +364,7 @@ and object_get_builtin s c b vthis l x = | Coq_builtin_get_function -> function0 s | Coq_builtin_get_args_obj -> if_some (run_object_method object_parameter_map_ s l) (fun lmapo -> - if_some lmapo (fun lmap -> + if_some (lmapo) (fun lmap -> if_spec (run_object_get_own_prop s c lmap x) (fun s0 d -> match d with @@ -883,7 +883,7 @@ and object_define_own_prop s c l x desc throwcont = ("Array length property descriptor cannot be accessor."))) | Coq_builtin_define_own_prop_args_obj -> if_some (run_object_method object_parameter_map_ s l) (fun lmapo -> - if_some lmapo (fun lmap -> + if_some (lmapo) (fun lmap -> if_spec (run_object_get_own_prop s c lmap x) (fun s0 d -> if_bool (def s0 x desc false) (fun s1 b0 -> @@ -926,7 +926,13 @@ and run_to_descriptor s c _foo_ = match _foo_ with if neg has then k s1 desc else if_value (run_object_get s1 c l name) (fun s2 v0 -> - if_spec (conv s2 v0 desc) k)) + if_spec (conv s2 v0 desc) (fun s3 r -> k s3 r))) + (*let%bool (s1,has) = object_has_prop s0 c l name in + if neg has + then k s1 desc + else let%value (s2,v0) = run_object_get s1 c l name in + let%spec (s3,r) = conv s2 v0 desc in + k s3 r))*) in sub0 s descriptor_intro_empty ("enumerable") @@ -1051,7 +1057,7 @@ and to_object s _foo_ = match _foo_ with and run_object_prim_value s l = if_some (run_object_method object_prim_value_ s l) (fun ov -> - if_some ov (fun v -> res_ter s (res_val v))) + if_some (ov) (fun v -> res_ter s (res_val v))) (** val prim_value_get : state -> execution_ctx -> value -> prop_name -> result **) @@ -1114,7 +1120,7 @@ and object_delete s c l x str = | Coq_builtin_delete_default -> object_delete_default s c l x str | Coq_builtin_delete_args_obj -> if_some (run_object_method object_parameter_map_ s l) (fun mo -> - if_some mo (fun m -> + if_some (mo) (fun m -> if_spec (run_object_get_own_prop s c m x) (fun s1 d -> if_bool (object_delete_default s1 c l x str) (fun s2 b0 -> if b0 @@ -1217,14 +1223,14 @@ and ref_get_value s c _foo_ = match _foo_ with match r.ref_base with | Coq_ref_base_type_value v -> if ref_kind_comparable (ref_kind_of r) Coq_ref_kind_primitive_base - then if_value (prim_value_get s c v r.ref_name) res_spec + then if_value (prim_value_get s c v r.ref_name) (fun s2 v -> res_spec s2 v) else (match v with | Coq_value_prim p -> (fun s m -> Debug.impossible_with_heap_because __LOC__ s m; Coq_result_impossible) s ("[ref_get_value] received a primitive value whose kind is not primitive.") | Coq_value_object l -> - if_value (run_object_get s c l r.ref_name) res_spec) + if_value (run_object_get s c l r.ref_name) (fun s2 v -> res_spec s2 v)) | Coq_ref_base_type_env_loc l -> (fun s m -> Debug.impossible_with_heap_because __LOC__ s m; Coq_result_impossible) s @@ -1247,7 +1253,7 @@ and ref_get_value s c _foo_ = match _foo_ with | Coq_ref_base_type_env_loc l -> if_value (env_record_get_binding_value s c l r.ref_name r.ref_strict) - res_spec)) + (fun s2 v -> res_spec s2 v))) (* DEBUG and ref_get_value runs s c r = @@ -1872,12 +1878,12 @@ and run_construct s c co l args = | Coq_construct_default -> run_construct_default s c l args | Coq_construct_after_bind -> if_some (run_object_method object_target_function_ s l) (fun otrg -> - if_some otrg (fun target -> + if_some (otrg) (fun target -> if_some (run_object_method object_construct_ s target) (fun oco -> match oco with | Some co0 -> if_some (run_object_method object_bound_args_ s l) (fun oarg -> - if_some oarg (fun boundArgs -> + if_some (oarg) (fun boundArgs -> let_binding (LibList.append boundArgs args) (fun arguments_ -> run_construct s c co0 target arguments_))) | None -> run_error s Coq_native_error_type))) @@ -1998,13 +2004,14 @@ and binding_inst_formal_params s c l args names str = then follow s1 else if_void (env_record_create_mutable_binding s1 c l argname - None) follow)))) + None) (fun s2 -> follow s2))))) (** val binding_inst_function_decls : state -> execution_ctx -> env_loc -> funcdecl list -> strictness_flag -> bool -> result_void **) and binding_inst_function_decls s c l fds str bconfig = + match fds with | [] -> res_void s | fd :: fds_2 -> @@ -2063,7 +2070,7 @@ and binding_inst_function_decls s c l fds str bconfig = else follow s2 else if_void (env_record_create_mutable_binding s2 c l - fname (Some bconfig)) follow))))))) + fname (Some bconfig)) (fun s3 -> follow s3)))))))) (** val make_arg_getter : state -> execution_ctx -> prop_name -> lexical_env -> result **) @@ -2248,7 +2255,7 @@ and binding_inst_var_decls s c l vds bconfig str = then bivd s1 else if_void (env_record_create_set_mutable_binding s1 c l vd (Some - bconfig) (Coq_value_prim Coq_prim_undef) str) bivd)) + bconfig) (Coq_value_prim Coq_prim_undef) str) (fun s2 -> bivd s2))) (** val execution_ctx_binding_inst : state -> execution_ctx -> codetype -> object_loc option -> @@ -2285,7 +2292,7 @@ and execution_ctx_binding_inst s c ct funco p args = then follow2 s2 else if_void (binding_inst_arg_obj s2 c func p names - args l) follow2 + args l) (fun s3 -> follow2 s3) | None -> if bdefined then follow2 s2 @@ -2300,7 +2307,7 @@ and execution_ctx_binding_inst s c ct funco p args = | Some func -> if_some (run_object_method object_formal_parameters_ s func) (fun nameso -> - if_some nameso (fun names -> + if_some (nameso) (fun names -> if_void (binding_inst_formal_params s c l args names str) (fun s_2 -> follow s_2 names))) @@ -2329,11 +2336,11 @@ and execution_ctx_binding_inst s c ct funco p args = and entering_func_code s c lf vthis args = if_some (run_object_method object_code_ s lf) (fun bdo -> - if_some bdo (fun bd -> + if_some (bdo) (fun bd -> let_binding (funcbody_is_strict bd) (fun str -> let_binding (fun s_2 vthis_2 -> if_some (run_object_method object_scope_ s_2 lf) (fun lexo -> - if_some lexo (fun lex -> + if_some (lexo) (fun lex -> let_binding (lexical_env_alloc_decl s_2 lex) (fun p -> let (lex_2, s1) = p in let_binding (execution_ctx_intro_same lex_2 vthis_2 str) @@ -2353,10 +2360,10 @@ and entering_func_code s c lf vthis args = | Coq_prim_null -> follow s (Coq_value_object (Coq_object_loc_prealloc Coq_prealloc_global)) - | Coq_prim_bool b -> if_value (to_object s vthis) follow - | Coq_prim_number n -> if_value (to_object s vthis) follow + | Coq_prim_bool b -> if_value (to_object s vthis) (fun s2 v -> follow s2 v) + | Coq_prim_number n -> if_value (to_object s vthis) (fun s2 v -> follow s2 v) | Coq_prim_string s0 -> - if_value (to_object s vthis) follow) + if_value (to_object s vthis) (fun s2 v -> follow s2 v)) | Coq_value_object lthis -> follow s vthis))))) (** val run_object_get_own_prop : @@ -2382,7 +2389,7 @@ and run_object_get_own_prop s c l x = | Coq_full_descriptor_some a -> if_some (run_object_method object_parameter_map_ s1 l) (fun lmapo -> - if_some lmapo (fun lmap -> + if_some (lmapo) (fun lmap -> if_spec (run_object_get_own_prop s1 c lmap x) (fun s2 d0 -> let_binding (fun s_2 a0 -> @@ -2479,7 +2486,7 @@ and run_object_has_instance s c b l v = lproto))) | Coq_builtin_has_instance_after_bind -> if_some (run_object_method object_target_function_ s l) (fun ol -> - if_some ol (fun l0 -> + if_some (ol) (fun l0 -> if_some (run_object_method object_has_instance_ s l0) (fun ob -> match ob with | Some b0 -> run_object_has_instance s c b0 l0 v @@ -2528,7 +2535,7 @@ and from_prop_descriptor s c _foo_ = match _foo_ with (object_define_own_prop s2 c l ("writable") (descriptor_of_attributes (Coq_attributes_data_of a2)) - throw_false) follow))) + throw_false) (fun s3 v -> follow s3 v)))) | Coq_attributes_accessor_of aa -> let_binding (attributes_data_intro_all_true aa.attributes_accessor_get) @@ -2543,7 +2550,8 @@ and from_prop_descriptor s c _foo_ = match _foo_ with if_bool (object_define_own_prop s2 c l ("set") (descriptor_of_attributes (Coq_attributes_data_of a2)) - throw_false) follow))))) + throw_false) (fun s3 v -> follow s3 v)))) + )) (** val is_lazy_op : binary_op -> bool option **) @@ -2762,21 +2770,21 @@ and convert_twice : specres **) and convert_twice_primitive s c v1 v2 = - convert_twice if_prim (fun s0 v -> to_primitive s0 c v None) s v1 v2 + convert_twice ifx_prim (fun s0 v -> to_primitive s0 c v None) s v1 v2 (** val convert_twice_number : state -> execution_ctx -> value -> value -> (number * number) specres **) and convert_twice_number s c v1 v2 = - convert_twice if_number (fun s0 v -> to_number s0 c v) s v1 v2 + convert_twice ifx_number (fun s0 v -> to_number s0 c v) s v1 v2 (** val convert_twice_string : state -> execution_ctx -> value -> value -> (string * string) specres **) and convert_twice_string s c v1 v2 = - convert_twice if_string (fun s0 v -> to_string s0 c v) s v1 v2 + convert_twice ifx_string (fun s0 v -> to_string s0 c v) s v1 v2 (** val issome : 'a1 option -> bool **) @@ -2791,8 +2799,8 @@ match _foo_ with and run_binary_op s c op v1 v2 = if binary_op_comparable op Coq_binary_op_add - then (* if_spec (convert_twice_primitive s c v1 v2) (fun s1 ww ->*) - (let%spec (s1,ww) = convert_twice_primitive s c v1 v2 in + then if_spec (convert_twice_primitive s c v1 v2) (fun s1 ww -> + (* let%spec (s1,ww) = convert_twice_primitive s c v1 v2 in *) let (w1, w2) = ww in if or_decidable (type_comparable (type_of (Coq_value_prim w1)) Coq_type_string) @@ -3188,7 +3196,7 @@ and run_block s c _foo_ = match _foo_ with | [] -> res_ter s (res_normal Coq_resvalue_empty) | t :: ts_rev_2 -> if_success (run_block s c ts_rev_2) (fun s0 rv0 -> - if_success_state rv0 (run_stat s0 c t) (fun x x0 -> + ifx_success_state rv0 (run_stat s0 c t) (fun x x0 -> result_out (Coq_out_ter (x, (res_normal x0))))) (** val run_expr_binary_op : @@ -3246,7 +3254,7 @@ and run_expr_assign s c opo e1 e2 = | Some op -> if_spec (ref_get_value s1 c rv1) (fun s2 v1 -> if_spec (run_expr_get_value s2 c e2) (fun s3 v2 -> - if_success (run_binary_op s3 c op v1 v2) follow)) + if_success (run_binary_op s3 c op v1 v2) (fun s4 v -> follow s4 v))) | None -> if_spec (run_expr_get_value s1 c e2) (fun x x0 -> follow x (Coq_resvalue_value x0)))) @@ -3389,7 +3397,7 @@ and run_expr_call s c e1 e2s = s3 ("[run_expr_call] unable to call a non-property function.") | Coq_ref_base_type_env_loc l0 -> - if_some (env_record_implicit_this_value s3 l0) follow)) + if_some (env_record_implicit_this_value s3 l0) (fun s4 v -> follow s4 v))) else run_error s3 Coq_native_error_type)))) (** val run_expr_conditionnal : @@ -3493,7 +3501,7 @@ and run_stat_switch_end s c rv _foo_ = match _foo_ with | [] -> result_out (Coq_out_ter (s, (res_normal rv))) | y :: scs_2 -> match y with Coq_switchclause_intro (e, ts) -> - if_success_state rv (run_block s c (rev ts)) (fun s1 rv1 -> + ifx_success_state rv (run_block s c (rev ts)) (fun s1 rv1 -> run_stat_switch_end s1 c rv1 scs_2) (** val run_stat_switch_no_default : @@ -3547,7 +3555,7 @@ and run_stat_switch_with_default_A s c found vi rv scs1 ts0 scs2 = | y :: scs_2 -> match y with Coq_switchclause_intro (e, ts) -> let_binding (fun s0 -> - if_success_state rv (run_block s0 c (rev ts)) (fun s1 rv0 -> + ifx_success_state rv (run_block s0 c (rev ts)) (fun s1 rv0 -> run_stat_switch_with_default_A s1 c true vi rv0 scs_2 ts0 scs2)) (fun follow -> if found @@ -3636,7 +3644,7 @@ and run_stat_try s c t1 t2o t3o = (env_record_create_set_mutable_binding s_2 c l x None v throw_irrelevant) (fun s2 -> let c_2 = execution_ctx_with_lex c lex_2 in - if_ter (run_stat s2 c_2 t2) finallycont)))) + if_ter (run_stat s2 c_2 t2) (fun s3 r -> finallycont s3 r))))) | None -> finallycont s1 (res_throw (Coq_resvalue_value v)))) (** val run_stat_throw : @@ -3946,7 +3954,7 @@ and run_get_args_for_apply s c l index n = let_binding (run_get_args_for_apply s1 c l (index +. 1.) n) (fun tail_args -> - if_spec tail_args (fun s2 tail -> res_spec s2 (v :: tail))))) + if_spec (tail_args) (fun s2 tail -> res_spec s2 (v :: tail))))) else res_spec s [] (** val valueToStringForJoin : @@ -3980,7 +3988,7 @@ and run_array_join_elements s c l k length0 sep sR = if k < length0 then let_binding (strappend sR sep) (fun ss -> let_binding (valueToStringForJoin s c l k) (fun sE -> - if_spec sE (fun s0 element -> + if_spec (sE) (fun s0 element -> let_binding (strappend ss element) (fun sR0 -> run_array_join_elements s0 c l (k +. 1.) length0 sep sR0)))) @@ -4270,7 +4278,7 @@ and run_call_prealloc s c b vthis args = (ilen -. (number_of_int (LibList.length a))))) else res_spec s_2 0.)) (fun vlength -> - if_spec vlength (fun s10 length0 -> + if_spec (vlength) (fun s10 length0 -> let_binding { attributes_data_value = (Coq_value_prim (Coq_prim_number (of_int length0))); @@ -4470,7 +4478,7 @@ and run_call_prealloc s c b vthis args = (res_val (Coq_value_prim (Coq_prim_string ""))) else let_binding (valueToStringForJoin s3 c l 0.) (fun sR -> - if_spec sR (fun s4 sR0 -> + if_spec (sR) (fun s4 sR0 -> run_array_join_elements s4 c l 1. ilen sep sR0)))))))) | Coq_prealloc_array_proto_pop -> if_object (to_object s vthis) (fun s0 l -> @@ -4557,17 +4565,17 @@ and run_call_prealloc s c b vthis args = and run_call s c l vthis args = if_some (run_object_method object_call_ s l) (fun co -> - if_some co (fun c0 -> + if_some (co) (fun c0 -> match c0 with | Coq_call_default -> entering_func_code s c l vthis args | Coq_call_after_bind -> if_some (run_object_method object_bound_args_ s l) (fun oarg -> - if_some oarg (fun boundArgs -> + if_some (oarg) (fun boundArgs -> if_some (run_object_method object_bound_this_ s l) (fun obnd -> - if_some obnd (fun boundThis -> + if_some (obnd) (fun boundThis -> if_some (run_object_method object_target_function_ s l) (fun otrg -> - if_some otrg (fun target -> + if_some (otrg) (fun target -> let_binding (LibList.append boundArgs args) (fun arguments_ -> run_call s c target boundThis arguments_))))))) diff --git a/generator/tests/jsref/JsInterpreterMonads.ml b/generator/tests/jsref/JsInterpreterMonads.ml index 3912e4f..15e0a29 100644 --- a/generator/tests/jsref/JsInterpreterMonads.ml +++ b/generator/tests/jsref/JsInterpreterMonads.ml @@ -381,3 +381,10 @@ let if_spec w k = | Coq_specret_val (s0, a) -> k s0 a | Coq_specret_out o -> if_abort o (fun x -> res_out o)) + + + +let ifx_prim w k = if_prim w k +let ifx_number w k = ifx_number w k +let ifx_string w k = ifx_string w k +let ifx_success_state a b c = if_success_state a b c diff --git a/generator/tests/jsref/convert_monads_to_ppx.php b/generator/tests/jsref/convert_monads_to_ppx.php new file mode 100644 index 0000000..f9db8ff --- /dev/null +++ b/generator/tests/jsref/convert_monads_to_ppx.php @@ -0,0 +1,224 @@ +<?php + +// usage: php -f convert_monads_to_ppx.php + +/* +$x = "aa"; +$y = $x; +$y[1] = "c"; +//$x[0] = "b"; +//$x[1] = "d"; +printf("%s %s\n", $x, $y); +*/ + + +$input = "JsInterpreter.ml"; +$output = "JsOutput.ml"; + +$sinput = file_get_contents($input); +/* + +$sinput = <<<EOF + + +and run_expr_assign s c opo e1 e2 = + if_success (run_expr s c e1) (fun s1 rv1 -> + let_binding (fun s0 rv_2 -> + match rv_2 with + | Coq_resvalue_empty -> + (fun s m -> Debug.impossible_with_heap_because __LOC__ s m; Coq_result_impossible) + s0 + ("Non-value result in [run_expr_assign].") + | Coq_resvalue_value v -> + if_void (ref_put_value s0 c rv1 v) (fun s_2 -> + result_out (Coq_out_ter (s_2, (res_val v)))) + | Coq_resvalue_ref r -> + (fun s m -> Debug.impossible_with_heap_because __LOC__ s m; Coq_result_impossible) + s0 + ("Non-value result in [run_expr_assign].")) + (fun follow -> + match opo with + | Some op -> + if_spec (ref_get_value s1 c rv1) (fun s2 v1 -> + if_spec (run_expr_get_value s2 c e2) (fun s3 v2 -> + if_success (run_binary_op s3 c op v1 v2) (fun s4 v -> follow s4 v))) + | None -> + if_spec (run_expr_get_value s1 c e2) (fun x x0 -> + follow x (Coq_resvalue_value x0)))) +EOF; +*/ +$ninput = strlen($sinput); + +/* +$matches = array(); +$n = preg_match('/\G\s*run_([^ ]*)/', $sinput, $matches, PREG_OFFSET_CAPTURE, 3); +print_r($matches); +exit; +*/ +//printf("%d\n", $n); + + +//printf("%s\n", $sinput); + +/* +let if_some op k = +let if_some_or_default o d k = +let if_result_some w k = +let if_out_some w k = +let if_ter w k = +let if_success_state rv w k = +let if_success w k = +let if_void w k = +let if_not_throw w k = +let if_any_or_throw w k1 k2 = +let if_success_or_return w k1 k2 = +let if_break w k = +let if_value w k = +let if_bool w k = +let if_object w k = +let if_string w k = +let if_number w k = +let if_prim w k = +let if_abort o k = +let if_spec w k = +*/ + +function fail($s, $i) { + global $sinput; + printf("error: %s\n", $s); + printf("at: %s\n", substr($sinput, $i, 200)); + exit(1); +} + + +// return index of matching parent +function matching_parenthesis($iOpenParent) { + global $sinput, $ninput; + if ($sinput[$iOpenParent] != "(") { + fail("matching not open", $iOpenParent); + } + $d = 1; + for ($i = $iOpenParent+1; $i < $ninput; $i++) { + $c = $sinput[$i]; + if ($c == '(') { + $d++; + } else if ($c == ')') { + $d--; + if ($d == 0) { + return $i; + } + } + } + return -1; +} + + +$soutput = ''; + +function process($start, $stop) { + //printf("process %d to %d\n", $start, $stop); + global $sinput, $soutput; + for ($i = $start; $i <= $stop;) { + $matches = array(); + $n = preg_match('/if_([^ \n]*)/', $sinput, $matches, PREG_OFFSET_CAPTURE, $i); + if ($n != 1) { + break; + } + $occ = $matches[0][1]; + if ($occ > $stop) { + break; + } + $npat = strlen($matches[0][0]); + $key = $matches[1][0]; + if ($key == "some_or_default" || $key == "empty_label" || $key == "any_or_throw" || $key == "empty") { + $i = $occ+1; + continue; + } + //printf("in %d to %d, offset %d, found %s at %s\n", $start, $stop, $i, $key, $occ); + //print_r($matches); + $matches1 = $matches; + $add = substr($sinput, $i, ($occ-1) - $i + 1); + $soutput .= $add; + + $n = preg_match('/\G\s*(\()/', $sinput, $matches, PREG_OFFSET_CAPTURE, $occ + $npat); + if ($n != 1) { + fail("no open parent for first arg of monad", $occ); + } + $open = $matches[1][1]; + if ($open > $stop) { + fail("no open parent for first arg of monad", $occ); + } + $close = matching_parenthesis($open); + //printf("-- first open from %d to %d\n", $open, $close); + if ($close == -1 || $close > $stop) { + fail("unclosed first parent", $open); + } + + $matches = array(); + $n = preg_match('/\G\s*(\(fun(.*?)->[ ]*)/', $sinput, $matches, PREG_OFFSET_CAPTURE, $close+1); + if ($n != 1) { + printf("key = '%s'\n", $key); + printf("when: %s\n", substr($sinput, $occ, 100)); + fail("no bopen parent for second arg of monad", $close+1); + } + $bopen = $matches[1][1]; + if ($bopen > $stop) { + fail("no bopen parent for second arg of monad", $occ); + } + //print_r($matches); + $bsize = strlen($matches[1][0]); + $args = $matches[2][0]; + // printf("args=%s\n", $args); + $args_pieces = preg_split('/\s+/', $args, NULL, PREG_SPLIT_NO_EMPTY); + // print_r($args_pieces); + if (count($args_pieces) == 1) { + $arg = $args_pieces[0]; + } else if (count($args_pieces) == 2) { + $arg = "(" . $args_pieces[0] . "," . $args_pieces[1] . ")"; + } else { + printf("when: %s\n", substr($sinput, $i, 100)); + printf("added: %s\n", $add); + print_r($matches1); + print_r($matches); + print_r($args_pieces); + fail("invalid count for pieces: " . count($args_pieces), $close); + } + + $bclose = matching_parenthesis($bopen); + if ($bclose == -1 || $bclose > $stop) { + printf("bclose=%d, stop=%d\n", $bclose, $stop); + printf("bopen: %s\n", substr($sinput, $bopen, 100)); + printf("when: %s\n", substr($sinput, $occ, 100)); + fail("unclosed second parent", $bopen); + } + $sinput[$bclose] = " "; + // &("-- second from %d to %d\n", $bopen, $bclose); + $len = ($close - 1) - ($open + 1) + 1; + $def = substr($sinput, $open + 1, $len); + $add = 'let%' . $key . " " . $arg . ' = ' . $def . " in\n"; + // printf("-- add: %s\n", $add); + $soutput .= $add; + + $sub = $bopen + $bsize; + $n = preg_match('/\G[ ]*(\n)/', $sinput, $matches, PREG_OFFSET_CAPTURE, $sub); + if ($n == 1) { + $sub = $matches[1][1] + 1; + } + process($sub, $bclose - 1); + $i = $bclose + 1; + // printf("-- continue at offset: %d\n", $i); + } + if ($i <= $stop) { + $add = substr($sinput, $i, $stop - $i); + $soutput .= $add; + } + // printf("-- add rest: %s\n", $add); + // printf("return %d to %d\n", $start, $stop); +} + + +process(0, $ninput-1); + file_put_contents($output, $soutput); +// printf("%s\n", $soutput); + +?> \ No newline at end of file -- GitLab