From 4f39ffe31805039df54124ce15562c34e12ac7e6 Mon Sep 17 00:00:00 2001 From: Chimrod <> Date: Sat, 15 Jun 2024 12:31:47 +0200 Subject: Better type handling --- lib/syntax/get_type.ml | 36 +++++++++++++++++++++++++++++++----- lib/syntax/type_of.ml | 50 ++++++++++++++++++++++++++------------------------ 2 files changed, 57 insertions(+), 29 deletions(-) (limited to 'lib/syntax') diff --git a/lib/syntax/get_type.ml b/lib/syntax/get_type.ml index 442f49f..b22f53c 100644 --- a/lib/syntax/get_type.ml +++ b/lib/syntax/get_type.ml @@ -15,6 +15,10 @@ type t' = t let v = Fun.id let get_type : t -> type_of = function Raw r -> r | Variable r -> r +let map : t -> type_of -> t = + fun t type_of -> + match t with Raw _ -> Raw type_of | Variable _ -> Variable type_of + let get_nature : t -> t -> type_of -> t = fun t1 t2 type_of -> match (t1, t2) with @@ -31,11 +35,33 @@ let ident : (S.pos, 'any) S.variable -> t = let literal : S.pos -> t T.literal list -> t = fun pos values -> ignore pos; - let init = Raw NumericString in - List.fold_left values ~init ~f:(fun state -> function - | T.Text t -> ( - match int_of_string_opt t with Some _ -> state | None -> Raw String) - | T.Expression t -> t) + let init = None in + let typed = + List.fold_left values ~init ~f:(fun state -> function + | T.Text t -> ( + (* Tranform the type, but keep the information is it’s a raw data + or a variable one *) + let nature = Option.value ~default:(Raw Integer) state in + match (Option.map get_type state, int_of_string_opt t) with + | None, Some _ + | Some Integer, Some _ + | Some NumericString, Some _ + | Some Bool, Some _ -> + Some (map nature NumericString) + | _, _ -> + if String.equal "" t then + (* If the text is empty, ignore it *) + state + else Some (map nature String)) + | T.Expression t -> ( + let nature = Option.value ~default:(Raw Integer) state in + match (Option.map get_type state, get_type t) with + | None, Integer | Some NumericString, Integer -> + Some (get_nature nature t NumericString) + | _ -> Some (map nature String))) + in + let result = Option.value ~default:(Raw String) typed in + result let uoperator : S.pos -> T.uoperator -> t -> t = fun pos operator t -> diff --git a/lib/syntax/type_of.ml b/lib/syntax/type_of.ml index ee6b314..3c04256 100644 --- a/lib/syntax/type_of.ml +++ b/lib/syntax/type_of.ml @@ -190,16 +190,19 @@ module TypedExpression = struct = fun pos values type_of -> ignore type_of; - let init = ({ pos; empty = true }, []) in - let result = - List.fold_left values ~init ~f:(fun (_, report) -> function + let init = (true, []) in + let empty, report = + List.fold_left values ~init ~f:(fun (was_empty, report) -> function | T.Text t -> - let empty = String.equal t String.empty in - ({ pos; empty }, report) - | T.Expression t -> snd t) + let empty_text = String.equal t String.empty in + let empty = was_empty && empty_text in + (empty, report) + | T.Expression (_, t) -> + let empty = was_empty && (fst t).empty in + let report = List.rev_append (snd t) (snd init) in + (empty, report)) in - - result + ({ pos; empty }, report) let function_ : S.pos -> @@ -334,23 +337,21 @@ module TypedExpression = struct | T.Eq | T.Neq | Lt | Gte | Lte | Gt -> (* If the expression is '' or 0, we accept the comparaison as if instead of raising a warning *) - if t1.empty || t2.empty then ({ pos; empty = false }, report) - else - let d = Helper.(Dynamic (DynType.t ())) in - let expected = [ d; d ] in - (* Compare and report as error if the types are incompatible. If no - error is reported, try in strict mode, and report as a warning. *) - let report = - match - Helper.compare_args ~level:Error pos expected (List.rev types) + let d = Helper.(Dynamic (DynType.t ())) in + let expected = [ d; d ] in + (* Compare and report as error if the types are incompatible. If no + error is reported, try in strict mode, and report as a warning. *) + let report = + match + Helper.compare_args ~level:Error pos expected (List.rev types) + report + with + | [] -> + Helper.compare_args ~strict:true pos expected (List.rev types) report - with - | [] -> - Helper.compare_args ~strict:true pos expected (List.rev types) - report - | report -> report - in - ({ pos; empty = false }, report) + | report -> report + in + ({ pos; empty = false }, report) | T.Mod | T.Minus | T.Product | T.Div -> (* Operation over number *) let expected = Helper.[ Fixed Integer; Fixed Integer ] in @@ -448,6 +449,7 @@ module Instruction = struct let report' = Option.map snd variable.index |> Option.value ~default:[] in let report = List.rev_append report' report in + match ( right_expression.empty, op, -- cgit v1.2.3