(* Running dispatchers *) open Value 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))) | _ -> assert false ) r in (code,ret) let make_result_record fields v bindings (code,r) = let ret = Array.map (function | `Catch -> v | `Const c -> const c | `Field (l,i) -> if (i < 0) then List.assoc l fields else (List.assoc l bindings).(i) | _ -> assert false ) 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 dummy_r = [||] let rec run_dispatcher d v = let actions = Patterns.Compile.actions d in match actions with | `Ignore r -> make_result_basic v r | `Kind 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.Patterns.Compile.prod | Record r -> run_disp_record r v [] r actions.Patterns.Compile.record | Atom a -> run_disp_basic v (fun t -> Types.Atom.has_atom t a) actions.Patterns.Compile.basic | Char c -> run_disp_basic v (fun t -> Types.Char.has_char t c) actions.Patterns.Compile.basic | Integer i -> run_disp_basic v (fun t -> Types.Int.has_int t i) actions.Patterns.Compile.basic | Abstraction (iface,_) -> run_disp_basic v (fun t -> Types.Arrow.check_iface iface t) actions.Patterns.Compile.basic | v -> run_disp_kind actions (normalize v) and run_disp_basic v f x = match x with | [(_,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 and run_disp_prod v v1 v2 x = match x with | `None -> 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 x = match x with | `None -> 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 f v bindings fields = function | None -> assert false | Some record -> run_disp_record' f v bindings None fields record and run_disp_record' f v bindings abs fields = function | `Result r -> make_result_record f v bindings r | `Absent -> run_disp_record f v bindings fields abs | `Label (l, present, absent) -> let rec aux = function | (l1,_) :: rem when l1 < l -> aux rem | (l1,vl) :: rem when l1 = l -> run_disp_field f v bindings abs rem l vl present | _ -> run_disp_record f v bindings fields absent in aux fields and run_disp_field f v bindings abs fields l vl = function | `None -> assert false | `Ignore r -> run_disp_record' f v bindings abs fields r | `TailCall d -> run_dispatcher d vl | `Dispatch (dl,bl) -> let (codel,rl) = run_dispatcher dl vl in run_disp_record' f v ((l,rl)::bindings) abs fields bl.(codel)