diff options
Diffstat (limited to 'lib/checks/type_of.ml')
-rw-r--r-- | lib/checks/type_of.ml | 115 |
1 files changed, 55 insertions, 60 deletions
diff --git a/lib/checks/type_of.ml b/lib/checks/type_of.ml index 42f9a2d..243c8b3 100644 --- a/lib/checks/type_of.ml +++ b/lib/checks/type_of.ml @@ -12,12 +12,15 @@ type context = unit let initialize = Fun.id let finalize () = [] +let depends = [ Get_type.ex ] + +type ex = Qsp_syntax.Identifier.t module Helper = struct - type argument_repr = { pos : S.pos; t : Get_type.t } + type argument_repr = { pos : S.pos; t : Get_type.Expression.t } module DynType = struct - type nonrec t = Get_type.t -> Get_type.t + type nonrec t = Get_type.Expression.t -> Get_type.Expression.t (** Dynamic type is a type unknown during the code. For example, the equality operator accept either Integer or String, but @@ -143,35 +146,35 @@ module Helper = struct msg :: report end -type t' = { result : Get_type.t Lazy.t; pos : S.pos } +type t' = { result : Get_type.Expression.t; pos : S.pos } -let arg_of_repr : Get_type.t Lazy.t -> S.pos -> Helper.argument_repr = - fun type_of pos -> { pos; t = Lazy.force type_of } +let arg_of_repr : Get_type.Expression.t -> S.pos -> Helper.argument_repr = + fun type_of pos -> { pos; t = type_of } -module TypedExpression = struct +module Expression = struct type nonrec t' = t' * Report.t list - type state = { pos : S.pos } + type state = { pos : S.pos; type_of : Get_type.Expression.t } type t = state * Report.t list - let v : Get_type.t Lazy.t * t -> t' = - fun (type_of, (t, r)) -> ({ result = type_of; pos = t.pos }, r) + let v : t -> t' = fun (t, r) -> ({ result = t.type_of; pos = t.pos }, r) (** The variable has type string when starting with a '$' *) - let ident : - (S.pos, Get_type.t Lazy.t * t) S.variable -> Get_type.t Lazy.t -> t = - fun var _type_of -> + let ident : ctx:Qsp_syntax.S.extract_context -> (S.pos, t) S.variable -> t = + fun ~ctx var -> (* Extract the error from the index *) let report = match var.index with | None -> [] | Some (_, expr) -> - let _, r = expr in + let r = expr in r in - ({ pos = var.pos }, report) + let type_of = Option.get (ctx.f Get_type.expression_id) in + ({ pos = var.pos; type_of }, report) - let integer : S.pos -> string -> Get_type.t Lazy.t -> t = - fun pos value _type_of -> + let integer : ctx:Qsp_syntax.S.extract_context -> S.pos -> string -> t = + fun ~ctx pos value -> + let type_of = Option.get (ctx.f Get_type.expression_id) in let int_value = int_of_string_opt value in let report = @@ -181,42 +184,36 @@ module TypedExpression = struct | None -> Report.error pos "Invalid integer value" :: [] in - ({ pos }, report) + ({ pos; type_of }, report) let literal : - S.pos -> (Get_type.t Lazy.t * t) T.literal list -> Get_type.t Lazy.t -> t - = - fun pos values type_of -> - ignore type_of; + ctx:Qsp_syntax.S.extract_context -> S.pos -> t T.literal list -> t = + fun ~ctx pos values -> + let type_of = Option.get (ctx.f Get_type.expression_id) in let init = [] in let report = List.fold_left values ~init ~f:(fun report -> function | T.Text _ -> report - | T.Expression (_, t) -> + | T.Expression t -> let report = List.rev_append (snd t) report in report) in - ({ pos }, report) + ({ pos; type_of }, report) let function_ : - S.pos -> - T.function_ -> - (Get_type.t Lazy.t * t) list -> - Get_type.t Lazy.t -> - t = - fun pos function_ params _type_of -> + ctx:Qsp_syntax.S.extract_context -> S.pos -> T.function_ -> t list -> t = + fun ~ctx pos function_ params -> + let type_of = Option.get (ctx.f Get_type.expression_id) in (* Accumulate the expressions and get the results, the report is given in the differents arguments, and we build a list with the type of the parameters. *) let types, report = - List.fold_left params ~init:([], []) - ~f:(fun (types, report) (type_of, param) -> - ignore type_of; + List.fold_left params ~init:([], []) ~f:(fun (types, report) param -> let t, r = param in - let arg = arg_of_repr type_of t.pos in + let arg = arg_of_repr t.type_of t.pos in (arg :: types, r @ report)) in - let types = List.rev types and default = { pos } in + let types = List.rev types and default = { pos; type_of } in match function_ with | Arrcomp | Arrpos | Arrsize | Countobj | Desc | Dyneval | Getobj | Instr @@ -229,7 +226,7 @@ module TypedExpression = struct let expected = Helper.[ Fixed Bool; Dynamic d; Dynamic d ] in let report = Helper.compare_args pos expected types report in (* Extract the type for the expression *) - ({ pos }, report) + ({ pos; type_of }, report) | Input | Input' -> (* Input should check the result if the variable is a num and raise a message in this case.*) @@ -257,7 +254,7 @@ module TypedExpression = struct (* All the arguments must have the same type *) let expected = Helper.[ Variable (Dynamic d) ] in let report = Helper.compare_args pos expected types report in - ({ pos }, report) + ({ pos; type_of }, report) | Mid | Mid' -> let expected = Helper.[ Fixed String; Variable (Fixed Integer) ] in let report = Helper.compare_args pos expected types report in @@ -292,29 +289,25 @@ module TypedExpression = struct (** Unary operator like [-123] or [+'Text']*) let uoperator : - S.pos -> T.uoperator -> Get_type.t Lazy.t * t -> Get_type.t Lazy.t -> t = - fun pos operator t1 type_of -> - ignore type_of; - let type_of, (t, report) = t1 in + ctx:Qsp_syntax.S.extract_context -> S.pos -> T.uoperator -> t -> t = + fun ~ctx pos operator t1 -> + let t, report = t1 in match operator with | Add -> (t, report) | Neg | No -> - let types = [ arg_of_repr type_of t.pos ] in + let types = [ arg_of_repr t.type_of t.pos ] in let expected = Helper.[ Fixed Integer ] in let report = Helper.compare_args pos expected types report in - ({ pos }, report) + let type_of = Option.get (ctx.f Get_type.expression_id) in + ({ pos; type_of }, report) let boperator : - S.pos -> - T.boperator -> - Get_type.t Lazy.t * t -> - Get_type.t Lazy.t * t -> - Get_type.t Lazy.t -> - t = - fun pos operator (type_1, t1) (type_2, t2) type_of -> - ignore type_of; + ctx:Qsp_syntax.S.extract_context -> S.pos -> T.boperator -> t -> t -> t = + fun ~ctx pos operator t1 t2 -> let t1, report1 = t1 in let t2, report2 = t2 in + let type_1 = t1.type_of and type_2 = t2.type_of in + let type_of = Option.get (ctx.f Get_type.expression_id) in let report = report1 @ report2 in @@ -327,7 +320,7 @@ module TypedExpression = struct When concatenating, it’s allowed to add an integer and a number. *) - ({ pos }, report) + ({ pos; type_of }, report) | 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 *) @@ -345,26 +338,24 @@ module TypedExpression = struct report | report -> report in - ({ pos }, report) + ({ pos; type_of }, report) | T.Mod | T.Minus | T.Product | T.Div -> (* Operation over number *) let expected = Helper.[ Fixed Integer; Fixed Integer ] in let report = Helper.compare_args pos expected types report in - ({ pos }, report) + ({ pos; type_of }, report) | T.And | T.Or -> (* Operation over booleans *) let expected = Helper.[ Fixed Bool; Fixed Bool ] in let report = Helper.compare_args pos expected types report in - ({ pos }, report) + ({ pos; type_of }, report) end -module Expression = Compose.TypeBuilder.Make (TypedExpression) - module Instruction = struct type t = Report.t list type t' = Report.t list - let v : t -> t' = fun local_report -> local_report + let v : t -> t' = Fun.id type expression = Expression.t' @@ -444,17 +435,21 @@ module Instruction = struct let report = List.rev_append report' report in - match (op, Get_type.get_type (Lazy.force right_expression.result)) with + match (op, Get_type.Expression.get_type right_expression.result) with | T.Eq', Get_type.Integer -> (* Assigning an intger is allowed in a string variable, but raise a warning. *) - let var_type = Lazy.from_val (Get_type.ident variable) in + let var_type = + Get_type.Expression.ident ~ctx:{ f = (fun _ -> None) } variable + in let op1 = arg_of_repr var_type variable.pos in let expected = Helper.[ Fixed Integer ] in Helper.compare_args ~strict:true ~level:Report.Warn pos expected [ op1 ] report | _, _ -> ( - let var_type = Lazy.from_val (Get_type.ident variable) in + let var_type = + Get_type.Expression.ident ~ctx:{ f = (fun _ -> None) } variable + in let op1 = arg_of_repr var_type variable.pos in let op2 = arg_of_repr right_expression.result right_expression.pos in |