aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSébastien Dailly <sebastien@chimrod.com>2017-11-24 13:46:00 +0100
committerSébastien Dailly <sebastien@chimrod.com>2017-11-27 10:53:30 +0100
commit098ac444e731d7674d8910264ae58fb876618a5a (patch)
tree8f4c9ab6ddcbed53f1ad2d993db98b688c41396a
parenta6b5a6bdd138a5ccc6827bcc73580df1e9218820 (diff)
Move function in their own modules
-rwxr-xr-xMakefile4
-rwxr-xr-xreadme.rst2
-rwxr-xr-xsrc/catalog.ml151
-rw-r--r--src/catalog.mli66
-rwxr-xr-xsrc/evaluator.ml323
-rwxr-xr-xsrc/evaluator.mli64
-rwxr-xr-xsrc/expressionParser.mly28
-rwxr-xr-xsrc/functions.ml208
-rwxr-xr-xsrc/functions.mli21
-rwxr-xr-xsrc/main.ml11
-rwxr-xr-xsrc/odf/odf_ExpressionParser.mly28
-rw-r--r--src/splay.ml7
-rwxr-xr-xsrc/symbols.ml14
-rwxr-xr-xsrc/symbols.mli16
-rwxr-xr-xtests/test.ml3
15 files changed, 506 insertions, 440 deletions
diff --git a/Makefile b/Makefile
index 4be3178..f6cb2b5 100755
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
OCAMLBUILD ?= ocamlbuild
-PACKAGES=dynlink,curses,camlzip,ezxmlm,text,str,menhirLib,zarith
+PACKAGES=dynlink,curses,camlzip,ezxmlm,text,str,menhirLib,zarith,base
PATHS=src,src/odf
MENHIR=-use-menhir
@@ -18,7 +18,7 @@ stub:
$(MAKE) -C stub LIB=$(LIB)
deps:
- opam install ocamlbuild curses camlzip ezxmlm ounit text menhir zarith
+ opam install ocamlbuild curses camlzip ezxmlm ounit text menhir zarith base
byte: stub
$(OCAMLBUILD) -pkgs $(PACKAGES) $(STUB_OPTIONS) $(MENHIR) -Is $(PATHS) main.byte
diff --git a/readme.rst b/readme.rst
index 5d213c2..755b289 100755
--- a/readme.rst
+++ b/readme.rst
@@ -16,7 +16,7 @@ licht requires ocaml 4.04 and ncurses
.. code-block:: console
# sudo aptitude install opam libncures-dev libiconv-dev
- $ opam install ocamlbuild curses camlzip ezxmlm ounit text menhir zarith
+ $ opam install ocamlbuild curses camlzip ezxmlm ounit text menhir zarith base
$ make
=====
diff --git a/src/catalog.ml b/src/catalog.ml
index e4cd34b..95f13ce 100755
--- a/src/catalog.ml
+++ b/src/catalog.ml
@@ -1,13 +1,63 @@
module T = Tools
module type DATA_SIG = sig
- type 'a typ
+ type 'a t
type 'a returnType
- val compare_typ: 'a typ -> 'b typ -> ('a, 'b) T.cmp
+ val compare_typ: 'a t -> 'b t -> ('a, 'b) T.cmp
- val repr: Format.formatter -> 'a typ -> unit
+ val repr: Format.formatter -> 'a t -> unit
+
+end
+
+module type CATALOG = sig
+
+ type 'a argument
+ type 'a returnType
+
+ type t
+
+ (** Create a new catalog builder used for registering all the functions *)
+ type catalog_builder
+
+ (** Empty catalog *)
+ val empty: catalog_builder
+
+ val register1:
+ string -> (* The function name *)
+ 'a argument -> (* The signature *)
+ 'b returnType -> (* The return type *)
+ ('a -> 'b) -> (* The function to call *)
+ catalog_builder -> catalog_builder
+
+ val register2:
+ string -> (* The function name *)
+ ('a argument * 'b argument) ->(* The signature *)
+ 'c returnType -> (* The return type *)
+ ( 'a -> 'b -> 'c) -> (* The function to call*)
+ catalog_builder -> catalog_builder
+
+ val register3:
+ string -> (* The function name *)
+ ('a argument * 'b argument * 'c argument) -> (* The signature *)
+ 'd returnType -> (* The return type *)
+ ( 'a -> 'b -> 'c -> 'd) -> (* The function to call*)
+ catalog_builder -> catalog_builder
+
+
+ (** Compile the catalog *)
+ val compile: catalog_builder -> t
+
+
+ type result =
+ | R : 'a returnType * 'a -> result
+
+ val eval1: t -> string -> ('a argument * 'a) -> result
+
+ val eval2: t -> string -> ('a argument * 'a) -> ('b argument * 'b) -> result
+
+ val eval3: t -> string -> ('a argument * 'a) -> ('b argument * 'b) -> ('c argument * 'c) -> result
end
@@ -19,6 +69,9 @@ exception RegisteredFunction
(** Catalog for all functions *)
module Make(Data:DATA_SIG) = struct
+ type 'a argument = 'a Data.t
+ type 'a returnType = 'a Data.returnType
+
(** This is the way the function is store in the map.
We just the return type, and the function itself. *)
type _ t_function =
@@ -28,39 +81,29 @@ module Make(Data:DATA_SIG) = struct
(** This is the key for storing functions in the map. *)
type _ sig_typ =
- | T1: 'a Data.typ -> 'a t_function sig_typ
- | T2: 'a Data.typ * 'b Data.typ -> ('a * 'b) t_function sig_typ
- | T3: 'a Data.typ * 'b Data.typ * 'c Data.typ -> ('a * 'b * 'c) t_function sig_typ
-
+ | T1: 'a Data.t -> 'a t_function sig_typ
+ | T2: 'a Data.t * 'b Data.t -> ('a * 'b) t_function sig_typ
+ | T3: 'a Data.t * 'b Data.t * 'c Data.t -> ('a * 'b * 'c) t_function sig_typ
- let repr: type a. Format.formatter -> a sig_typ -> unit = fun formatter -> function
- | T1 t -> Format.fprintf formatter "(%a)" Data.repr t
- | T2 (t1, t2) -> Format.fprintf formatter "(%a,%a)" Data.repr t1 Data.repr t2
- | T3 (t1, t2, t3) -> Format.fprintf formatter "(%a,%a,%a)" Data.repr t1 Data.repr t2 Data.repr t3
module ComparableSignature = struct
- type 'a t = string * 'a sig_typ
+ type 'a t = 'a sig_typ
(* Type for pure equality *)
type (_, _) eq = Eq : ('a, 'a) eq
(** Compare two signature *)
- let comp: type a b. string * a sig_typ -> string * b sig_typ -> (a, b) T.cmp = begin fun (namea, a) (nameb, b) ->
+ let comp: type a b. a sig_typ -> b sig_typ -> (a, b) T.cmp = begin fun a b ->
- let cmp: type c d. c Data.typ -> d Data.typ -> ((c, d) eq -> (a, b) T.cmp) -> (a, b) T.cmp =
+ let cmp: type c d. c Data.t -> d Data.t -> ((c, d) eq -> (a, b) T.cmp) -> (a, b) T.cmp =
begin fun a b f -> match Data.compare_typ a b with
| T.Eq -> f Eq
| T.Lt -> T.Lt
| T.Gt -> T.Gt
end in
- if namea < nameb then
- T.Lt
- else if namea > nameb then
- T.Gt
- else match a, b with
-
+ match a, b with
| T1(a), T1(b) -> cmp a b (fun Eq -> T.Eq)
| T1(_), _ -> T.Lt
| _, T1(_) -> T.Gt
@@ -78,27 +121,27 @@ module Make(Data:DATA_SIG) = struct
cmp c f (fun Eq -> T.Eq)
)
)
-
end
-
- let repr : type a. Format.formatter -> a t -> unit = begin fun formatter (str, typ) ->
- Format.fprintf formatter "%s:%a"
- str
- repr typ
- end
+ let repr : type a. Format.formatter -> a t -> unit = begin fun formatter -> function
+ | T1 t -> Format.fprintf formatter "(%a)" Data.repr t
+ | T2 (t1, t2) -> Format.fprintf formatter "(%a,%a)" Data.repr t1 Data.repr t2
+ | T3 (t1, t2, t3) -> Format.fprintf formatter "(%a,%a,%a)" Data.repr t1 Data.repr t2 Data.repr t3
+ end
end
+ module Catalog = Map.Make(String)
module Functions = Splay.Make(ComparableSignature)
(* This is the map which contains all the registered functions.
Each name is binded with another map with contains the function for each
signature.
*)
- type t = Functions.t
+ type t = Functions.t Base.String_dict.t
+ type catalog_builder = Functions.t Catalog.t
- let empty = Functions.empty
+ let empty = Catalog.empty
(**
Register a function in the catalog. If the function is already defined,
@@ -107,19 +150,57 @@ module Make(Data:DATA_SIG) = struct
let register t name signature f = begin
let name' = String.uppercase_ascii name in
- if Functions.member (name', signature) t then
- raise RegisteredFunction
- else
- Functions.add (name', signature) f t
+ let map = begin match Catalog.find name' t with
+ | exception Not_found ->
+ Functions.add signature f Functions.empty
+ | x ->
+ if Functions.member signature x then
+ raise RegisteredFunction
+ else
+ Functions.add signature f x
+ end in
+ Catalog.add name' map t
end
+ let register1 name typ1 returnType f catalog =
+ register catalog name (T1(typ1)) (Fn1 (returnType, f))
+
+ let register2 name (typ1, typ2) result f catalog =
+ register catalog name (T2(typ1, typ2)) (Fn2 (result, f))
+
+ let register3 name (typ1, typ2, typ3) result f catalog =
+ register catalog name (T3(typ1, typ2, typ3)) (Fn3 (result, f))
+
(** Look in the catalog for a function with the given name and signature *)
let find_function:
type a. t -> string -> a t_function sig_typ -> a t_function =
begin fun t name signature ->
- Functions.find ((String.uppercase_ascii name), signature) t
+ Base.String_dict.find_exn t (String.uppercase_ascii name)
+ |> Functions.find signature
+ end
+
+ let compile t =
+ (* Use efficient Base.String_dict.
+ The requirement to have a unique key is garantee by the Map structure.
+ *)
+ Base.String_dict.of_alist_exn (Catalog.bindings t)
+
+
+ type result =
+ | R : 'a returnType * 'a -> result
+
+ let eval1 catalog name (t1, arg1) = begin
+ let Fn1(ret, f) = find_function catalog name (T1 t1) in
+ R (ret, f arg1)
end
- let repr = Functions.repr
+ let eval2 catalog name (t1, arg1) (t2, arg2) = begin
+ let Fn2(ret, f) = find_function catalog name (T2 (t1, t2)) in
+ R (ret, f arg1 arg2)
+ end
+ let eval3 catalog name (t1, arg1) (t2, arg2) (t3, arg3) = begin
+ let Fn3(ret, f) = find_function catalog name (T3 (t1, t2, t3)) in
+ R (ret, f arg1 arg2 arg3)
+ end
end
diff --git a/src/catalog.mli b/src/catalog.mli
index e871378..f39e87b 100644
--- a/src/catalog.mli
+++ b/src/catalog.mli
@@ -1,38 +1,66 @@
module type DATA_SIG = sig
- type 'a typ
+ type 'a t
type 'a returnType
- val compare_typ: 'a typ -> 'b typ -> ('a, 'b) Tools.cmp
+ val compare_typ: 'a t -> 'b t -> ('a, 'b) Tools.cmp
- val repr: Format.formatter -> 'a typ -> unit
+ val repr: Format.formatter -> 'a t -> unit
end
-module Make(D:DATA_SIG): sig
+module type CATALOG = sig
+
+ type 'a argument
+ type 'a returnType
type t
- type 'a t_function =
- | Fn1: 'b D.returnType * ('a -> 'b) -> 'a t_function
- | Fn2: 'c D.returnType * ('a -> 'b -> 'c) -> ('a * 'b) t_function
- | Fn3: 'd D.returnType * ('a -> 'b -> 'c -> 'd) -> ('a * 'b * 'c) t_function
+ (** Create a new catalog builder used for registering all the functions *)
+ type catalog_builder
+
+ (** Empty catalog *)
+ val empty: catalog_builder
- type 'a sig_typ =
- | T1: 'a D.typ -> 'a t_function sig_typ
- | T2: 'a D.typ * 'b D.typ -> ('a * 'b) t_function sig_typ
- | T3: 'a D.typ * 'b D.typ * 'c D.typ -> ('a * 'b * 'c) t_function sig_typ
+ val register1:
+ string -> (* The function name *)
+ 'a argument -> (* The signature *)
+ 'b returnType -> (* The return type *)
+ ('a -> 'b) -> (* The function to call *)
+ catalog_builder -> catalog_builder
+
+ val register2:
+ string -> (* The function name *)
+ ('a argument * 'b argument) ->(* The signature *)
+ 'c returnType -> (* The return type *)
+ ( 'a -> 'b -> 'c) -> (* The function to call*)
+ catalog_builder -> catalog_builder
+
+ val register3:
+ string -> (* The function name *)
+ ('a argument * 'b argument * 'c argument) -> (* The signature *)
+ 'd returnType -> (* The return type *)
+ ( 'a -> 'b -> 'c -> 'd) -> (* The function to call*)
+ catalog_builder -> catalog_builder
- (** Empty catalog *)
- val empty: t
- (** Register a new function in the catalog *)
- val register : t -> string -> 'a t_function sig_typ -> 'a t_function -> t
+ (** Compile the catalog *)
+ val compile: catalog_builder -> t
- (** Find a function with the given name and signature *)
- val find_function: t -> string -> 'a t_function sig_typ -> 'a t_function
- val repr: Format.formatter -> t -> unit
+ type result =
+ | R : 'a returnType * 'a -> result
+
+ val eval1: t -> string -> ('a argument * 'a) -> result
+
+ val eval2: t -> string -> ('a argument * 'a) -> ('b argument * 'b) -> result
+
+ val eval3: t -> string -> ('a argument * 'a) -> ('b argument * 'b) -> ('c argument * 'c) -> result
end
+
+module Make(D:DATA_SIG) : CATALOG
+ with type 'a argument = 'a D.t
+ and type 'a returnType = 'a D.returnType
+
diff --git a/src/evaluator.ml b/src/evaluator.ml
index f718e1f..ed384e6 100755
--- a/src/evaluator.ml
+++ b/src/evaluator.ml
@@ -1,103 +1,42 @@
module D = DataType
-module T = Tools
+module F = Functions
module Data = struct
-(** Data format *)
+ (*** Values definitions *)
-type 'a dataFormat = 'a ScTypes.dataFormat
+ type 'a value =
+ | Bool: D.Bool.t -> D.Bool.t value
+ | Num: D.Num.t ScTypes.dataFormat * D.Num.t -> D.Num.t value
+ | String: UTF8.t -> UTF8.t value
+ | List: 'a ScTypes.dataFormat * 'a list -> 'a list value
+ | Matrix: 'a ScTypes.dataFormat * 'a list list -> 'a list list value
-(*** Type definitions *)
-
-type _ typ =
- | Unit: unit typ
- | Bool: D.Bool.t typ
- | Num: D.Num.t typ
- | String: UTF8.t typ
- | List: 'a typ -> 'a list typ
-
-let typ_of_format: type a. a ScTypes.dataFormat -> a typ = function
- | ScTypes.Date -> Num
- | ScTypes.Number -> Num
- | ScTypes.String -> String
- | ScTypes.Bool -> Bool
-
-let rec compare_typ: type a b. a typ -> b typ -> (a, b) T.cmp =
-begin fun a b ->
- match a, b with
- | Unit, Unit -> T.Eq
- | Bool, Bool -> T.Eq
- | Num, Num -> T.Eq
- | String, String -> T.Eq
- | List l1, List l2 ->
- begin match compare_typ l1 l2 with
- | T.Lt -> T.Lt
- | T.Eq -> T.Eq
- | T.Gt -> T.Gt
- end
- | x, y -> if (T.Ex x) > (T.Ex y) then T.Gt else T.Lt
-end
-
-let rec repr:
-type a. Format.formatter -> a typ -> unit =
-fun printer typ -> match typ with
- | Unit -> Format.fprintf printer "Unit"
- | Bool -> Format.fprintf printer "Bool"
- | Num -> Format.fprintf printer "Num"
- | String -> Format.fprintf printer "String"
- | List t -> Format.fprintf printer "List[%a]"
- repr t
-
-type 'a returnType = 'a ScTypes.returnType
-
-(*** Values definitions *)
-
-type 'a value =
- | Bool: D.Bool.t -> D.Bool.t value
- | Num: D.Num.t ScTypes.dataFormat * D.Num.t -> D.Num.t value
- | String: UTF8.t -> UTF8.t value
- | List: 'a ScTypes.dataFormat * 'a list -> 'a list value
- | Matrix: 'a ScTypes.dataFormat * 'a list list -> 'a list list value
-
-(** Get the value out of the box *)
-let get_value_content: type a. a value -> a = function
- | Bool b -> b
- | Num (_, n) -> n
- | String s -> s
- | List (t, l) -> l
- | Matrix (t, l) -> l
-
-(* Extract the type from a boxed value *)
-let type_of_value: type a. a value -> a typ = function
- | Bool b -> Bool
- | Num (n, _) -> Num
- | String s -> String
- | List (t, l) -> List (typ_of_format t)
- | Matrix (t, l) -> List (List (typ_of_format t))
+ (** Extract the type and the content from a value *)
+ let get_argument: type a. a value -> a F.typ * a = function
+ | Bool b -> F.t_bool, b
+ | Num (_, n) -> F.t_int, n
+ | String s -> F.t_string, s
+ | List (t, l) -> F.t_list (F.typ_of_format t), l
+ | Matrix (t, l) -> F.t_list (F.t_list (F.typ_of_format t)), l
end
-module C = Catalog.Make(Data)
-
-
-type t = C.t
-
-let catalog = ref C.empty
-
-let get_catalog () = !catalog
+(** Functions are stored as a mutable catalog. A setter is given *)
+let catalog = ref (F.C.compile F.C.empty)
-let repr = C.repr
+let set_catalog t = catalog := t
type existencialResult =
| Result : 'a Data.value -> existencialResult [@@unboxed]
let inject:
-type a. a Data.dataFormat -> a -> existencialResult = fun resultFormat res ->
+type a. a ScTypes.dataFormat -> a -> existencialResult = fun resultFormat res ->
begin match resultFormat with
- | ScTypes.Bool -> Result (Data.Bool res)
- | ScTypes.String -> Result (Data.String res)
- | ScTypes.Number -> Result (Data.Num (resultFormat, res))
- | ScTypes.Date -> Result (Data.Num (resultFormat, res))
+ | ScTypes.Bool -> Result (Data.Bool res)
+ | ScTypes.String -> Result (Data.String res)
+ | ScTypes.Number -> Result (Data.Num (resultFormat, res))
+ | ScTypes.Date -> Result (Data.Num (resultFormat, res))
end
@@ -106,58 +45,50 @@ let build_format_list ll () =
List.map (fun (Result x) ->
begin match x with
- | Data.Bool _ -> ScTypes.DataFormat.F (ScTypes.Bool)
- | Data.Num (x, _) -> ScTypes.DataFormat.F x
- | Data.String _ -> ScTypes.DataFormat.F (ScTypes.String)
- | Data.List (f, _) -> ScTypes.DataFormat.F f
- | Data.Matrix (f, _) -> ScTypes.DataFormat.F f
+ | Data.Bool _ -> ScTypes.DataFormat.F (ScTypes.Bool)
+ | Data.Num (x, _) -> ScTypes.DataFormat.F x
+ | Data.String _ -> ScTypes.DataFormat.F (ScTypes.String)
+ | Data.List (f, _) -> ScTypes.DataFormat.F f
+ | Data.Matrix (f, _) -> ScTypes.DataFormat.F f
end
) ll
-
-let register0 name returnType f =
- catalog := C.register !catalog name (C.T1(Data.Unit)) (C.Fn1 (returnType, f))
-
-let register1 name typ1 returnType f =
- catalog := C.register !catalog name (C.T1(typ1)) (C.Fn1 (returnType, f))
-
-let register2 name (typ1, typ2) result f =
- catalog := C.register !catalog name (C.T2(typ1, typ2)) (C.Fn2 (result, f))
-
-let register3 name (typ1, typ2, typ3) result f =
- catalog := C.register !catalog name (C.T3(typ1, typ2, typ3)) (C.Fn3 (result, f))
-
+(** Call the function with the arguments *)
let call name args = begin
let name' = UTF8.to_utf8string name in
begin try match args with
| [] ->
- let C.Fn1(ret, f) = C.find_function !catalog name' (C.T1 Data.Unit) in
+ let arg1 = (F.t_unit, ()) in
+ let F.C.R(ret, res) = F.C.eval1 !catalog name' arg1 in
let returnType = ScTypes.DataFormat.guess_format_result ret (fun () -> raise Errors.TypeError) in
- inject returnType (f ())
+ inject returnType res
| (Result p1)::[] ->
- let C.Fn1(ret, f) =
- C.find_function !catalog name' (C.T1 (Data.type_of_value p1)) in
+ let arg1 = Data.get_argument p1 in
+ let F.C.R(ret, res) = F.C.eval1 !catalog name' arg1 in
let returnType = ScTypes.DataFormat.guess_format_result ret (build_format_list args) in
- inject returnType (f (Data.get_value_content p1))
+ inject returnType res
| (Result p1)::(Result p2)::[] ->
- let C.Fn2(ret, f) =
- C.find_function !catalog name' (C.T2 (Data.type_of_value p1, Data.type_of_value p2)) in
+ let arg1 = Data.get_argument p1
+ and arg2 = Data.get_argument p2 in
+ let F.C.R(ret, res) = F.C.eval2 !catalog name' arg1 arg2 in
let returnType = ScTypes.DataFormat.guess_format_result ret (build_format_list args) in
- inject returnType (f (Data.get_value_content p1) (Data.get_value_content p2))
+ inject returnType res
| (Result p1)::(Result p2)::(Result p3)::[] ->
- let C.Fn3(ret, f) =
- C.find_function !catalog name' (C.T3 (Data.type_of_value p1, Data.type_of_value p2, Data.type_of_value p3)) in
+ let arg1 = Data.get_argument p1
+ and arg2 = Data.get_argument p2
+ and arg3 = Data.get_argument p3 in
+ let F.C.R(ret, res) = F.C.eval3 !catalog name' arg1 arg2 arg3 in
let returnType = ScTypes.DataFormat.guess_format_result ret (build_format_list args) in
- inject returnType (f (Data.get_value_content p1) (Data.get_value_content p2) (Data.get_value_content p3))
+ inject returnType res
| _ -> raise Not_found
with Not_found ->
let signature = List.map (fun (Result x) ->
let formatter = Format.str_formatter in
- Data.repr formatter (Data.type_of_value x);
+ Functions.repr formatter (fst @@ Data.get_argument x);
Format.flush_str_formatter ()) args in
raise (Errors.Undefined (name, signature))
@@ -201,173 +132,17 @@ let eval mapper value = begin
| ScTypes.Call (name, args) ->
let args' = List.map extract args in
call name args'
- end
- in
+ end in
+
let Result r = ((extract[@tailrec]) value) in
begin match r with
| Data.Bool b -> ScTypes.Result (ScTypes.boolean b)
| Data.String s -> ScTypes.Result (ScTypes.string s)
- | Data.Num (format, n) -> begin match ScTypes.get_numeric_type format with
+ | Data.Num (format, n) ->
+ begin match ScTypes.get_numeric_type format with
| ScTypes.Date -> ScTypes.Result (ScTypes.date n)
| ScTypes.Number -> ScTypes.Result (ScTypes.number n)
end
| _ -> raise Errors.TypeError
end
end
-
-let wrap f =
- let old_catalog = !catalog in
- Tools.try_finally
- (fun () -> catalog := C.empty; f ())
- (fun () -> catalog := old_catalog)
-
-
-(* Register the standard functions *)
-type 'a returnType = 'a ScTypes.returnType
-
-let f_num = ScTypes.f_num
-let f_date = ScTypes.f_date
-let f_number = ScTypes.f_number
-let f_string = ScTypes.f_string
-let f_bool = ScTypes.f_bool
-
-module Make_Compare(C: D.COMPARABLE) = struct
-
- let register t = begin
- register2 "=" (t, t) f_bool C.eq;
- register2 "<>" (t, t) f_bool C.neq;
- register2 ">" (t, t) f_bool C.gt;
- register2 ">=" (t, t) f_bool C.ge;
- register2 "<" (t, t) f_bool C.lt;
- register2 "<=" (t, t) f_bool C.le;
- end
-
-end
-
-type 'a typ = 'a Data.typ
-let t_bool: DataType.Bool.t typ = Data.Bool
-let t_int: DataType.Num.t typ = Data.Num
-let t_string: UTF8.t typ = Data.String
-let t_list (t: 'a typ): 'a list typ = Data.List t
-
-(* Helper for list functions : reduce over a list of elements *)
-let reduce name typ res f = begin
- register1 name (t_list typ) res (fun x ->
- List.fold_left f (List.hd x) x);
- register1 name (t_list (t_list typ)) res (fun x ->
- List.fold_left (List.fold_left f) (List.hd (List.hd x)) x);
-end
-
-(* Helper for list functions : fold over a list of elements *)
-let fold name t_in t_out f init = begin
- register1 name (t_list t_in) t_out (fun x ->
- List.fold_left f init x);
- register1 name (t_list (t_list t_in)) t_out (fun x ->
- List.fold_left (List.fold_left f) init x);
-end
-
-let if_: type a. bool -> a -> a -> a = fun a b c -> if a then b else c
-
-
-let () = begin
-
- (* Build a date *)
- register3 "date" (t_int, t_int, t_int) f_date (
- fun year month day ->
- D.Date.get_julian_day
- (D.Num.to_int year)
- (D.Num.to_int month)
- (D.Num.to_int day)
- );
-
- let module CompareNum = Make_Compare(D.Num) in
- Data.(
- CompareNum.register t_int;
- register0 "rand" f_number D.Num.rnd;
-
- register0 "pi" f_number (fun () -> D.Num.of_float (4. *. atan 1.));
- register1 "sin" t_int f_number (fun x -> D.Num.of_float (sin @@ D.Num.to_float x));
- register1 "cos" t_int f_number (fun x -> D.Num.of_float (cos @@ D.Num.to_float x));
- register1 "tan" t_int f_number (fun x -> D.Num.of_float (tan @@ D.Num.to_float x));
- register1 "atan" t_int f_number (fun x -> D.Num.of_float (atan @@ D.Num.to_float x));
- register1 "asin" t_int f_number (fun x -> D.Num.of_float (asin @@ D.Num.to_float x));
- register1 "acos" t_int f_number (fun x -> D.Num.of_float (acos @@ D.Num.to_float x));
- register1 "sinh" t_int f_number (fun x -> D.Num.of_float (sinh @@ D.Num.to_float x));
- register1 "cosh" t_int f_number (fun x -> D.Num.of_float (cosh @@ D.Num.to_float x));
- register1 "tanh" t_int f_number (fun x -> D.Num.of_float (tanh @@ D.Num.to_float x));
- register2 "atan2" (t_int, t_int)f_number (fun x y ->
- D.Num.of_float (atan2 (D.Num.to_float x) (D.Num.to_float y))
- );
-
- register1 "sqrt" t_int f_number (fun x -> D.Num.of_float (sqrt @@ D.Num.to_float x));
- register1 "exp" t_int f_number (fun x -> D.Num.of_float (exp @@ D.Num.to_float x));
- register1 "ln" t_int f_number (fun x -> D.Num.of_float (log @@ D.Num.to_float x));
-
- register3 "if" (t_bool, t_int, t_int) f_number if_;
- register3 "if" (t_bool, t_bool, t_bool) f_bool if_;
- register3 "if" (t_bool, t_string, t_string) f_string if_;
-
- register1 "abs" t_int f_number D.Num.abs;
- register1 "int" t_int f_number D.Num.floor;
- register1 "rounddown" t_int f_number D.Num.round_down;
- register1 "round" t_int f_number D.Num.round;
-
- register1 "trim" t_string f_string UTF8.trim;
- register1 "right" t_string f_string (fun x -> UTF8.get x (-1));
- register2 "right" (t_string, t_int) f_string (
- fun t n ->
- let n' = D.Num.to_int n in
- UTF8.sub t (-(n')) n'
- );
- register1 "left" t_string f_string (fun x -> UTF8.get x 0);
- register2 "left" (t_string, t_int) f_string (
- fun t n ->
- let n' = D.Num.to_int n in
- UTF8.sub t 0 n'
- );
- register1 "len" t_string f_number (fun x -> D.Num.of_int @@ UTF8.length x);
- register1 "lenb" t_string f_number (fun x -> D.Num.of_int @@ String.length @@ UTF8.to_utf8string x);
- register1 "lower" t_string f_string UTF8.lower;
- register1 "unicode" t_string f_number (fun x -> D.Num.of_int @@ UTF8.code x);
- register1 "unichar" t_int f_string (fun x -> UTF8.char @@ D.Num.to_int x);
- register1 "upper" t_string f_string UTF8.upper;
- register3 "substitute" (t_string, t_string, t_string) f_string UTF8.replace;
- register2 "rept" (t_string, t_int) f_string (fun t n -> UTF8.repeat (D.Num.to_int n) t);
-
- let module CompareBool = Make_Compare(D.Bool) in
- CompareBool.register t_bool;
- register0 "true" f_bool (fun () -> D.Bool.true_);
- register0 "false" f_bool (fun () -> D.Bool.false_);
- register1 "not" t_bool f_bool D.Bool.not;
- register2 "and" (t_bool, t_bool) f_bool D.Bool.and_;
-(* fold "and" t_bool f_bool D.Bool.and_ (D.Bool.true_); *)
- register2 "or" (t_bool, t_bool) f_bool D.Bool.or_;
-(* fold "or" t_bool f_bool D.Bool.or_ (D.Bool.false_); *)
- register2 "xor" (t_bool, t_bool) f_bool D.Bool.neq;
-(* fold "xor" t_bool f_bool D.Bool.neq (D.Bool.false_); *)
-
- let module CompareString = Make_Compare(D.String) in
- CompareString.register t_string;
-
- reduce "min" t_int f_num D.Num.min; (* Minimum value from a list *)
- reduce "max" t_int f_num D.Num.max; (* Maximum value from a list *)
-
- fold "sum" t_int f_number D.Num.add (D.Num.zero);
- fold "product" t_int f_number D.Num.mult (D.Num.one);
-
- register2 "^" (t_int, t_int) f_number D.Num.pow;
- register2 "power" (t_int, t_int) f_number D.Num.pow;
-
- register2 "gcd"(t_int, t_int) f_number D.Num.gcd;
- register2 "lcm"(t_int, t_int) f_number D.Num.lcm;
- register1 "+" t_int f_num (fun x -> x);
- register1 "-" t_int f_num D.Num.neg; (* Unary negation *)
- register2 "+" (t_int, t_int) f_num D.Num.add;
- register2 "-" (t_int, t_int) f_num D.Num.sub;
- register2 "*" (t_int, t_int) f_number D.Num.mult;
- register2 "/" (t_int, t_int) f_number D.Num.div;
-
- )
-
-end
-
diff --git a/src/evaluator.mli b/src/evaluator.mli
index b296b90..e338b8d 100755
--- a/src/evaluator.mli
+++ b/src/evaluator.mli
@@ -1,66 +1,4 @@
-type t
-
val eval: (ScTypes.refs -> ScTypes.result option ScTypes.Refs.range) -> ScTypes.expression -> ScTypes.result
-val repr: Format.formatter -> t -> unit
-
-val get_catalog: unit -> t
-
-(** Type definitions *)
-
-type 'a typ
-val t_bool: DataType.Bool.t typ
-val t_int: DataType.Num.t typ
-val t_string: UTF8.t typ
-val t_list: 'a typ -> 'a list typ
-
-(** Result formats *)
-
-type 'a returnType
-
-(** Numeric (any format) *)
-val f_num: DataType.Num.t returnType
-
-(** Date *)
-val f_date: DataType.Num.t returnType
-
-(** Number *)
-val f_number: DataType.Num.t returnType
-
-(** Boolean result *)
-val f_bool: DataType.Bool.t returnType
-
-(** String *)
-val f_string: DataType.String.t returnType
-
-(** Catalog *)
-
-val register0:
- string -> (* The function name *)
- 'a returnType -> (* The return type *)
- (unit -> 'a) (* The function to call *)
- -> unit
-
-val register1:
- string -> (* The function name *)
- 'a typ -> (* The signature *)
- 'b returnType -> (* The return type *)
- ('a -> 'b) (* The function to call *)
- -> unit
-
-val register2:
- string -> (* The function name *)
- ('a typ * 'b typ) ->(* The signature *)
- 'c returnType -> (* The return type *)
- ( 'a -> 'b -> 'c) (* The function to call*)
- -> unit
-
-val register3:
- string -> (* The function name *)
- ('a typ * 'b typ * 'c typ) ->(* The signature *)
- 'd returnType -> (* The return type *)
- ( 'a -> 'b -> 'c -> 'd) (* The function to call*)
- -> unit
+val set_catalog: Functions.C.t -> unit
-(** [wrap f] run [f] inside a context where there is no functions *)
-val wrap: (unit -> 'a) -> 'a
diff --git a/src/expressionParser.mly b/src/expressionParser.mly
index b7f77ae..473797f 100755
--- a/src/expressionParser.mly
+++ b/src/expressionParser.mly
@@ -1,6 +1,6 @@
%{
open ScTypes
- module F = Functions
+ module S = Symbols
let u = UTF8.from_utf8string
@@ -67,8 +67,8 @@ basic:
expr:
| num {Value (number ($1))}
- | MINUS expr {Call (F.sub, [$2])}
- | PLUS expr {Call (F.add, [$2])}
+ | MINUS expr {Call (S.sub, [$2])}
+ | PLUS expr {Call (S.add, [$2])}
| LETTERS ident LPAREN separated_list(SEMICOLON, expr) RPAREN { Call (u($1 ^ $2), $4) }
@@ -81,19 +81,19 @@ expr:
| STR {Value (string (u $1))}
(* Mathematical operators *)
- | expr MINUS expr {Call (F.sub, [$1; $3])}
- | expr DIVIDE expr {Call (F.div, [$1; $3])}
- | expr TIMES expr {Call (F.mul, [$1; $3])}
- | expr PLUS expr {Call (F.add, [$1; $3])}
- | expr POW expr {Call (F.pow, [$1; $3])}
+ | expr MINUS expr {Call (S.sub, [$1; $3])}
+ | expr DIVIDE expr {Call (S.div, [$1; $3])}
+ | expr TIMES expr {Call (S.mul, [$1; $3])}
+ | expr PLUS expr {Call (S.add, [$1; $3])}
+ | expr POW expr {Call (S.pow, [$1; $3])}
(* Comparaison *)
- | expr EQ expr {Call (F.eq, [$1; $3])}
- | expr NEQ expr {Call (F.neq, [$1; $3])}
- | expr LT expr {Call (F.lt, [$1; $3])}
- | expr GT expr {Call (F.gt, [$1; $3])}
- | expr LE expr {Call (F.le, [$1; $3])}
- | expr GE expr {Call (F.ge, [$1; $3])}
+ | expr EQ expr {Call (S.eq, [$1; $3])}
+ | expr NEQ expr {Call (S.neq, [$1; $3])}
+ | expr LT expr {Call (S.lt, [$1; $3])}
+ | expr GT expr {Call (S.gt, [$1; $3])}
+ | expr LE expr {Call (S.le, [$1; $3])}
+ | expr GE expr {Call (S.ge, [$1; $3])}
%inline cell:
| LETTERS NUM { Cell.from_string (false, $1) (false, int_of_string $2) }
diff --git a/src/functions.ml b/src/functions.ml
index 56d7530..62426e9 100755
--- a/src/functions.ml
+++ b/src/functions.ml
@@ -1,14 +1,194 @@
-let u = UTF8.from_utf8string
-
-let eq = u"="
-let neq = u"<>"
-let lt = u"<"
-let le = u"<="
-let gt = u">"
-let ge = u">="
-
-let add = u"+"
-let mul = u"*"
-let pow = u"^"
-let div = u"/"
-let sub = u"-"
+module D = DataType
+module T = Tools
+
+type _ typ =
+ | Unit: unit typ
+ | Bool: D.Bool.t typ
+ | Num: D.Num.t typ
+ | String: UTF8.t typ
+ | List: 'a typ -> 'a list typ
+
+let t_unit = Unit
+let t_bool: DataType.Bool.t typ = Bool
+let t_int: DataType.Num.t typ = Num
+let t_string: UTF8.t typ = String
+let t_list (t: 'a typ): 'a list typ = List t
+
+let typ_of_format: type a. a ScTypes.dataFormat -> a typ = function
+ | ScTypes.Date -> Num
+ | ScTypes.Number -> Num
+ | ScTypes.String -> String
+ | ScTypes.Bool -> Bool
+
+
+let rec repr:
+type a. Format.formatter -> a typ -> unit =
+fun printer typ -> match typ with
+ | Unit -> Format.fprintf printer "Unit"
+ | Bool -> Format.fprintf printer "Bool"
+ | Num -> Format.fprintf printer "Num"
+ | String -> Format.fprintf printer "String"
+ | List t -> Format.fprintf printer "List[%a]"
+ repr t
+
+module C = Catalog.Make(struct
+
+ let repr = repr
+
+ let rec compare_typ: type a b. a typ -> b typ -> (a, b) T.cmp =
+ begin fun a b ->
+ match a, b with
+ | Unit, Unit -> T.Eq
+ | Bool, Bool -> T.Eq
+ | Num, Num -> T.Eq
+ | String, String -> T.Eq
+ | List l1, List l2 ->
+ begin match compare_typ l1 l2 with
+ | T.Lt -> T.Lt
+ | T.Eq -> T.Eq
+ | T.Gt -> T.Gt
+ end
+ | x, y -> if (T.Ex x) > (T.Ex y) then T.Gt else T.Lt
+ end
+
+ type 'a t = 'a typ
+
+ type 'a returnType = 'a ScTypes.returnType
+
+
+end)
+
+let f_num = ScTypes.f_num
+let f_date = ScTypes.f_date
+let f_number = ScTypes.f_number
+let f_string = ScTypes.f_string
+let f_bool = ScTypes.f_bool
+
+module Make_Compare(Comp: D.COMPARABLE) = struct
+
+ let register t catalog = begin catalog
+ |> C.register2 "=" (t, t) f_bool Comp.eq
+ |> C.register2 "<>" (t, t) f_bool Comp.neq
+ |> C.register2 ">" (t, t) f_bool Comp.gt
+ |> C.register2 ">=" (t, t) f_bool Comp.ge
+ |> C.register2 "<" (t, t) f_bool Comp.lt
+ |> C.register2 "<=" (t, t) f_bool Comp.le
+ end
+
+end
+
+let built_in catalog = begin
+
+ let module CompareNum = Make_Compare(D.Num) in
+ let module CompareString = Make_Compare(D.String) in
+ let module CompareBool = Make_Compare(D.Bool) in
+
+ (* Helper for list functions : reduce over a list of elements *)
+ let reduce name typ res f c = begin
+ C.register1 name (t_list typ) res (fun x ->
+ List.fold_left f (List.hd x) x) c
+ |> C.register1 name (t_list (t_list typ)) res (fun x ->
+ List.fold_left (List.fold_left f) (List.hd (List.hd x)) x);
+ end in
+
+ (* Helper for list functions : fold over a list of elements *)
+ let fold name t_in t_out f init c = begin
+ C.register1 name (t_list t_in) t_out (fun x ->
+ List.fold_left f init x) c
+ |> C.register1 name (t_list (t_list t_in)) t_out (fun x ->
+ List.fold_left (List.fold_left f) init x)
+ end in
+
+
+ let if_: type a. bool -> a -> a -> a = fun a b c -> if a then b else c in
+
+ (* Build a date *)
+ C.register3 "date" (t_int, t_int, t_int) f_date (
+ fun year month day ->
+ D.Date.get_julian_day
+ (D.Num.to_int year)
+ (D.Num.to_int month)
+ (D.Num.to_int day)
+ ) catalog
+ |> CompareNum.register t_int
+
+ |> C.register1 "rand" t_unit f_number D.Num.rnd
+
+ |> C.register1 "pi" t_unit f_number (fun () -> D.Num.of_float (4. *. atan 1.))
+ |> C.register1 "sin" t_int f_number (fun x -> D.Num.of_float (sin (D.Num.to_float x)))
+ |> C.register1 "cos" t_int f_number (fun x -> D.Num.of_float (cos (D.Num.to_float x)))
+ |> C.register1 "tan" t_int f_number (fun x -> D.Num.of_float (tan (D.Num.to_float x)))
+ |> C.register1 "atan" t_int f_number (fun x -> D.Num.of_float (atan (D.Num.to_float x)))
+ |> C.register1 "asin" t_int f_number (fun x -> D.Num.of_float (asin (D.Num.to_float x)))
+ |> C.register1 "acos" t_int f_number (fun x -> D.Num.of_float (acos (D.Num.to_float x)))
+ |> C.register1 "sinh" t_int f_number (fun x -> D.Num.of_float (sinh (D.Num.to_float x)))
+ |> C.register1 "cosh" t_int f_number (fun x -> D.Num.of_float (cosh (D.Num.to_float x)))
+ |> C.register1 "tanh" t_int f_number (fun x -> D.Num.of_float (tanh (D.Num.to_float x)))
+ |> C.register2 "atan2" (t_int, t_int)f_number (fun x y ->
+ D.Num.of_float (atan2 (D.Num.to_float x) (D.Num.to_float y))
+ )
+
+ |> C.register1 "sqrt" t_int f_number (fun x -> D.Num.of_float (sqrt(D.Num.to_float x)))
+ |> C.register1 "exp" t_int f_number (fun x -> D.Num.of_float (exp (D.Num.to_float x)))
+ |> C.register1 "ln" t_int f_number (fun x -> D.Num.of_float (log (D.Num.to_float x)))
+
+ |> C.register3 "if" (t_bool, t_int, t_int) f_number if_
+ |> C.register3 "if" (t_bool, t_bool, t_bool) f_bool if_
+ |> C.register3 "if" (t_bool, t_string, t_string) f_string if_
+
+ |> C.register1 "abs" t_int f_number D.Num.abs
+ |> C.register1 "int" t_int f_number D.Num.floor
+ |> C.register1 "rounddown" t_int f_number D.Num.round_down
+ |> C.register1 "round" t_int f_number D.Num.round
+
+ |> C.register1 "trim" t_string f_string UTF8.trim
+ |> C.register1 "right" t_string f_string (fun x -> UTF8.get x (-1))
+ |> C.register2 "right" (t_string, t_int) f_string (
+ fun t n ->
+ let n' = D.Num.to_int n in
+ UTF8.sub t (-(n')) n'
+ )
+ |> C.register1 "left" t_string f_string (fun x -> UTF8.get x 0)
+ |> C.register2 "left" (t_string, t_int) f_string (
+ fun t n ->
+ let n' = D.Num.to_int n in
+ UTF8.sub t 0 n'
+ )
+ |> C.register1 "len" t_string f_number (fun x -> D.Num.of_int (UTF8.length x))
+ |> C.register1 "lenb" t_string f_number (fun x -> D.Num.of_int (String.length (UTF8.to_utf8string x)))
+ |> C.register1 "lower" t_string f_string UTF8.lower
+ |> C.register1 "unicode" t_string f_number (fun x -> D.Num.of_int (UTF8.code x))
+ |> C.register1 "unichar" t_int f_string (fun x -> UTF8.char (D.Num.to_int x))
+ |> C.register1 "upper" t_string f_string UTF8.upper
+ |> C.register3 "substitute" (t_string, t_string, t_string) f_string UTF8.replace
+ |> C.register2 "rept" (t_string, t_int) f_string (fun t n -> UTF8.repeat (D.Num.to_int n) t)
+
+ |> CompareBool.register t_bool
+ |> C.register1 "true" t_unit f_bool (fun () -> D.Bool.true_)
+ |> C.register1 "false" t_unit f_bool (fun () -> D.Bool.false_)
+ |> C.register1 "not" t_bool f_bool D.Bool.not
+ |> C.register2 "and" (t_bool, t_bool) f_bool D.Bool.and_
+ |> C.register2 "or" (t_bool, t_bool) f_bool D.Bool.or_
+ |> C.register2 "xor" (t_bool, t_bool) f_bool D.Bool.neq
+
+ |> CompareString.register t_string
+
+ |> reduce "min" t_int f_num D.Num.min (* Minimum value from a list *)
+ |> reduce "max" t_int f_num D.Num.max (* Maximum value from a list *)
+
+ |> fold "sum" t_int f_number D.Num.add (D.Num.zero)
+ |> fold "product" t_int f_number D.Num.mult (D.Num.one)
+
+ |> C.register2 "^" (t_int, t_int) f_number D.Num.pow
+ |> C.register2 "power" (t_int, t_int) f_number D.Num.pow
+
+ |> C.register2 "gcd"(t_int, t_int) f_number D.Num.gcd
+ |> C.register2 "lcm"(t_int, t_int) f_number D.Num.lcm
+ |> C.register1 "+" t_int f_num (fun x -> x)
+ |> C.register1 "-" t_int f_num D.Num.neg (* Unary negation *)
+ |> C.register2 "+" (t_int, t_int) f_num D.Num.add
+ |> C.register2 "-" (t_int, t_int) f_num D.Num.sub
+ |> C.register2 "*" (t_int, t_int) f_number D.Num.mult
+ |> C.register2 "/" (t_int, t_int) f_number D.Num.div
+
+end
diff --git a/src/functions.mli b/src/functions.mli
new file mode 100755
index 0000000..c6904b2
--- /dev/null
+++ b/src/functions.mli
@@ -0,0 +1,21 @@
+
+(** Function signature *)
+
+type 'a typ
+
+val t_unit: unit typ
+val t_bool: DataType.Bool.t typ
+val t_int: DataType.Num.t typ
+val t_string: UTF8.t typ
+val t_list: 'a typ -> 'a list typ
+
+val typ_of_format: 'a ScTypes.dataFormat -> 'a typ
+
+val repr: Format.formatter -> 'a typ -> unit
+
+module C : Catalog.CATALOG
+ with type 'a argument = 'a typ
+ and type 'a returnType = 'a ScTypes.returnType
+
+(** Load all the built_in functions *)
+val built_in: C.catalog_builder -> C.catalog_builder
diff --git a/src/main.ml b/src/main.ml
index 3b83e85..4491025 100755
--- a/src/main.ml
+++ b/src/main.ml
@@ -55,9 +55,12 @@ let f screen = ActionParser.(
| _ -> raise Not_found
end)
+let menhirParser =
+ MenhirLib.Convert.Simplified.traditional2revised ActionParser.normal
+
let parser screen = begin
let get_value () = f screen, Lexing.dummy_pos, Lexing.dummy_pos in
- MenhirLib.Convert.Simplified.traditional2revised ActionParser.normal get_value
+ menhirParser get_value
end
let rec normal_mode (t, screen) = begin
@@ -215,12 +218,14 @@ and command (t, screen) action = begin
| ("w", file) -> (* Save the file *)
Odf.save t.Sheet.data file;
normal_mode @@ redraw t screen
+(*
| ("repr", file) -> (* Save the file *)
let out_gv = open_out_bin file in
let form = Format.formatter_of_out_channel out_gv in
Evaluator.repr form (Evaluator.get_catalog ());
close_out out_gv;
normal_mode @@ redraw t screen
+*)
| ("enew", _) -> (* Start a new spreadsheet *)
normal_mode @@ redraw (Sheet.create Sheet.Raw.empty) screen
| ("q", _) -> (* Quit *)
@@ -230,6 +235,10 @@ end
let () = begin
+ let catalog = Functions.built_in Functions.C.empty in
+ ignore @@ Evaluator.set_catalog (Functions.C.compile catalog);
+
+
let sheet =
if Array.length Sys.argv = 1 then
Sheet.Raw.empty
diff --git a/src/odf/odf_ExpressionParser.mly b/src/odf/odf_ExpressionParser.mly
index 6b571a9..54836cd 100755
--- a/src/odf/odf_ExpressionParser.mly
+++ b/src/odf/odf_ExpressionParser.mly
@@ -1,6 +1,6 @@
%{
open ScTypes
- module F = Functions
+ module S = Symbols
let u = UTF8.from_utf8string
@@ -44,8 +44,8 @@ value:
expr:
| num {Value (number ($1))}
- | MINUS expr {Call (F.sub, [$2])}
- | PLUS expr {Call (F.add, [$2])}
+ | MINUS expr {Call (S.sub, [$2])}
+ | PLUS expr {Call (S.add, [$2])}
| L_SQ_BRACKET ref R_SQ_BRACKET {$2}
@@ -54,19 +54,19 @@ expr:
| STR {Value (string (u $1))}
(* Mathematical operators *)
- | expr MINUS expr {Call (F.sub, [$1; $3])}
- | expr DIVIDE expr {Call (F.div, [$1; $3])}
- | expr TIMES expr {Call (F.mul, [$1; $3])}
- | expr PLUS expr {Call (F.add, [$1; $3])}
- | expr POW expr {Call (F.pow, [$1; $3])}
+ | expr MINUS expr {Call (S.sub, [$1; $3])}
+ | expr DIVIDE expr {Call (S.div, [$1; $3])}
+ | expr TIMES expr {Call (S.mul, [$1; $3])}
+ | expr PLUS expr {Call (S.add, [$1; $3])}
+ | expr POW expr {Call (S.pow, [$1; $3])}
(* Comparaison *)
- | expr EQ expr {Call (F.eq, [$1; $3])}
- | expr NEQ expr {Call (F.neq, [$1; $3])}
- | expr LT expr {Call (F.lt, [$1; $3])}
- | expr GT expr {Call (F.gt, [$1; $3])}
- | expr LE expr {Call (F.le, [$1; $3])}
- | expr GE expr {Call (F.ge, [$1; $3])}
+ | expr EQ expr {Call (S.eq, [$1; $3])}
+ | expr NEQ expr {Call (S.neq, [$1; $3])}
+ | expr LT expr {Call (S.lt, [$1; $3])}
+ | expr GT expr {Call (S.gt, [$1; $3])}
+ | expr LE expr {Call (S.le, [$1; $3])}
+ | expr GE expr {Call (S.ge, [$1; $3])}
| ident LPAREN separated_list(SEMICOLON, expr) RPAREN { Call (u $1, $3) }
diff --git a/src/splay.ml b/src/splay.ml
index ec5750c..4bbc3dd 100644
--- a/src/splay.ml
+++ b/src/splay.ml
@@ -1,10 +1,11 @@
module type KEY = sig
- type 'a t
+ type 'a t
- val comp: 'a t -> 'b t -> ('a, 'b) Tools.cmp
+ (** Parametrized comparator *)
+ val comp: 'a t -> 'b t -> ('a, 'b) Tools.cmp
- val repr: Format.formatter -> 'a t -> unit
+ val repr: Format.formatter -> 'a t -> unit
end
diff --git a/src/symbols.ml b/src/symbols.ml
new file mode 100755
index 0000000..56d7530
--- /dev/null
+++ b/src/symbols.ml
@@ -0,0 +1,14 @@
+let u = UTF8.from_utf8string
+
+let eq = u"="
+let neq = u"<>"
+let lt = u"<"
+let le = u"<="
+let gt = u">"
+let ge = u">="
+
+let add = u"+"
+let mul = u"*"
+let pow = u"^"
+let div = u"/"
+let sub = u"-"
diff --git a/src/symbols.mli b/src/symbols.mli
new file mode 100755
index 0000000..764b539
--- /dev/null
+++ b/src/symbols.mli
@@ -0,0 +1,16 @@
+
+(** Symbols *)
+
+val eq : UTF8.t
+val neq : UTF8.t
+val lt : UTF8.t
+val le : UTF8.t
+val gt : UTF8.t
+val ge : UTF8.t
+val add : UTF8.t
+val mul : UTF8.t
+val pow : UTF8.t
+val div : UTF8.t
+val sub : UTF8.t
+
+
diff --git a/tests/test.ml b/tests/test.ml
index b9672ab..2d881ca 100755
--- a/tests/test.ml
+++ b/tests/test.ml
@@ -1,4 +1,7 @@
let () =
+
+ Evaluator.set_catalog (Functions.C.compile @@ Functions.built_in @@ Functions.C.empty);
+
let tests = OUnit2.test_list [
Tools_test.tests;
DataType_test.num_tests;