diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/syntax/type_of.ml | 136 |
1 files changed, 60 insertions, 76 deletions
diff --git a/lib/syntax/type_of.ml b/lib/syntax/type_of.ml index 462f1cd..1cefc22 100644 --- a/lib/syntax/type_of.ml +++ b/lib/syntax/type_of.ml @@ -110,30 +110,18 @@ end module Expression = struct type 'a obs + type t = { result : Helper.t; pos : pos; empty : bool } - type t = { - result : Helper.t; - report : Report.t list; (* See the comment below *) - pos : pos; - empty : bool; - } - - type repr = Report.t list -> t + type repr = Report.t list -> t * Report.t list (** The type repr is a function accepting the report as a first argement. When the report is given, it will be reported into the tree and collected in bottom-top. - - It’s easy to forget that the report is updated when the type is created. - The function takes the report in argument, and store the report in the - returned type. Maybe should I make a tupple instead in order to make it - explicit ? *) type variable = { pos : pos; name : string; index : repr option } let arg_of_repr : t -> Helper.argument_repr = - fun { result; report; pos; empty } -> - ignore report; + fun { result; pos; empty } -> ignore empty; { pos; t = result } @@ -142,8 +130,8 @@ module Expression = struct fun var report -> let empty = false in match var.name.[0] with - | '$' -> { result = String; report; pos = var.pos; empty } - | _ -> { result = Integer; report; pos = var.pos; empty } + | '$' -> ({ result = String; pos = var.pos; empty }, report) + | _ -> ({ result = Integer; pos = var.pos; empty }, report) let integer : pos -> string -> repr = fun pos value report -> @@ -151,12 +139,12 @@ module Expression = struct match int_of_string_opt value with Some 0 -> true | _ -> false in - { result = Integer; report; pos; empty } + ({ result = Integer; pos; empty }, report) let literal : pos -> string -> repr = fun pos value report -> let empty = String.equal String.empty value in - { result = String; report; pos; empty } + ({ result = String; pos; empty }, report) let function_ : pos -> T.function_ -> repr list -> repr = fun pos function_ params _acc -> @@ -165,106 +153,105 @@ module Expression = struct parameters. *) let types, report = List.fold_left params ~init:([], _acc) ~f:(fun (types, report) param -> - let t = param report in + let t, report = param report in let arg = arg_of_repr t in - (arg :: types, t.report)) + (arg :: types, report)) in let types = List.rev types - and default = { result = Any; report; pos; empty = false } in + and default = { result = Any; pos; empty = false } in match function_ with | Arrcomp | Arrpos | Arrsize | Countobj | Desc | Dyneval | Func | Getobj | Instr | Isplay -> - { default with result = Integer } - | Desc' | Dyneval' | Func' | Getobj' -> { default with result = String } + ({ default with result = Integer }, report) + | Desc' | Dyneval' | Func' | Getobj' -> + ({ default with result = String }, report) | Iif | Iif' -> let d = Helper.dyn_type () in 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 *) let result = d Helper.Bool in - { result; report; pos; empty = false } + ({ result; pos; empty = false }, report) | Input | Input' -> (* Input should check the result if the variable is a num and raise a message in this case.*) let expected = Helper.[ Fixed String ] in let report = Helper.compare_args pos expected types report in - { result = String; report; pos; empty = false } + ({ result = String; pos; empty = false }, report) | Isnum -> let expected = Helper.[ Fixed String ] in let report = Helper.compare_args pos expected types report in - { result = Bool; report; pos; empty = false } + ({ result = Bool; pos; empty = false }, report) | Lcase | Lcase' | Ucase | Ucase' -> let expected = Helper.[ Fixed String ] in let report = Helper.compare_args pos expected types report in - { result = String; report; pos; empty = false } + ({ result = String; pos; empty = false }, report) | Len -> let expected = Helper.[ Fixed Any ] in let report = Helper.compare_args pos expected types report in - { result = Integer; report; pos; empty = false } + ({ result = Integer; pos; empty = false }, report) | Loc -> let expected = Helper.[ Fixed String ] in let report = Helper.compare_args pos expected types report in - { result = Bool; report; pos; empty = false } + ({ result = Bool; pos; empty = false }, report) | Max | Max' | Min | Min' -> let d = Helper.dyn_type () in (* 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 let result = d Helper.Bool in - { result; report; pos; empty = false } + ({ result; pos; empty = false }, report) | Mid | Mid' -> let expected = Helper.[ Fixed String; Variable (Fixed Integer) ] in let report = Helper.compare_args pos expected types report in - { result = String; report; pos; empty = false } - | Msecscount -> { result = Integer; report; pos; empty = false } + ({ result = String; pos; empty = false }, report) + | Msecscount -> ({ result = Integer; pos; empty = false }, report) | Rand -> let expected = Helper.[ Variable (Fixed Integer) ] in let report = Helper.compare_args pos expected types report in - { result = Integer; report; pos; empty = false } - | Replace -> { result = Integer; report; pos; empty = false } - | Replace' -> { result = String; report; pos; empty = false } - | Rgb -> { result = Integer; report; pos; empty = false } + ({ result = Integer; pos; empty = false }, report) + | Replace -> ({ result = Integer; pos; empty = false }, report) + | Replace' -> ({ result = String; pos; empty = false }, report) + | Rgb -> ({ result = Integer; pos; empty = false }, report) | Qspver | Qspver' | Rnd -> (* No arg *) let report = Helper.compare_args pos [] types report in - { result = Integer; report; pos; empty = false } - | Selact -> { result = Integer; report; pos; empty = false } - | Stattxt -> { result = Integer; report; pos; empty = false } - | Stattxt' -> { result = String; report; pos; empty = false } + ({ result = Integer; pos; empty = false }, report) + | Selact -> ({ result = Integer; pos; empty = false }, report) + | Stattxt -> ({ result = Integer; pos; empty = false }, report) + | Stattxt' -> ({ result = String; pos; empty = false }, report) | Str | Str' -> let expected = Helper.[ Variable (Fixed Integer) ] in let report = Helper.compare_args pos expected types report in - { default with result = String; report } - | Strcomp -> { result = Integer; report; pos; empty = false } - | Strfind -> { result = Integer; report; pos; empty = false } - | Strfind' -> { result = String; report; pos; empty = false } - | Strpos -> { result = Integer; report; pos; empty = false } - | Trim -> { result = Integer; report; pos; empty = false } - | Trim' -> { result = String; report; pos; empty = false } + ({ default with result = String }, report) + | Strcomp -> ({ result = Integer; pos; empty = false }, report) + | Strfind -> ({ result = Integer; pos; empty = false }, report) + | Strfind' -> ({ result = String; pos; empty = false }, report) + | Strpos -> ({ result = Integer; pos; empty = false }, report) + | Trim -> ({ result = Integer; pos; empty = false }, report) + | Trim' -> ({ result = String; pos; empty = false }, report) | Val -> let expected = Helper.[ Fixed Any ] in let report = Helper.compare_args pos expected types report in - { result = Integer; report; pos; empty = false } + ({ result = Integer; pos; empty = false }, report) (** Unary operator like [-123] or [+'Text']*) let uoperator : pos -> T.uoperator -> repr -> repr = fun pos operator t1 report -> - let t = t1 report in - let report = t.report in + let t, report = t1 report in match operator with - | Add -> t + | Add -> (t, report) | Neg | No -> let types = [ arg_of_repr t ] in let expected = Helper.[ Fixed Integer ] in let report = Helper.compare_args pos expected types report in - { result = Integer; report; pos; empty = false } + ({ result = Integer; pos; empty = false }, report) let boperator : pos -> T.boperator -> repr -> repr -> repr = fun pos operator t1 t2 report -> - let t1 = t1 report in - let t2 = t2 t1.report in - let report = t2.report in + let t1, report = t1 report in + let t2, report = t2 report in let types = [ arg_of_repr t1; arg_of_repr t2 ] in match operator with | T.Plus -> @@ -273,12 +260,12 @@ module Expression = struct let expected = Helper.[ Dynamic d; Dynamic d ] in let report = Helper.compare_args pos expected types report in let result = d Helper.Integer in - { result; report; pos; empty = false } + ({ result; pos; empty = false }, report) | T.Eq | T.Neq -> (* If the expression is '' or 0, we accept the comparaison as if instead of raising a warning *) if t1.empty || t2.empty then - { result = Bool; report; pos; empty = false } + ({ result = Bool; pos; empty = false }, report) else let d = Helper.(Dynamic (dyn_type ())) in let expected = [ d; d ] in @@ -286,22 +273,22 @@ module Expression = struct Helper.compare_args ~strict:true pos expected (List.rev types) report in - { result = Bool; report; pos; empty = false } + ({ result = Bool; pos; empty = false }, report) | Lt | Gte | Lte | Gt -> let d = Helper.(Dynamic (dyn_type ())) in let expected = [ d; d ] in let report = Helper.compare_args pos expected types report in - { result = Bool; report; pos; empty = false } + ({ result = Bool; pos; empty = false }, 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 - { result = Integer; report; pos; empty = false } + ({ result = Integer; pos; empty = false }, 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 - { result = Bool; report; pos; empty = false } + ({ result = Bool; pos; empty = false }, report) end module Instruction = struct @@ -313,8 +300,9 @@ module Instruction = struct let call : pos -> T.keywords -> expression list -> repr = fun _pos _ expressions report -> List.fold_left expressions ~init:report ~f:(fun report expression -> - let result = expression report in - result.Expression.report) + let result, report = expression report in + ignore result; + report) let location : pos -> string -> repr = fun _pos _ report -> report @@ -323,7 +311,7 @@ module Instruction = struct (** Raw expression *) let expression : expression -> repr = - fun expression report -> (expression report).report + fun expression report -> snd (expression report) type clause = pos * expression * repr list @@ -331,11 +319,9 @@ module Instruction = struct fun _pos clause ~elifs ~else_ report -> (* Helper function *) let fold_clause report (_pos, expr, instructions) : Report.t list = - let result = expr report in + let result, report = expr report in let report = - Helper.compare Helper.Bool - (Expression.arg_of_repr result) - result.Expression.report + Helper.compare Helper.Bool (Expression.arg_of_repr result) report in List.fold_left instructions ~init:report ~f:(fun report instruction -> instruction report) @@ -349,23 +335,21 @@ module Instruction = struct let act : pos -> label:expression -> repr list -> repr = fun _pos ~label instructions report -> - let result = label report in + let result, report = label report in let report = - Helper.compare Helper.String - (Expression.arg_of_repr result) - result.Expression.report + Helper.compare Helper.String (Expression.arg_of_repr result) report in List.fold_left instructions ~init:report ~f:(fun report instruction -> instruction report) let assign : pos -> variable -> T.assignation_operator -> expression -> repr = fun pos variable _ expression report -> - let right_expression = expression report in + let right_expression, report = expression report in match right_expression.empty with | true -> report | false -> - let op1 = Expression.arg_of_repr (Expression.ident variable report) in - let report = right_expression.Expression.report in + let expr1, report = Expression.ident variable report in + let op1 = Expression.arg_of_repr expr1 in let op2 = Expression.arg_of_repr right_expression in let d = Helper.dyn_type () in |