From 8619aa285ca8322ab9b209dd4509f5536f2440a1 Mon Sep 17 00:00:00 2001 From: Erwan Jahier <erwan.jahier@univ-grenoble-alpes.fr> Date: Fri, 13 Mar 2020 10:19:57 +0100 Subject: [PATCH] New: add the string type. --- Makefile | 2 + dune-project | 2 +- lib/data.ml | 29 +++-- lib/data.mli | 8 +- lib/mypervasives.ml | 97 ++++++++-------- lib/rifIO.ml | 264 ++++++++++++++++++++++---------------------- 6 files changed, 210 insertions(+), 192 deletions(-) diff --git a/Makefile b/Makefile index 8f0e968..356e565 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,8 @@ clean: dune clean rm -f lib/lutilsVersion.ml +odoc: + dune build @doc ############################### # for developpers diff --git a/dune-project b/dune-project index f75713f..929c696 100644 --- a/dune-project +++ b/dune-project @@ -1 +1 @@ -(lang dune 1.2) +(lang dune 2.0) diff --git a/lib/data.ml b/lib/data.ml index 82d7681..801246c 100644 --- a/lib/data.ml +++ b/lib/data.ml @@ -1,9 +1,10 @@ -(* Time-stamp: <modified the 23/08/2019 (at 11:32) by Erwan Jahier> *) +(* Time-stamp: <modified the 12/03/2020 (at 15:40) by Erwan Jahier> *) type ident = string type v = I of int | F of float | B of bool - | E of ident * int - | A of v array | S of (ident * v) list | U + | E of ident * int + | A of v array | S of (ident * v) list | U + | Str of string type t = | Bool | Int | Real @@ -13,7 +14,8 @@ type t = | Array of (t * int) | Alpha of int | Alias of (string * t) - + | String + let (val_to_string_type : v -> string) = function | I _ -> "int" @@ -23,7 +25,8 @@ let (val_to_string_type : v -> string) = | S _ -> "struct" | A _ -> "array" | U -> "nil" - + | Str _ -> "string" + let rec (val_to_string : (float -> string) -> v -> string) = fun s2f -> function @@ -40,6 +43,7 @@ let rec (val_to_string : (float -> string) -> v -> string) = Array.iteri f a; (!str^"]") | U -> "nil" + | Str str -> str let (val_to_rif_string : (float -> string) -> v -> string) = fun s2f -> @@ -57,19 +61,21 @@ let (val_to_rif_string : (float -> string) -> v -> string) = Array.iteri f a; (!str) | U -> "nil" + | Str str -> str let rec (type_to_string_gen : bool -> t -> string) = fun alias v -> let str = match v with + | String -> "string" | Bool -> "bool" - | Int -> "int" - | Real-> "real" - | Extern s -> s ^ "(*extern*)" -(* | Enum (s, sl) -> "enum " ^ s ^ " {" ^ (String.concat ", " sl) ^ "}" *) - | Enum (s, _sl) -> s - | Struct (sid,_) -> sid ^ "(*struct*)" + | Int -> "int" + | Real -> "real" + | Extern _s -> "string" (* what else should be done? *) + (* | Enum (s, sl) -> "enum " ^ s ^ " {" ^ (String.concat ", " sl) ^ "}" *) + | Enum (s, _sl) -> s + | Struct (sid,_) -> sid | Array (ty, sz) -> Printf.sprintf "%s^%d" (type_to_string_gen alias ty) sz | Alpha nb -> (* On génère des "types" à la Caml : 'a, 'b, 'c, etc. *) @@ -98,6 +104,7 @@ let (type_of_string : string -> t) = | "real" -> Real | "float" -> Real | "int" -> Int + | "string" -> String | s -> failwith (s ^ ": unsupported type.\n") diff --git a/lib/data.mli b/lib/data.mli index bbe9f79..e9bada8 100644 --- a/lib/data.mli +++ b/lib/data.mli @@ -1,9 +1,10 @@ -(* Time-stamp: <modified the 04/04/2019 (at 21:27) by Erwan Jahier> *) +(* Time-stamp: <modified the 06/03/2020 (at 11:51) by Erwan Jahier> *) type ident = string type v = I of int | F of float | B of bool - | E of ident * int - | A of v array | S of (ident * v) list | U + | E of ident * int + | A of v array | S of (ident * v) list | U + | Str of string type t = | Bool | Int | Real @@ -13,6 +14,7 @@ type t = | Array of (t * int) | Alpha of int | Alias of (string * t) + | String val val_to_string : (float -> string) -> v -> string diff --git a/lib/mypervasives.ml b/lib/mypervasives.ml index 807e7ae..82565b8 100644 --- a/lib/mypervasives.ml +++ b/lib/mypervasives.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 23/08/2019 (at 11:29) by Erwan Jahier> *) +(* Time-stamp: <modified the 14/02/2020 (at 14:08) by Erwan Jahier> *) (* Should rather be named misc or utils *) @@ -64,7 +64,8 @@ let rec (list_split7: ('a * 'b * 'c * 'd * 'e * 'f * 'g) list -> let list_minus a b = List.filter (fun v -> not (List.mem v b)) a (* returns a U b *) -let list_union a b = List.fold_left (fun acc x -> if (List.mem x acc) then acc else x::acc) a b +let list_union a b = + List.fold_left (fun acc x -> if (List.mem x acc) then acc else x::acc) a b (** Removes duplicates from a list (conserving its order) *) let (list_rm_dup : 'a list -> 'a list) = @@ -156,64 +157,64 @@ let (my_create_process : ?(wait = true) prog args -> try let pid = - List.iter (fun x -> output_string stderr (x ^ " ")) (prog::args); - output_string stderr "\n"; - flush stderr; - Unix.create_process - prog - (Array.of_list (prog::args)) - (std_in) - (std_out) - (std_err) + List.iter (fun x -> output_string stderr (x ^ " ")) (prog::args); + output_string stderr "\n"; + flush stderr; + Unix.create_process + prog + (Array.of_list (prog::args)) + (std_in) + (std_out) + (std_err) in - if not wait then PID pid else - let (_,status) = (Unix.waitpid [Unix.WUNTRACED] pid) in - ( match status with - Unix.WEXITED i -> - if i = 0 || i = 1 then - ( - output_string stderr (" ... "^prog^" exited normally.\n"); - flush stderr; - OK - ) - else - ( - output_string stderr ( + if not wait then PID pid else + let (_,status) = (Unix.waitpid [Unix.WUNTRACED] pid) in + ( match status with + Unix.WEXITED i -> + if i = 0 || i = 1 then + ( + output_string stderr (" ... "^prog^" exited normally.\n"); + flush stderr; + OK + ) + else + ( + output_string stderr ( "*** Error: " ^ prog ^ " exited abnormally (return code=" ^ (string_of_int i)^").\n"); - flush stderr; - KO - ) + flush stderr; + KO + ) | Unix.WSIGNALED i-> - output_string stderr ( + output_string stderr ( "*** Error: " ^ prog ^ " process was killed by signal "^(string_of_int i)^"\n"); - flush stderr; - KO + flush stderr; + KO | Unix.WSTOPPED i -> - output_string stderr ( + output_string stderr ( "*** Error: " ^ prog ^ " process was stopped by signal " ^ (string_of_int i)^"\n"); - flush stderr; - KO - ) + flush stderr; + KO + ) with | Unix.Unix_error(error, name, arg) -> - let msg = ( "*** '" ^ - (Unix.error_message error) ^ - "'in the system call: '" ^ name ^ " " ^ arg ^ "'\n") - in - output_string stdout msg; - flush stdout; - output_string stderr msg; - flush stderr; - KO + let msg = ( "*** '" ^ + (Unix.error_message error) ^ + "'in the system call: '" ^ name ^ " " ^ arg ^ "'\n") + in + output_string stdout msg; + flush stdout; + output_string stderr msg; + flush stderr; + KO | e -> - output_string stdout (Printexc.to_string e); - flush stdout; - output_string stderr (Printexc.to_string e); - flush stderr; - KO + output_string stdout (Printexc.to_string e); + flush stdout; + output_string stderr (Printexc.to_string e); + flush stderr; + KO (* run a cmd and collect the stdout lines into a list (requires sed) *) let (run : string -> (string -> string option) -> string list) = diff --git a/lib/rifIO.ml b/lib/rifIO.ml index 05b90e8..99f16f4 100644 --- a/lib/rifIO.ml +++ b/lib/rifIO.ml @@ -1,4 +1,4 @@ -(* Time-stamp: <modified the 23/08/2019 (at 11:35) by Erwan Jahier> *) +(* Time-stamp: <modified the 13/03/2020 (at 10:18) by Erwan Jahier> *) (*----------------------------------------------------------------------- ** This file may only be copied under the terms of the CeCILL ** Public License @@ -154,143 +154,149 @@ let (read_interface : ?debug:(bool) -> ?label:(string) -> in_channel -> (* exported *) (** Reads input values on ic. It should follow the rif format. *) let rec (read : ?debug:(bool) -> ?label:(string) -> ?pragma:(string list) -> - in_channel -> out_channel option -> vntl -> subst list) = + in_channel -> out_channel option -> vntl -> subst list) = fun ?(debug=false) ?(label="") ?(pragma = dflt_pragmas) ic oc vntl -> - let tbl = [] in - if vntl = [] then tbl else - let str,stream = get_stream debug label ic oc in - parse_rif_stream ~debug:debug label ic oc vntl (str,stream) tbl pragma - + let tbl = [] in + if vntl = [] then tbl else + let str,stream = get_stream debug label ic oc in + parse_rif_stream ~debug:debug label ic oc vntl (str,stream) tbl pragma + and (parse_rif_stream : ?debug:(bool) -> string -> in_channel -> out_channel option -> vntl -> string * stream -> subst list -> string list -> subst list) = fun ?(debug=false) label ic oc vntl (str,stream) tbl pragma -> - if vntl = [] then tbl else - let tok_list = Stream.npeek 2 stream in - match tok_list with - | [LocalGenlex.Kwd ("#"); LocalGenlex.Ident (id)] -> - if List.mem id pragma then ( - Stream.junk stream ; - Stream.junk stream ; - if id = "quit" || id = "q" then raise Bye; - if id = "reset" then raise Reset; - parse_rif_stream label ic oc vntl (str,stream) tbl pragma - ) else ( - (* We skip everything that occurs after a [#], until the next eol. *) - Stream.junk stream ; - (* prerr_endline (">>" ^str); print the ignored string on stderr *) - parse_rif_stream label ic oc - vntl (get_stream debug label ic oc) tbl pragma - ) - | (LocalGenlex.Kwd ("ERROR"|"Error"|"error"))::_ -> - print_string ("#ERROR value read. bye! ("^str^")\n"); - flush stdout; - raise Bye - | (LocalGenlex.Kwd ("#"))::(LocalGenlex.Kwd ("ERROR"|"Error"|"end"))::_ -> - print_string ("#ERROR value read. bye! ("^str^")\n"); - flush stdout; - raise Bye - | (LocalGenlex.Kwd ("#"))::_ -> - Stream.junk stream ; - (* prerr_endline (">>>" ^str); print the ignored string on stderr *) - parse_rif_stream label ic oc vntl (get_stream debug label ic oc) tbl pragma - | (LocalGenlex.Kwd ("q"))::_ -> print_string "# bye!\n"; raise Bye - | (LocalGenlex.Kwd ("#@"))::_ -> - (* Beginning of multi-line comment. Note that here, - unlike the rif format, we ignore multi line pragmas; - namely, we handle them as a multi-line comment. *) - ( - Stream.junk stream ; - ignore_toks_until_end_of_pragmas - debug label ic oc vntl (str,stream) tbl pragma - ) - | (LocalGenlex.Kwd ("nil"))::_ - | (LocalGenlex.Kwd ("?"))::_ -> - Stream.junk stream ; - let tbl = tbl @[fst (hd vntl), U] in - parse_rif_stream label ic oc (tl vntl) (str,stream) tbl pragma - - | (LocalGenlex.Float (f))::_ -> - ( - Stream.junk stream ; - (* Hashtbl.add tbl (Var.name (hd vntl)) (N(F(f))) ; *) - let v = - match snd (hd vntl) with - | Data.Bool -> B(f<>0.0) - | Data.Real -> F(f) - | Data.Int -> - let i = int_of_float f in - print_string ("\n*** Warning: type error, " ^ (string_of_float f) - ^" is an real, but an int is expected. I convert it to '"^ - (string_of_int i)^"'\n"); - I(i) - | e -> - print_string ("\n*** Type Error: float found, "^ - (Data.type_to_string e) ^ "expected\n"); - assert false - in - let tbl = tbl@ [fst (hd vntl), v] in - parse_rif_stream label ic oc (tl vntl) (str,stream) tbl pragma - ) - | (LocalGenlex.Int (i))::_ -> ( - Stream.junk stream ; - let v = - match snd (hd vntl) with - | Data.Bool -> B(i<>0) - | Data.Int -> I(i) - | Data.Real -> - let f = float_of_int i in - print_string "\n*** Warning: type error, "; - print_string ((string_of_int i) - ^ " is an int, but a real is expected. I convert it to '"^ - (string_of_float f)^"'\n"); - F(f) - | e -> - print_string ("\n*** Type Error: int found, "^ (Data.type_to_string e) - ^ "expected \n"); - assert false - in - let tbl = tbl @[fst (hd vntl), v] in - parse_rif_stream label ic oc (tl vntl) (str,stream) tbl pragma - ) - | (LocalGenlex.Ident (b))::_ -> ( - Stream.junk stream ; - let v = if mem b ["f"; "F";"false"] then B(false) - else if mem b ["t"; "T";"true"] then B(true) - else if mem b ["nil";"?";" ?"] then assert false - else failwith ("### rif parse error: `" ^ b ^ - "' read, where a bool was expected ("^str^").\n") - in - let tbl = tbl @ [fst (hd vntl), v] in - parse_rif_stream label ic oc (tl vntl) (str,stream) tbl pragma - ) - | [] -> - (* Eol is is reached; proceed with the next one *) - parse_rif_stream label ic oc vntl (get_stream debug label ic oc) - tbl pragma - | _ -> failwith ("### rif parse error: not in RIF format ("^str^").\n") - + if vntl = [] then tbl else + let tok_list = Stream.npeek 2 stream in + match tok_list with + | [LocalGenlex.Kwd ("#"); LocalGenlex.Ident (id)] -> + if List.mem id pragma then ( + Stream.junk stream ; + Stream.junk stream ; + if id = "quit" || id = "q" then raise Bye; + if id = "reset" then raise Reset; + parse_rif_stream label ic oc vntl (str,stream) tbl pragma + ) else ( + (* We skip everything that occurs after a [#], until the next eol. *) + Stream.junk stream ; + (* prerr_endline (">>" ^str); print the ignored string on stderr *) + parse_rif_stream label ic oc + vntl (get_stream debug label ic oc) tbl pragma + ) + | (LocalGenlex.Kwd ("ERROR"|"Error"|"error"))::_ -> + print_string ("#ERROR value read. bye! ("^str^")\n"); + flush stdout; + raise Bye + | (LocalGenlex.Kwd ("#"))::(LocalGenlex.Kwd ("ERROR"|"Error"|"end"))::_ -> + print_string ("#ERROR value read. bye! ("^str^")\n"); + flush stdout; + raise Bye + | (LocalGenlex.Kwd ("#"))::_ -> + Stream.junk stream ; + (* prerr_endline (">>>" ^str); print the ignored string on stderr *) + parse_rif_stream label ic oc vntl (get_stream debug label ic oc) tbl pragma + | (LocalGenlex.Kwd ("q"))::_ -> print_string "# bye!\n"; raise Bye + | (LocalGenlex.Kwd ("#@"))::_ -> + (* Beginning of multi-line comment. Note that here, + unlike the rif format, we ignore multi line pragmas; + namely, we handle them as a multi-line comment. *) + ( + Stream.junk stream ; + ignore_toks_until_end_of_pragmas + debug label ic oc vntl (str,stream) tbl pragma + ) + | (LocalGenlex.Kwd ("nil"))::_ + | (LocalGenlex.Kwd ("?"))::_ -> + Stream.junk stream ; + let tbl = tbl @[fst (hd vntl), U] in + parse_rif_stream label ic oc (tl vntl) (str,stream) tbl pragma + + | (LocalGenlex.Float (f))::_ -> + ( + Stream.junk stream ; + (* Hashtbl.add tbl (Var.name (hd vntl)) (N(F(f))) ; *) + let v = + match snd (hd vntl) with + | Data.Bool -> B(f<>0.0) + | Data.Real -> F(f) + | Data.Int -> + let i = int_of_float f in + print_string ("\n*** Warning: type error, " ^ (string_of_float f) + ^" is an real, but an int is expected. I convert it to '"^ + (string_of_int i)^"'\n"); + I(i) + | e -> + print_string ("\n*** Type Error: float found, "^ + (Data.type_to_string e) ^ "expected\n"); + assert false + in + let tbl = tbl@ [fst (hd vntl), v] in + parse_rif_stream label ic oc (tl vntl) (str,stream) tbl pragma + ) + | (LocalGenlex.Int (i))::_ -> ( + Stream.junk stream ; + let v = + match snd (hd vntl) with + | Data.Bool -> B(i<>0) + | Data.Int -> I(i) + | Data.Real -> + let f = float_of_int i in + print_string "\n*** Warning: type error, "; + print_string ((string_of_int i) + ^ " is an int, but a real is expected. I convert it to '"^ + (string_of_float f)^"'\n"); + F(f) + | Data.String -> Data.Str (string_of_int i) + | e -> + print_string ("\n*** Type Error: int found, "^ (Data.type_to_string e) + ^ "expected \n"); + assert false + in + let tbl = tbl @[fst (hd vntl), v] in + parse_rif_stream label ic oc (tl vntl) (str,stream) tbl pragma + ) + | (LocalGenlex.String (b))::_ -> ( + Stream.junk stream ; + let v = Str(b) in + let tbl = tbl @ [fst (hd vntl), v] in + parse_rif_stream label ic oc (tl vntl) (str,stream) tbl pragma + ) + | (LocalGenlex.Ident (b))::_ -> ( + Stream.junk stream ; + let v = if mem b ["f"; "F";"false"] then B(false) + else if mem b ["t"; "T";"true"] then B(true) + else if mem b ["nil";"?";" ?"] then assert false + else Str(b) + in + let tbl = tbl @ [fst (hd vntl), v] in + parse_rif_stream label ic oc (tl vntl) (str,stream) tbl pragma + ) + | [] -> + (* Eol is is reached; proceed with the next one *) + parse_rif_stream label ic oc vntl (get_stream debug label ic oc) + tbl pragma + | _ -> failwith ("### rif parse error: not in RIF format ("^str^").\n") + and (ignore_toks_until_end_of_pragmas : bool -> string -> in_channel -> out_channel option-> vntl -> string * stream -> subst list -> string list -> subst list) = fun debug label ic oc vntl (str,stream) tbl pragma -> - (* ignore all tokens until "@#" is reached *) - let tok_opt = Stream.peek stream in - match tok_opt with - | Some(LocalGenlex.Kwd ("@#")) -> - ( - Stream.junk stream ; - parse_rif_stream label ic oc vntl (str,stream) tbl pragma - ) - | Some(_) -> - ( - Stream.junk stream ; - ignore_toks_until_end_of_pragmas debug label ic oc vntl (str,stream) tbl pragma - ) - | None -> - (* Eol is is reached; proceed with the next one *) - (ignore_toks_until_end_of_pragmas debug label ic oc vntl - (get_stream debug label ic oc) tbl pragma) + (* ignore all tokens until "@#" is reached *) + let tok_opt = Stream.peek stream in + match tok_opt with + | Some(LocalGenlex.Kwd ("@#")) -> + ( + Stream.junk stream ; + parse_rif_stream label ic oc vntl (str,stream) tbl pragma + ) + | Some(_) -> + ( + Stream.junk stream ; + ignore_toks_until_end_of_pragmas debug label ic oc vntl (str,stream) tbl pragma + ) + | None -> + (* Eol is is reached; proceed with the next one *) + (ignore_toks_until_end_of_pragmas debug label ic oc vntl + (get_stream debug label ic oc) tbl pragma) -- GitLab