aboutsummaryrefslogtreecommitdiff
path: root/src/expressions/evaluate.ml
diff options
context:
space:
mode:
Diffstat (limited to 'src/expressions/evaluate.ml')
-rwxr-xr-xsrc/expressions/evaluate.ml142
1 files changed, 142 insertions, 0 deletions
diff --git a/src/expressions/evaluate.ml b/src/expressions/evaluate.ml
new file mode 100755
index 0000000..e910c19
--- /dev/null
+++ b/src/expressions/evaluate.ml
@@ -0,0 +1,142 @@
+(** Internal representation for each type *)
+type 'a value =
+ | Bool: DataType.Bool.t -> DataType.Bool.t value
+ | Num: DataType.Num.t ScTypes.DataFormat.t * DataType.Num.t -> DataType.Num.t value
+ | String: DataType.String.t -> DataType.String.t value
+ | List: 'a ScTypes.DataFormat.t * 'a list -> 'a list value
+ | Matrix: 'a ScTypes.DataFormat.t * 'a list list -> 'a list list value
+
+type existencialResult =
+ | Result : 'a value -> existencialResult [@@unboxed]
+
+type t = (Functions.C.t * (int * int -> ScTypes.Result.t option))
+
+type repr = existencialResult
+
+type obs = ScTypes.Result.t
+
+module T:Sym_type.SYM_TYPE with type 'a obs = existencialResult = struct
+
+ type 'a t = 'a value
+
+ type 'a obs = existencialResult
+
+ let str s = String s
+
+ let num n = Num (ScTypes.DataFormat.Number, n)
+
+ let date d = Num (ScTypes.DataFormat.Date, d)
+
+ let bool b = Bool b
+
+ let observe x = Result x
+
+end
+
+module R = Eval_ref
+
+(** Extract the type and the content from a value *)
+let get_argument: type a. a value -> a Functions.typ * a = function
+ | Bool b -> Functions.t_bool, b
+ | Num (_, n) -> Functions.t_int, n
+ | String s -> Functions.t_string, s
+ | List (t, l) -> Functions.t_list (Functions.typ_of_format t), l
+ | Matrix (t, l) -> Functions.t_list (Functions.t_list (Functions.typ_of_format t)), l
+
+let wrap_call (Functions.C.R(ret, res)) type_builder = begin
+ let returnType = ScTypes.ReturnType.guess_format_result ret type_builder in
+ begin match returnType with
+ | ScTypes.DataFormat.Bool -> T.observe (T.bool res)
+ | ScTypes.DataFormat.String -> T.observe (T.str res)
+ | ScTypes.DataFormat.Number -> T.observe (T.num res)
+ | ScTypes.DataFormat.Date -> T.observe (T.date res)
+ end
+end
+
+(** Extract the format from a list of results *)
+let build_format_list ll =
+
+ List.map (fun (Result x) ->
+ begin match x with
+ | Bool _ -> ScTypes.DataFormat.F (ScTypes.DataFormat.Bool)
+ | Num (x, _) -> ScTypes.DataFormat.F x
+ | String _ -> ScTypes.DataFormat.F (ScTypes.DataFormat.String)
+ | List (f, _) -> ScTypes.DataFormat.F f
+ | Matrix (f, _) -> ScTypes.DataFormat.F f
+ end
+ ) ll
+
+let value v _ = T.observe v
+
+let ref r (_, mapper) = begin
+ match R.observe r mapper with
+ | R.Value (f, res) -> begin match f with
+ | ScTypes.DataFormat.Bool -> T.observe (T.bool res)
+ | ScTypes.DataFormat.String -> T.observe (T.str res)
+ | ScTypes.DataFormat.Number -> T.observe (T.num res)
+ | ScTypes.DataFormat.Date -> T.observe (T.date res)
+ end
+ | R.List (t, l) -> Result (List(t, l))
+ | R.Matrix (t, l) -> Result (Matrix(t, l))
+end
+
+let call0 ident (catalog, _) =
+ let name' = UTF8.to_utf8string ident in
+ let arg1 = (Functions.t_unit, ()) in
+ wrap_call
+ (Functions.C.eval1 catalog name' arg1)
+ (fun () -> raise Errors.TypeError)
+
+let call1 ident p1 (catalog, _) =
+ let name' = UTF8.to_utf8string ident in
+ let (Result r1) = p1 in
+ let arg1 = get_argument r1 in
+ wrap_call
+ (Functions.C.eval1 catalog name' arg1)
+ (fun () -> build_format_list [p1])
+
+let call2 ident p1 p2 (catalog, _) =
+ let name' = UTF8.to_utf8string ident in
+ let (Result r1) = p1 in
+ let (Result r2) = p2 in
+ let arg1 = get_argument r1
+ and arg2 = get_argument r2 in
+ wrap_call
+ (Functions.C.eval2 catalog name' arg1 arg2)
+ (fun () -> build_format_list [p1; p2])
+
+let call3 ident p1 p2 p3 (catalog, _) =
+ let name' = UTF8.to_utf8string ident in
+ let (Result r1) = p1 in
+ let (Result r2) = p2 in
+ let (Result r3) = p3 in
+ let arg1 = get_argument r1
+ and arg2 = get_argument r2
+ and arg3 = get_argument r3 in
+ wrap_call
+ (Functions.C.eval3 catalog name' arg1 arg2 arg3)
+ (fun () -> build_format_list [p1; p2 ; p3])
+
+let callN ident params (catalog, _) =
+ let signature = List.map (fun (Result r) ->
+ let formatter = Format.str_formatter in
+ Functions.repr formatter (fst @@ get_argument r);
+ Format.flush_str_formatter ()) params in
+ raise (Errors.Undefined (ident, signature))
+
+let expression e _ = e
+
+let observe repr = begin
+ let Result r = repr in match r with
+ | Bool b -> ScTypes.Result.Ok (ScTypes.Type.boolean b)
+ | String s -> ScTypes.Result.Ok (ScTypes.Type.string s)
+ | Num (format, n) ->
+ begin match format with
+ (* We can only match numeric formats here *)
+ | ScTypes.DataFormat.Date -> ScTypes.Result.Ok (ScTypes.Type.date n)
+ | ScTypes.DataFormat.Number -> ScTypes.Result.Ok (ScTypes.Type.number n)
+ end
+ | _ -> raise Errors.TypeError
+
+end
+