(* Running dispatchers *) open Value open Ident open Patterns.Compile (* module Array = struct include Array let get = unsafe_get end *) let make_result_prod v1 r1 v2 r2 v (code,r) = let ret = Array.map (function | Catch -> v | Const c -> const c | Left i -> if (i < 0) then v1 else r1.(i) | Right j -> if (j < 0) then v2 else r2.(j) | Recompose (i,j) -> Pair ((if (i < 0) then v1 else r1.(i)), (if (j < 0) then v2 else r2.(j))) ) r in (code,ret) let make_result_basic v (code,r) = let ret = Array.map (function | Catch -> v | Const c -> const c | _ -> assert false ) r in (code,ret) let make_result_char ch (code,r) = let ret = Array.map (function | Catch -> Char ch | Const c -> const c | _ -> assert false ) r in (code,ret) let tail_string i j s q = if i + 1 = j then q else String (i + 1,j,s,q) let make_result_string i j s q r1 r2 (code,r) = let ret = Array.map (function | Catch -> String (i,j,s,q) | Const c -> const c | Left n -> if (n < 0) then Char (Chars.mk_char s.[i]) else r1.(n) | Right m -> if (m < 0) then tail_string i j s q else r2.(m) | Recompose (n,m) -> Pair ((if (n < 0) then Char (Chars.mk_char s.[i]) else r1.(n)), (if (m < 0) then tail_string i j s q else r2.(m))) ) r in (code,ret) let rec run_disp_basic v f = function | [(_,r)] -> make_result_basic v r | (t,r)::rem -> if f t then make_result_basic v r else run_disp_basic v f rem | _ -> assert false let dummy_r = [||] let rec run_dispatcher d v = (* Format.fprintf Format.std_formatter "Matching (%a) with:@\n" Value.print v; Patterns.Compile.print_dispatcher Format.std_formatter d; *) match actions d with | AIgnore r -> make_result_basic v r | AKind k -> run_disp_kind k v and run_disp_kind actions v = match v with | Pair (v1,v2) -> run_disp_prod v v1 v2 actions.prod | Xml (v1,v2) -> run_disp_prod v v1 v2 actions.xml | Record r -> run_disp_record false v (LabelMap.get r) actions.record | String (i,j,s,q) -> run_disp_string i j s q actions | Atom a -> make_result_basic v (Atoms.get_map a actions.atoms) | Char c -> make_result_basic v (Chars.get_map c actions.chars) | Integer i -> run_disp_basic v (fun t -> Types.Int.has_int t i) actions.basic | Abstraction (iface,_) -> run_disp_basic v (fun t -> Types.Arrow.check_iface iface t) actions.basic | Absent -> run_disp_basic v (fun t -> Types.Record.has_absent t) actions.basic | v -> run_disp_kind actions (normalize v) and run_disp_prod v v1 v2 = function | Impossible -> assert false | TailCall d1 -> run_dispatcher d1 v1 | Ignore d2 -> run_disp_prod2 v1 dummy_r v v2 d2 | Dispatch (d1,b1) -> let (code1,r1) = run_dispatcher d1 v1 in run_disp_prod2 v1 r1 v v2 b1.(code1) and run_disp_prod2 v1 r1 v v2 = function | Impossible -> assert false | Ignore r -> make_result_prod v1 r1 v2 dummy_r v r | TailCall d2 -> run_dispatcher d2 v2 | Dispatch (d2,b2) -> let (code2,r2) = run_dispatcher d2 v2 in make_result_prod v1 r1 v2 r2 v b2.(code2) and run_disp_record other v fields = function | None -> assert false | Some (RecLabel (l,d)) -> let rec aux other = function | (l1,_) :: rem when l1 < l -> aux true rem | (l1,vl) :: rem when l1 = l -> run_disp_record1 other vl rem d | rem -> run_disp_record1 other Absent rem d in aux other fields | Some (RecNolabel (some,none)) -> let r = if other then some else none in match r with | Some r -> make_result_basic v r | None -> assert false and run_disp_record1 other v1 rem = function | Impossible -> assert false | TailCall d1 -> run_dispatcher d1 v1 | Ignore d2 -> run_disp_record2 other v1 dummy_r rem d2 | Dispatch (d1,b1) -> let (code1,r1) = run_dispatcher d1 v1 in run_disp_record2 other v1 r1 rem b1.(code1) and run_disp_record2 other v1 r1 rem = function | Impossible -> assert false | Ignore r -> make_result_prod v1 r1 Absent dummy_r Absent r | TailCall d2 -> run_disp_record_loop other rem d2 | Dispatch (d2,b2) -> let (code2,r2) = run_disp_record_loop other rem d2 in make_result_prod v1 r1 Absent r2 Absent b2.(code2) and run_disp_record_loop other rem d = match actions d with | AIgnore r -> make_result_basic Absent r | AKind k -> run_disp_record other Absent rem k.record and run_disp_string i j s q actions = if i = j then run_disp_kind actions q else match actions.prod with | Impossible -> assert false | TailCall d1 -> run_disp_string_char d1 (Chars.mk_char s.[i]) | Ignore d2 -> run_disp_string2 dummy_r i j s q d2 | Dispatch (d1,b1) -> let (code1,r1) = run_disp_string_char d1 (Chars.mk_char s.[i]) in run_disp_string2 r1 i j s q b1.(code1) and run_disp_string_char d ch = match actions d with | AIgnore r -> make_result_char ch r | AKind k -> make_result_char ch (Chars.get_map ch k.chars) and run_disp_string2 r1 i j s q = function | Impossible -> assert false | Ignore r -> make_result_string i j s q r1 dummy_r r | TailCall d2 -> run_disp_string_loop i j s q d2 | Dispatch (d2,b2) -> let (code2,r2) = run_disp_string_loop i j s q d2 in make_result_string i j s q r1 r2 b2.(code2) and run_disp_string_loop i j s q d = match actions d with | AIgnore r -> make_result_basic Absent r | AKind k -> run_disp_string (succ i) j s q k (* TODO: finir d'implémenter les capture pour les string ... *)