/shdl_repr.ml

http://github.com/nicoolas25/ohs · OCaml · 243 lines · 177 code · 40 blank · 26 comment · 6 complexity · bbb48079839d24f7914378f77d200b1d MD5 · raw file

  1. open Shdl_types
  2. (* Internal representation *)
  3. module Ctx =
  4. struct
  5. type value = bool
  6. and index = string
  7. and element = User of (t option -> value list -> value list)
  8. | Base of (unit -> value list -> value list)
  9. | Variable of value list
  10. and t = {
  11. dict : (index, element) Hashtbl.t ;
  12. parent : t option ;
  13. }
  14. exception Index_not_found of index
  15. exception Box_needed of index
  16. exception Variable_needed of index
  17. exception Overriding_error of index
  18. exception Undeclared_error of index
  19. exception Out_of_bound_error of index * int
  20. let create size parent =
  21. { dict = Hashtbl.create size ; parent = parent }
  22. let rec lookup t idx =
  23. try
  24. Hashtbl.find t.dict idx
  25. with Not_found ->
  26. begin
  27. match t.parent with
  28. | None -> raise (Index_not_found(idx))
  29. | Some p -> lookup p idx
  30. end
  31. let register t idx elem =
  32. if Hashtbl.mem t.dict idx then
  33. raise (Overriding_error idx)
  34. else
  35. Hashtbl.add t.dict idx elem
  36. let register_base t idx gen = register t idx (Base gen)
  37. let register_user t idx gen = register t idx (User gen)
  38. let declare =
  39. let rec make_var size acc =
  40. if size = 0 then Variable(acc)
  41. else make_var (size-1) (false::acc)
  42. in
  43. fun t size idx ->
  44. let elem = (make_var size []) in
  45. register t idx elem
  46. let instanciate t idx =
  47. match lookup t idx with
  48. | User gen -> gen (Some t)
  49. | Base gen -> gen ()
  50. | other -> raise (Box_needed idx)
  51. let assign t idx content =
  52. if Hashtbl.mem t.dict idx then
  53. let elem = Variable content in
  54. let _ = Hashtbl.replace t.dict idx elem in
  55. content
  56. else
  57. raise (Undeclared_error idx)
  58. let assign_one =
  59. let rec replace l nth v acc =
  60. match nth, l with
  61. | 0, h::r -> (List.rev (v::acc))@r
  62. | n, h::r -> replace r (n-1) v (h::acc)
  63. | _ -> raise (Invalid_argument "")
  64. in
  65. fun t idx n value ->
  66. try
  67. match Hashtbl.find t.dict idx with
  68. | Variable vl ->
  69. Hashtbl.replace t.dict idx (Variable (replace vl n value []))
  70. | _ -> raise (Variable_needed idx)
  71. with
  72. | Not_found -> raise (Undeclared_error idx)
  73. | Invalid_argument _ -> raise (Out_of_bound_error (idx, n))
  74. let input =
  75. let rec sublist start size l acc =
  76. match start, size, l with
  77. | (0, n, h::t) when n > 0 -> sublist 0 (n-1) t (h::acc)
  78. | (n, _, h::t) when n > 0 -> sublist (n-1) size t acc
  79. | _ -> List.rev acc
  80. in
  81. fun t inputs start size idx ->
  82. let content = sublist start size inputs [] in
  83. assign t idx content
  84. let print t =
  85. Hashtbl.iter
  86. ( fun idx elem -> match elem with
  87. | Variable vl ->
  88. begin
  89. print_string ("var" ^ " : " ^ idx ^ " : ") ;
  90. List.iter
  91. ( fun b -> print_string ((string_of_bool b) ^ ";") )
  92. vl ;
  93. print_newline ()
  94. end
  95. | _ -> print_endline ("box : " ^ idx) )
  96. t.dict
  97. end
  98. (* Examples *)
  99. let toplevel = Ctx.create 10 None
  100. let not_box =
  101. let not_base = fun inputs -> List.map ( fun b -> not b ) inputs in
  102. fun () -> not_base
  103. let _ = Ctx.register_base toplevel "not" not_box
  104. let and_box =
  105. let and_base = fun inputs -> [List.for_all ( fun b -> b ) inputs] in
  106. fun () -> and_base
  107. let _ = Ctx.register_base toplevel "and" and_box
  108. let or_box =
  109. let or_base = fun inputs -> [List.exists ( fun b -> b ) inputs] in
  110. fun () -> or_base
  111. let _ = Ctx.register_base toplevel "or" or_box
  112. (*
  113. let mux parent =
  114. let ctx = Ctx.create 5 parent in
  115. let _ = Ctx.declare ctx 1 "x"
  116. and _ = Ctx.declare ctx 1 "y"
  117. and _ = Ctx.declare ctx 1 "o"
  118. and _ = Ctx.declare ctx 2 "a"
  119. and _ = Ctx.declare ctx 1 "sel"
  120. and f_1 = Ctx.instanciate ctx "and"
  121. and f_2 = Ctx.instanciate ctx "not"
  122. and f_3 = Ctx.instanciate ctx "and"
  123. and f_4 = Ctx.instanciate ctx "or" in
  124. fun ins ->
  125. (* inputs *)
  126. let a = Ctx.input ctx ins 0 2 "a"
  127. and sel = Ctx.input ctx ins 2 1 "sel" in
  128. (* definitions *)
  129. let x = Ctx.assign ctx "x" ( f_1 ([] @ (f_2 sel) @ [List.nth a 0] ) ) in
  130. let y = Ctx.assign ctx "y" ( f_3 ([] @ sel @ [List.nth a 1] ) ) in
  131. let o = Ctx.assign ctx "o" ( f_4 ([] @ x @ y ) ) in
  132. (* result *)
  133. [] @ o
  134. let _ = Ctx.register_user toplevel "mux" mux
  135. *)
  136. (** Generation part **)
  137. type pos = int
  138. type ident_repr = Ctx.index * pos option
  139. type expr_repr = Repr_b of bool
  140. | Repr_v of ident_repr
  141. | Repr_c of (Ctx.value list -> Ctx.value list) * expr_repr list
  142. type def_repr = Repr_d of ident_repr * expr_repr
  143. (* Inputs helper *)
  144. let inputs_fn ctx inputs (Ident(n,s)) ptr =
  145. let _ = Ctx.input ctx inputs ptr s n in
  146. ptr + s
  147. (* Definition helpers *)
  148. let convert_ident (Ident(n,s)) = (n, if s > 0 then Some s else None)
  149. let convert_expr n_translator =
  150. let rec aux = function
  151. | Call(n,exprs) -> Repr_c(n_translator n, List.map aux exprs)
  152. | Boolean b -> Repr_b b
  153. | Value(i) -> Repr_v (convert_ident i)
  154. in
  155. aux
  156. let convert_defs n_translator defs =
  157. List.map
  158. ( fun (Definition(i,e)) ->
  159. Repr_d(convert_ident i, convert_expr n_translator e) )
  160. defs
  161. let expr_eval ctx =
  162. let rec aux = function
  163. | Repr_b b -> [b]
  164. | Repr_v(idx, pos) ->
  165. begin
  166. match Ctx.lookup ctx idx with
  167. | Ctx.Variable vl ->
  168. begin
  169. match pos with
  170. | None -> vl
  171. | Some n -> [List.nth vl n]
  172. end
  173. | _ -> raise (Ctx.Variable_needed idx)
  174. end
  175. | Repr_c(f, inputs) -> f (List.flatten (List.map aux inputs))
  176. in
  177. fun expr -> aux expr
  178. let def_eval ctx (Repr_d((idx,pos), expr)) =
  179. match pos with
  180. | None -> ignore (Ctx.assign ctx idx (expr_eval ctx expr))
  181. | Some n -> Ctx.assign_one ctx idx n (List.hd (expr_eval ctx expr))
  182. let generate_box box =
  183. let Box(_, ins, outs, vars, defs) = box in
  184. let all_ident = List.flatten [ins ; outs ; vars] in
  185. let ident_asc = List.map (fun (Ident(n,s)) -> (n,s)) all_ident in
  186. let ctx_size = List.fold_left (fun sum (_, a) -> sum + a) 0 ident_asc in
  187. fun parent ->
  188. let ctx = Ctx.create ctx_size parent in
  189. (* Declarations *)
  190. List.iter ( fun (n,s) -> Ctx.declare ctx s n ) ident_asc ;
  191. let defs_r = convert_defs ( fun call -> Ctx.instanciate ctx call ) defs in
  192. (* TODO: Get aux box *)
  193. fun inputs ->
  194. (* TODO: Inputs *)
  195. let _ = List.fold_right (inputs_fn ctx inputs) ins 0 in
  196. (* TODO: Definitions *)
  197. List.iter (def_eval ctx) defs_r ;
  198. (* TODO: Ouputs *)
  199. List.fold_left
  200. ( fun acc (Ident(n,_)) ->
  201. acc@(expr_eval ctx (Repr_v(n, None))) )
  202. []
  203. outs