run_dispatch.ml 3.4 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
(* 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

49
50
and run_disp_kind actions v =
  match v with
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  | 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) 


69
70
and run_disp_basic v f x = 
  match x with
71
72
73
74
75
  | [(_,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
  

76
77
and run_disp_prod v v1 v2 x =
  match x with
78
79
80
81
82
83
84
  | `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)

85
86
and run_disp_prod2 v1 r1 v v2 x =
  match x with
87
88
89
90
91
92
93
94
95
  | `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
96
  | Some record -> run_disp_record' f v bindings None fields record
97

98
and run_disp_record' f v bindings abs fields = function
99
  | `Result r -> make_result_record f v bindings r
100
  | `Absent -> run_disp_record f v bindings fields abs
101
102
103
104
  | `Label (l, present, absent) ->
      let rec aux = function
	| (l1,_) :: rem when l1 < l -> aux rem
	| (l1,vl) :: rem when l1 = l -> 
105
	    run_disp_field f v bindings abs rem l vl present
106
107
108
109
	| _ -> run_disp_record f v bindings fields absent
      in
      aux fields

110
and run_disp_field f v bindings abs fields l vl = function
111
  | `None -> assert false
112
  | `Ignore r -> run_disp_record' f v bindings abs fields r
113
114
115
  | `TailCall d -> run_dispatcher d vl
  | `Dispatch (dl,bl) ->
      let (codel,rl) = run_dispatcher dl vl in
116
      run_disp_record' f v ((l,rl)::bindings) abs fields bl.(codel)