From f54847b1684bf525829c2c08e188cb3974db35e4 Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Thu, 16 Sep 2021 14:02:50 -0400 Subject: [PATCH 01/15] Simplify semantic warnings --- src/frontend/Frontend_utils.ml | 26 +++++++++++--------------- src/frontend/Semantic_check.ml | 12 +++--------- src/frontend/Semantic_check.mli | 4 +--- src/middle/Warnings.ml | 6 ++++-- src/middle/Warnings.mli | 1 + 5 files changed, 20 insertions(+), 29 deletions(-) diff --git a/src/frontend/Frontend_utils.ml b/src/frontend/Frontend_utils.ml index f8a6a649ac..9a40d848d0 100644 --- a/src/frontend/Frontend_utils.ml +++ b/src/frontend/Frontend_utils.ml @@ -23,7 +23,7 @@ let typed_ast_of_string_exn s = failwith "Internal compiler error: no message from Semantic_check." )) |> Result.map_error ~f:Errors.to_string - |> Result.ok_or_failwith |> emit_warnings_and_return_ast + |> Result.ok_or_failwith let get_ast_or_exit ?printed_filename ?(print_warnings = true) filename = let res, warnings = Parse.parse_file Parser.Incremental.program filename in @@ -36,17 +36,13 @@ let get_ast_or_exit ?printed_filename ?(print_warnings = true) filename = | Result.Error err -> Errors.pp Fmt.stderr err ; exit 1 let type_ast_or_exit ast = - try - match Semantic_check.semantic_check_program ast with - | Result.Ok p -> emit_warnings_and_return_ast p - | Result.Error (error :: _) -> - Errors.pp_semantic_error Fmt.stderr error ; - exit 1 - | Result.Error [] -> - Printf.eprintf - "Semantic check failed but reported no errors. This should never \ - happen." ; - exit 1 - with Errors.SemanticError err -> - Errors.pp_semantic_error Fmt.stderr err ; - exit 1 + match Semantic_check.semantic_check_program ast with + | Result.Ok p -> p + | Result.Error (error :: _) -> + Errors.pp_semantic_error Fmt.stderr error ; + exit 1 + | Result.Error [] -> + Printf.eprintf + "Semantic check failed but reported no errors. This should never \ + happen." ; + exit 1 diff --git a/src/frontend/Semantic_check.ml b/src/frontend/Semantic_check.ml index 5212878b44..620e6dbf63 100644 --- a/src/frontend/Semantic_check.ml +++ b/src/frontend/Semantic_check.ml @@ -10,13 +10,6 @@ open Ast open Errors module Validate = Common.Validation.Make (Semantic_error) -let warnings = ref [] - -let add_warning (span : Location_span.t) (message : string) = - warnings := (span, message) :: !warnings - -let attach_warnings (x : typed_program) = (x, List.rev !warnings) - (* There is a semantic checking function for each AST node that calls the checking functions for its children left to right. *) @@ -725,7 +718,8 @@ and semantic_check_expression cf ({emeta; expr} : Ast.untyped_expression) : "If rounding is intended please use the integer division \ operator %/%." in - add_warning x.emeta.loc s ; (x, y) + Warnings.pp_warning Fmt.stderr (x.emeta.loc, s) ; + (x, y) | _ -> (x, y) in Validate.( @@ -1954,5 +1948,5 @@ let semantic_check_program |> apply_to upb |> apply_to utpb |> apply_to umb |> apply_to ugb |> check_correctness_invariant_validate |> get_with - ~with_ok:(fun ok -> Result.Ok (attach_warnings ok)) + ~with_ok:(fun ok -> Result.Ok ok) ~with_errors:(fun errs -> Result.Error errs)) diff --git a/src/frontend/Semantic_check.mli b/src/frontend/Semantic_check.mli index 7d9c5b0d45..39695b1b3b 100644 --- a/src/frontend/Semantic_check.mli +++ b/src/frontend/Semantic_check.mli @@ -17,9 +17,7 @@ val semantic_check_binop_exn : val semantic_check_program : Ast.untyped_program - -> ( Ast.typed_program * Middle.Warnings.t list - , Middle.Semantic_error.t list ) - result + -> (Ast.typed_program, Middle.Semantic_error.t list) result (** Performs semantic check on AST and returns original AST embellished with type decorations *) val check_that_all_functions_have_definition : bool ref diff --git a/src/middle/Warnings.ml b/src/middle/Warnings.ml index 7e91b2807f..309968dfdb 100644 --- a/src/middle/Warnings.ml +++ b/src/middle/Warnings.ml @@ -8,5 +8,7 @@ let pp ?printed_filename ppf (span, message) = Fmt.pf ppf "@[Warning%s: %s@]" loc_str message let pp_warnings ?printed_filename ppf warnings = - Fmt.( - pf ppf "@[%a@]%a" (list ~sep:cut (pp ?printed_filename)) warnings cut ()) + Fmt.(pf ppf "@[%a@]@," (list ~sep:cut (pp ?printed_filename)) warnings) + +let pp_warning ?printed_filename ppf warning = + Fmt.(pf ppf "@[%a@]" (pp ?printed_filename) warning) diff --git a/src/middle/Warnings.mli b/src/middle/Warnings.mli index a41dd84615..799602039f 100644 --- a/src/middle/Warnings.mli +++ b/src/middle/Warnings.mli @@ -2,3 +2,4 @@ type t = Location_span.t * string val pp : ?printed_filename:string -> t Fmt.t val pp_warnings : ?printed_filename:string -> t list Fmt.t +val pp_warning : ?printed_filename:string -> t Fmt.t From 800976489e3490e69efe5c5e8f289295b29702d8 Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Thu, 16 Sep 2021 14:05:13 -0400 Subject: [PATCH 02/15] Remove unused functions --- src/frontend/Semantic_check.ml | 11 ----------- src/frontend/Semantic_check.mli | 13 ------------- 2 files changed, 24 deletions(-) diff --git a/src/frontend/Semantic_check.ml b/src/frontend/Semantic_check.ml index 620e6dbf63..08898ef50b 100644 --- a/src/frontend/Semantic_check.ml +++ b/src/frontend/Semantic_check.ml @@ -455,14 +455,6 @@ let semantic_check_binop loc op (le, re) = |> ok | Void -> error err )) -let to_exn v = - v |> Validate.to_result - |> Result.map_error ~f:Fmt.(to_to_string @@ list ~sep:cut Semantic_error.pp) - |> Result.ok_or_failwith - -let semantic_check_binop_exn loc op (le, re) = - semantic_check_binop loc op (le, re) |> to_exn - (* -- Prefix Operators ------------------------------------------------------ *) let semantic_check_prefixop loc op e = @@ -625,9 +617,6 @@ let inferred_unsizedtype_of_indexed ~loc ut indices = in aux ut (List.map ~f:indexing_type indices) -let inferred_unsizedtype_of_indexed_exn ~loc ut indices = - inferred_unsizedtype_of_indexed ~loc ut indices |> to_exn - let inferred_ad_type_of_indexed at uindices = UnsizedType.lub_ad_type ( at diff --git a/src/frontend/Semantic_check.mli b/src/frontend/Semantic_check.mli index 39695b1b3b..56e1d1e8bc 100644 --- a/src/frontend/Semantic_check.mli +++ b/src/frontend/Semantic_check.mli @@ -2,19 +2,6 @@ open Core_kernel -val inferred_unsizedtype_of_indexed_exn : - loc:Middle.Location_span.t - -> Middle.UnsizedType.t - -> Ast.typed_expression Ast.index list - -> Middle.UnsizedType.t -(** Infers unsized type of an `Indexed` expression *) - -val semantic_check_binop_exn : - Middle.Location_span.t - -> Middle.Operator.t - -> Ast.typed_expression * Ast.typed_expression - -> Ast.typed_expression - val semantic_check_program : Ast.untyped_program -> (Ast.typed_program, Middle.Semantic_error.t list) result From bb4a577a3428efaba06ccfcf14cd125b9e01a438 Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Fri, 17 Sep 2021 10:26:11 -0400 Subject: [PATCH 03/15] New typechecker --- src/frontend/Ast_to_Mir.ml | 2 +- src/frontend/Environment.ml | 119 ++ src/frontend/Environment.mli | 51 + src/frontend/Frontend_utils.ml | 21 +- src/frontend/Semantic_check.ml | 26 +- src/frontend/Typechecker.ml | 1551 ++++++++++++++++++++++ src/frontend/Typechecker.mli | 14 + src/middle/Semantic_error.ml | 2 +- src/middle/SignatureMismatch.mli | 2 + src/stan2tfp/Stan2tfp.ml | 5 +- src/stanc/stanc.ml | 12 +- src/stancjs/stancjs.ml | 18 +- test/integration/bad/functions-bad2.stan | 6 + test/integration/bad/shadow.stan | 5 + test/integration/bad/stanc.expected | 26 +- test/integration/good/pretty.expected | 9 + test/integration/good/shadow.stan | 7 + test/stancjs/stancjs.expected | 8 +- 18 files changed, 1818 insertions(+), 66 deletions(-) create mode 100644 src/frontend/Environment.ml create mode 100644 src/frontend/Environment.mli create mode 100644 src/frontend/Typechecker.ml create mode 100644 src/frontend/Typechecker.mli create mode 100644 test/integration/bad/shadow.stan create mode 100644 test/integration/good/shadow.stan diff --git a/src/frontend/Ast_to_Mir.ml b/src/frontend/Ast_to_Mir.ml index 6bb90fc8eb..d09c88483c 100644 --- a/src/frontend/Ast_to_Mir.ml +++ b/src/frontend/Ast_to_Mir.ml @@ -878,5 +878,5 @@ let trans_prog filename (p : Ast.typed_program) : Program.Typed.t = ; generate_quantities ; transform_inits ; output_vars - ; prog_name= normalize_prog_name !Semantic_check.model_name + ; prog_name= normalize_prog_name !Typechecker.model_name ; prog_path= filename } diff --git a/src/frontend/Environment.ml b/src/frontend/Environment.ml new file mode 100644 index 0000000000..f063cd796b --- /dev/null +++ b/src/frontend/Environment.ml @@ -0,0 +1,119 @@ +open Core_kernel +open Middle + +(** Origin blocks, to keep track of where variables are declared *) +type originblock = + | MathLibrary + | Functions + | Data + | TData + | Param + | TParam + | Model + | GQuant +[@@deriving sexp] + +type varinfo = {origin: originblock; global: bool; readonly: bool} +[@@deriving sexp] + +type info = + { type_: UnsizedType.t + ; kind: + [ `Variable of varinfo + | `UserDeclared of Location_span.t + | `StanMath + | `UserDefined ] } +[@@deriving sexp] + +type t = info list String.Map.t + +let create () = + let functions = + Hashtbl.to_alist Stan_math_signatures.stan_math_signatures + |> List.map ~f:(fun (key, values) -> + ( key + , List.map + ~f:(fun (rt, args, mem) -> + let type_ = + UnsizedType.UFun (args, rt, Fun_kind.FnPlain, mem) + in + {type_; kind= `StanMath} ) + values ) ) + |> String.Map.of_alist_exn + in + functions + +let add env key type_ kind = Map.add_multi env ~key ~data:{type_; kind} + +let add_all_raw env key data = + let env = Map.remove env key in + List.fold ~init:env ~f:(fun env data -> Map.add_multi env ~key ~data) data + +let find env key = Map.find_multi env key +let mem env key = Map.mem env key +let iter env f = Map.iter env ~f + +(* TODO move this to SignatureMismatch.ml when semantic_check is removed *) + +let extract_function_types f = + match f with + | {type_= UFun (args, return, _, mem); kind= `StanMath} -> + Some (return, args, (fun x -> Ast.StanLib x), mem) + | {type_= UFun (args, return, _, mem); _} -> + Some (return, args, (fun x -> UserDefined x), mem) + | _ -> None + +let rec check_same_type depth t1 t2 = + let open SignatureMismatch in + let wrap_func = Option.map ~f:(fun e -> TypeMismatch (t1, t2, Some e)) in + match (t1, t2) with + | t1, t2 when t1 = t2 -> None + | UnsizedType.(UReal, UInt) when depth < 1 -> None + | UFun (_, _, s1, _), UFun (_, _, s2, _) + when Fun_kind.without_propto s1 <> Fun_kind.without_propto s2 -> + Some + (SuffixMismatch (Fun_kind.without_propto s1, Fun_kind.without_propto s2)) + |> wrap_func + | UFun (_, rt1, _, _), UFun (_, rt2, _, _) when rt1 <> rt2 -> + Some (ReturnTypeMismatch (rt1, rt2)) |> wrap_func + | UFun (l1, _, _, _), UFun (l2, _, _, _) -> + check_compatible_arguments (depth + 1) l2 l1 + |> Option.map ~f:(fun e -> InputMismatch e) + |> wrap_func + | t1, t2 -> Some (TypeMismatch (t1, t2, None)) + +and check_compatible_arguments depth args1 args2 = + let open SignatureMismatch in + match List.zip args1 args2 with + | None -> Some (ArgNumMismatch (List.length args1, List.length args2)) + | Some l -> + List.find_mapi l ~f:(fun i ((ad1, ut1), (ad2, ut2)) -> + match check_same_type depth ut1 ut2 with + | Some e -> Some (ArgError (i + 1, e)) + | None -> + if ad1 = ad2 then None + else if depth < 2 && UnsizedType.autodifftype_can_convert ad1 ad2 + then None + else Some (ArgError (i + 1, DataOnlyError)) ) + +let returntype env name args = + let open SignatureMismatch in + (* NB: Variadic arguments are special-cased in Semantic_check and not handled here *) + let name = Utils.stdlib_distribution_name name in + find env name + |> List.filter_map ~f:extract_function_types + |> List.sort ~compare:(fun (x, _, _, _) (y, _, _, _) -> + UnsizedType.compare_returntype x y ) + (* Check the least return type first in case there are multiple options (due to implicit UInt-UReal conversion), where UInt List.fold_until ~init:[] + ~f:(fun errors (rt, tys, funkind_constructor, _) -> + match check_compatible_arguments 0 tys args with + | None -> Stop (Ok (rt, funkind_constructor)) + | Some e -> Continue (((rt, tys), e) :: errors) ) + ~finish:(fun errors -> + let errors = + List.sort errors ~compare:(fun (_, e1) (_, e2) -> + compare_errors e1 e2 ) + in + let errors, omitted = List.split_n errors 5 in + Error (errors, not (List.is_empty omitted)) ) diff --git a/src/frontend/Environment.mli b/src/frontend/Environment.mli new file mode 100644 index 0000000000..0a77bd39dc --- /dev/null +++ b/src/frontend/Environment.mli @@ -0,0 +1,51 @@ +open Middle + +type originblock = + | MathLibrary + | Functions + | Data + | TData + | Param + | TParam + | Model + | GQuant +[@@deriving sexp] + +type varinfo = {origin: originblock; global: bool; readonly: bool} +[@@deriving sexp] + +type info = + { type_: UnsizedType.t + ; kind: + [ `Variable of varinfo + | `UserDeclared of Location_span.t + | `StanMath + | `UserDefined ] } +[@@deriving sexp] + +type t + +val create : unit -> t +val find : t -> string -> info list + +val add : + t + -> string + -> Middle.UnsizedType.t + -> [ `UserDeclared of Location_span.t + | `StanMath + | `UserDefined + | `Variable of varinfo ] + -> t + +val add_all_raw : t -> string -> info list -> t +val mem : t -> string -> bool +val iter : t -> (info list -> unit) -> unit + +val returntype : + t + -> string + -> (UnsizedType.autodifftype * UnsizedType.t) list + -> ( UnsizedType.returntype * (bool Middle.Fun_kind.suffix -> Ast.fun_kind) + , SignatureMismatch.signature_error list * bool ) + result diff --git a/src/frontend/Frontend_utils.ml b/src/frontend/Frontend_utils.ml index 9a40d848d0..643635c3ea 100644 --- a/src/frontend/Frontend_utils.ml +++ b/src/frontend/Frontend_utils.ml @@ -8,20 +8,12 @@ let untyped_ast_of_string s = Fmt.epr "%a" (Fmt.list ~sep:Fmt.nop Warnings.pp) warnings ; res -let emit_warnings_and_return_ast (ast, warnings) = - if List.length warnings > 0 then Warnings.pp_warnings Fmt.stderr warnings ; - ast - let typed_ast_of_string_exn s = Result.( untyped_ast_of_string s >>= fun ast -> - Semantic_check.semantic_check_program ast - |> map_error ~f:(function - | err :: _ -> Errors.Semantic_error err - | [] -> - failwith - "Internal compiler error: no message from Semantic_check." )) + Typechecker.check_program ast + |> map_error ~f:(fun e -> Errors.Semantic_error e)) |> Result.map_error ~f:Errors.to_string |> Result.ok_or_failwith @@ -36,13 +28,8 @@ let get_ast_or_exit ?printed_filename ?(print_warnings = true) filename = | Result.Error err -> Errors.pp Fmt.stderr err ; exit 1 let type_ast_or_exit ast = - match Semantic_check.semantic_check_program ast with + match Typechecker.check_program ast with | Result.Ok p -> p - | Result.Error (error :: _) -> + | Result.Error error -> Errors.pp_semantic_error Fmt.stderr error ; exit 1 - | Result.Error [] -> - Printf.eprintf - "Semantic check failed but reported no errors. This should never \ - happen." ; - exit 1 diff --git a/src/frontend/Semantic_check.ml b/src/frontend/Semantic_check.ml index 08898ef50b..f5dd7f00bc 100644 --- a/src/frontend/Semantic_check.ml +++ b/src/frontend/Semantic_check.ml @@ -1861,14 +1861,14 @@ let semantic_check_functions_have_defn function_block_stmts_opt = (* The actual semantic checks for all AST nodes! *) let semantic_check_program - { functionblock= fb - ; datablock= db - ; transformeddatablock= tdb - ; parametersblock= pb - ; transformedparametersblock= tpb - ; modelblock= mb - ; generatedquantitiesblock= gb - ; comments } = + ( { functionblock= fb + ; datablock= db + ; transformeddatablock= tdb + ; parametersblock= pb + ; transformedparametersblock= tpb + ; modelblock= mb + ; generatedquantitiesblock= gb + ; comments } as ast ) = (* NB: We always want to make sure we start with an empty symbol table, in case we are processing multiple files in one run. *) unsafe_clear_symbol_table vm ; @@ -1911,15 +1911,7 @@ let semantic_check_program let check_correctness_invariant (decorated_ast : typed_program) : typed_program = if - compare_untyped_program - { functionblock= fb - ; datablock= db - ; transformeddatablock= tdb - ; parametersblock= pb - ; transformedparametersblock= tpb - ; modelblock= mb - ; generatedquantitiesblock= gb - ; comments } + compare_untyped_program ast (untyped_program_of_typed_program decorated_ast) = 0 then decorated_ast diff --git a/src/frontend/Typechecker.ml b/src/frontend/Typechecker.ml new file mode 100644 index 0000000000..2bb5a4319d --- /dev/null +++ b/src/frontend/Typechecker.ml @@ -0,0 +1,1551 @@ +(** a type/semantic checker for Stan ASTs + + Functions which begin with "check_" return a typed version of their input + Functions which begin with "verify_" return unit if a check succeeds, or else + throw an Errors.SemanticError exception. + + All Error.SemanticError excpetions are caught by check_program + which turns the ast or exception into a Result.t for external usage + + A type environment (Env.t) is used to hold variables and functions, including + stan math functions. This is a functional map, meaning it is handled immutably. +*) + +open Core_kernel +open Middle +open Ast +module Env = Environment + +(* we only allow errors raised by this function *) +let error e = raise (Errors.SemanticError e) + +(* model name - don't love this here *) +let model_name = ref "" +let check_that_all_functions_have_definition = ref true + +(* Record structure holding flags and other markers about context to be + used for error reporting. *) +type context_flags_record = + { current_block: Env.originblock + ; in_toplevel_decl: bool + ; in_fun_def: bool + ; in_returning_fun_def: bool + ; in_rng_fun_def: bool + ; in_lp_fun_def: bool + ; in_udf_dist_def: bool + ; loop_depth: int } + +let context block = + { current_block= block + ; in_toplevel_decl= false + ; in_fun_def= false + ; in_returning_fun_def= false + ; in_rng_fun_def= false + ; in_lp_fun_def= false + ; in_udf_dist_def= false + ; loop_depth= 0 } + +let calculate_autodifftype cf at ut = + match at with + | Env.(Param | TParam | Model | Functions) + when not (UnsizedType.contains_int ut || cf.current_block = GQuant) -> + UnsizedType.AutoDiffable + | _ -> DataOnly + +let arg_type x = (x.emeta.ad_level, x.emeta.type_) +let get_arg_types = List.map ~f:arg_type +let type_of_expr_typed ue = ue.emeta.type_ +let has_int_type ue = ue.emeta.type_ = UInt +let has_int_array_type ue = ue.emeta.type_ = UArray UInt + +let has_int_or_real_type ue = + match ue.emeta.type_ with UInt | UReal -> true | _ -> false + +let probability_distribution_name_variants id = + let name = id.name in + let open String in + List.map + ~f:(fun n -> {name= n; id_loc= id.id_loc}) + ( if name = "multiply_log" || name = "binomial_coefficient_log" then [name] + else if is_suffix ~suffix:"_lpmf" name then + [name; drop_suffix name 5 ^ "_lpdf"; drop_suffix name 5 ^ "_log"] + else if is_suffix ~suffix:"_lpdf" name then + [name; drop_suffix name 5 ^ "_lpmf"; drop_suffix name 5 ^ "_log"] + else if is_suffix ~suffix:"_lcdf" name then + [name; drop_suffix name 5 ^ "_cdf_log"] + else if is_suffix ~suffix:"_lccdf" name then + [name; drop_suffix name 6 ^ "_ccdf_log"] + else if is_suffix ~suffix:"_cdf_log" name then + [name; drop_suffix name 8 ^ "_lcdf"] + else if is_suffix ~suffix:"_ccdf_log" name then + [name; drop_suffix name 9 ^ "_lccdf"] + else if is_suffix ~suffix:"_log" name then + [name; drop_suffix name 4 ^ "_lpmf"; drop_suffix name 4 ^ "_lpdf"] + else [name] ) + +(* -- General checks ---------------------------------------------- *) +let reserved_keywords = + [ "true"; "false"; "repeat"; "until"; "then"; "var"; "fvar"; "STAN_MAJOR" + ; "STAN_MINOR"; "STAN_PATCH"; "STAN_MATH_MAJOR"; "STAN_MATH_MINOR" + ; "STAN_MATH_PATCH"; "alignas"; "alignof"; "and"; "and_eq"; "asm"; "auto" + ; "bitand"; "bitor"; "bool"; "break"; "case"; "catch"; "char"; "char16_t" + ; "char32_t"; "class"; "compl"; "const"; "constexpr"; "const_cast" + ; "continue"; "decltype"; "default"; "delete"; "do"; "double"; "dynamic_cast" + ; "else"; "enum"; "explicit"; "export"; "extern"; "false"; "float"; "for" + ; "friend"; "goto"; "if"; "inline"; "int"; "long"; "mutable"; "namespace" + ; "new"; "noexcept"; "not"; "not_eq"; "nullptr"; "operator"; "or"; "or_eq" + ; "private"; "protected"; "public"; "register"; "reinterpret_cast"; "return" + ; "short"; "signed"; "sizeof"; "static"; "static_assert"; "static_cast" + ; "struct"; "switch"; "template"; "this"; "thread_local"; "throw"; "true" + ; "try"; "typedef"; "typeid"; "typename"; "union"; "unsigned"; "using" + ; "virtual"; "void"; "volatile"; "wchar_t"; "while"; "xor"; "xor_eq" + ; "functions"; "data"; "parameters"; "model"; "return"; "if"; "else"; "while" + ; "for"; "in"; "break"; "continue"; "void"; "int"; "real"; "complex" + ; "vector"; "row_vector"; "matrix"; "ordered"; "positive_ordered"; "simplex" + ; "unit_vector"; "cholesky_factor_corr"; "cholesky_factor_cov"; "corr_matrix" + ; "cov_matrix"; "print"; "reject"; "target"; "get_lp"; "profile" ] + +let verify_identifier id : unit = + if id.name = !model_name then + Semantic_error.ident_is_model_name id.id_loc id.name |> error + else if + String.is_suffix id.name ~suffix:"__" + || List.mem reserved_keywords id.name ~equal:String.equal + then Semantic_error.ident_is_keyword id.id_loc id.name |> error + else () + +let verify_name_fresh_var tenv id = + if Utils.is_unnormalized_distribution id.name then + Semantic_error.ident_has_unnormalized_suffix id.id_loc id.name |> error + else if + Env.mem tenv id.name + && not (Stan_math_signatures.is_stan_math_function_name id.name) + then Semantic_error.ident_in_use id.id_loc id.name |> error + else () + +let verify_name_fresh_udf tenv id = + if + Stan_math_signatures.is_stan_math_function_name id.name + (* variadic functions are currently not in math sigs *) + || Stan_math_signatures.is_reduce_sum_fn id.name + || Stan_math_signatures.is_variadic_ode_fn id.name + then Semantic_error.ident_is_stanmath_name id.id_loc id.name |> error + else if Utils.is_unnormalized_distribution id.name then + Semantic_error.udf_is_unnormalized_fn id.id_loc id.name |> error + else if Env.mem tenv id.name then + (* adapt for overloading later *) + Semantic_error.ident_in_use id.id_loc id.name |> error + else () + +(** Checks that a variable/function name: + - a function/identifier does not have the _lupdf/_lupmf suffix + - is not already in use (for now) +*) +let verify_name_fresh tenv id ~is_udf = + let f = + if is_udf then verify_name_fresh_udf tenv else verify_name_fresh_var tenv + in + List.iter ~f (probability_distribution_name_variants id) + +let is_of_compatible_return_type rt1 srt2 = + UnsizedType.( + match (rt1, srt2) with + | Void, NoReturnType + |Void, Incomplete Void + |Void, Complete Void + |Void, AnyReturnType -> + true + | ReturnType UReal, Complete (ReturnType UInt) -> true + | ReturnType UComplex, Complete (ReturnType UReal) -> true + | ReturnType UComplex, Complete (ReturnType UInt) -> true + | ReturnType rt1, Complete (ReturnType rt2) -> rt1 = rt2 + | ReturnType _, AnyReturnType -> true + | _ -> false) + +(* -- Expressions ------------------------------------------------- *) +let check_ternary_if loc pe te fe = + match + (pe.emeta.type_, UnsizedType.common_type (te.emeta.type_, fe.emeta.type_)) + with + | UInt, Some type_ when not (UnsizedType.is_fun_type type_) -> + mk_typed_expression + ~expr:(TernaryIf (pe, te, fe)) + ~ad_level:(expr_ad_lub [pe; te; fe]) + ~type_ ~loc + | _, _ -> + Semantic_error.illtyped_ternary_if loc pe.emeta.type_ te.emeta.type_ + fe.emeta.type_ + |> error + +let verify_operator _ = () + +let check_binop loc op le re = + let rt = + [le; re] |> get_arg_types + |> Stan_math_signatures.operator_stan_math_return_type op + in + match rt with + | Some (ReturnType type_) -> + mk_typed_expression + ~expr:(BinOp (le, op, re)) + ~ad_level:(expr_ad_lub [le; re]) + ~type_ ~loc + | _ -> + Semantic_error.illtyped_binary_op loc op le.emeta.type_ re.emeta.type_ + |> error + +let check_prefixop loc op te = + let rt = + Stan_math_signatures.operator_stan_math_return_type op [arg_type te] + in + match rt with + | Some (ReturnType type_) -> + mk_typed_expression + ~expr:(PrefixOp (op, te)) + ~ad_level:(expr_ad_lub [te]) + ~type_ ~loc + | _ -> Semantic_error.illtyped_prefix_op loc op te.emeta.type_ |> error + +let check_postfixop loc op te = + let rt = + Stan_math_signatures.operator_stan_math_return_type op [arg_type te] + in + match rt with + | Some (ReturnType type_) -> + mk_typed_expression + ~expr:(PostfixOp (te, op)) + ~ad_level:(expr_ad_lub [te]) + ~type_ ~loc + | _ -> Semantic_error.illtyped_postfix_op loc op te.emeta.type_ |> error + +let check_variable cf loc tenv id = + match Env.find tenv (Utils.stdlib_distribution_name id.name) with + | [] -> + (* OCaml in these situations suggests similar names + We could too, if we did a fuzzy search on the keys in tenv + *) + Semantic_error.ident_not_in_scope loc id.name |> error + | {kind= `StanMath; _} :: _ -> + mk_typed_expression ~expr:(Variable id) + ~ad_level:(calculate_autodifftype cf MathLibrary UMathLibraryFunction) + ~type_:UMathLibraryFunction ~loc + | {kind= `Variable {origin= Param | TParam | GQuant; _}; _} :: _ + when cf.in_toplevel_decl -> + Semantic_error.non_data_variable_size_decl loc |> error + | _ :: _ + when Utils.is_unnormalized_distribution id.name + && not + ( (cf.in_fun_def && (cf.in_udf_dist_def || cf.in_lp_fun_def)) + || cf.current_block = Model ) -> + Semantic_error.invalid_unnormalized_fn loc |> error + | {kind= `Variable {origin; _}; type_} :: _ -> + mk_typed_expression ~expr:(Variable id) + ~ad_level:(calculate_autodifftype cf origin type_) + ~type_ ~loc + (* TODO - When it's time for overloading, will this need + some kind of filter/match on arg types? *) + | { kind= `UserDefined | `UserDeclared _ + ; type_= UFun (args, rt, FnLpdf _, mem_pattern) } + :: _ -> + let type_ = + UnsizedType.UFun + (args, rt, Fun_kind.suffix_from_name id.name, mem_pattern) + in + mk_typed_expression ~expr:(Variable id) + ~ad_level:(calculate_autodifftype cf Functions type_) + ~type_ ~loc + | {kind= `UserDefined | `UserDeclared _; type_} :: _ -> + mk_typed_expression ~expr:(Variable id) + ~ad_level:(calculate_autodifftype cf Functions type_) + ~type_ ~loc + +let get_consistent_types ad_level type_ es = + let f state e = + match state with + | Error e -> Error e + | Ok (ad, ty) -> ( + let ad = + if UnsizedType.autodifftype_can_convert e.emeta.ad_level ad then + e.emeta.ad_level + else ad + in + match UnsizedType.common_type (ty, e.emeta.type_) with + | Some ty -> Ok (ad, ty) + | None -> Error (ty, e.emeta) ) + in + List.fold ~init:(Ok (ad_level, type_)) ~f es + +let check_array_expr loc es = + match es with + | [] -> Semantic_error.empty_array loc |> error + | {emeta= {ad_level; type_; _}; _} :: elements -> ( + match get_consistent_types ad_level type_ elements with + | Error (ty, meta) -> + Semantic_error.mismatched_array_types meta.loc ty meta.type_ |> error + | Ok (ad_level, type_) -> + let type_ = UnsizedType.UArray type_ in + mk_typed_expression ~expr:(ArrayExpr es) ~ad_level ~type_ ~loc ) + +let check_rowvector loc es = + match es with + | {emeta= {ad_level; type_= UnsizedType.URowVector; _}; _} :: elements -> ( + match get_consistent_types ad_level URowVector elements with + | Ok (ad_level, _) -> + mk_typed_expression ~expr:(RowVectorExpr es) ~ad_level ~type_:UMatrix + ~loc + | Error (_, meta) -> + Semantic_error.invalid_matrix_types meta.loc meta.type_ |> error ) + | _ -> ( + match get_consistent_types DataOnly UReal es with + | Ok (ad_level, _) -> + mk_typed_expression ~expr:(RowVectorExpr es) ~ad_level + ~type_:URowVector ~loc + | Error (_, meta) -> + Semantic_error.invalid_row_vector_types meta.loc meta.type_ |> error ) + +(* index checking *) + +let indexing_type idx = + match idx with + | Single {emeta= {type_= UnsizedType.UInt; _}; _} -> `Single + | _ -> `Multi + +let inferred_unsizedtype_of_indexed ~loc ut indices = + let rec aux type_ idcs = + match (type_, idcs) with + | _, [] -> type_ + | UnsizedType.UArray type_, `Single :: tl -> aux type_ tl + | UArray type_, `Multi :: tl -> aux type_ tl |> UnsizedType.UArray + | (UVector | URowVector), [`Single] | UMatrix, [`Single; `Single] -> + UnsizedType.UReal + | (UVector | URowVector | UMatrix), [`Multi] | UMatrix, [`Multi; `Multi] -> + type_ + | UMatrix, ([`Single] | [`Single; `Multi]) -> UnsizedType.URowVector + | UMatrix, [`Multi; `Single] -> UnsizedType.UVector + | UMatrix, _ :: _ :: _ :: _ + |(UVector | URowVector), _ :: _ :: _ + |(UInt | UReal | UComplex | UFun _ | UMathLibraryFunction), _ :: _ -> + Semantic_error.not_indexable loc ut (List.length indices) |> error + in + aux ut (List.map ~f:indexing_type indices) + +let inferred_ad_type_of_indexed at uindices = + UnsizedType.lub_ad_type + ( at + :: List.map + ~f:(function + | All -> UnsizedType.DataOnly + | Single ue1 | Upfrom ue1 | Downfrom ue1 -> + UnsizedType.lub_ad_type [at; ue1.emeta.ad_level] + | Between (ue1, ue2) -> + UnsizedType.lub_ad_type + [at; ue1.emeta.ad_level; ue2.emeta.ad_level]) + uindices ) + +(* function checking *) + +let verify_conddist_name loc id = + if + List.exists + ~f:(fun x -> String.is_suffix id.name ~suffix:x) + Utils.conditioning_suffices + then () + else Semantic_error.conditional_notation_not_allowed loc |> error + +let verify_fn_conditioning loc id = + if + List.exists + ~f:(fun suffix -> String.is_suffix id.name ~suffix) + Utils.conditioning_suffices + && not (String.is_suffix id.name ~suffix:"_cdf") + then Semantic_error.conditioning_required loc |> error + else () + +(** `Target+=` can only be used in model and functions + with right suffix (same for tilde etc) +*) +let verify_fn_target_plus_equals cf loc id = + if + String.is_suffix id.name ~suffix:"_lp" + && not + ( cf.in_lp_fun_def || cf.current_block = Model + || cf.current_block = TParam ) + then Semantic_error.target_plusequals_outisde_model_or_logprob loc |> error + else () + +(** Rng functions cannot be used in Tp or Model and only + in function defs with the right suffix +*) +let verify_fn_rng cf loc id = + if String.is_suffix id.name ~suffix:"_rng" && cf.in_toplevel_decl then + Semantic_error.invalid_decl_rng_fn loc |> error + else if + String.is_suffix id.name ~suffix:"_rng" + && ( (cf.in_fun_def && not cf.in_rng_fun_def) + || cf.current_block = TParam || cf.current_block = Model ) + then Semantic_error.invalid_rng_fn loc |> error + else () + +(** unnormalized _lpdf/_lpmf functions can only be used in _lpdf/_lpmf/_lp udfs + or the model block +*) +let verify_unnormalized cf loc id = + if + Utils.is_unnormalized_distribution id.name + && not ((cf.in_fun_def && cf.in_udf_dist_def) || cf.current_block = Model) + then Semantic_error.invalid_unnormalized_fn loc |> error + else () + +let mk_fun_app ~is_cond_dist (x, y, z) = + if is_cond_dist then CondDistApp (x, y, z) else FunApp (x, y, z) + +let check_fn ~is_cond_dist loc tenv id es = + match Env.find tenv (Utils.normalized_name id.name) with + | {kind= `Variable _; _} :: _ + (* variables can sometimes shadow stanlib functions, so we have to check this *) + when not + (Stan_math_signatures.is_stan_math_function_name + (Utils.normalized_name id.name)) -> + Semantic_error.returning_fn_expected_nonfn_found loc id.name |> error + | [] -> + Semantic_error.returning_fn_expected_undeclaredident_found loc id.name + |> error + | _ (* a function *) -> ( + match Env.returntype tenv id.name (get_arg_types es) with + | Ok (Void, _) -> + Semantic_error.returning_fn_expected_nonreturning_found loc id.name + |> error + | Ok (ReturnType ut, fnk) -> + mk_typed_expression + ~expr: + (mk_fun_app ~is_cond_dist + (fnk (Fun_kind.suffix_from_name id.name), id, es)) + ~ad_level:(expr_ad_lub es) ~type_:ut ~loc + | Error x -> + es + |> List.map ~f:(fun e -> e.emeta.type_) + |> Semantic_error.illtyped_stanlib_fn_app loc id.name x + |> error ) + +let check_reduce_sum ~is_cond_dist loc id es = + match es with + | { emeta= + { type_= + UnsizedType.UFun + (((_, sliced_arg_fun_type) as sliced_arg_fun) :: _, _, _, _); _ + }; _ } + :: _ + when List.mem Stan_math_signatures.reduce_sum_slice_types + sliced_arg_fun_type ~equal:( = ) -> ( + let mandatory_args = [sliced_arg_fun; (AutoDiffable, UInt)] in + let mandatory_fun_args = + [sliced_arg_fun; (DataOnly, UInt); (DataOnly, UInt)] + in + match + SignatureMismatch.check_variadic_args true mandatory_args + mandatory_fun_args UReal (get_arg_types es) + with + | None -> + mk_typed_expression + ~expr:(mk_fun_app ~is_cond_dist (StanLib FnPlain, id, es)) + ~ad_level:(expr_ad_lub es) ~type_:UnsizedType.UReal ~loc + | Some (expected_args, err) -> + Semantic_error.illtyped_reduce_sum loc id.name + (List.map ~f:type_of_expr_typed es) + expected_args err + |> error ) + | _ -> + let mandatory_args = + UnsizedType.[(AutoDiffable, UArray UReal); (AutoDiffable, UInt)] + in + let mandatory_fun_args = + UnsizedType. + [(AutoDiffable, UArray UReal); (DataOnly, UInt); (DataOnly, UInt)] + in + let expected_args, err = + SignatureMismatch.check_variadic_args true mandatory_args + mandatory_fun_args UReal (get_arg_types es) + |> Option.value_exn + in + Semantic_error.illtyped_reduce_sum_generic loc id.name + (List.map ~f:type_of_expr_typed es) + expected_args err + |> error + +let check_variadic_ode ~is_cond_dist loc id es = + let optional_tol_mandatory_args = + if Stan_math_signatures.variadic_ode_adjoint_fn = id.name then + Stan_math_signatures.variadic_ode_adjoint_ctl_tol_arg_types + else if Stan_math_signatures.is_variadic_ode_nonadjoint_tol_fn id.name then + Stan_math_signatures.variadic_ode_tol_arg_types + else [] + in + let mandatory_arg_types = + Stan_math_signatures.variadic_ode_mandatory_arg_types + @ optional_tol_mandatory_args + in + match + SignatureMismatch.check_variadic_args false mandatory_arg_types + Stan_math_signatures.variadic_ode_mandatory_fun_args + Stan_math_signatures.variadic_ode_fun_return_type (get_arg_types es) + with + | None -> + mk_typed_expression + ~expr:(mk_fun_app ~is_cond_dist (StanLib FnPlain, id, es)) + ~ad_level:(expr_ad_lub es) + ~type_:Stan_math_signatures.variadic_ode_return_type ~loc + | Some (expected_args, err) -> + Semantic_error.illtyped_variadic_ode loc id.name + (List.map ~f:type_of_expr_typed es) + expected_args err + |> error + +let check_fn ~is_cond_dist loc tenv id es = + if Stan_math_signatures.is_reduce_sum_fn id.name then + check_reduce_sum ~is_cond_dist loc id es + else if Stan_math_signatures.is_variadic_ode_fn id.name then + check_variadic_ode ~is_cond_dist loc id es + else check_fn ~is_cond_dist loc tenv id es + +let rec check_funapp loc cf tenv ~is_cond_dist id tes = + (* overloading will need to defer typechecking of arguments? *) + let name_check = + if is_cond_dist then verify_conddist_name else verify_fn_conditioning + in + let res = check_fn ~is_cond_dist loc tenv id tes in + verify_identifier id ; + name_check loc id ; + verify_fn_target_plus_equals cf loc id ; + verify_fn_rng cf loc id ; + verify_unnormalized cf loc id ; + res + +and check_indexed loc cf tenv e indices = + let tindices = List.map ~f:(check_index cf tenv) indices in + let te = check_expression cf tenv e in + let ad_level = inferred_ad_type_of_indexed te.emeta.ad_level tindices in + let type_ = inferred_unsizedtype_of_indexed ~loc te.emeta.type_ tindices in + mk_typed_expression ~expr:(Indexed (te, tindices)) ~ad_level ~type_ ~loc + +and check_index cf tenv = function + | All -> All + (* Check that indexes have int (container) type *) + | Single e -> + let te = check_expression cf tenv e in + if has_int_type te || has_int_array_type te then Single te + else + Semantic_error.int_intarray_or_range_expected te.emeta.loc + te.emeta.type_ + |> error + | Upfrom e -> check_expression_of_int_type cf tenv e "Range bound" |> Upfrom + | Downfrom e -> + check_expression_of_int_type cf tenv e "Range bound" |> Downfrom + | Between (e1, e2) -> + let le = check_expression_of_int_type cf tenv e1 "Range bound" in + let ue = check_expression_of_int_type cf tenv e2 "Range bound" in + Between (le, ue) + +and check_expression cf tenv ({emeta; expr} : Ast.untyped_expression) : + Ast.typed_expression = + let loc = emeta.loc in + let ce = check_expression cf tenv in + match expr with + | TernaryIf (e1, e2, e3) -> + let pe = ce e1 in + let te = ce e2 in + let fe = ce e3 in + check_ternary_if loc pe te fe + | BinOp (e1, op, e2) -> + let le = ce e1 in + let re = ce e2 in + let warn_int_division x y = + match (x.emeta.type_, y.emeta.type_, op) with + | UInt, UInt, Divide -> + let hint ppf () = + match (x.expr, y.expr) with + | IntNumeral x, _ -> + Fmt.pf ppf "%s.0 / %a" x Pretty_printing.pp_typed_expression + y + | _, Ast.IntNumeral y -> + Fmt.pf ppf "%a / %s.0" Pretty_printing.pp_typed_expression x + y + | _ -> + Fmt.pf ppf "%a * 1.0 / %a" + Pretty_printing.pp_typed_expression x + Pretty_printing.pp_typed_expression y + in + let s = + Fmt.strf + "@[@[Found int division:@]@ @[%a@]@,@[%a@]@ @[%a@]@,@[%a@]@]" + Pretty_printing.pp_expression {expr; emeta} Fmt.text + "Values will be rounded towards zero. If rounding is not \ + desired you can write the division as" + hint () Fmt.text + "If rounding is intended please use the integer division \ + operator %/%." + in + Warnings.pp_warning Fmt.stderr (x.emeta.loc, s) ; + () + | _ -> () + in + verify_operator op ; warn_int_division le re ; check_binop loc op le re + | PrefixOp (op, e) -> + verify_operator op ; + ce e |> check_prefixop loc op + | PostfixOp (e, op) -> + verify_operator op ; + ce e |> check_postfixop loc op + | Variable id -> + verify_identifier id ; + check_variable cf loc tenv id + | IntNumeral s -> ( + match float_of_string_opt s with + | Some i when i < 2_147_483_648.0 -> + mk_typed_expression ~expr:(IntNumeral s) ~ad_level:DataOnly ~type_:UInt + ~loc + | _ -> Semantic_error.bad_int_literal loc |> error ) + | RealNumeral s -> + mk_typed_expression ~expr:(RealNumeral s) ~ad_level:DataOnly ~type_:UReal + ~loc + | ImagNumeral s -> + mk_typed_expression ~expr:(ImagNumeral s) ~ad_level:DataOnly + ~type_:UComplex ~loc + | GetLP -> + (* Target+= can only be used in model and functions with right suffix (same for tilde etc) *) + if + not + ( cf.in_lp_fun_def || cf.current_block = Model + || cf.current_block = TParam ) + then + Semantic_error.target_plusequals_outisde_model_or_logprob loc |> error + else + mk_typed_expression ~expr:GetLP + ~ad_level:(calculate_autodifftype cf cf.current_block UReal) + ~type_:UReal ~loc + | GetTarget -> + (* Target+= can only be used in model and functions with right suffix (same for tilde etc) *) + if + not + ( cf.in_lp_fun_def || cf.current_block = Model + || cf.current_block = TParam ) + then + Semantic_error.target_plusequals_outisde_model_or_logprob loc |> error + else + mk_typed_expression ~expr:GetTarget + ~ad_level:(calculate_autodifftype cf cf.current_block UReal) + ~type_:UReal ~loc + | ArrayExpr es -> es |> List.map ~f:ce |> check_array_expr loc + | RowVectorExpr es -> es |> List.map ~f:ce |> check_rowvector loc + | Paren e -> + let te = ce e in + mk_typed_expression ~expr:(Paren te) ~ad_level:te.emeta.ad_level + ~type_:te.emeta.type_ ~loc + | Indexed (e, indices) -> check_indexed loc cf tenv e indices + | FunApp ((), id, es) -> + es |> List.map ~f:ce |> check_funapp loc cf tenv ~is_cond_dist:false id + | CondDistApp ((), id, es) -> + es |> List.map ~f:ce |> check_funapp loc cf tenv ~is_cond_dist:true id + +and check_expression_of_int_type cf tenv e name = + let te = check_expression cf tenv e in + if has_int_type te then te + else Semantic_error.int_expected te.emeta.loc name te.emeta.type_ |> error + +let check_expression_of_int_or_real_type cf tenv e name = + let te = check_expression cf tenv e in + if has_int_or_real_type te then te + else + Semantic_error.int_or_real_expected te.emeta.loc name te.emeta.type_ + |> error + +let check_expression_of_scalar_or_type cf tenv t e name = + let te = check_expression cf tenv e in + if UnsizedType.is_scalar_type te.emeta.type_ || te.emeta.type_ = t then te + else + Semantic_error.scalar_or_type_expected te.emeta.loc name t te.emeta.type_ + |> error + +(* -- Statements ------------------------------------------------- *) +(* non returning functions *) +let verify_nrfn_target loc cf id = + if + String.is_suffix id.name ~suffix:"_lp" + && not + ( cf.in_lp_fun_def || cf.current_block = Model + || cf.current_block = TParam ) + then Semantic_error.target_plusequals_outisde_model_or_logprob loc |> error + else () + +let check_nrfn loc tenv id es = + match Env.find tenv id.name with + | {kind= `Variable _; _} :: _ + (* variables can shadow stanlib functions, so we have to check this *) + when not (Stan_math_signatures.is_stan_math_function_name id.name) -> + Semantic_error.nonreturning_fn_expected_nonfn_found loc id.name |> error + | [] -> + Semantic_error.nonreturning_fn_expected_undeclaredident_found loc id.name + |> error + | _ (* a function *) -> ( + match Env.returntype tenv id.name (get_arg_types es) with + | Ok (Void, fnk) -> + mk_typed_statement + ~stmt:(NRFunApp (fnk (Fun_kind.suffix_from_name id.name), id, es)) + ~return_type:NoReturnType ~loc + | Ok (ReturnType _, _) -> + Semantic_error.nonreturning_fn_expected_returning_found loc id.name + |> error + | Error x -> + es + |> List.map ~f:type_of_expr_typed + (* todo rename this to just illtyped_fn_app *) + |> Semantic_error.illtyped_stanlib_fn_app loc id.name x + |> error ) + +let check_nr_fn_app loc cf tenv id es = + let tes = List.map ~f:(check_expression cf tenv) es in + verify_identifier id ; + verify_nrfn_target loc cf id ; + check_nrfn loc tenv id tes + +(* assignments *) +let verify_assignment_read_only loc is_readonly id = + if is_readonly then + Semantic_error.cannot_assign_to_read_only loc id.name |> error + else () + +(* Variables from previous blocks are read-only. + In particular, data and parameters never assigned to + *) +let verify_assignment_global loc cf block is_global id = + if (not is_global) || block = cf.current_block then () + else Semantic_error.cannot_assign_to_global loc id.name |> error + +let mk_assignment_from_indexed_expr assop lhs rhs = + Assignment + {assign_lhs= Ast.lvalue_of_expr lhs; assign_op= assop; assign_rhs= rhs} + +let check_assignment_operator loc assop lhs rhs = + let err op = + Semantic_error.illtyped_assignment loc op lhs.emeta.type_ rhs.emeta.type_ + in + let () = + match assop with + | Assign | ArrowAssign -> + if + UnsizedType.check_of_same_type_mod_array_conv "" lhs.emeta.type_ + rhs.emeta.type_ + then () + else err Operator.Equals |> error + | OperatorAssign op -> ( + let args = List.map ~f:arg_type [lhs; rhs] in + let return_type = + Stan_math_signatures.assignmentoperator_stan_math_return_type op args + in + match return_type with Some Void -> () | _ -> err op |> error ) + in + mk_typed_statement ~return_type:NoReturnType ~loc + ~stmt:(mk_assignment_from_indexed_expr assop lhs rhs) + +let check_assignment loc cf tenv assign_lhs assign_op assign_rhs = + let assign_id = Ast.id_of_lvalue assign_lhs in + let lhs = assign_lhs |> expr_of_lvalue |> check_expression cf tenv in + let rhs = check_expression cf tenv assign_rhs in + let block, global, readonly = + let var = Env.find tenv assign_id.name in + match var with + | {kind= `Variable {origin; global; readonly}; _} :: _ -> + (origin, global, readonly) + | {kind= `StanMath; _} :: _ -> (MathLibrary, true, false) + | {kind= `UserDefined | `UserDeclared _; _} :: _ -> (Functions, true, false) + | _ -> Semantic_error.ident_not_in_scope loc assign_id.name |> error + in + verify_assignment_global loc cf block global assign_id ; + verify_assignment_read_only loc readonly assign_id ; + check_assignment_operator loc assign_op lhs rhs + +(* target plus-equals / increment log-prob *) + +let verify_target_pe_expr_type loc e = + match e.emeta.type_ with + | UFun _ | UMathLibraryFunction -> + Semantic_error.int_or_real_container_expected loc e.emeta.type_ |> error + | _ -> () + +let verify_target_pe_usage loc cf = + if cf.in_lp_fun_def || cf.current_block = Model then () + else Semantic_error.target_plusequals_outisde_model_or_logprob loc |> error + +let check_target_pe loc cf tenv e = + let te = check_expression cf tenv e in + verify_target_pe_usage loc cf ; + verify_target_pe_expr_type loc te ; + mk_typed_statement ~stmt:(TargetPE te) ~return_type:NoReturnType ~loc + +let check_incr_logprob loc cf tenv e = + let te = check_expression cf tenv e in + verify_target_pe_usage loc cf ; + verify_target_pe_expr_type loc te ; + mk_typed_statement ~stmt:(IncrementLogProb te) ~return_type:NoReturnType ~loc + +(* tilde/sampling notation*) +let verify_sampling_pdf_pmf id = + if + String.( + is_suffix id.name ~suffix:"_lpdf" + || is_suffix id.name ~suffix:"_lpmf" + || is_suffix id.name ~suffix:"_lupdf" + || is_suffix id.name ~suffix:"_lupmf") + then Semantic_error.invalid_sampling_pdf_or_pmf id.id_loc |> error + else () + +let verify_sampling_cdf_ccdf loc id = + if + String.( + is_suffix id.name ~suffix:"_cdf" || is_suffix id.name ~suffix:"_ccdf") + then Semantic_error.invalid_sampling_cdf_or_ccdf loc id.name |> error + else () + +(* Target+= can only be used in model and functions with right suffix (same for tilde etc) *) +let verify_valid_sampling_pos loc cf = + if cf.in_lp_fun_def || cf.current_block = Model then () + else Semantic_error.target_plusequals_outisde_model_or_logprob loc |> error + +let verify_sampling_distribution loc tenv id arguments = + let name = id.name + and argumenttypes = List.map ~f:arg_type arguments + and is_real_rt = function + | UnsizedType.ReturnType UReal -> true + | _ -> false + in + let is_name_w_suffix_sampling_dist suffix = + Stan_math_signatures.stan_math_returntype (name ^ suffix) argumenttypes + |> Option.value_map ~default:false ~f:is_real_rt + in + let is_sampling_dist_in_math = + List.exists ~f:is_name_w_suffix_sampling_dist + (Utils.distribution_suffices @ Utils.unnormalized_suffices) + && name <> "binomial_coefficient" + && name <> "multiply" + in + let is_name_w_suffix_udf_sampling_dist suffix = + let f v = + match v with + | Env.({ kind= `UserDefined | `UserDeclared _ + ; type_= UFun (listedtypes, ReturnType UReal, FnLpdf _, _) }) + when UnsizedType.check_compatible_arguments_mod_conv name listedtypes + argumenttypes -> + true + | _ -> false + in + List.exists (Env.find tenv (name ^ suffix)) ~f + in + let is_udf_sampling_dist = + List.exists ~f:is_name_w_suffix_udf_sampling_dist + (Utils.distribution_suffices @ Utils.unnormalized_suffices) + in + if is_sampling_dist_in_math || is_udf_sampling_dist then () + else Semantic_error.invalid_sampling_no_such_dist loc name |> error + +let is_cumulative_density_defined tenv id arguments = + let name = id.name + and argumenttypes = List.map ~f:arg_type arguments + and is_real_rt = function + | UnsizedType.ReturnType UReal -> true + | _ -> false + in + let is_real_rt_for_suffix suffix = + Stan_math_signatures.stan_math_returntype (name ^ suffix) argumenttypes + |> Option.value_map ~default:false ~f:is_real_rt + and valid_arg_types_for_suffix suffix = + let f v = + match v with + | Env.({ kind= `UserDefined | `UserDeclared _ + ; type_= UFun (listedtypes, ReturnType UReal, FnPlain, _) }) + when UnsizedType.check_compatible_arguments_mod_conv name listedtypes + argumenttypes -> + true + | _ -> false + in + List.exists (Env.find tenv (name ^ suffix)) ~f + in + ( is_real_rt_for_suffix "_lcdf" + || valid_arg_types_for_suffix "_lcdf" + || is_real_rt_for_suffix "_cdf_log" + || valid_arg_types_for_suffix "_cdf_log" ) + && ( is_real_rt_for_suffix "_lccdf" + || valid_arg_types_for_suffix "_lccdf" + || is_real_rt_for_suffix "_ccdf_log" + || valid_arg_types_for_suffix "_ccdf_log" ) + +let verify_can_truncate_distribution loc (arg : typed_expression) = function + | NoTruncate -> () + | _ -> + if UnsizedType.is_scalar_type arg.emeta.type_ then () + else Semantic_error.multivariate_truncation loc |> error + +let verify_sampling_cdf_defined loc tenv id truncation args = + let check e = is_cumulative_density_defined tenv id (e :: args) in + match truncation with + | NoTruncate -> () + | (TruncateUpFrom e | TruncateDownFrom e) when check e -> () + | TruncateBetween (e1, e2) when check e1 && check e2 -> () + | _ -> Semantic_error.invalid_truncation_cdf_or_ccdf loc |> error + +let check_truncation cf tenv truncation = + let check e = + check_expression_of_int_or_real_type cf tenv e "Truncation bound" + in + match truncation with + | NoTruncate -> NoTruncate + | TruncateUpFrom e -> check e |> TruncateUpFrom + | TruncateDownFrom e -> check e |> TruncateDownFrom + | TruncateBetween (e1, e2) -> (check e1, check e2) |> TruncateBetween + +let check_tilde loc cf tenv distribution truncation arg args = + let te = check_expression cf tenv arg in + let tes = List.map ~f:(check_expression cf tenv) args in + let ttrunc = check_truncation cf tenv truncation in + verify_identifier distribution ; + verify_sampling_pdf_pmf distribution ; + verify_valid_sampling_pos loc cf ; + verify_sampling_cdf_ccdf loc distribution ; + verify_sampling_distribution loc tenv distribution (te :: tes) ; + verify_sampling_cdf_defined loc tenv distribution ttrunc tes ; + verify_can_truncate_distribution loc te ttrunc ; + let stmt = Tilde {arg= te; distribution; args= tes; truncation= ttrunc} in + mk_typed_statement ~stmt ~loc ~return_type:NoReturnType + +(* Break and continue only occur in loops. *) +let check_break loc cf = + if cf.loop_depth = 0 then Semantic_error.break_outside_loop loc |> error + else mk_typed_statement ~stmt:Break ~return_type:NoReturnType ~loc + +let check_continue loc cf = + if cf.loop_depth = 0 then Semantic_error.continue_outside_loop loc |> error + else mk_typed_statement ~stmt:Continue ~return_type:NoReturnType ~loc + +let check_return loc cf tenv e = + if not cf.in_returning_fun_def then + Semantic_error.expression_return_outside_returning_fn loc |> error + else + let te = check_expression cf tenv e in + mk_typed_statement ~stmt:(Return te) + ~return_type:(Complete (ReturnType te.emeta.type_)) ~loc + +let check_returnvoid loc cf = + if (not cf.in_fun_def) || cf.in_returning_fun_def then + Semantic_error.void_ouside_nonreturning_fn loc |> error + else mk_typed_statement ~stmt:ReturnVoid ~return_type:(Complete Void) ~loc + +let check_printable cf tenv = function + | PString s -> PString s + (* Print/reject expressions cannot be of function type. *) + | PExpr e -> ( + let te = check_expression cf tenv e in + match te.emeta.type_ with + | UFun _ | UMathLibraryFunction -> + Semantic_error.not_printable te.emeta.loc |> error + | _ -> PExpr te ) + +let check_print loc cf tenv ps = + let tps = List.map ~f:(check_printable cf tenv) ps in + mk_typed_statement ~stmt:(Print tps) ~return_type:NoReturnType ~loc + +let check_reject loc cf tenv ps = + let tps = List.map ~f:(check_printable cf tenv) ps in + mk_typed_statement ~stmt:(Reject tps) ~return_type:AnyReturnType ~loc + +let check_skip loc = + mk_typed_statement ~stmt:Skip ~return_type:NoReturnType ~loc + +let rec stmt_is_escape {stmt; _} = + match stmt with + | Break | Continue | Reject _ | Return _ | ReturnVoid -> true + | _ -> false + +and list_until_escape xs = + let rec aux accu = function + | next :: next' :: _ when stmt_is_escape next' -> + List.rev (next' :: next :: accu) + | next :: rest -> aux (next :: accu) rest + | [] -> List.rev accu + in + aux [] xs + +let returntype_leastupperbound loc rt1 rt2 = + match (rt1, rt2) with + | UnsizedType.ReturnType UReal, UnsizedType.ReturnType UInt + |ReturnType UInt, ReturnType UReal -> + UnsizedType.ReturnType UReal + | _, _ when rt1 = rt2 -> rt2 + | _ -> Semantic_error.mismatched_return_types loc rt1 rt2 |> error + +let try_compute_block_statement_returntype loc srt1 srt2 = + match (srt1, srt2) with + | Complete rt1, Complete rt2 | Incomplete rt1, Complete rt2 -> + Complete (returntype_leastupperbound loc rt1 rt2) + | Incomplete rt1, Incomplete rt2 | Complete rt1, Incomplete rt2 -> + Incomplete (returntype_leastupperbound loc rt1 rt2) + | NoReturnType, NoReturnType -> NoReturnType + | AnyReturnType, Incomplete rt + |Complete rt, NoReturnType + |NoReturnType, Incomplete rt + |Incomplete rt, NoReturnType -> + Incomplete rt + | NoReturnType, Complete rt + |Complete rt, AnyReturnType + |Incomplete rt, AnyReturnType + |AnyReturnType, Complete rt -> + Complete rt + | AnyReturnType, NoReturnType + |NoReturnType, AnyReturnType + |AnyReturnType, AnyReturnType -> + AnyReturnType + +let try_compute_ifthenelse_statement_returntype loc srt1 srt2 = + match (srt1, srt2) with + | Complete rt1, Complete rt2 -> + returntype_leastupperbound loc rt1 rt2 |> Complete + | Incomplete rt1, Incomplete rt2 + |Complete rt1, Incomplete rt2 + |Incomplete rt1, Complete rt2 -> + returntype_leastupperbound loc rt1 rt2 |> Incomplete + | AnyReturnType, NoReturnType + |NoReturnType, AnyReturnType + |NoReturnType, NoReturnType -> + NoReturnType + | AnyReturnType, Incomplete rt + |Incomplete rt, AnyReturnType + |Complete rt, NoReturnType + |NoReturnType, Complete rt + |NoReturnType, Incomplete rt + |Incomplete rt, NoReturnType -> + Incomplete rt + | Complete rt, AnyReturnType | AnyReturnType, Complete rt -> Complete rt + | AnyReturnType, AnyReturnType -> AnyReturnType + +(* statements which contain statements, and therefore need to be mutually recursive + with check_statement +*) +let rec check_if_then_else loc cf tenv pred_e s_true s_false_opt = + (* we don't need these nested type environments *) + let _, ts_true = check_statement cf tenv s_true in + let ts_false_opt = + s_false_opt |> Option.map ~f:(check_statement cf tenv) |> Option.map ~f:snd + in + let te = + check_expression_of_int_or_real_type cf tenv pred_e + "Condition in conditional" + in + let stmt = IfThenElse (te, ts_true, ts_false_opt) in + let srt1 = ts_true.smeta.return_type in + let srt2 = + ts_false_opt + |> Option.map ~f:(fun s -> s.smeta.return_type) + |> Option.value ~default:NoReturnType + in + let return_type = + try_compute_ifthenelse_statement_returntype loc srt1 srt2 + in + mk_typed_statement ~stmt ~return_type ~loc + +and check_while loc cf tenv cond_e loop_body = + let _, ts = + check_statement {cf with loop_depth= cf.loop_depth + 1} tenv loop_body + and te = + check_expression_of_int_or_real_type cf tenv cond_e + "Condition in while-loop" + in + mk_typed_statement + ~stmt:(While (te, ts)) + ~return_type:ts.smeta.return_type ~loc + +and check_for loc cf tenv loop_var lower_bound_e upper_bound_e loop_body = + let te1 = + check_expression_of_int_type cf tenv lower_bound_e + "Lower bound of for-loop" + and te2 = + check_expression_of_int_type cf tenv upper_bound_e + "Upper bound of for-loop" + in + verify_identifier loop_var ; + let ts = check_loop_body cf tenv loop_var UnsizedType.UInt loop_body in + mk_typed_statement + ~stmt: + (For + { loop_variable= loop_var + ; lower_bound= te1 + ; upper_bound= te2 + ; loop_body= ts }) + ~return_type:ts.smeta.return_type ~loc + +and check_foreach_loop_identifier_type loc ty = + match ty with + | UnsizedType.UArray ut -> ut + | UVector | URowVector | UMatrix -> UnsizedType.UReal + | _ -> Semantic_error.array_vector_rowvector_matrix_expected loc ty |> error + +and check_foreach loc cf tenv loop_var foreach_e loop_body = + let te = check_expression cf tenv foreach_e in + verify_identifier loop_var ; + let loop_var_ty = + check_foreach_loop_identifier_type te.emeta.loc te.emeta.type_ + in + let ts = check_loop_body cf tenv loop_var loop_var_ty loop_body in + mk_typed_statement + ~stmt:(ForEach (loop_var, te, ts)) + ~return_type:ts.smeta.return_type ~loc + +and check_loop_body cf tenv loop_var loop_var_ty loop_body = + verify_name_fresh tenv loop_var ~is_udf:false ; + (* Add to type environment as readonly. + Check that function args and loop identifiers are not modified in + function. (passed by const ref) + *) + let tenv = + Env.add tenv loop_var.name loop_var_ty + (`Variable {origin= cf.current_block; global= false; readonly= true}) + in + snd (check_statement {cf with loop_depth= cf.loop_depth + 1} tenv loop_body) + +and check_block loc cf tenv stmts = + let _, checked_stmts = + List.fold_map stmts ~init:tenv ~f:(check_statement cf) + in + let stmts = list_until_escape checked_stmts in + let return_type = + stmts + |> List.map ~f:(fun s -> s.smeta.return_type) + |> List.fold ~init:NoReturnType + ~f:(try_compute_block_statement_returntype loc) + in + mk_typed_statement ~stmt:(Block stmts) ~return_type ~loc + +and check_profile loc cf tenv name stmts = + let _, checked_stmts = + List.fold_map stmts ~init:tenv ~f:(check_statement cf) + in + let stmts = list_until_escape checked_stmts in + let return_type = + stmts + |> List.map ~f:(fun s -> s.smeta.return_type) + |> List.fold ~init:NoReturnType + ~f:(try_compute_block_statement_returntype loc) + in + mk_typed_statement ~stmt:(Profile (name, stmts)) ~return_type ~loc + +(* variable declarations *) +and verify_valid_transformation_for_type loc is_global sized_ty trans = + let is_real {emeta; _} = emeta.type_ = UReal in + let is_real_transformation = + match trans with + | Transformation.Lower e -> is_real e + | Upper e -> is_real e + | LowerUpper (e1, e2) -> is_real e1 || is_real e2 + | _ -> false + in + if is_global && sized_ty = SizedType.SInt && is_real_transformation then + Semantic_error.non_int_bounds loc |> error + else () ; + let is_transformation = + match trans with Transformation.Identity -> false | _ -> true + in + if + is_global + && SizedType.(inner_type sized_ty = SComplex) + && is_transformation + then Semantic_error.complex_transform loc |> error + else () + +and verify_transformed_param_ty loc cf is_global unsized_ty = + if + is_global + && (cf.current_block = Param || cf.current_block = TParam) + && UnsizedType.contains_int unsized_ty + then Semantic_error.transformed_params_int loc |> error + else () + +and check_sizedtype cf tenv sizedty = + let check e msg = check_expression_of_int_type cf tenv e msg in + match sizedty with + | SizedType.SInt -> SizedType.SInt + | SReal -> SReal + | SComplex -> SComplex + | SVector (mem_pattern, e) -> + let te = check e "Vector sizes" in + SizedType.SVector (mem_pattern, te) + | SRowVector (mem_pattern, e) -> + let te = check e "Row vector sizes" in + SizedType.SRowVector (mem_pattern, te) + | SMatrix (mem_pattern, e1, e2) -> + let te1 = check e1 "Matrix sizes" in + let te2 = check e2 "Matrix sizes" in + SizedType.SMatrix (mem_pattern, te1, te2) + | SArray (st, e) -> + let tst = check_sizedtype cf tenv st in + let te = check e "Array sizes" in + SizedType.SArray (tst, te) + +and check_var_decl_initial_value loc cf tenv id init_val_opt = + match init_val_opt with + | Some e -> ( + let stmt = + Assignment + { assign_lhs= {lval= LVariable id; lmeta= {loc}} + ; assign_op= Assign + ; assign_rhs= e } + in + mk_untyped_statement ~loc ~stmt + |> check_statement cf tenv |> snd + |> fun ts -> + match (ts.stmt, ts.smeta.return_type) with + | Assignment {assign_rhs= ue; _}, NoReturnType -> Some ue + | _ -> + raise_s + [%message "Internal error: check_var_decl: `Assignment` expected."] + ) + | None -> None + +and check_transformation cf tenv ut trans = + let check e msg = check_expression_of_scalar_or_type cf tenv ut e msg in + match trans with + | Transformation.Identity -> Transformation.Identity + | Lower e -> check e "Lower bound" |> Lower + | Upper e -> check e "Upper bound" |> Upper + | LowerUpper (e1, e2) -> + (check e1 "Lower bound", check e2 "Upper bound") |> LowerUpper + | Offset e -> check e "Offset" |> Offset + | Multiplier e -> check e "Multiplier" |> Multiplier + | OffsetMultiplier (e1, e2) -> + (check e1 "Offset", check e2 "Multiplier") |> OffsetMultiplier + | Ordered -> Ordered + | PositiveOrdered -> PositiveOrdered + | Simplex -> Simplex + | UnitVector -> UnitVector + | CholeskyCorr -> CholeskyCorr + | CholeskyCov -> CholeskyCov + | Correlation -> Correlation + | Covariance -> Covariance + +and check_var_decl loc cf tenv sized_ty trans id init is_global = + let checked_type = + check_sizedtype {cf with in_toplevel_decl= is_global} tenv sized_ty + in + let unsized_type = SizedType.to_unsized checked_type in + let checked_trans = check_transformation cf tenv unsized_type trans in + verify_identifier id ; + verify_name_fresh tenv id ~is_udf:false ; + let tenv = + Env.add tenv id.name unsized_type + (`Variable + {origin= cf.current_block; global= is_global; readonly= false}) + in + let tinit = check_var_decl_initial_value loc cf tenv id init in + verify_valid_transformation_for_type loc is_global checked_type checked_trans ; + verify_transformed_param_ty loc cf is_global unsized_type ; + let stmt = + VarDecl + { decl_type= Sized checked_type + ; transformation= checked_trans + ; identifier= id + ; initial_value= tinit + ; is_global } + in + (tenv, mk_typed_statement ~stmt ~loc ~return_type:NoReturnType) + +(* function definitions *) +and exists_matching_fn_declared tenv id arg_tys rt = + let f v = + match v with + | Env.({kind= `UserDeclared _; type_= UFun (listedtypes, rt', _, _)}) + when arg_tys = listedtypes && rt = rt' -> + true + | _ -> false + in + List.exists (Env.find tenv id.name) ~f + +and verify_fundef_overloaded loc tenv id arg_tys rt = + (* User defined functions cannot be overloaded at the moment + *) + if exists_matching_fn_declared tenv id arg_tys rt then () + else + let f = function Env.({kind= `UserDeclared _; _}) -> true | _ -> false in + if List.exists ~f (Env.find tenv id.name) then + (* a function of the same name but different signature *) + Env.find tenv id.name |> List.hd + |> Option.map ~f:(fun x -> x.type_) + |> Semantic_error.mismatched_fn_def_decl loc id.name + |> error + else verify_name_fresh tenv id ~is_udf:true + +and get_fn_decl_or_defn loc tenv id arg_tys rt body = + match body with + | {stmt= Skip; _} -> + if exists_matching_fn_declared tenv id arg_tys rt then + Semantic_error.fn_decl_without_def loc |> error + else `UserDeclared id.id_loc + | _ -> `UserDefined + +and verify_fundef_dist_rt loc id return_ty = + let is_dist = + List.exists + ~f:(fun x -> String.is_suffix id.name ~suffix:x) + Utils.conditioning_suffices_w_log + in + if is_dist then + match return_ty with + | UnsizedType.ReturnType UReal -> () + | _ -> Semantic_error.non_real_prob_fn_def loc |> error + else () + +and verify_pdf_fundef_first_arg_ty loc id arg_tys = + if String.is_suffix id.name ~suffix:"_lpdf" then + let rt = List.hd arg_tys |> Option.map ~f:snd in + match rt with + | Some rt when UnsizedType.is_real_type rt -> () + | _ -> Semantic_error.prob_density_non_real_variate loc rt |> error + +and verify_pmf_fundef_first_arg_ty loc id arg_tys = + if String.is_suffix id.name ~suffix:"_lpmf" then + let rt = List.hd arg_tys |> Option.map ~f:snd in + match rt with + | Some rt when UnsizedType.is_int_type rt -> () + | _ -> Semantic_error.prob_mass_non_int_variate loc rt |> error + +and verify_fundef_distinct_arg_ids loc arg_names = + let dup_exists l = + match List.find_a_dup ~compare:String.compare l with + | Some _ -> true + | None -> false + in + if dup_exists arg_names then Semantic_error.duplicate_arg_names loc |> error + else () + +and verify_fundef_return_tys loc return_type body = + if + body.stmt = Skip + || is_of_compatible_return_type return_type body.smeta.return_type + then () + else Semantic_error.incompatible_return_types loc |> error + +(* Probably nothing to do here *) +and verify_autodifftype _ = () + +(* also does absolutely nothing right now *) +and verify_unsizedtype = function + | UnsizedType.UFun (l, rt, _, _) -> + verify_returntype rt ; + List.iter + ~f:(fun (at, ut) -> verify_autodifftype at ; verify_unsizedtype ut) + l + | UArray ut -> verify_unsizedtype ut + | _ -> () + +and verify_returntype = function + | Void -> () + | ReturnType ut -> verify_unsizedtype ut + +and add_function tenv name type_ defined = + (* if we're providing a definition, we remove prior declarations + to simplify the environment *) + if defined = `UserDefined then + let existing_defns = Env.find tenv name in + let defns = + List.filter + ~f:(function + | Env.({kind= `UserDeclared _; type_= type'}) when type' = type_ -> + false + | _ -> true) + existing_defns + in + let new_fn = Env.{kind= `UserDefined; type_} in + Env.add_all_raw tenv name (new_fn :: defns) + else Env.add tenv name type_ defined + +and check_fundef loc cf tenv return_ty id args body = + let () = + List.iter args ~f:(fun (at, ut, id) -> + verify_autodifftype at ; verify_unsizedtype ut ; verify_identifier id + ) + in + verify_identifier id ; + verify_returntype return_ty ; + let arg_types = List.map ~f:(fun (w, y, _) -> (w, y)) args in + let arg_identifiers = List.map ~f:(fun (_, _, z) -> z) args in + let arg_names = List.map ~f:(fun x -> x.name) arg_identifiers in + verify_fundef_overloaded loc tenv id arg_types return_ty ; + let defined = get_fn_decl_or_defn loc tenv id arg_types return_ty body in + verify_fundef_dist_rt loc id return_ty ; + verify_pdf_fundef_first_arg_ty loc id arg_types ; + verify_pmf_fundef_first_arg_ty loc id arg_types ; + let tenv = + add_function tenv id.name + (UFun (arg_types, return_ty, Fun_kind.suffix_from_name id.name, AoS)) + defined + in + List.iter + ~f:(fun id -> verify_name_fresh tenv id ~is_udf:false) + arg_identifiers ; + verify_fundef_distinct_arg_ids loc arg_names ; + (* We treat DataOnly arguments as if they are data and AutoDiffable arguments + as if they are parameters, for the purposes of type checking. + *) + let arg_types_internal = + List.map + ~f:(function + | UnsizedType.DataOnly, ut -> (Env.Data, ut) + | AutoDiffable, ut -> (Param, ut)) + arg_types + in + let tenv_body = + List.fold2_exn arg_names arg_types_internal ~init:tenv + ~f:(fun env name (origin, typ) -> + Env.add env name typ + (* readonly so that function args and loop identifiers + are not modified in function. (passed by const ref) *) + (`Variable {origin; readonly= true; global= false}) ) + in + let context = + let is_udf_dist name = + List.exists + ~f:(fun suffix -> String.is_suffix name ~suffix) + Utils.distribution_suffices + in + { cf with + in_fun_def= true + ; in_rng_fun_def= String.is_suffix id.name ~suffix:"_rng" + ; in_lp_fun_def= String.is_suffix id.name ~suffix:"_lp" + ; in_udf_dist_def= is_udf_dist id.name + ; in_returning_fun_def= return_ty <> Void } + in + let _, checked_body = check_statement context tenv_body body in + verify_fundef_return_tys loc return_ty checked_body ; + let stmt = + FunDef + {returntype= return_ty; funname= id; arguments= args; body= checked_body} + in + (* NB: **not** tenv_body, so args don't leak out *) + (tenv, mk_typed_statement ~return_type:NoReturnType ~loc ~stmt) + +and check_statement (cf : context_flags_record) (tenv : Env.t) + (s : Ast.untyped_statement) : Env.t * typed_statement = + let loc = s.smeta.loc in + match s.stmt with + | NRFunApp (_, id, es) -> (tenv, check_nr_fn_app loc cf tenv id es) + | Assignment {assign_lhs; assign_op; assign_rhs} -> + (tenv, check_assignment loc cf tenv assign_lhs assign_op assign_rhs) + | TargetPE e -> (tenv, check_target_pe loc cf tenv e) + | IncrementLogProb e -> (tenv, check_incr_logprob loc cf tenv e) + | Tilde {arg; distribution; args; truncation} -> + (tenv, check_tilde loc cf tenv distribution truncation arg args) + | Break -> (tenv, check_break loc cf) + | Continue -> (tenv, check_continue loc cf) + | Return e -> (tenv, check_return loc cf tenv e) + | ReturnVoid -> (tenv, check_returnvoid loc cf) + | Print ps -> (tenv, check_print loc cf tenv ps) + | Reject ps -> (tenv, check_reject loc cf tenv ps) + | Skip -> (tenv, check_skip loc) + (* the following can contain further statements *) + | IfThenElse (e, s1, os2) -> (tenv, check_if_then_else loc cf tenv e s1 os2) + | While (e, s) -> (tenv, check_while loc cf tenv e s) + | For {loop_variable; lower_bound; upper_bound; loop_body} -> + ( tenv + , check_for loc cf tenv loop_variable lower_bound upper_bound loop_body + ) + | ForEach (id, e, s) -> (tenv, check_foreach loc cf tenv id e s) + | Block stmts -> (tenv, check_block loc cf tenv stmts) + | Profile (name, vdsl) -> (tenv, check_profile loc cf tenv name vdsl) + | VarDecl {decl_type= Unsized _; _} -> + (* currently unallowed by parser *) + raise_s [%message "Don't support unsized declarations yet."] + (* these two are special in that they're allowed to change the type environment *) + | VarDecl + { decl_type= Sized st + ; transformation + ; identifier + ; initial_value + ; is_global } -> + check_var_decl loc cf tenv st transformation identifier initial_value + is_global + | FunDef {returntype; funname; arguments; body} -> + check_fundef loc cf tenv returntype funname arguments body + +let verify_fun_def_body_in_block = function + | {stmt= FunDef {body= {stmt= Block _; _}; _}; _} + |{stmt= FunDef {body= {stmt= Skip; _}; _}; _} -> + () + | {stmt= FunDef {body= {stmt= _; smeta}; _}; _} -> + Semantic_error.fn_decl_needs_block smeta.loc |> error + | _ -> () + +let verify_functions_have_defn tenv function_block_stmts_opt = + let error_on_undefined funs = + List.iter funs ~f:(fun f -> + match f with + | Env.({kind= `UserDeclared loc; _}) -> + Semantic_error.fn_decl_without_def loc |> error + | _ -> () ) + in + if !check_that_all_functions_have_definition then + Env.iter tenv error_on_undefined ; + match function_block_stmts_opt with + | Some {stmts= []; _} | None -> () + | Some {stmts= ls; _} -> List.iter ~f:verify_fun_def_body_in_block ls + +let check_toplevel_block block tenv stmts_opt = + let cf = context block in + match stmts_opt with + | Some {stmts; xloc} -> + let tenv', stmts = + List.fold_map stmts ~init:tenv ~f:(check_statement cf) + in + (tenv', Some {stmts; xloc}) + | None -> (tenv, None) + +let verify_correctness_invariant (ast : untyped_program) + (decorated_ast : typed_program) = + let detyped = untyped_program_of_typed_program decorated_ast in + if compare_untyped_program ast detyped = 0 then () + else + raise_s + [%message + "Type checked AST does not match original AST. Please file a bug!" + (detyped : untyped_program) + (ast : untyped_program)] + +let check_program_exn + ( { functionblock= fb + ; datablock= db + ; transformeddatablock= tdb + ; parametersblock= pb + ; transformedparametersblock= tpb + ; modelblock= mb + ; generatedquantitiesblock= gqb + ; comments } as ast ) : typed_program = + (* create a new type environment which has only stan-math functions *) + let tenv = Env.create () in + let tenv, typed_fb = check_toplevel_block Functions tenv fb in + verify_functions_have_defn tenv typed_fb ; + let tenv, typed_db = check_toplevel_block Data tenv db in + let tenv, typed_tdb = check_toplevel_block TData tenv tdb in + let tenv, typed_pb = check_toplevel_block Param tenv pb in + let tenv, typed_tpb = check_toplevel_block TParam tenv tpb in + let _, typed_mb = check_toplevel_block Model tenv mb in + let _, typed_gqb = check_toplevel_block GQuant tenv gqb in + let prog = + { functionblock= typed_fb + ; datablock= typed_db + ; transformeddatablock= typed_tdb + ; parametersblock= typed_pb + ; transformedparametersblock= typed_tpb + ; modelblock= typed_mb + ; generatedquantitiesblock= typed_gqb + ; comments } + in + verify_correctness_invariant ast prog ; + prog + +let check_program ast = + try Result.Ok (check_program_exn ast) with Errors.SemanticError err -> + Result.Error err diff --git a/src/frontend/Typechecker.mli b/src/frontend/Typechecker.mli new file mode 100644 index 0000000000..3e165beb45 --- /dev/null +++ b/src/frontend/Typechecker.mli @@ -0,0 +1,14 @@ +open Ast + +val check_program_exn : untyped_program -> typed_program +(** Can raise Errors.SemanticError *) + +val check_program : + untyped_program -> (typed_program, Middle.Semantic_error.t) result + +val model_name : string ref +(** A reference to hold the model name. Relevant for checking variable + clashes and used in code generation. *) + +val check_that_all_functions_have_definition : bool ref +(** A switch to determine whether we check that all functions have a definition *) diff --git a/src/middle/Semantic_error.ml b/src/middle/Semantic_error.ml index 4e716b5c23..00a25b24a3 100644 --- a/src/middle/Semantic_error.ml +++ b/src/middle/Semantic_error.ml @@ -387,7 +387,7 @@ For example, "target += normal_lpdf(y, 0, 1)" should become "y ~ normal(0, 1)." "Function '%s' has already been declared. A definition is expected." name | FunDeclNoDefn -> - Fmt.pf ppf "Some function is declared without specifying a definition." + Fmt.pf ppf "Function is declared without specifying a definition." | FunDeclNeedsBlock -> Fmt.pf ppf "Function definitions must be wrapped in curly braces." | NonRealProbFunDef -> diff --git a/src/middle/SignatureMismatch.mli b/src/middle/SignatureMismatch.mli index 5baeb788fd..3f4a5aa372 100644 --- a/src/middle/SignatureMismatch.mli +++ b/src/middle/SignatureMismatch.mli @@ -47,3 +47,5 @@ val pp_signature_mismatch : list * bool ) -> unit + +val compare_errors : function_mismatch -> function_mismatch -> int diff --git a/src/stan2tfp/Stan2tfp.ml b/src/stan2tfp/Stan2tfp.ml index d8afc0f8ea..8ae401b950 100644 --- a/src/stan2tfp/Stan2tfp.ml +++ b/src/stan2tfp/Stan2tfp.ml @@ -22,8 +22,7 @@ let set_model_file s = match !model_file with | "" -> model_file := s ; - Semantic_check.model_name := - remove_dotstan (Filename.basename s) ^ "_model" + Typechecker.model_name := remove_dotstan (Filename.basename s) ^ "_model" | _ -> raise_s [%message "Can only pass in one model file."] let main () = @@ -31,7 +30,7 @@ let main () = let mir = !model_file |> Frontend_utils.get_ast_or_exit |> Frontend_utils.type_ast_or_exit - |> Ast_to_Mir.trans_prog !Semantic_check.model_name + |> Ast_to_Mir.trans_prog !Typechecker.model_name in if !dump_mir then mir |> Middle.Program.Typed.sexp_of_t |> Sexp.to_string_hum diff --git a/src/stanc/stanc.ml b/src/stanc/stanc.ml index daf129b0b1..743db3a4b8 100644 --- a/src/stanc/stanc.ml +++ b/src/stanc/stanc.ml @@ -100,7 +100,7 @@ let options = exit 0 ) , " Display stanc version number" ) ; ( "--name" - , Arg.Set_string Semantic_check.model_name + , Arg.Set_string Typechecker.model_name , " Take a string to set the model name (default = \ \"$model_filename_model\")" ) ; ( "--O" @@ -114,10 +114,10 @@ let options = , Arg.Set print_model_cpp , " If set, output the generated C++ Stan model class to stdout." ) ; ( "--allow-undefined" - , Arg.Clear Semantic_check.check_that_all_functions_have_definition + , Arg.Clear Typechecker.check_that_all_functions_have_definition , " Do not fail if a function is declared but not defined" ) ; ( "--allow_undefined" - , Arg.Clear Semantic_check.check_that_all_functions_have_definition + , Arg.Clear Typechecker.check_that_all_functions_have_definition , " Deprecated. Same as --allow-undefined." ) ; ( "--include-paths" , Arg.String @@ -256,12 +256,12 @@ let main () = exit 0 ) ; (* Just translate a stan program *) if !model_file = "" then model_file_err () ; - if !Semantic_check.model_name = "" then - Semantic_check.model_name := + if !Typechecker.model_name = "" then + Typechecker.model_name := mangle (remove_dotstan List.(hd_exn (rev (String.split !model_file ~on:'/')))) ^ "_model" - else Semantic_check.model_name := mangle !Semantic_check.model_name ; + else Typechecker.model_name := mangle !Typechecker.model_name ; if !output_file = "" then output_file := remove_dotstan !model_file ^ ".hpp" ; use_file !model_file diff --git a/src/stancjs/stancjs.ml b/src/stancjs/stancjs.ml index 91c31cdbf6..a7a7ea2744 100644 --- a/src/stancjs/stancjs.ml +++ b/src/stancjs/stancjs.ml @@ -20,8 +20,8 @@ let warn_uninitialized_msgs Set.Poly.(to_list (map filtered_uninit_vars ~f:show_var_info)) let stan2cpp model_name model_string is_flag_set = - Semantic_check.model_name := model_name ; - Semantic_check.check_that_all_functions_have_definition := + Typechecker.model_name := model_name ; + Typechecker.check_that_all_functions_have_definition := not (is_flag_set "allow_undefined" || is_flag_set "allow-undefined") ; Transform_Mir.use_opencl := is_flag_set "use-opencl" ; Stan_math_code_gen.standalone_functions := is_flag_set "standalone-functions" ; @@ -40,15 +40,13 @@ let stan2cpp model_name model_string is_flag_set = let result = ast >>= fun ast -> - let typed_ast_and_warnings = - Semantic_check.semantic_check_program ast - |> Result.map_error ~f:(fun errs -> - Errors.Semantic_error (List.hd_exn errs) ) + let typed_ast = + Typechecker.check_program ast + |> Result.map_error ~f:(fun e -> Errors.Semantic_error e) in - typed_ast_and_warnings - >>| fun typed_ast_and_warnings -> - let typed_ast, semantic_warnings = typed_ast_and_warnings in - let warnings = parser_warnings @ semantic_warnings in + typed_ast + >>| fun typed_ast -> + let warnings = parser_warnings in if is_flag_set "info" then r.return (Result.Ok (Info.info typed_ast), warnings, []) ; if is_flag_set "print-canonical" then diff --git a/test/integration/bad/functions-bad2.stan b/test/integration/bad/functions-bad2.stan index 110a0051d0..bcf9675761 100644 --- a/test/integration/bad/functions-bad2.stan +++ b/test/integration/bad/functions-bad2.stan @@ -1,4 +1,10 @@ functions { + int foobar(int x); + + int foobar(int x){ + return 1; + } + real barfoo(real x); // error not defining barfoo } diff --git a/test/integration/bad/shadow.stan b/test/integration/bad/shadow.stan new file mode 100644 index 0000000000..c887884295 --- /dev/null +++ b/test/integration/bad/shadow.stan @@ -0,0 +1,5 @@ +functions { + int log10(int x) { + return 1; + } +} \ No newline at end of file diff --git a/test/integration/bad/stanc.expected b/test/integration/bad/stanc.expected index 4bcfd2dbdc..9ae7cc8e82 100644 --- a/test/integration/bad/stanc.expected +++ b/test/integration/bad/stanc.expected @@ -1096,16 +1096,17 @@ Semantic error in 'functions-bad19.stan', line 4, column 2 to line 6, column 3: Function 'my_fun3' has already been declared to have type (data real) => real $ ../../../../install/default/bin/stanc functions-bad2.stan -Semantic error in 'functions-bad2.stan', line 2, column 2 to column 22: +Semantic error in 'functions-bad2.stan', line 8, column 7 to column 13: ------------------------------------------------- - 1: functions { - 2: real barfoo(real x); - ^ - 3: // error not defining barfoo - 4: } + 6: } + 7: + 8: real barfoo(real x); + ^ + 9: // error not defining barfoo + 10: } ------------------------------------------------- -Some function is declared without specifying a definition. +Function is declared without specifying a definition. $ ../../../../install/default/bin/stanc functions-bad20.stan Semantic error in 'functions-bad20.stan', line 4, column 2 to line 6, column 3: ------------------------------------------------- @@ -2037,6 +2038,17 @@ Semantic error in 'row_vector_expr_bad2.stan', line 5, column 25 to column 26: ------------------------------------------------- Row_vector expression must have all int or real entries. Found type row_vector. + $ ../../../../install/default/bin/stanc shadow.stan +Semantic error in 'shadow.stan', line 2, column 7 to column 12: + ------------------------------------------------- + 1: functions { + 2: int log10(int x) { + ^ + 3: return 1; + 4: } + ------------------------------------------------- + +Identifier 'log10' clashes with Stan Math library function. $ ../../../../install/default/bin/stanc signature_function_known.stan Warning in 'signature_function_known.stan', line 8, column 2: increment_log_prob(...); is deprecated and will be removed in the future. Use target += ...; instead.Semantic error in 'signature_function_known.stan', line 8, column 21 to column 50: ------------------------------------------------- diff --git a/test/integration/good/pretty.expected b/test/integration/good/pretty.expected index c05922731a..9282e894f8 100644 --- a/test/integration/good/pretty.expected +++ b/test/integration/good/pretty.expected @@ -5411,6 +5411,15 @@ generated quantities { real sd_y = sd(y); } + $ ../../../../install/default/bin/stanc --auto-format shadow.stan +parameters { + real pow; +} +transformed parameters { + print(pow(1, 1)); + print(pow); +} + $ ../../../../install/default/bin/stanc --auto-format single-arg-conddist.stan functions { real foo_lpdf(real x) { diff --git a/test/integration/good/shadow.stan b/test/integration/good/shadow.stan new file mode 100644 index 0000000000..2d2d2dea8f --- /dev/null +++ b/test/integration/good/shadow.stan @@ -0,0 +1,7 @@ +parameters { + real pow; +} +transformed parameters { + print(pow(1,1)); + print(pow); +} diff --git a/test/stancjs/stancjs.expected b/test/stancjs/stancjs.expected index b6bed36979..aef3a7f293 100644 --- a/test/stancjs/stancjs.expected +++ b/test/stancjs/stancjs.expected @@ -1,6 +1,6 @@ $ node allow-undefined.js -Semantic error in 'string', line 3, column 4 to column 20: -Some function is declared without specifying a definition. +Semantic error in 'string', line 3, column 8 to column 11: +Function is declared without specifying a definition. $ node auto-format.js parameters { real y; @@ -76,8 +76,8 @@ $ node info.js "included_files": [ ] } $ node optimization.js -Semantic error in 'string', line 3, column 4 to column 20: -Some function is declared without specifying a definition. +Semantic error in 'string', line 3, column 8 to column 11: +Function is declared without specifying a definition. $ node pedantic.js ["Warning in 'string', line 7, column 17: Argument 10000 suggests there may be parameters that are not unit scale; consider rescaling with a multiplier (see manual section 22.12).","Warning: The parameter k was declared but was not used in the density calculation."] [] From 2b539dbe1fb3c23c6eecb3b949128bc14ff3827b Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Mon, 27 Sep 2021 15:04:06 -0400 Subject: [PATCH 04/15] Remove old semantic_error and reorganize --- README.md | 36 +- docs/img/information-flow.png | Bin 64903 -> 119468 bytes src/common/Common.ml | 1 - src/common/Common.mli | 1 - src/common/Validation.ml | 167 -- src/common/Validation.mli | 38 - src/frontend/Environment.ml | 65 - src/frontend/Environment.mli | 8 - src/{middle => frontend}/Errors.ml | 20 +- src/{middle => frontend}/Errors.mli | 6 +- src/frontend/Frontend_utils.ml | 2 - src/frontend/Parse.mli | 4 +- src/frontend/Preprocessor.ml | 4 +- src/frontend/Pretty_printing.ml | 4 +- src/frontend/Semantic_check.ml | 1933 ----------------- src/frontend/Semantic_check.mli | 15 - src/{middle => frontend}/Semantic_error.ml | 26 +- src/{middle => frontend}/Semantic_error.mli | 13 +- src/{middle => frontend}/SignatureMismatch.ml | 21 +- .../SignatureMismatch.mli | 10 +- src/frontend/Symbol_table.ml | 79 - src/frontend/Symbol_table.mli | 43 - src/frontend/Typechecker.ml | 9 +- src/frontend/Typechecker.mli | 3 +- src/frontend/lexer.mll | 1 - src/middle/Middle.ml | 3 - test/unit/Parse_tests.ml | 2 +- 27 files changed, 89 insertions(+), 2425 deletions(-) delete mode 100644 src/common/Validation.ml delete mode 100644 src/common/Validation.mli rename src/{middle => frontend}/Errors.ml (78%) rename src/{middle => frontend}/Errors.mli (89%) delete mode 100644 src/frontend/Semantic_check.ml delete mode 100644 src/frontend/Semantic_check.mli rename src/{middle => frontend}/Semantic_error.ml (96%) rename src/{middle => frontend}/Semantic_error.mli (95%) rename src/{middle => frontend}/SignatureMismatch.ml (95%) rename src/{middle => frontend}/SignatureMismatch.mli (88%) delete mode 100644 src/frontend/Symbol_table.ml delete mode 100644 src/frontend/Symbol_table.mli diff --git a/README.md b/README.md index f319fe164f..86bd7919aa 100644 --- a/README.md +++ b/README.md @@ -15,13 +15,43 @@ The entrypoint for the compiler is in `src/stanc/stanc.ml` which sequences the v ### Distinct stanc Phases The phases of stanc are summarized in the following information flowchart and list. - + ![stanc3 information flow](docs/img/information-flow.png) 1. [Lex](src/frontend/lexer.mll) the Stan language into tokens. 1. [Parse](src/frontend/parser.mly) Stan language into AST that represents the syntax quite closely and aides in development of pretty-printers and linters. `stanc --debug-ast` to print this out. -1. Typecheck & add type information [Semantic_check.ml](src/frontend/Semantic_check.ml). `stanc --debug-decorated-ast` -1. [Desugaring phase](src/frontend/Desugar.ml) (AST -> AST). `stanc --debug-desugared` +1. Typecheck & add type information [Typechecker.ml](src/frontend/Typechecker.ml). `stanc --debug-decorated-ast` 1. [Lower](src/frontend/Ast_to_Mir.ml) into [Middle Intermediate Representation](src/middle/Mir.ml) (AST -> MIR) `stanc --debug-mir` (or `--debug-mir-pretty`) 1. Analyze & optimize (MIR -> MIR) 1. Backend MIR transform (MIR -> MIR) [Transform_Mir.ml](src/stan_math_backend/Transform_Mir.ml) `stanc --debug-transformed-mir` diff --git a/docs/img/information-flow.png b/docs/img/information-flow.png index 7b37f4b0db8860fe60abdab2f1748257a3c6689b..05be35226ddb0fa931743492f27009b1a709a047 100644 GIT binary patch literal 119468 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

GZX%voj{^lhq^a_~3%@{+b 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%0A@Me=$?CI{T%Ll^ac319J(Un+~h6)vkT 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 z z+)6GbJ56QtgqM0R58Z&HFSZVv)G({0$5Doq;U3 zd-508@F%xRwolI^Y|74FX;qrylNL@Easm0A?IzA0^hm&ku9ml>%34^Zm)t|PX`vzR z=gM8mm<4;SJ2xHV`@9b8*=#WJeT4b@fcfjpplZrz7#^M+xIgQMFIRk{tK(m0bqdEIojTW)`97XLTB;^!ZbQvhS8FPQEH^U zH+21pSncn@z4-j|{zlQxs2zXnf)fF;^S65MT@rT|uNR-QPL&2WbptK$B#d)2NDDMr z#qOZlM{+Q$pUhgpPZO6&$ga87(5F%$E?AA23hh+_bdI}VJf7_+qucDzor4FgS~DWc zo|qs)(fQ2vkR&b0HvN5XpD55CL*a1Q-)sGD)M?*46K*2@)iGr&M!)ayy26|y5H3;XJvLsW}Xa9 zt!sU-f4XJI9|A33T8%`{#tK0`Xm-+n9NFwkkVuGA^9VfezOzl0*ADr(M5;H-Llutu z1Ep|eC&KXiX(vcYGVf#fZqd8t`YlE-qK`p6cs%)BsSoRGP4&UQ|FC^9pQx!tHxrK;HRJTpmN(_xr0a{L+-u&HV+)ogyIq!tn z2)CaJdo9$WcR-nfu4l z<-WmBw>ZI>zbDJG*j!kz>_R%$K>k_=ZoWpbJ?K~>q^+#;()O|S>`g7}XhkBS2KLLZghb(+bDtm`)-6Eq3!Uh9DRSr?d1_&J9P`YQ z8ZUW!A4g{dFyKrEQhFBKbE7j{qju+7mT)`QxuoMiO;39VZ2xe^`8ajC8BZwXppyG_ zpot~*YgB;L2p^9KI`%y;!ee!mEjn~#G1zff`(wf@vdQrrWOm?`gy|pkji)SMzeS1kB{Bby zo8@luctMK+jV$G{zPj)sikJj!@RIzoi@PmbNiy#7n#fKtWIW01T}t_y$&GRDPtfP- z0JL{zHi9pwKN>+39DhAL85fmY?_b=lH+fIJedrhB#qub2ja}CLvXJe`DAT>aHsaCJ zoJG|Oe0j|LtfcM$Aq@%Y-p2qQErCAV&pG*~$K9XEdGEPc$ynZ*J$#|&YwebOCpWT{_b-gsZEYU>@laI2IKk=K{+hMCjf|zIYd_Na6^ck1KJ6N- zwgc0t&OGVyhX3b|>5q&Hlr&im{K_=u1fCf@@+IHS@Gzc;C$tFms{cHS=(g!Mrwc7A zWqeY!!>Ke)i1uavacM5`tKt*;;-bv`h+%A8ZTukCjL=wdu7N>de)w<`50>=BAHxm< zL?WL;%@D4&uqMG?R^Zx$yJ6*Q>h=OOhN9ELw82O`d-&D-q(%(9g^jAy-(WW=aov#PCG~+}# zNx0xaSE;&4UL+aJderxp@9v-B8#M(+gn?;=VVed+n{J<@~+%m_<&{lYH(%6mO}mTfaz5&G;B| zDI{cn=-U?up}>UkXL?PsDx0Bru^7u2PdQ(MXMR7BC<$Yp>TgQyAohF*_T8w;vZ%A2 z1Ci=kIWX&+4RXKj8V6E6iHXVlo`S^0asj`UpO_fde`)jX1rxHiKt)CU9upG~VCdxK z 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

$dXrxVkKPxFRrN4SumB_Dp27BEkMlxTHs-o` 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 diff --git a/src/common/Common.ml b/src/common/Common.ml index 44d102e602..690a60392d 100644 --- a/src/common/Common.ml +++ b/src/common/Common.ml @@ -2,7 +2,6 @@ module Foldable = Foldable (* Other signatures *) -module Validation = Validation module Pretty = Pretty (* 'Two-level type' signatures and functors *) diff --git a/src/common/Common.mli b/src/common/Common.mli index 5f84f04468..4cf470fab7 100644 --- a/src/common/Common.mli +++ b/src/common/Common.mli @@ -2,7 +2,6 @@ module Foldable : module type of Foldable (* Other signatures *) -module Validation : module type of Validation module Pretty : module type of Pretty (* 'Two-level type' signatures and functors *) diff --git a/src/common/Validation.ml b/src/common/Validation.ml deleted file mode 100644 index 6f94a53af8..0000000000 --- a/src/common/Validation.ml +++ /dev/null @@ -1,167 +0,0 @@ -include Core_kernel - -module type Infix = sig - type 'a t - - val ( >>= ) : 'a t -> ('a -> 'b t) -> 'b t -end - -module type S = sig - type error - type 'a t - - val map : 'a t -> f:('a -> 'b) -> 'b t - val pure : 'a -> 'a t - val apply : 'a t -> f:('a -> 'b) t -> 'b t - val apply_const : 'a t -> 'b t -> 'b t - val bind : 'a t -> f:('a -> 'b t) -> 'b t - val liftA2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t - val liftA3 : ('a -> 'b -> 'c -> 'd) -> 'a t -> 'b t -> 'c t -> 'd t - val sequence : 'a t list -> 'a list t - val ok : 'a -> 'a t - val error : error -> _ t - val is_error : 'a t -> bool - val is_success : 'a t -> bool - val get_errors_opt : 'a t -> error list option - val get_first_error_opt : 'a t -> error option - val get_success_opt : 'a t -> 'a option - - val get_with : - 'a t -> with_ok:('a -> 'b) -> with_errors:(error list -> 'b) -> 'b - - val to_result : 'a t -> ('a, error list) result - - module Validation_infix : Infix with type 'a t := 'a t - include Infix with type 'a t := 'a t -end - -(** - It is common need in a compiler to check for certain errors e.g. syntax - errors, type errors, other semantic errors, etc. Some typical ways of doing - this include exceptions or representing success/failure with `Result.t`. - In both of these approaches, the computation will 'fail' when we reach the - first error condition. - - In some situations, it may be preferable to report _all_ of these errors to a - user in one go. `Validation` gives us this ability*. - - The implementation below is an example of an OCaml `functor` i.e. a module - that is _parametrized_ by another module. Our `Valiation.Make` functor is - parameterized over another module containing the type of errors. - - When applied, the functor returns a module with signature `Validation.S` but - with the underlying error type fixed at the type `t` contained in the module `X`. - As an example, we use this functor with the module `Semantic_error` - (defined in `frontend`) so the type `error` is made equal to `Semantic_error.t` - - Under the hood, `Validation` is just a `Result.t` with a `NonEmpty` list of - `error`s. The main workhorse of the module is the `apply` function. - The function accepts a value lifted into our result type `'a t` and a - _function_ lifted into the result type `('a -> 'b) t`. - - ``` - let apply x ~f = - match (f,x) with - ``` - - `apply` 'unwraps' the function and the value and performs different actions - depending on whether an error has occured. Because we have two arguments each - of which can be in two states, we have to check for four conditions: - - The first condition is that both the function `f` and the value `x` are `Ok`; - in this case we can simply apply the function to the value and lift is back - into the result type: - - ``` - | Ok f , Ok x -> Ok (f x) - ``` - - The second situation is the the function is an `Error`; in this case we can't - apply the function so we simply return the same error: - - ``` - | Error e , Ok _ -> Error e - ``` - - The third situation is that the function `f` is `Ok` but he value `x` is an - `Error`; again, we can't apply the function so we return the error: - - ``` - | Ok _ , Error e -> Error e - ``` - - The final situation is that both `f` and `x` are errors; because our error - type is a `NonEmpty` list, we can combine them using the `append` function and - track both: - - ``` - | Error e1 , Error e2 -> Error(append e1 e2) - ``` - - The module hides the implementation of `'a t` but exposes the functions `ok` - and `error` to construct this type. - - * This is true so long as we restrict our usage to `apply` (and related) - functions i.e. the _applicative_ interface.As soon as we use `bind` - (i.e. the _monadic_ interface) we lose this ability. Technically, `Validation` - doesn't constitute a monad since it violates the law: - - ``` - liftM2 f m1 m2 === apply f a1 s2 - ``` -*) -module Make (X : sig - type t -end) : S with type error := X.t = struct - type errors = NonEmpty of X.t * X.t list - - let append xs ys = - match (xs, ys) with - | NonEmpty (x, []), NonEmpty (y, []) -> NonEmpty (x, [y]) - | NonEmpty (x, xs), NonEmpty (y, ys) -> NonEmpty (x, xs @ (y :: ys)) - - type 'a t = ('a, errors) result - - let map x ~f = match x with Ok x -> Ok (f x) | Error x -> Error x - let pure x = Ok x - - let apply x ~f = - match (f, x) with - | Ok f, Ok x -> Ok (f x) - | Error e, Ok _ -> Error e - | Ok _, Error e -> Error e - | Error e1, Error e2 -> Error (append e1 e2) - - let apply_const a b = apply b ~f:(map a ~f:(fun _ x -> x)) - let bind x ~f = match x with Ok x -> f x | Error e -> Error e - let liftA2 f x y = apply y ~f:(apply x ~f:(pure f)) - let liftA3 f x y z = apply z ~f:(apply y ~f:(apply x ~f:(pure f))) - let consA next rest = liftA2 List.cons next rest - let sequence ts = List.fold_right ~init:(pure []) ~f:consA ts - - module Validation_infix = struct let ( >>= ) x f = bind x ~f end - include Validation_infix - - let ok x = pure x - let error x = Error (NonEmpty (x, [])) - let is_error = function Error _ -> true | _ -> false - let is_success = function Ok _ -> true | _ -> false - - let get_errors_opt = function - | Error (NonEmpty (x, xs)) -> Some (x :: xs) - | _ -> None - - let get_first_error_opt = function - | Error (NonEmpty (x, _)) -> Some x - | _ -> None - - let get_success_opt = function Ok x -> Some x | _ -> None - - let get_with x ~with_ok ~with_errors = - match x with - | Ok x -> with_ok x - | Error (NonEmpty (x, xs)) -> with_errors @@ (x :: xs) - - let to_result x = - match x with Ok x -> Ok x | Error (NonEmpty (x, xs)) -> Error (x :: xs) -end diff --git a/src/common/Validation.mli b/src/common/Validation.mli deleted file mode 100644 index d158a3251c..0000000000 --- a/src/common/Validation.mli +++ /dev/null @@ -1,38 +0,0 @@ -module type Infix = sig - type 'a t - - val ( >>= ) : 'a t -> ('a -> 'b t) -> 'b t -end - -module type S = sig - type error - type 'a t - - val map : 'a t -> f:('a -> 'b) -> 'b t - val pure : 'a -> 'a t - val apply : 'a t -> f:('a -> 'b) t -> 'b t - val apply_const : 'a t -> 'b t -> 'b t - val bind : 'a t -> f:('a -> 'b t) -> 'b t - val liftA2 : ('a -> 'b -> 'c) -> 'a t -> 'b t -> 'c t - val liftA3 : ('a -> 'b -> 'c -> 'd) -> 'a t -> 'b t -> 'c t -> 'd t - val sequence : 'a t list -> 'a list t - val ok : 'a -> 'a t - val error : error -> _ t - val is_error : 'a t -> bool - val is_success : 'a t -> bool - val get_errors_opt : 'a t -> error list option - val get_first_error_opt : 'a t -> error option - val get_success_opt : 'a t -> 'a option - - val get_with : - 'a t -> with_ok:('a -> 'b) -> with_errors:(error list -> 'b) -> 'b - - val to_result : 'a t -> ('a, error list) result - - module Validation_infix : Infix with type 'a t := 'a t - include Infix with type 'a t := 'a t -end - -module Make (X : sig - type t -end) : S with type error := X.t diff --git a/src/frontend/Environment.ml b/src/frontend/Environment.ml index f063cd796b..460a61b884 100644 --- a/src/frontend/Environment.ml +++ b/src/frontend/Environment.ml @@ -52,68 +52,3 @@ let add_all_raw env key data = let find env key = Map.find_multi env key let mem env key = Map.mem env key let iter env f = Map.iter env ~f - -(* TODO move this to SignatureMismatch.ml when semantic_check is removed *) - -let extract_function_types f = - match f with - | {type_= UFun (args, return, _, mem); kind= `StanMath} -> - Some (return, args, (fun x -> Ast.StanLib x), mem) - | {type_= UFun (args, return, _, mem); _} -> - Some (return, args, (fun x -> UserDefined x), mem) - | _ -> None - -let rec check_same_type depth t1 t2 = - let open SignatureMismatch in - let wrap_func = Option.map ~f:(fun e -> TypeMismatch (t1, t2, Some e)) in - match (t1, t2) with - | t1, t2 when t1 = t2 -> None - | UnsizedType.(UReal, UInt) when depth < 1 -> None - | UFun (_, _, s1, _), UFun (_, _, s2, _) - when Fun_kind.without_propto s1 <> Fun_kind.without_propto s2 -> - Some - (SuffixMismatch (Fun_kind.without_propto s1, Fun_kind.without_propto s2)) - |> wrap_func - | UFun (_, rt1, _, _), UFun (_, rt2, _, _) when rt1 <> rt2 -> - Some (ReturnTypeMismatch (rt1, rt2)) |> wrap_func - | UFun (l1, _, _, _), UFun (l2, _, _, _) -> - check_compatible_arguments (depth + 1) l2 l1 - |> Option.map ~f:(fun e -> InputMismatch e) - |> wrap_func - | t1, t2 -> Some (TypeMismatch (t1, t2, None)) - -and check_compatible_arguments depth args1 args2 = - let open SignatureMismatch in - match List.zip args1 args2 with - | None -> Some (ArgNumMismatch (List.length args1, List.length args2)) - | Some l -> - List.find_mapi l ~f:(fun i ((ad1, ut1), (ad2, ut2)) -> - match check_same_type depth ut1 ut2 with - | Some e -> Some (ArgError (i + 1, e)) - | None -> - if ad1 = ad2 then None - else if depth < 2 && UnsizedType.autodifftype_can_convert ad1 ad2 - then None - else Some (ArgError (i + 1, DataOnlyError)) ) - -let returntype env name args = - let open SignatureMismatch in - (* NB: Variadic arguments are special-cased in Semantic_check and not handled here *) - let name = Utils.stdlib_distribution_name name in - find env name - |> List.filter_map ~f:extract_function_types - |> List.sort ~compare:(fun (x, _, _, _) (y, _, _, _) -> - UnsizedType.compare_returntype x y ) - (* Check the least return type first in case there are multiple options (due to implicit UInt-UReal conversion), where UInt List.fold_until ~init:[] - ~f:(fun errors (rt, tys, funkind_constructor, _) -> - match check_compatible_arguments 0 tys args with - | None -> Stop (Ok (rt, funkind_constructor)) - | Some e -> Continue (((rt, tys), e) :: errors) ) - ~finish:(fun errors -> - let errors = - List.sort errors ~compare:(fun (_, e1) (_, e2) -> - compare_errors e1 e2 ) - in - let errors, omitted = List.split_n errors 5 in - Error (errors, not (List.is_empty omitted)) ) diff --git a/src/frontend/Environment.mli b/src/frontend/Environment.mli index 0a77bd39dc..ab4802856f 100644 --- a/src/frontend/Environment.mli +++ b/src/frontend/Environment.mli @@ -41,11 +41,3 @@ val add : val add_all_raw : t -> string -> info list -> t val mem : t -> string -> bool val iter : t -> (info list -> unit) -> unit - -val returntype : - t - -> string - -> (UnsizedType.autodifftype * UnsizedType.t) list - -> ( UnsizedType.returntype * (bool Middle.Fun_kind.suffix -> Ast.fun_kind) - , SignatureMismatch.signature_error list * bool ) - result diff --git a/src/middle/Errors.ml b/src/frontend/Errors.ml similarity index 78% rename from src/middle/Errors.ml rename to src/frontend/Errors.ml index e90e04f17c..19a8c32271 100644 --- a/src/middle/Errors.ml +++ b/src/frontend/Errors.ml @@ -5,9 +5,9 @@ module Str = Re.Str (** Our type of syntax error information *) type syntax_error = - | Lexing of string * Location.t - | Include of string * Location.t - | Parsing of string * Location_span.t + | Lexing of string * Middle.Location.t + | Include of string * Middle.Location.t + | Parsing of string * Middle.Location_span.t (** Exception for Syntax Errors *) exception SyntaxError of syntax_error @@ -31,13 +31,13 @@ let fatal_error ?(msg = "") _ = let pp_context_with_message ppf (msg, loc) = Fmt.pf ppf "%a@,%s" (Fmt.option Fmt.string) - (Location.context_to_string loc) + (Middle.Location.context_to_string loc) msg let pp_semantic_error ?printed_filename ppf err = let loc_span = Semantic_error.location err in Fmt.pf ppf "Semantic error in %s:@;%a" - (Location_span.to_string ?printed_filename loc_span) + (Middle.Location_span.to_string ?printed_filename loc_span) pp_context_with_message (Fmt.strf "%a" Semantic_error.pp err, loc_span.begin_loc) @@ -45,18 +45,18 @@ let pp_semantic_error ?printed_filename ppf err = let pp_syntax_error ?printed_filename ppf = function | Parsing (message, loc_span) -> Fmt.pf ppf "Syntax error in %s, parsing error:@,%a" - (Location_span.to_string ?printed_filename loc_span) + (Middle.Location_span.to_string ?printed_filename loc_span) pp_context_with_message (message, loc_span.begin_loc) | Lexing (_, loc) -> - Fmt.pf ppf "Syntax error in %s, lexing error:@,%a" - (Location.to_string ?printed_filename + Fmt.pf ppf "Syntax error in %s, lexing error:@,%a@." + (Middle.Location.to_string ?printed_filename {loc with col_num= loc.col_num - 1}) pp_context_with_message ("Invalid character found.", loc) | Include (message, loc) -> - Fmt.pf ppf "Syntax error in %s, include error:@,%a" - (Location.to_string loc ?printed_filename) + Fmt.pf ppf "Syntax error in %s, include error:@,%a@." + (Middle.Location.to_string loc ?printed_filename) pp_context_with_message (message, loc) let pp ?printed_filename ppf = function diff --git a/src/middle/Errors.mli b/src/frontend/Errors.mli similarity index 89% rename from src/middle/Errors.mli rename to src/frontend/Errors.mli index 8b3cc78d91..1ecd70b79d 100644 --- a/src/middle/Errors.mli +++ b/src/frontend/Errors.mli @@ -2,9 +2,9 @@ (** Our type of syntax error information *) type syntax_error = - | Lexing of string * Location.t - | Include of string * Location.t - | Parsing of string * Location_span.t + | Lexing of string * Middle.Location.t + | Include of string * Middle.Location.t + | Parsing of string * Middle.Location_span.t (** Exception for Syntax Errors *) exception SyntaxError of syntax_error diff --git a/src/frontend/Frontend_utils.ml b/src/frontend/Frontend_utils.ml index 643635c3ea..c3cfc3148f 100644 --- a/src/frontend/Frontend_utils.ml +++ b/src/frontend/Frontend_utils.ml @@ -1,7 +1,5 @@ open Core_kernel module Warnings = Middle.Warnings -module Errors = Middle.Errors -module Semantic_error = Middle.Semantic_error let untyped_ast_of_string s = let res, warnings = Parse.parse_string Parser.Incremental.program s in diff --git a/src/frontend/Parse.mli b/src/frontend/Parse.mli index 3033347878..7136257046 100644 --- a/src/frontend/Parse.mli +++ b/src/frontend/Parse.mli @@ -5,13 +5,13 @@ open Core_kernel val parse_file : (Lexing.position -> Ast.untyped_program Parser.MenhirInterpreter.checkpoint) -> string - -> (Ast.untyped_program, Middle.Errors.t) result * Middle.Warnings.t list + -> (Ast.untyped_program, Errors.t) result * Middle.Warnings.t list (** A helper function to take a parser, a filename and produce an AST. Under the hood, it takes care of Menhir's custom syntax error messages. *) val parse_string : (Lexing.position -> Ast.untyped_program Parser.MenhirInterpreter.checkpoint) -> string - -> (Ast.untyped_program, Middle.Errors.t) result * Middle.Warnings.t list + -> (Ast.untyped_program, Errors.t) result * Middle.Warnings.t list (** A helper function to take a parser, a string and produce an AST. Under the hood, it takes care of Menhir's custom syntax error messages. *) diff --git a/src/frontend/Preprocessor.ml b/src/frontend/Preprocessor.ml index 21208bbb22..ac3da2f5af 100644 --- a/src/frontend/Preprocessor.ml +++ b/src/frontend/Preprocessor.ml @@ -17,7 +17,7 @@ let rec try_open_in paths fname pos = match paths with | [] -> raise - (Middle.Errors.SyntaxError + (Errors.SyntaxError (Include ( "Could not find include file " ^ fname ^ " in specified include paths.\n" @@ -50,7 +50,7 @@ let try_get_new_lexbuf fname pos = new_lexbuf.lex_curr_p <- new_lexbuf.lex_start_p ; if dup_exists (Str.split (Str.regexp ", included from\n") path) then raise - (Middle.Errors.SyntaxError + (Errors.SyntaxError (Include ( Printf.sprintf "File %s recursively included itself.\n" fname , Middle.Location.of_position_exn diff --git a/src/frontend/Pretty_printing.ml b/src/frontend/Pretty_printing.ml index d2d6852d61..258d66a0b4 100644 --- a/src/frontend/Pretty_printing.ml +++ b/src/frontend/Pretty_printing.ml @@ -267,7 +267,7 @@ and pp_expression ppf ({expr= e_content; emeta= {loc; _}} : untyped_expression) ) | CondDistApp (_, id, es) -> ( match es with - | [] -> Middle.Errors.fatal_error () + | [] -> Errors.fatal_error () | e :: es' -> with_hbox ppf (fun () -> Fmt.pf ppf "%a(%a| %a)" pp_identifier id pp_expression e @@ -325,7 +325,7 @@ let pp_sizedtype ppf = function | SRowVector (_, e) -> Fmt.pf ppf "row_vector[%a]" pp_expression e | SMatrix (_, e1, e2) -> Fmt.pf ppf "matrix[%a, %a]" pp_expression e1 pp_expression e2 - | SArray _ -> raise (Middle.Errors.FatalError "This should never happen.") + | SArray _ -> raise (Errors.FatalError "This should never happen.") let pp_transformation ppf = function | Middle.Transformation.Identity -> Fmt.pf ppf "" diff --git a/src/frontend/Semantic_check.ml b/src/frontend/Semantic_check.ml deleted file mode 100644 index f5dd7f00bc..0000000000 --- a/src/frontend/Semantic_check.ml +++ /dev/null @@ -1,1933 +0,0 @@ -(** Semantic validation of AST*) - -(* Idea: check many of things related to identifiers that are hard to check - during parsing and are in fact irrelevant for building up the parse tree *) - -open Core_kernel -open Symbol_table -open Middle -open Ast -open Errors -module Validate = Common.Validation.Make (Semantic_error) - -(* There is a semantic checking function for each AST node that calls - the checking functions for its children left to right. *) - -(* Top level function semantic_check_program declares the AST while operating - on (1) a global symbol table vm, and (2) structure of type context_flags_record - to communicate information down the AST. *) - -let check_of_compatible_return_type rt1 srt2 = - UnsizedType.( - match (rt1, srt2) with - | Void, NoReturnType - |Void, Incomplete Void - |Void, Complete Void - |Void, AnyReturnType -> - true - | ReturnType UReal, Complete (ReturnType UInt) -> true - | ReturnType UComplex, Complete (ReturnType UReal) -> true - | ReturnType UComplex, Complete (ReturnType UInt) -> true - | ReturnType rt1, Complete (ReturnType rt2) -> rt1 = rt2 - | ReturnType _, AnyReturnType -> true - | _ -> false) - -(** Origin blocks, to keep track of where variables are declared *) -type originblock = - | MathLibrary - | Functions - | Data - | TData - | Param - | TParam - | Model - | GQuant - -(** Print all the signatures of a stan math operator, for the purposes of error messages. *) -let check_that_all_functions_have_definition = ref true - -let model_name = ref "" -let vm = Symbol_table.initialize () - -(* Record structure holding flags and other markers about context to be - used for error reporting. *) -type context_flags_record = - { current_block: originblock - ; in_toplevel_decl: bool - ; in_fun_def: bool - ; in_returning_fun_def: bool - ; in_rng_fun_def: bool - ; in_lp_fun_def: bool - ; in_udf_dist_def: bool - ; loop_depth: int } - -(* Some helper functions *) -let dup_exists l = - match List.find_a_dup ~compare:String.compare l with - | Some _ -> true - | None -> false - -let type_of_expr_typed ue = ue.emeta.type_ - -let calculate_autodifftype cf at ut = - match at with - | (Param | TParam | Model | Functions) - when not (UnsizedType.contains_int ut || cf.current_block = GQuant) -> - UnsizedType.AutoDiffable - | _ -> DataOnly - -let has_int_type ue = ue.emeta.type_ = UInt -let has_int_array_type ue = ue.emeta.type_ = UArray UInt - -let has_int_or_real_type ue = - match ue.emeta.type_ with UInt | UReal -> true | _ -> false - -let probability_distribution_name_variants id = - let name = id.name in - let open String in - List.map - ~f:(fun n -> {name= n; id_loc= id.id_loc}) - ( if name = "multiply_log" || name = "binomial_coefficient_log" then [name] - else if is_suffix ~suffix:"_lpmf" name then - [name; drop_suffix name 5 ^ "_lpdf"; drop_suffix name 5 ^ "_log"] - else if is_suffix ~suffix:"_lpdf" name then - [name; drop_suffix name 5 ^ "_lpmf"; drop_suffix name 5 ^ "_log"] - else if is_suffix ~suffix:"_lcdf" name then - [name; drop_suffix name 5 ^ "_cdf_log"] - else if is_suffix ~suffix:"_lccdf" name then - [name; drop_suffix name 6 ^ "_ccdf_log"] - else if is_suffix ~suffix:"_cdf_log" name then - [name; drop_suffix name 8 ^ "_lcdf"] - else if is_suffix ~suffix:"_ccdf_log" name then - [name; drop_suffix name 9 ^ "_lccdf"] - else if is_suffix ~suffix:"_log" name then - [name; drop_suffix name 4 ^ "_lpmf"; drop_suffix name 4 ^ "_lpdf"] - else [name] ) - -let lub_rt loc rt1 rt2 = - match (rt1, rt2) with - | UnsizedType.ReturnType UReal, UnsizedType.ReturnType UInt - |ReturnType UInt, ReturnType UReal -> - Validate.ok (UnsizedType.ReturnType UReal) - | _, _ when rt1 = rt2 -> Validate.ok rt2 - | _ -> Semantic_error.mismatched_return_types loc rt1 rt2 |> Validate.error - -(* -Checks that a variable/function name: - - if UDF that it does not match a Stan Math function - - a function/identifier does not have the _lupdf/_lupmf suffix - - is not already in use -*) -let check_fresh_variable_basic id is_udf = - Validate.( - if - is_udf - && ( Stan_math_signatures.is_stan_math_function_name id.name - (* variadic functions are currently not in math sigs *) - || Stan_math_signatures.is_reduce_sum_fn id.name - || Stan_math_signatures.is_variadic_ode_fn id.name ) - then Semantic_error.ident_is_stanmath_name id.id_loc id.name |> error - else if Utils.is_unnormalized_distribution id.name then - if is_udf then - Semantic_error.udf_is_unnormalized_fn id.id_loc id.name |> error - else - Semantic_error.ident_has_unnormalized_suffix id.id_loc id.name |> error - else - match Symbol_table.look vm id.name with - | Some _ -> Semantic_error.ident_in_use id.id_loc id.name |> error - | None -> ok ()) - -let check_fresh_variable id is_udf = - List.fold ~init:(Validate.ok ()) - ~f:(fun v0 name -> - check_fresh_variable_basic name is_udf |> Validate.apply_const v0 ) - (probability_distribution_name_variants id) - -(* == SEMANTIC CHECK OF PROGRAM ELEMENTS ==================================== *) - -(* Probably nothing to do here *) -let semantic_check_assignmentoperator op = Validate.ok op - -(* Probably nothing to do here *) -let semantic_check_autodifftype at = Validate.ok at - -(* Probably nothing to do here *) -let rec semantic_check_unsizedtype : UnsizedType.t -> unit Validate.t = - function - | UFun (l, rt, _, _) -> - (* fold over argument types accumulating errors with initial state - given by validating the return type *) - List.fold - ~f:(fun v0 (at, ut) -> - Validate.( - apply_const - (apply_const v0 (semantic_check_autodifftype at)) - (semantic_check_unsizedtype ut)) ) - ~init:(semantic_check_returntype rt) - l - | UArray ut -> semantic_check_unsizedtype ut - | _ -> Validate.ok () - -and semantic_check_returntype : UnsizedType.returntype -> unit Validate.t = - function - | Void -> Validate.ok () - | ReturnType ut -> semantic_check_unsizedtype ut - -(* -- Indentifiers ---------------------------------------------------------- *) -let reserved_keywords = - [ "true"; "false"; "repeat"; "until"; "then"; "var"; "fvar"; "STAN_MAJOR" - ; "STAN_MINOR"; "STAN_PATCH"; "STAN_MATH_MAJOR"; "STAN_MATH_MINOR" - ; "STAN_MATH_PATCH"; "alignas"; "alignof"; "and"; "and_eq"; "asm"; "auto" - ; "bitand"; "bitor"; "bool"; "break"; "case"; "catch"; "char"; "char16_t" - ; "char32_t"; "class"; "compl"; "const"; "constexpr"; "const_cast" - ; "continue"; "decltype"; "default"; "delete"; "do"; "double"; "dynamic_cast" - ; "else"; "enum"; "explicit"; "export"; "extern"; "false"; "float"; "for" - ; "friend"; "goto"; "if"; "inline"; "int"; "long"; "mutable"; "namespace" - ; "new"; "noexcept"; "not"; "not_eq"; "nullptr"; "operator"; "or"; "or_eq" - ; "private"; "protected"; "public"; "register"; "reinterpret_cast"; "return" - ; "short"; "signed"; "sizeof"; "static"; "static_assert"; "static_cast" - ; "struct"; "switch"; "template"; "this"; "thread_local"; "throw"; "true" - ; "try"; "typedef"; "typeid"; "typename"; "union"; "unsigned"; "using" - ; "virtual"; "void"; "volatile"; "wchar_t"; "while"; "xor"; "xor_eq" - ; "functions"; "data"; "parameters"; "model"; "return"; "if"; "else"; "while" - ; "for"; "in"; "break"; "continue"; "void"; "int"; "real"; "complex" - ; "vector"; "row_vector"; "matrix"; "ordered"; "positive_ordered"; "simplex" - ; "unit_vector"; "cholesky_factor_corr"; "cholesky_factor_cov"; "corr_matrix" - ; "cov_matrix"; "print"; "reject"; "target"; "get_lp"; "profile" ] - -let semantic_check_identifier id = - Validate.( - if id.name = !model_name then - Semantic_error.ident_is_model_name id.id_loc id.name |> error - else if - String.is_suffix id.name ~suffix:"__" - || List.exists ~f:(fun str -> str = id.name) reserved_keywords - then Semantic_error.ident_is_keyword id.id_loc id.name |> error - else ok ()) - -(* -- Operators ------------------------------------------------------------- *) -let semantic_check_operator _ = Validate.ok () - -(* == Expressions =========================================================== *) - -let arg_type x = (x.emeta.ad_level, x.emeta.type_) -let get_arg_types = List.map ~f:arg_type - -(* -- Function application -------------------------------------------------- *) - -let semantic_check_fn_conditioning ~loc id = - Validate.( - if - List.exists - ~f:(fun suffix -> String.is_suffix id.name ~suffix) - Utils.conditioning_suffices - && not (String.is_suffix id.name ~suffix:"_cdf") - then Semantic_error.conditioning_required loc |> error - else ok ()) - -(** `Target+=` can only be used in model and functions - with right suffix (same for tilde etc) -*) -let semantic_check_fn_target_plus_equals cf ~loc id = - Validate.( - if - String.is_suffix id.name ~suffix:"_lp" - && not - ( cf.in_lp_fun_def || cf.current_block = Model - || cf.current_block = TParam ) - then Semantic_error.target_plusequals_outisde_model_or_logprob loc |> error - else ok ()) - -(** Rng functions cannot be used in Tp or Model and only - in function defs with the right suffix -*) -let semantic_check_fn_rng cf ~loc id = - Validate.( - if String.is_suffix id.name ~suffix:"_rng" && cf.in_toplevel_decl then - Semantic_error.invalid_decl_rng_fn loc |> error - else if - String.is_suffix id.name ~suffix:"_rng" - && ( (cf.in_fun_def && not cf.in_rng_fun_def) - || cf.current_block = TParam || cf.current_block = Model ) - then Semantic_error.invalid_rng_fn loc |> error - else ok ()) - -(** unnormalized _lpdf/_lpmf functions can only be used in _lpdf/_lpmf/_lp udfs - or the model block -*) -let semantic_check_unnormalized cf ~loc id = - Validate.( - if - Utils.is_unnormalized_distribution id.name - && not ((cf.in_fun_def && cf.in_udf_dist_def) || cf.current_block = Model) - then Semantic_error.invalid_unnormalized_fn loc |> error - else ok ()) - -let mk_fun_app ~is_cond_dist (x, y, z) = - if is_cond_dist then CondDistApp (x, y, z) else FunApp (x, y, z) - -(* Regular function application *) -let semantic_check_fn_normal ~is_cond_dist ~loc id es = - Validate.( - match Symbol_table.look vm (Utils.normalized_name id.name) with - | Some (_, UnsizedType.UFun (_, Void, _, _)) -> - Semantic_error.returning_fn_expected_nonreturning_found loc id.name - |> error - | Some (_, UFun (listedtypes, ReturnType ut, _, _)) -> ( - match - SignatureMismatch.check_compatible_arguments_mod_conv listedtypes - (get_arg_types es) - with - | Some x -> - es - |> List.map ~f:type_of_expr_typed - |> Semantic_error.illtyped_userdefined_fn_app loc id.name listedtypes - (ReturnType ut) x - |> error - | None -> - mk_typed_expression - ~expr: - (mk_fun_app ~is_cond_dist - (UserDefined (Fun_kind.suffix_from_name id.name), id, es)) - ~ad_level:(expr_ad_lub es) ~type_:ut ~loc - |> ok ) - | Some _ -> - (* Check that Funaps are actually functions *) - Semantic_error.returning_fn_expected_nonfn_found loc id.name |> error - | None -> - Semantic_error.returning_fn_expected_undeclaredident_found loc id.name - |> error) - -(* Stan-Math function application *) -let semantic_check_fn_stan_math ~is_cond_dist ~loc id es = - match SignatureMismatch.stan_math_returntype id.name (get_arg_types es) with - | Ok Void -> - Semantic_error.returning_fn_expected_nonreturning_found loc id.name - |> Validate.error - | Ok (ReturnType ut) -> - mk_typed_expression - ~expr: - (mk_fun_app ~is_cond_dist - (StanLib (Fun_kind.suffix_from_name id.name), id, es)) - ~ad_level:(expr_ad_lub es) ~type_:ut ~loc - |> Validate.ok - | Error x -> - es - |> List.map ~f:(fun e -> e.emeta.type_) - |> Semantic_error.illtyped_stanlib_fn_app loc id.name x - |> Validate.error - -let semantic_check_reduce_sum ~is_cond_dist ~loc id es = - match es with - | { emeta= - { type_= - UnsizedType.UFun - (((_, sliced_arg_fun_type) as sliced_arg_fun) :: _, _, _, _); _ - }; _ } - :: _ - when List.mem Stan_math_signatures.reduce_sum_slice_types - sliced_arg_fun_type ~equal:( = ) -> ( - let mandatory_args = [sliced_arg_fun; (AutoDiffable, UInt)] in - let mandatory_fun_args = - [sliced_arg_fun; (DataOnly, UInt); (DataOnly, UInt)] - in - match - SignatureMismatch.check_variadic_args true mandatory_args - mandatory_fun_args UReal (get_arg_types es) - with - | None -> - mk_typed_expression - ~expr:(mk_fun_app ~is_cond_dist (StanLib FnPlain, id, es)) - ~ad_level:(expr_ad_lub es) ~type_:UnsizedType.UReal ~loc - |> Validate.ok - | Some (expected_args, error) -> - Semantic_error.illtyped_reduce_sum loc id.name - (List.map ~f:type_of_expr_typed es) - expected_args error - |> Validate.error ) - | _ -> - let mandatory_args = - UnsizedType.[(AutoDiffable, UArray UReal); (AutoDiffable, UInt)] - in - let mandatory_fun_args = - UnsizedType. - [(AutoDiffable, UArray UReal); (DataOnly, UInt); (DataOnly, UInt)] - in - let expected_args, error = - SignatureMismatch.check_variadic_args true mandatory_args - mandatory_fun_args UReal (get_arg_types es) - |> Option.value_exn - in - Semantic_error.illtyped_reduce_sum_generic loc id.name - (List.map ~f:type_of_expr_typed es) - expected_args error - |> Validate.error - -let semantic_check_variadic_ode ~is_cond_dist ~loc id es = - let optional_tol_mandatory_args = - if Stan_math_signatures.variadic_ode_adjoint_fn = id.name then - Stan_math_signatures.variadic_ode_adjoint_ctl_tol_arg_types - else if Stan_math_signatures.is_variadic_ode_nonadjoint_tol_fn id.name then - Stan_math_signatures.variadic_ode_tol_arg_types - else [] - in - let mandatory_arg_types = - Stan_math_signatures.variadic_ode_mandatory_arg_types - @ optional_tol_mandatory_args - in - match - SignatureMismatch.check_variadic_args false mandatory_arg_types - Stan_math_signatures.variadic_ode_mandatory_fun_args - Stan_math_signatures.variadic_ode_fun_return_type (get_arg_types es) - with - | None -> - mk_typed_expression - ~expr:(mk_fun_app ~is_cond_dist (StanLib FnPlain, id, es)) - ~ad_level:(expr_ad_lub es) - ~type_:Stan_math_signatures.variadic_ode_return_type ~loc - |> Validate.ok - | Some (expected_args, err) -> - Semantic_error.illtyped_variadic_ode loc id.name - (List.map ~f:type_of_expr_typed es) - expected_args err - |> Validate.error - -let fn_kind_from_application id es = - (* We need to check an application here, rather than a mere name of the - function because, technically, user defined functions can shadow - constants in StanLib. *) - let suffix = Fun_kind.suffix_from_name id.name in - if - Stan_math_signatures.stan_math_returntype id.name - (List.map ~f:(fun x -> (x.emeta.ad_level, x.emeta.type_)) es) - <> None - || Symbol_table.look vm id.name = None - && Stan_math_signatures.is_stan_math_function_name id.name - then StanLib suffix - else UserDefined suffix - -(** Determines the function kind based on the identifier and performs the - corresponding semantic check -*) -let semantic_check_fn ~is_cond_dist ~loc id es = - match fn_kind_from_application id es with - | StanLib FnPlain when Stan_math_signatures.is_reduce_sum_fn id.name -> - semantic_check_reduce_sum ~is_cond_dist ~loc id es - | StanLib FnPlain when Stan_math_signatures.is_variadic_ode_fn id.name -> - semantic_check_variadic_ode ~is_cond_dist ~loc id es - | StanLib _ -> semantic_check_fn_stan_math ~is_cond_dist ~loc id es - | UserDefined _ -> semantic_check_fn_normal ~is_cond_dist ~loc id es - -(* -- Ternary If ------------------------------------------------------------ *) - -let semantic_check_ternary_if loc (pe, te, fe) = - Validate.( - let err = - Semantic_error.illtyped_ternary_if loc pe.emeta.type_ te.emeta.type_ - fe.emeta.type_ - in - if pe.emeta.type_ = UInt then - match UnsizedType.common_type (te.emeta.type_, fe.emeta.type_) with - | Some type_ when not (UnsizedType.is_fun_type type_) -> - mk_typed_expression - ~expr:(TernaryIf (pe, te, fe)) - ~ad_level:(expr_ad_lub [pe; te; fe]) - ~type_ ~loc - |> ok - | Some _ | None -> error err - else error err) - -(* -- Binary (Infix) Operators ---------------------------------------------- *) - -let semantic_check_binop loc op (le, re) = - Validate.( - let err = - Semantic_error.illtyped_binary_op loc op le.emeta.type_ re.emeta.type_ - in - [le; re] |> List.map ~f:arg_type - |> Stan_math_signatures.operator_stan_math_return_type op - |> Option.value_map ~default:(error err) ~f:(function - | ReturnType type_ -> - mk_typed_expression - ~expr:(BinOp (le, op, re)) - ~ad_level:(expr_ad_lub [le; re]) - ~type_ ~loc - |> ok - | Void -> error err )) - -(* -- Prefix Operators ------------------------------------------------------ *) - -let semantic_check_prefixop loc op e = - Validate.( - let err = Semantic_error.illtyped_prefix_op loc op e.emeta.type_ in - Stan_math_signatures.operator_stan_math_return_type op [arg_type e] - |> Option.value_map ~default:(error err) ~f:(function - | ReturnType type_ -> - mk_typed_expression - ~expr:(PrefixOp (op, e)) - ~ad_level:(expr_ad_lub [e]) - ~type_ ~loc - |> ok - | Void -> error err )) - -(* -- Postfix operators ----------------------------------------------------- *) - -let semantic_check_postfixop loc op e = - Validate.( - let err = Semantic_error.illtyped_postfix_op loc op e.emeta.type_ in - Stan_math_signatures.operator_stan_math_return_type op [arg_type e] - |> Option.value_map ~default:(error err) ~f:(function - | ReturnType type_ -> - mk_typed_expression - ~expr:(PostfixOp (e, op)) - ~ad_level:(expr_ad_lub [e]) - ~type_ ~loc - |> ok - | Void -> error err )) - -(* -- Variables ------------------------------------------------------------- *) -let semantic_check_variable cf loc id = - Validate.( - match Symbol_table.look vm (Utils.stdlib_distribution_name id.name) with - | None when not (Stan_math_signatures.is_stan_math_function_name id.name) - -> - Semantic_error.ident_not_in_scope loc id.name |> error - | None -> - mk_typed_expression ~expr:(Variable id) - ~ad_level: - (calculate_autodifftype cf MathLibrary UMathLibraryFunction) - ~type_:UMathLibraryFunction ~loc - |> ok - | Some ((Param | TParam | GQuant), _) when cf.in_toplevel_decl -> - Semantic_error.non_data_variable_size_decl loc |> error - | Some _ - when Utils.is_unnormalized_distribution id.name - && not - ( (cf.in_fun_def && (cf.in_udf_dist_def || cf.in_lp_fun_def)) - || cf.current_block = Model ) -> - Semantic_error.invalid_unnormalized_fn loc |> error - | Some (originblock, UFun (args, rt, FnLpdf _, mem_pattern)) -> - let type_ = - UnsizedType.UFun - (args, rt, Fun_kind.suffix_from_name id.name, mem_pattern) - in - mk_typed_expression ~expr:(Variable id) - ~ad_level:(calculate_autodifftype cf originblock type_) - ~type_ ~loc - |> ok - | Some (originblock, type_) -> - mk_typed_expression ~expr:(Variable id) - ~ad_level:(calculate_autodifftype cf originblock type_) - ~type_ ~loc - |> ok) - -(* -- Conditioned Distribution Application ---------------------------------- *) - -let semantic_check_conddist_name ~loc id = - Validate.( - if - List.exists - ~f:(fun x -> String.is_suffix id.name ~suffix:x) - Utils.conditioning_suffices - then ok () - else Semantic_error.conditional_notation_not_allowed loc |> error) - -(* -- Array Expressions ----------------------------------------------------- *) - -let check_consistent_types ad_level type_ es = - let f state e = - match state with - | Error e -> Error e - | Ok (ad, ty) -> ( - let ad = - if UnsizedType.autodifftype_can_convert e.emeta.ad_level ad then - e.emeta.ad_level - else ad - in - match UnsizedType.common_type (ty, e.emeta.type_) with - | Some ty -> Ok (ad, ty) - | None -> Error (ty, e.emeta) ) - in - List.fold ~init:(Ok (ad_level, type_)) ~f es - -let semantic_check_array_expr ~loc es = - Validate.( - match es with - | [] -> Semantic_error.empty_array loc |> error - | {emeta= {ad_level; type_; _}; _} :: elements -> ( - match check_consistent_types ad_level type_ elements with - | Error (ty, meta) -> - Semantic_error.mismatched_array_types meta.loc ty meta.type_ |> error - | Ok (ad_level, type_) -> - let type_ = UnsizedType.UArray type_ in - mk_typed_expression ~expr:(ArrayExpr es) ~ad_level ~type_ ~loc |> ok - )) - -(* -- Row Vector Expresssion ------------------------------------------------ *) - -let semantic_check_rowvector ~loc es = - Validate.( - match es with - | {emeta= {ad_level; type_= UnsizedType.URowVector; _}; _} :: elements -> ( - match check_consistent_types ad_level URowVector elements with - | Ok (ad_level, _) -> - mk_typed_expression ~expr:(RowVectorExpr es) ~ad_level ~type_:UMatrix - ~loc - |> ok - | Error (_, meta) -> - Semantic_error.invalid_matrix_types meta.loc meta.type_ |> error ) - | _ -> ( - match check_consistent_types DataOnly UReal es with - | Ok (ad_level, _) -> - mk_typed_expression ~expr:(RowVectorExpr es) ~ad_level - ~type_:URowVector ~loc - |> ok - | Error (_, meta) -> - Semantic_error.invalid_row_vector_types meta.loc meta.type_ |> error - )) - -(* -- Indexed Expressions --------------------------------------------------- *) -let tuple2 a b = (a, b) -let tuple3 a b c = (a, b, c) - -let indexing_type idx = - match idx with - | Single {emeta= {type_= UnsizedType.UInt; _}; _} -> `Single - | _ -> `Multi - -let inferred_unsizedtype_of_indexed ~loc ut indices = - let rec aux type_ idcs = - match (type_, idcs) with - | _, [] -> Validate.ok type_ - | UnsizedType.UArray type_, `Single :: tl -> aux type_ tl - | UArray type_, `Multi :: tl -> - aux type_ tl |> Validate.map ~f:(fun t -> UnsizedType.UArray t) - | (UVector | URowVector), [`Single] | UMatrix, [`Single; `Single] -> - Validate.ok UnsizedType.UReal - | (UVector | URowVector | UMatrix), [`Multi] | UMatrix, [`Multi; `Multi] -> - Validate.ok type_ - | UMatrix, ([`Single] | [`Single; `Multi]) -> - Validate.ok UnsizedType.URowVector - | UMatrix, [`Multi; `Single] -> Validate.ok UnsizedType.UVector - | UMatrix, _ :: _ :: _ :: _ - |(UVector | URowVector), _ :: _ :: _ - |(UInt | UReal | UComplex | UFun _ | UMathLibraryFunction), _ :: _ -> - Semantic_error.not_indexable loc ut (List.length indices) - |> Validate.error - in - aux ut (List.map ~f:indexing_type indices) - -let inferred_ad_type_of_indexed at uindices = - UnsizedType.lub_ad_type - ( at - :: List.map - ~f:(function - | All -> UnsizedType.DataOnly - | Single ue1 | Upfrom ue1 | Downfrom ue1 -> - UnsizedType.lub_ad_type [at; ue1.emeta.ad_level] - | Between (ue1, ue2) -> - UnsizedType.lub_ad_type - [at; ue1.emeta.ad_level; ue2.emeta.ad_level]) - uindices ) - -let rec semantic_check_indexed ~loc ~cf e indices = - Validate.( - indices - |> List.map ~f:(semantic_check_index cf) - |> sequence - |> liftA2 tuple2 (semantic_check_expression cf e) - >>= fun (ue, uindices) -> - let at = inferred_ad_type_of_indexed ue.emeta.ad_level uindices in - uindices - |> inferred_unsizedtype_of_indexed ~loc ue.emeta.type_ - |> map ~f:(fun ut -> - mk_typed_expression - ~expr:(Indexed (ue, uindices)) - ~ad_level:at ~type_:ut ~loc )) - -and semantic_check_index cf = function - | All -> Validate.ok All - (* Check that indexes have int (container) type *) - | Single e -> - Validate.( - semantic_check_expression cf e - >>= fun ue -> - if has_int_type ue || has_int_array_type ue then ok @@ Single ue - else - Semantic_error.int_intarray_or_range_expected ue.emeta.loc - ue.emeta.type_ - |> error) - | Upfrom e -> - semantic_check_expression_of_int_type cf e "Range bound" - |> Validate.map ~f:(fun e -> Upfrom e) - | Downfrom e -> - semantic_check_expression_of_int_type cf e "Range bound" - |> Validate.map ~f:(fun e -> Downfrom e) - | Between (e1, e2) -> - let le = semantic_check_expression_of_int_type cf e1 "Range bound" - and ue = semantic_check_expression_of_int_type cf e2 "Range bound" in - Validate.liftA2 (fun l u -> Between (l, u)) le ue - -(* -- Top-level expressions ------------------------------------------------- *) -and semantic_check_expression cf ({emeta; expr} : Ast.untyped_expression) : - Ast.typed_expression Validate.t = - match expr with - | TernaryIf (e1, e2, e3) -> - let pe = semantic_check_expression cf e1 - and te = semantic_check_expression cf e2 - and fe = semantic_check_expression cf e3 in - Validate.(liftA3 tuple3 pe te fe >>= semantic_check_ternary_if emeta.loc) - | BinOp (e1, op, e2) -> - let le = semantic_check_expression cf e1 - and re = semantic_check_expression cf e2 - and warn_int_division (x, y) = - match (x.emeta.type_, y.emeta.type_, op) with - | UInt, UInt, Divide -> - let hint ppf () = - match (x.expr, y.expr) with - | IntNumeral x, _ -> - Fmt.pf ppf "%s.0 / %a" x Pretty_printing.pp_typed_expression - y - | _, Ast.IntNumeral y -> - Fmt.pf ppf "%a / %s.0" Pretty_printing.pp_typed_expression x - y - | _ -> - Fmt.pf ppf "%a * 1.0 / %a" - Pretty_printing.pp_typed_expression x - Pretty_printing.pp_typed_expression y - in - let s = - Fmt.strf - "@[@[Found int division:@]@ @[%a@]@,@[%a@]@ @[%a@]@,@[%a@]@]" - Pretty_printing.pp_expression {expr; emeta} Fmt.text - "Values will be rounded towards zero. If rounding is not \ - desired you can write the division as" - hint () Fmt.text - "If rounding is intended please use the integer division \ - operator %/%." - in - Warnings.pp_warning Fmt.stderr (x.emeta.loc, s) ; - (x, y) - | _ -> (x, y) - in - Validate.( - liftA2 tuple2 le re |> map ~f:warn_int_division - |> apply_const (semantic_check_operator op) - >>= semantic_check_binop emeta.loc op) - | PrefixOp (op, e) -> - Validate.( - semantic_check_expression cf e - |> apply_const (semantic_check_operator op) - >>= semantic_check_prefixop emeta.loc op) - | PostfixOp (e, op) -> - Validate.( - semantic_check_expression cf e - |> apply_const (semantic_check_operator op) - >>= semantic_check_postfixop emeta.loc op) - | Variable id -> - semantic_check_variable cf emeta.loc id - |> Validate.apply_const (semantic_check_identifier id) - | IntNumeral s -> ( - match float_of_string_opt s with - | Some i when i < 2_147_483_648.0 -> - mk_typed_expression ~expr:(IntNumeral s) ~ad_level:DataOnly ~type_:UInt - ~loc:emeta.loc - |> Validate.ok - | _ -> Semantic_error.bad_int_literal emeta.loc |> Validate.error ) - | RealNumeral s -> - mk_typed_expression ~expr:(RealNumeral s) ~ad_level:DataOnly ~type_:UReal - ~loc:emeta.loc - |> Validate.ok - | ImagNumeral s -> - mk_typed_expression ~expr:(ImagNumeral s) ~ad_level:DataOnly - ~type_:UComplex ~loc:emeta.loc - |> Validate.ok - | FunApp ((), id, es) -> - semantic_check_funapp ~is_cond_dist:false id es cf emeta - | CondDistApp ((), id, es) -> - semantic_check_funapp ~is_cond_dist:true id es cf emeta - | GetLP -> - (* Target+= can only be used in model and functions with right suffix (same for tilde etc) *) - if - not - ( cf.in_lp_fun_def || cf.current_block = Model - || cf.current_block = TParam ) - then - Semantic_error.target_plusequals_outisde_model_or_logprob emeta.loc - |> Validate.error - else - mk_typed_expression ~expr:GetLP - ~ad_level:(calculate_autodifftype cf cf.current_block UReal) - ~type_:UReal ~loc:emeta.loc - |> Validate.ok - | GetTarget -> - (* Target+= can only be used in model and functions with right suffix (same for tilde etc) *) - if - not - ( cf.in_lp_fun_def || cf.current_block = Model - || cf.current_block = TParam ) - then - Semantic_error.target_plusequals_outisde_model_or_logprob emeta.loc - |> Validate.error - else - mk_typed_expression ~expr:GetTarget - ~ad_level:(calculate_autodifftype cf cf.current_block UReal) - ~type_:UReal ~loc:emeta.loc - |> Validate.ok - | ArrayExpr es -> - Validate.( - es - |> List.map ~f:(semantic_check_expression cf) - |> sequence - >>= fun ues -> semantic_check_array_expr ~loc:emeta.loc ues) - | RowVectorExpr es -> - Validate.( - es - |> List.map ~f:(semantic_check_expression cf) - |> sequence - >>= semantic_check_rowvector ~loc:emeta.loc) - | Paren e -> - semantic_check_expression cf e - |> Validate.map ~f:(fun ue -> - mk_typed_expression ~expr:(Paren ue) ~ad_level:ue.emeta.ad_level - ~type_:ue.emeta.type_ ~loc:emeta.loc ) - | Indexed (e, indices) -> semantic_check_indexed ~loc:emeta.loc ~cf e indices - -and semantic_check_funapp ~is_cond_dist id es cf emeta = - let name_check = - if is_cond_dist then semantic_check_conddist_name - else semantic_check_fn_conditioning - in - Validate.( - es - |> List.map ~f:(semantic_check_expression cf) - |> sequence - >>= fun ues -> - semantic_check_fn ~is_cond_dist ~loc:emeta.loc id ues - |> apply_const (semantic_check_identifier id) - |> apply_const (name_check ~loc:emeta.loc id) - |> apply_const (semantic_check_fn_target_plus_equals cf ~loc:emeta.loc id) - |> apply_const (semantic_check_fn_rng cf ~loc:emeta.loc id) - |> apply_const (semantic_check_unnormalized cf ~loc:emeta.loc id)) - -and semantic_check_expression_of_int_type cf e name = - Validate.( - semantic_check_expression cf e - >>= fun ue -> - if has_int_type ue then ok ue - else Semantic_error.int_expected ue.emeta.loc name ue.emeta.type_ |> error) - -and semantic_check_expression_of_int_or_real_type cf e name = - Validate.( - semantic_check_expression cf e - >>= fun ue -> - if has_int_or_real_type ue then ok ue - else - Semantic_error.int_or_real_expected ue.emeta.loc name ue.emeta.type_ - |> error) - -let semantic_check_expression_of_scalar_or_type cf t e name = - Validate.( - semantic_check_expression cf e - >>= fun ue -> - if UnsizedType.is_scalar_type ue.emeta.type_ || ue.emeta.type_ = t then - ok ue - else - Semantic_error.scalar_or_type_expected ue.emeta.loc name t ue.emeta.type_ - |> error) - -(* -- Sized Types ----------------------------------------------------------- *) -let rec semantic_check_sizedtype cf = function - | SizedType.SInt -> Validate.ok SizedType.SInt - | SReal -> Validate.ok SizedType.SReal - | SComplex -> Validate.ok SizedType.SComplex - | SVector (mem_pattern, e) -> - semantic_check_expression_of_int_type cf e "Vector sizes" - |> Validate.map ~f:(fun ue -> SizedType.SVector (mem_pattern, ue)) - | SRowVector (mem_pattern, e) -> - semantic_check_expression_of_int_type cf e "Row vector sizes" - |> Validate.map ~f:(fun ue -> SizedType.SRowVector (mem_pattern, ue)) - | SMatrix (mem_pattern, e1, e2) -> - let ue1 = semantic_check_expression_of_int_type cf e1 "Matrix sizes" - and ue2 = semantic_check_expression_of_int_type cf e2 "Matrix sizes" in - Validate.liftA2 - (fun ue1 ue2 -> SizedType.SMatrix (mem_pattern, ue1, ue2)) - ue1 ue2 - | SArray (st, e) -> - let ust = semantic_check_sizedtype cf st - and ue = semantic_check_expression_of_int_type cf e "Array sizes" in - Validate.liftA2 (fun ust ue -> SizedType.SArray (ust, ue)) ust ue - -(* -- Transformations ------------------------------------------------------- *) -let semantic_check_transformation cf ut = function - | Transformation.Identity -> Validate.ok Transformation.Identity - | Lower e -> - semantic_check_expression_of_scalar_or_type cf ut e "Lower bound" - |> Validate.map ~f:(fun ue -> Transformation.Lower ue) - | Upper e -> - semantic_check_expression_of_scalar_or_type cf ut e "Upper bound" - |> Validate.map ~f:(fun ue -> Transformation.Upper ue) - | LowerUpper (e1, e2) -> - let ue1 = - semantic_check_expression_of_scalar_or_type cf ut e1 "Lower bound" - and ue2 = - semantic_check_expression_of_scalar_or_type cf ut e2 "Upper bound" - in - Validate.liftA2 - (fun ue1 ue2 -> Transformation.LowerUpper (ue1, ue2)) - ue1 ue2 - | Offset e -> - semantic_check_expression_of_scalar_or_type cf ut e "Offset" - |> Validate.map ~f:(fun ue -> Transformation.Offset ue) - | Multiplier e -> - semantic_check_expression_of_scalar_or_type cf ut e "Multiplier" - |> Validate.map ~f:(fun ue -> Transformation.Multiplier ue) - | OffsetMultiplier (e1, e2) -> - let ue1 = semantic_check_expression_of_scalar_or_type cf ut e1 "Offset" - and ue2 = - semantic_check_expression_of_scalar_or_type cf ut e2 "Multiplier" - in - Validate.liftA2 - (fun ue1 ue2 -> Transformation.OffsetMultiplier (ue1, ue2)) - ue1 ue2 - | Ordered -> Validate.ok Transformation.Ordered - | PositiveOrdered -> Validate.ok Transformation.PositiveOrdered - | Simplex -> Validate.ok Transformation.Simplex - | UnitVector -> Validate.ok Transformation.UnitVector - | CholeskyCorr -> Validate.ok Transformation.CholeskyCorr - | CholeskyCov -> Validate.ok Transformation.CholeskyCov - | Correlation -> Validate.ok Transformation.Correlation - | Covariance -> Validate.ok Transformation.Covariance - -(* -- Printables ------------------------------------------------------------ *) - -let semantic_check_printable cf = function - | PString s -> Validate.ok @@ PString s - (* Print/reject expressions cannot be of function type. *) - | PExpr e -> ( - Validate.( - semantic_check_expression cf e - >>= fun ue -> - match ue.emeta.type_ with - | UFun _ | UMathLibraryFunction -> - Semantic_error.not_printable ue.emeta.loc |> error - | _ -> ok @@ PExpr ue) ) - -(* -- Truncations ----------------------------------------------------------- *) - -let semantic_check_truncation cf = function - | NoTruncate -> Validate.ok NoTruncate - | TruncateUpFrom e -> - semantic_check_expression_of_int_or_real_type cf e "Truncation bound" - |> Validate.map ~f:(fun ue -> TruncateUpFrom ue) - | TruncateDownFrom e -> - semantic_check_expression_of_int_or_real_type cf e "Truncation bound" - |> Validate.map ~f:(fun ue -> TruncateDownFrom ue) - | TruncateBetween (e1, e2) -> - let ue1 = - semantic_check_expression_of_int_or_real_type cf e1 "Truncation bound" - and ue2 = - semantic_check_expression_of_int_or_real_type cf e2 "Truncation bound" - in - Validate.liftA2 (fun ue1 ue2 -> TruncateBetween (ue1, ue2)) ue1 ue2 - -(* == Statements ============================================================ *) - -(* -- Non-returning function application ------------------------------------ *) - -let semantic_check_nrfn_target ~loc ~cf id = - Validate.( - if - String.is_suffix id.name ~suffix:"_lp" - && not - ( cf.in_lp_fun_def || cf.current_block = Model - || cf.current_block = TParam ) - then Semantic_error.target_plusequals_outisde_model_or_logprob loc |> error - else ok ()) - -let semantic_check_nrfn_normal ~loc id es = - Validate.( - match Symbol_table.look vm id.name with - | Some (_, UFun (listedtypes, Void, suffix, _)) -> ( - match - SignatureMismatch.check_compatible_arguments_mod_conv listedtypes - (get_arg_types es) - with - | None -> - mk_typed_statement - ~stmt:(NRFunApp (UserDefined suffix, id, es)) - ~return_type:NoReturnType ~loc - |> ok - | Some x -> - es - |> List.map ~f:type_of_expr_typed - |> Semantic_error.illtyped_userdefined_fn_app loc id.name listedtypes - Void x - |> error ) - | Some (_, UFun (_, ReturnType _, _, _)) -> - Semantic_error.nonreturning_fn_expected_returning_found loc id.name - |> error - | Some _ -> - Semantic_error.nonreturning_fn_expected_nonfn_found loc id.name - |> error - | None -> - Semantic_error.nonreturning_fn_expected_undeclaredident_found loc - id.name - |> error) - -let semantic_check_nrfn_stan_math ~loc id es = - Validate.( - match - SignatureMismatch.stan_math_returntype id.name (get_arg_types es) - with - | Ok Void -> - mk_typed_statement - ~stmt:(NRFunApp (StanLib FnPlain, id, es)) - ~return_type:NoReturnType ~loc - |> ok - | Ok (ReturnType _) -> - Semantic_error.nonreturning_fn_expected_returning_found loc id.name - |> error - | Error x -> - es - |> List.map ~f:type_of_expr_typed - |> Semantic_error.illtyped_stanlib_fn_app loc id.name x - |> error) - -let semantic_check_nr_fnkind ~loc id es = - match fn_kind_from_application id es with - | StanLib _ -> semantic_check_nrfn_stan_math ~loc id es - | UserDefined _ -> semantic_check_nrfn_normal ~loc id es - -let semantic_check_nr_fn_app ~loc ~cf id es = - Validate.( - es - |> List.map ~f:(semantic_check_expression cf) - |> sequence - |> apply_const (semantic_check_identifier id) - |> apply_const (semantic_check_nrfn_target ~loc ~cf id) - >>= semantic_check_nr_fnkind ~loc id) - -(* -- Assignment ------------------------------------------------------------ *) - -let semantic_check_assignment_read_only ~loc id = - Validate.( - if Symbol_table.get_read_only vm id.name then - Semantic_error.cannot_assign_to_read_only loc id.name |> error - else ok ()) - -(* Variables from previous blocks are read-only. - In particular, data and parameters never assigned to -*) -let semantic_check_assignment_global ~loc ~cf ~block id = - Validate.( - if (not (Symbol_table.is_global vm id.name)) || block = cf.current_block - then ok () - else Semantic_error.cannot_assign_to_global loc id.name |> error) - -let mk_assignment_from_indexed_expr assop lhs rhs = - Assignment - {assign_lhs= Ast.lvalue_of_expr lhs; assign_op= assop; assign_rhs= rhs} - -let semantic_check_assignment_operator ~loc assop lhs rhs = - let op = - match assop with - | Assign | ArrowAssign -> Operator.Equals - | OperatorAssign op -> op - in - Validate.( - let err = - Semantic_error.illtyped_assignment loc op lhs.emeta.type_ rhs.emeta.type_ - in - match assop with - | Assign | ArrowAssign -> - if - UnsizedType.check_of_same_type_mod_array_conv "" lhs.emeta.type_ - rhs.emeta.type_ - then - mk_typed_statement ~return_type:NoReturnType ~loc - ~stmt:(mk_assignment_from_indexed_expr assop lhs rhs) - |> ok - else error err - | OperatorAssign op -> - List.map ~f:arg_type [lhs; rhs] - |> Stan_math_signatures.assignmentoperator_stan_math_return_type op - |> Option.value_map ~default:(error err) ~f:(function - | ReturnType _ -> error err - | Void -> - mk_typed_statement ~return_type:NoReturnType ~loc - ~stmt:(mk_assignment_from_indexed_expr assop lhs rhs) - |> ok )) - -let semantic_check_assignment ~loc ~cf assign_lhs assign_op assign_rhs = - let assign_id = Ast.id_of_lvalue assign_lhs in - let lhs = expr_of_lvalue assign_lhs |> semantic_check_expression cf - and assop = semantic_check_assignmentoperator assign_op - and rhs = semantic_check_expression cf assign_rhs - and block = - Symbol_table.look vm assign_id.name - |> Option.map ~f:(fun (block, _) -> Validate.ok block) - |> Option.value - ~default: - ( if Stan_math_signatures.is_stan_math_function_name assign_id.name - then Validate.ok MathLibrary - else - Validate.error - @@ Semantic_error.ident_not_in_scope loc assign_id.name ) - in - Validate.( - liftA2 tuple2 (liftA3 tuple3 lhs assop rhs) block - >>= fun ((lhs, assop, rhs), block) -> - semantic_check_assignment_operator ~loc assop lhs rhs - |> apply_const (semantic_check_assignment_global ~loc ~cf ~block assign_id) - |> apply_const (semantic_check_assignment_read_only ~loc assign_id)) - -(* -- Target plus-equals / Increment log-prob ------------------------------- *) - -let semantic_check_target_pe_expr_type ~loc e = - match e.emeta.type_ with - | UFun _ | UMathLibraryFunction -> - Semantic_error.int_or_real_container_expected loc e.emeta.type_ - |> Validate.error - | _ -> Validate.ok () - -let semantic_check_target_pe_usage ~loc ~cf = - if cf.in_lp_fun_def || cf.current_block = Model then Validate.ok () - else - Semantic_error.target_plusequals_outisde_model_or_logprob loc - |> Validate.error - -let semantic_check_target_pe ~loc ~cf e = - Validate.( - semantic_check_expression cf e - |> apply_const (semantic_check_target_pe_usage ~loc ~cf) - >>= fun ue -> - semantic_check_target_pe_expr_type ~loc ue - |> map ~f:(fun _ -> - mk_typed_statement ~stmt:(TargetPE ue) ~return_type:NoReturnType - ~loc )) - -let semantic_check_incr_logprob ~loc ~cf e = - Validate.( - semantic_check_expression cf e - |> apply_const (semantic_check_target_pe_usage ~loc ~cf) - >>= fun ue -> - semantic_check_target_pe_expr_type ~loc ue - |> map ~f:(fun _ -> - mk_typed_statement ~stmt:(IncrementLogProb ue) - ~return_type:NoReturnType ~loc )) - -(* -- Tilde (Sampling notation) --------------------------------------------- *) - -let semantic_check_sampling_pdf_pmf id = - Validate.( - if - String.( - is_suffix id.name ~suffix:"_lpdf" - || is_suffix id.name ~suffix:"_lpmf" - || is_suffix id.name ~suffix:"_lupdf" - || is_suffix id.name ~suffix:"_lupmf") - then error @@ Semantic_error.invalid_sampling_pdf_or_pmf id.id_loc - else ok ()) - -let semantic_check_sampling_cdf_ccdf ~loc id = - Validate.( - if - String.( - is_suffix id.name ~suffix:"_cdf" || is_suffix id.name ~suffix:"_ccdf") - then error @@ Semantic_error.invalid_sampling_cdf_or_ccdf loc id.name - else ok ()) - -(* Target+= can only be used in model and functions with right suffix (same for tilde etc) *) -let semantic_check_valid_sampling_pos ~loc ~cf = - Validate.( - if not (cf.in_lp_fun_def || cf.current_block = Model) then - error @@ Semantic_error.target_plusequals_outisde_model_or_logprob loc - else ok ()) - -let semantic_check_sampling_distribution ~loc id arguments = - let name = id.name - and argumenttypes = List.map ~f:arg_type arguments - and is_real_rt = function - | UnsizedType.ReturnType UReal -> true - | _ -> false - in - let is_name_w_suffix_sampling_dist suffix = - Stan_math_signatures.stan_math_returntype (name ^ suffix) argumenttypes - |> Option.value_map ~default:false ~f:is_real_rt - in - let is_sampling_dist_in_math = - List.exists ~f:is_name_w_suffix_sampling_dist - (Utils.distribution_suffices @ Utils.unnormalized_suffices) - && name <> "binomial_coefficient" - && name <> "multiply" - in - let is_name_w_suffix_udf_sampling_dist suffix = - match Symbol_table.look vm (name ^ suffix) with - | Some (Functions, UFun (listedtypes, ReturnType UReal, FnLpdf _, _)) -> - UnsizedType.check_compatible_arguments_mod_conv name listedtypes - argumenttypes - | _ -> false - in - let is_udf_sampling_dist = - List.exists ~f:is_name_w_suffix_udf_sampling_dist - (Utils.distribution_suffices @ Utils.unnormalized_suffices) - in - Validate.( - if is_sampling_dist_in_math || is_udf_sampling_dist then ok () - else error @@ Semantic_error.invalid_sampling_no_such_dist loc name) - -let cumulative_density_is_defined id arguments = - let name = id.name - and argumenttypes = List.map ~f:arg_type arguments - and is_real_rt = function - | UnsizedType.ReturnType UReal -> true - | _ -> false - in - let is_real_rt_for_suffix suffix = - Stan_math_signatures.stan_math_returntype (name ^ suffix) argumenttypes - |> Option.value_map ~default:false ~f:is_real_rt - and valid_arg_types_for_suffix suffix = - match Symbol_table.look vm (name ^ suffix) with - | Some (Functions, UFun (listedtypes, ReturnType UReal, FnPlain, _)) -> - UnsizedType.check_compatible_arguments_mod_conv name listedtypes - argumenttypes - | _ -> false - in - ( is_real_rt_for_suffix "_lcdf" - || valid_arg_types_for_suffix "_lcdf" - || is_real_rt_for_suffix "_cdf_log" - || valid_arg_types_for_suffix "_cdf_log" ) - && ( is_real_rt_for_suffix "_lccdf" - || valid_arg_types_for_suffix "_lccdf" - || is_real_rt_for_suffix "_ccdf_log" - || valid_arg_types_for_suffix "_ccdf_log" ) - -let can_truncate_distribution ~loc (arg : typed_expression) = function - | NoTruncate -> Validate.ok () - | _ -> - if UnsizedType.is_scalar_type arg.emeta.type_ then Validate.ok () - else Validate.error @@ Semantic_error.multivariate_truncation loc - -let semantic_check_sampling_cdf_defined ~loc id truncation args = - Validate.( - match truncation with - | NoTruncate -> ok () - | TruncateUpFrom e when cumulative_density_is_defined id (e :: args) -> - ok () - | TruncateDownFrom e when cumulative_density_is_defined id (e :: args) -> - ok () - | TruncateBetween (e1, e2) - when cumulative_density_is_defined id (e1 :: args) - && cumulative_density_is_defined id (e2 :: args) -> - ok () - | _ -> error @@ Semantic_error.invalid_truncation_cdf_or_ccdf loc) - -let semantic_check_tilde ~loc ~cf distribution truncation arg args = - Validate.( - let ue = semantic_check_expression cf arg - and ues = List.map ~f:(semantic_check_expression cf) args |> sequence - and ut = semantic_check_truncation cf truncation in - liftA3 tuple3 ut ue ues - |> apply_const (semantic_check_identifier distribution) - |> apply_const (semantic_check_sampling_pdf_pmf distribution) - |> apply_const (semantic_check_valid_sampling_pos ~loc ~cf) - |> apply_const (semantic_check_sampling_cdf_ccdf ~loc distribution) - >>= fun (truncation, arg, args) -> - semantic_check_sampling_distribution ~loc distribution (arg :: args) - |> apply_const - (semantic_check_sampling_cdf_defined ~loc distribution truncation args) - |> apply_const (can_truncate_distribution ~loc arg truncation) - |> map ~f:(fun _ -> - let stmt = Tilde {arg; distribution; args; truncation} in - mk_typed_statement ~stmt ~loc ~return_type:NoReturnType )) - -(* -- Break ----------------------------------------------------------------- *) -(* Break and continue only occur in loops. *) -let semantic_check_break ~loc ~cf = - Validate.( - if cf.loop_depth = 0 then Semantic_error.break_outside_loop loc |> error - else mk_typed_statement ~stmt:Break ~return_type:NoReturnType ~loc |> ok) - -(* -- Continue -------------------------------------------------------------- *) - -let semantic_check_continue ~loc ~cf = - Validate.( - (* Break and continue only occur in loops. *) - if cf.loop_depth = 0 then Semantic_error.continue_outside_loop loc |> error - else mk_typed_statement ~stmt:Continue ~return_type:NoReturnType ~loc |> ok) - -(* -- Return ---------------------------------------------------------------- *) - -(** No returns outside of function definitions - In case of void function, no return statements anywhere -*) -let semantic_check_return ~loc ~cf e = - Validate.( - if not cf.in_returning_fun_def then - Semantic_error.expression_return_outside_returning_fn loc |> error - else - semantic_check_expression cf e - |> map ~f:(fun ue -> - mk_typed_statement ~stmt:(Return ue) - ~return_type:(Complete (ReturnType ue.emeta.type_)) ~loc )) - -(* -- Return `void` --------------------------------------------------------- *) - -let semantic_check_returnvoid ~loc ~cf = - Validate.( - if (not cf.in_fun_def) || cf.in_returning_fun_def then - Semantic_error.void_ouside_nonreturning_fn loc |> error - else - mk_typed_statement ~stmt:ReturnVoid ~return_type:(Complete Void) ~loc - |> ok) - -(* -- Print ----------------------------------------------------------------- *) - -let semantic_check_print ~loc ~cf ps = - Validate.( - ps - |> List.map ~f:(semantic_check_printable cf) - |> sequence - |> map ~f:(fun ups -> - mk_typed_statement ~stmt:(Print ups) ~return_type:NoReturnType ~loc - )) - -(* -- Reject ---------------------------------------------------------------- *) - -let semantic_check_reject ~loc ~cf ps = - Validate.( - ps - |> List.map ~f:(semantic_check_printable cf) - |> sequence - |> map ~f:(fun ups -> - mk_typed_statement ~stmt:(Reject ups) ~return_type:AnyReturnType - ~loc )) - -(* -- Skip ------------------------------------------------------------------ *) - -let semantic_check_skip ~loc = - mk_typed_statement ~stmt:Skip ~return_type:NoReturnType ~loc |> Validate.ok - -(* -- If-Then-Else ---------------------------------------------------------- *) - -let try_compute_ifthenelse_statement_returntype loc srt1 srt2 = - match (srt1, srt2) with - | Complete rt1, Complete rt2 -> - lub_rt loc rt1 rt2 |> Validate.map ~f:(fun t -> Complete t) - | Incomplete rt1, Incomplete rt2 - |Complete rt1, Incomplete rt2 - |Incomplete rt1, Complete rt2 -> - lub_rt loc rt1 rt2 |> Validate.map ~f:(fun t -> Incomplete t) - | AnyReturnType, NoReturnType - |NoReturnType, AnyReturnType - |NoReturnType, NoReturnType -> - Validate.ok NoReturnType - | AnyReturnType, Incomplete rt - |Incomplete rt, AnyReturnType - |Complete rt, NoReturnType - |NoReturnType, Complete rt - |NoReturnType, Incomplete rt - |Incomplete rt, NoReturnType -> - Validate.ok @@ Incomplete rt - | Complete rt, AnyReturnType | AnyReturnType, Complete rt -> - Validate.ok @@ Complete rt - | AnyReturnType, AnyReturnType -> Validate.ok AnyReturnType - -let rec semantic_check_if_then_else ~loc ~cf pred_e s_true s_false_opt = - let us1 = semantic_check_statement cf s_true - and uos2 = - s_false_opt - |> Option.map ~f:(fun s -> - semantic_check_statement cf s |> Validate.map ~f:Option.some ) - |> Option.value ~default:(Validate.ok None) - and ue = - semantic_check_expression_of_int_or_real_type cf pred_e - "Condition in conditional" - in - Validate.( - liftA3 tuple3 ue us1 uos2 - >>= fun (ue, us1, uos2) -> - let stmt = IfThenElse (ue, us1, uos2) - and srt1 = us1.smeta.return_type - and srt2 = - uos2 - |> Option.map ~f:(fun s -> s.smeta.return_type) - |> Option.value ~default:NoReturnType - in - try_compute_ifthenelse_statement_returntype loc srt1 srt2 - |> map ~f:(fun return_type -> mk_typed_statement ~stmt ~return_type ~loc)) - -(* -- While Statements ------------------------------------------------------ *) -and semantic_check_while ~loc ~cf e s = - let us = semantic_check_statement {cf with loop_depth= cf.loop_depth + 1} s - and ue = - semantic_check_expression_of_int_or_real_type cf e - "Condition in while-loop" - in - Validate.liftA2 - (fun ue us -> - mk_typed_statement - ~stmt:(While (ue, us)) - ~return_type:us.smeta.return_type ~loc ) - ue us - -(* -- For Statements -------------------------------------------------------- *) -and semantic_check_loop_body ~cf loop_var loop_var_ty loop_body = - Symbol_table.begin_scope vm ; - let is_fresh_var = check_fresh_variable loop_var false in - Symbol_table.enter vm loop_var.name (cf.current_block, loop_var_ty) ; - (* Check that function args and loop identifiers are not modified in - function. (passed by const ref) *) - Symbol_table.set_read_only vm loop_var.name ; - let us = - semantic_check_statement {cf with loop_depth= cf.loop_depth + 1} loop_body - |> Validate.apply_const is_fresh_var - in - Symbol_table.end_scope vm ; us - -and semantic_check_for ~loc ~cf loop_var lower_bound_e upper_bound_e loop_body - = - let ue1 = - semantic_check_expression_of_int_type cf lower_bound_e - "Lower bound of for-loop" - and ue2 = - semantic_check_expression_of_int_type cf upper_bound_e - "Upper bound of for-loop" - in - Validate.( - liftA2 tuple2 ue1 ue2 - |> apply_const (semantic_check_identifier loop_var) - >>= fun (ue1, ue2) -> - semantic_check_loop_body ~cf loop_var UInt loop_body - |> map ~f:(fun us -> - mk_typed_statement - ~stmt: - (For - { loop_variable= loop_var - ; lower_bound= ue1 - ; upper_bound= ue2 - ; loop_body= us }) - ~return_type:us.smeta.return_type ~loc )) - -(* -- Foreach Statements ---------------------------------------------------- *) -and semantic_check_foreach_loop_identifier_type ~loc ty = - Validate.( - match ty with - | UnsizedType.UArray ut -> ok ut - | UVector | URowVector | UMatrix -> ok UnsizedType.UReal - | _ -> - Semantic_error.array_vector_rowvector_matrix_expected loc ty |> error) - -and semantic_check_foreach ~loc ~cf loop_var foreach_expr loop_body = - Validate.( - semantic_check_expression cf foreach_expr - |> apply_const (semantic_check_identifier loop_var) - >>= fun ue -> - semantic_check_foreach_loop_identifier_type ~loc:ue.emeta.loc - ue.emeta.type_ - >>= fun loop_var_ty -> - semantic_check_loop_body ~cf loop_var loop_var_ty loop_body - |> map ~f:(fun us -> - mk_typed_statement - ~stmt:(ForEach (loop_var, ue, us)) - ~return_type:us.smeta.return_type ~loc )) - -(* -- Blocks ---------------------------------------------------------------- *) -and stmt_is_escape {stmt; _} = - match stmt with - | Break | Continue | Reject _ | Return _ | ReturnVoid -> true - | _ -> false - -and list_until_escape xs = - let rec aux accu = function - | next :: next' :: _ when stmt_is_escape next' -> - List.rev (next' :: next :: accu) - | next :: rest -> aux (next :: accu) rest - | [] -> List.rev accu - in - aux [] xs - -and try_compute_block_statement_returntype loc srt1 srt2 = - match (srt1, srt2) with - | Complete rt1, Complete rt2 | Incomplete rt1, Complete rt2 -> - lub_rt loc rt1 rt2 |> Validate.map ~f:(fun t -> Complete t) - | Incomplete rt1, Incomplete rt2 | Complete rt1, Incomplete rt2 -> - lub_rt loc rt1 rt2 |> Validate.map ~f:(fun t -> Incomplete t) - | NoReturnType, NoReturnType -> Validate.ok NoReturnType - | AnyReturnType, Incomplete rt - |Complete rt, NoReturnType - |NoReturnType, Incomplete rt - |Incomplete rt, NoReturnType -> - Validate.ok @@ Incomplete rt - | NoReturnType, Complete rt - |Complete rt, AnyReturnType - |Incomplete rt, AnyReturnType - |AnyReturnType, Complete rt -> - Validate.ok @@ Complete rt - | AnyReturnType, NoReturnType - |NoReturnType, AnyReturnType - |AnyReturnType, AnyReturnType -> - Validate.ok AnyReturnType - -and semantic_check_block ~loc ~cf stmts = - Symbol_table.begin_scope vm ; - (* Any statements after a break or continue or return or reject - do not count for the return type. - *) - let validated_stmts = - List.map ~f:(semantic_check_statement cf) stmts |> Validate.sequence - in - Symbol_table.end_scope vm ; - Validate.( - validated_stmts - >>= fun xs -> - let return_ty = - xs |> list_until_escape - |> List.map ~f:(fun s -> s.smeta.return_type) - |> List.fold ~init:(ok NoReturnType) ~f:(fun accu x -> - accu >>= fun y -> try_compute_block_statement_returntype loc y x - ) - in - map return_ty ~f:(fun return_type -> - mk_typed_statement ~stmt:(Block xs) ~return_type ~loc )) - -and semantic_check_profile ~loc ~cf name stmts = - Symbol_table.begin_scope vm ; - (* Any statements after a break or continue or return or reject - do not count for the return type. - *) - let validated_stmts = - List.map ~f:(semantic_check_statement cf) stmts |> Validate.sequence - in - Symbol_table.end_scope vm ; - Validate.( - validated_stmts - >>= fun xs -> - let return_ty = - xs |> list_until_escape - |> List.map ~f:(fun s -> s.smeta.return_type) - |> List.fold ~init:(ok NoReturnType) ~f:(fun accu x -> - accu >>= fun y -> try_compute_block_statement_returntype loc y x - ) - in - map return_ty ~f:(fun return_type -> - mk_typed_statement ~stmt:(Profile (name, xs)) ~return_type ~loc )) - -(* -- Variable Declarations ------------------------------------------------- *) -and semantic_check_var_decl_bounds ~loc is_global sized_ty trans = - let is_real {emeta; _} = emeta.type_ = UReal in - let is_real_transformation = - match trans with - | Transformation.Lower e -> is_real e - | Upper e -> is_real e - | LowerUpper (e1, e2) -> is_real e1 || is_real e2 - | _ -> false - in - let is_transformation = - match trans with Transformation.Identity -> false | _ -> true - in - Validate.( - if is_global && sized_ty = SizedType.SInt && is_real_transformation then - Semantic_error.non_int_bounds loc |> error - else if - is_global - && SizedType.(inner_type sized_ty = SComplex) - && is_transformation - then Semantic_error.complex_transform loc |> error - else ok ()) - -and semantic_check_transformed_param_ty ~loc ~cf is_global unsized_ty = - Validate.( - if - is_global - && (cf.current_block = Param || cf.current_block = TParam) - && UnsizedType.contains_int unsized_ty - then Semantic_error.transformed_params_int loc |> error - else ok ()) - -and semantic_check_var_decl_initial_value ~loc ~cf id init_val_opt = - init_val_opt - |> Option.value_map ~default:(Validate.ok None) ~f:(fun e -> - let stmt = - Assignment - { assign_lhs= {lval= LVariable id; lmeta= {loc}} - ; assign_op= Assign - ; assign_rhs= e } - in - mk_untyped_statement ~loc ~stmt - |> semantic_check_statement cf - |> Validate.map ~f:(fun ts -> - match (ts.stmt, ts.smeta.return_type) with - | Assignment {assign_rhs= ue; _}, NoReturnType -> Some ue - | _ -> - let msg = - "semantic_check_var_decl: `Assignment` expected." - in - fatal_error ~msg () ) ) - -and semantic_check_var_decl ~loc ~cf sized_ty trans id init is_global = - let checked_stmt = - semantic_check_sizedtype {cf with in_toplevel_decl= is_global} sized_ty - in - Validate.( - let checked_trans = - checked_stmt - >>= fun ust -> - semantic_check_transformation cf (SizedType.to_unsized ust) trans - in - liftA2 tuple2 checked_stmt checked_trans - |> apply_const (semantic_check_identifier id) - |> apply_const (check_fresh_variable id false) - >>= fun (ust, utrans) -> - let ut = SizedType.to_unsized ust in - Symbol_table.enter vm id.name (cf.current_block, ut) ; - semantic_check_var_decl_initial_value ~loc ~cf id init - |> apply_const (semantic_check_var_decl_bounds ~loc is_global ust utrans) - |> apply_const (semantic_check_transformed_param_ty ~loc ~cf is_global ut) - |> map ~f:(fun uinit -> - let stmt = - VarDecl - { decl_type= Sized ust - ; transformation= utrans - ; identifier= id - ; initial_value= uinit - ; is_global } - in - mk_typed_statement ~stmt ~loc ~return_type:NoReturnType )) - -(* -- Function definitions -------------------------------------------------- *) -and semantic_check_fundef_overloaded ~loc id arg_tys rt = - Validate.( - (* User defined functions cannot be overloaded *) - if Symbol_table.check_is_unassigned vm id.name then - match Symbol_table.look vm id.name with - | Some (Functions, UFun (arg_tys', rt', _, _)) - when arg_tys' = arg_tys && rt' = rt -> - ok () - | _ -> - Symbol_table.look vm id.name - |> Option.map ~f:snd - |> Semantic_error.mismatched_fn_def_decl loc id.name - |> error - else check_fresh_variable id true) - -(** WARNING: side effecting *) -and semantic_check_fundef_decl ~loc id body = - Validate.( - match body with - | {stmt= Skip; _} -> - if Symbol_table.check_is_unassigned vm id.name then - error @@ Semantic_error.fn_decl_without_def loc - else - let () = Symbol_table.set_is_unassigned vm id.name in - ok () - | _ -> - Symbol_table.set_is_assigned vm id.name ; - ok ()) - -and semantic_check_fundef_dist_rt ~loc id return_ty = - Validate.( - let is_dist = - List.exists - ~f:(fun x -> String.is_suffix id.name ~suffix:x) - Utils.conditioning_suffices_w_log - in - if is_dist then - match return_ty with - | UnsizedType.ReturnType UReal -> ok () - | _ -> error @@ Semantic_error.non_real_prob_fn_def loc - else ok ()) - -and semantic_check_pdf_fundef_first_arg_ty ~loc id arg_tys = - Validate.( - (* TODO: I think these kind of functions belong with the type definition *) - let is_real_type = function - | UnsizedType.UReal | UVector | URowVector | UMatrix - |UArray UReal - |UArray UVector - |UArray URowVector - |UArray UMatrix -> - true - | _ -> false - in - if String.is_suffix id.name ~suffix:"_lpdf" then - List.hd arg_tys - |> Option.value_map - ~default: - (error @@ Semantic_error.prob_density_non_real_variate loc None) - ~f:(fun (_, rt) -> - if is_real_type rt then ok () - else - error - @@ Semantic_error.prob_density_non_real_variate loc (Some rt) ) - else ok ()) - -and semantic_check_pmf_fundef_first_arg_ty ~loc id arg_tys = - Validate.( - (* TODO: I think these kind of functions belong with the type definition *) - let is_int_type = function - | UnsizedType.UInt | UArray UInt -> true - | _ -> false - in - if String.is_suffix id.name ~suffix:"_lpmf" then - List.hd arg_tys - |> Option.value_map - ~default:(error @@ Semantic_error.prob_mass_non_int_variate loc None) - ~f:(fun (_, rt) -> - if is_int_type rt then ok () - else - error @@ Semantic_error.prob_mass_non_int_variate loc (Some rt) - ) - else ok ()) - -(* All function arguments are distinct *) -and semantic_check_fundef_distinct_arg_ids ~loc arg_names = - Validate.( - if dup_exists arg_names then - error @@ Semantic_error.duplicate_arg_names loc - else ok ()) - -(* Check that every trace through function body contains return statement of right type *) -and semantic_check_fundef_return_tys ~loc id return_type body = - Validate.( - if - Symbol_table.check_is_unassigned vm id.name - || check_of_compatible_return_type return_type body.smeta.return_type - then ok () - else error @@ Semantic_error.incompatible_return_types loc) - -and semantic_check_fundef ~loc ~cf return_ty id args body = - let uargs = - List.map args ~f:(fun (at, ut, id) -> - Validate.( - semantic_check_autodifftype at - |> apply_const (semantic_check_unsizedtype ut) - |> apply_const (semantic_check_identifier id) - |> map ~f:(fun at -> (at, ut, id))) ) - |> Validate.sequence - in - Validate.( - uargs - |> apply_const (semantic_check_identifier id) - |> apply_const (semantic_check_returntype return_ty) - >>= fun uargs -> - let urt = return_ty in - let uarg_types = List.map ~f:(fun (w, y, _) -> (w, y)) uargs in - let uarg_identifiers = List.map ~f:(fun (_, _, z) -> z) uargs in - let uarg_names = List.map ~f:(fun x -> x.name) uarg_identifiers in - semantic_check_fundef_overloaded ~loc id uarg_types urt - |> apply_const (semantic_check_fundef_decl ~loc id body) - >>= fun _ -> - (* WARNING: SIDE EFFECTING *) - Symbol_table.enter vm id.name - ( Functions - , UFun (uarg_types, urt, Fun_kind.suffix_from_name id.name, AoS) ) ; - (* Check that function args and loop identifiers are not modified in - function. (passed by const ref)*) - List.iter ~f:(Symbol_table.set_read_only vm) uarg_names ; - semantic_check_fundef_dist_rt ~loc id urt - |> apply_const (semantic_check_pdf_fundef_first_arg_ty ~loc id uarg_types) - |> apply_const (semantic_check_pmf_fundef_first_arg_ty ~loc id uarg_types) - >>= fun _ -> - (* WARNING: SIDE EFFECTING *) - Symbol_table.begin_scope vm ; - List.map ~f:(fun x -> check_fresh_variable x false) uarg_identifiers - |> sequence - |> apply_const (semantic_check_fundef_distinct_arg_ids ~loc uarg_names) - >>= fun _ -> - (* TODO: Bob was suggesting that function arguments must be allowed to - shadow user defined functions but not library functions. - Should we allow for that? - *) - (* We treat DataOnly arguments as if they are data and AutoDiffable arguments - as if they are parameters, for the purposes of type checking. - *) - (* WARNING: SIDE EFFECTING *) - let _ : unit Base.List.Or_unequal_lengths.t = - List.iter2 ~f:(Symbol_table.enter vm) uarg_names - (List.map - ~f:(function - | UnsizedType.DataOnly, ut -> (Data, ut) - | AutoDiffable, ut -> (Param, ut)) - uarg_types) - and context = - let is_udf_dist name = - List.exists - ~f:(fun suffix -> String.is_suffix name ~suffix) - Utils.distribution_suffices - in - { cf with - in_fun_def= true - ; in_rng_fun_def= String.is_suffix id.name ~suffix:"_rng" - ; in_lp_fun_def= String.is_suffix id.name ~suffix:"_lp" - ; in_udf_dist_def= is_udf_dist id.name - ; in_returning_fun_def= urt <> Void } - in - let body' = semantic_check_statement context body in - body' - >>= fun ub -> - semantic_check_fundef_return_tys ~loc id urt ub - |> map ~f:(fun _ -> - (* WARNING: SIDE EFFECTING *) - Symbol_table.end_scope vm ; - let stmt = - FunDef {returntype= urt; funname= id; arguments= uargs; body= ub} - in - mk_typed_statement ~return_type:NoReturnType ~loc ~stmt )) - -(* -- Top-level Statements -------------------------------------------------- *) -and semantic_check_statement cf (s : Ast.untyped_statement) : - Ast.typed_statement Validate.t = - let loc = s.smeta.loc in - match s.stmt with - | NRFunApp (_, id, es) -> semantic_check_nr_fn_app ~loc ~cf id es - | Assignment {assign_lhs; assign_op; assign_rhs} -> - semantic_check_assignment ~loc ~cf assign_lhs assign_op assign_rhs - | TargetPE e -> semantic_check_target_pe ~loc ~cf e - | IncrementLogProb e -> semantic_check_incr_logprob ~loc ~cf e - | Tilde {arg; distribution; args; truncation} -> - semantic_check_tilde ~loc ~cf distribution truncation arg args - | Break -> semantic_check_break ~loc ~cf - | Continue -> semantic_check_continue ~loc ~cf - | Return e -> semantic_check_return ~loc ~cf e - | ReturnVoid -> semantic_check_returnvoid ~loc ~cf - | Print ps -> semantic_check_print ~loc ~cf ps - | Reject ps -> semantic_check_reject ~loc ~cf ps - | Skip -> semantic_check_skip ~loc - | IfThenElse (e, s1, os2) -> semantic_check_if_then_else ~loc ~cf e s1 os2 - | While (e, s) -> semantic_check_while ~loc ~cf e s - | For {loop_variable; lower_bound; upper_bound; loop_body} -> - semantic_check_for ~loc ~cf loop_variable lower_bound upper_bound - loop_body - | ForEach (id, e, s) -> semantic_check_foreach ~loc ~cf id e s - | Block vdsl -> semantic_check_block ~loc ~cf vdsl - | Profile (name, vdsl) -> semantic_check_profile ~loc ~cf name vdsl - | VarDecl {decl_type= Unsized _; _} -> - raise_s [%message "Don't support unsized declarations yet."] - | VarDecl - { decl_type= Sized st - ; transformation - ; identifier - ; initial_value - ; is_global } -> - semantic_check_var_decl ~loc ~cf st transformation identifier - initial_value is_global - | FunDef {returntype; funname; arguments; body} -> - semantic_check_fundef ~loc ~cf returntype funname arguments body - -(* == Untyped programs ====================================================== *) - -let semantic_check_ostatements_in_block ~cf block stmts_opt = - let cf' = {cf with current_block= block} in - Option.value_map stmts_opt ~default:(Validate.ok None) - ~f:(fun {stmts; xloc} -> - (* I'm folding since I'm not sure if map is guaranteed to - respect the ordering of the list *) - List.fold ~init:[] stmts ~f:(fun accu stmt -> - let s = semantic_check_statement cf' stmt in - s :: accu ) - |> List.rev |> Validate.sequence - |> Validate.map ~f:(fun stmts -> Some {stmts; xloc}) ) - -let check_fun_def_body_in_block = function - | {stmt= FunDef {body= {stmt= Block _; _}; _}; _} - |{stmt= FunDef {body= {stmt= Skip; _}; _}; _} -> - Validate.ok () - | {stmt= FunDef {body= {stmt= _; smeta}; _}; _} -> - Validate.error @@ Semantic_error.fn_decl_needs_block smeta.loc - | _ -> Validate.ok () - -let semantic_check_functions_have_defn function_block_stmts_opt = - Validate.( - if - Symbol_table.check_some_id_is_unassigned vm - && !check_that_all_functions_have_definition - then - match function_block_stmts_opt with - | Some {stmts= {smeta; _} :: _; _} -> - (* TODO: insert better location in the error *) - error @@ Semantic_error.fn_decl_without_def smeta.loc - | Some {stmts= []; _} | None -> - fatal_error ~msg:"semantic_check_functions_have_defn" () - else - match function_block_stmts_opt with - | Some {stmts= []; _} | None -> ok () - | Some {stmts= ls; _} -> - List.map ~f:check_fun_def_body_in_block ls - |> sequence - |> map ~f:(List.iter ~f:Fn.id)) - -(* The actual semantic checks for all AST nodes! *) -let semantic_check_program - ( { functionblock= fb - ; datablock= db - ; transformeddatablock= tdb - ; parametersblock= pb - ; transformedparametersblock= tpb - ; modelblock= mb - ; generatedquantitiesblock= gb - ; comments } as ast ) = - (* NB: We always want to make sure we start with an empty symbol table, in - case we are processing multiple files in one run. *) - unsafe_clear_symbol_table vm ; - let cf = - { current_block= Functions - ; in_toplevel_decl= false - ; in_fun_def= false - ; in_returning_fun_def= false - ; in_rng_fun_def= false - ; in_lp_fun_def= false - ; in_udf_dist_def= false - ; loop_depth= 0 } - in - let ufb = - Validate.( - semantic_check_ostatements_in_block ~cf Functions fb - >>= fun xs -> - semantic_check_functions_have_defn xs |> map ~f:(fun () -> xs)) - in - let udb = semantic_check_ostatements_in_block ~cf Data db in - let utdb = semantic_check_ostatements_in_block ~cf TData tdb in - let upb = semantic_check_ostatements_in_block ~cf Param pb in - let utpb = semantic_check_ostatements_in_block ~cf TParam tpb in - (* Model top level variables only assigned and read in model *) - Symbol_table.begin_scope vm ; - let umb = semantic_check_ostatements_in_block ~cf Model mb in - Symbol_table.end_scope vm ; - let ugb = semantic_check_ostatements_in_block ~cf GQuant gb in - let mk_typed_prog ufb udb utdb upb utpb umb ugb : Ast.typed_program = - { functionblock= ufb - ; datablock= udb - ; transformeddatablock= utdb - ; parametersblock= upb - ; transformedparametersblock= utpb - ; modelblock= umb - ; generatedquantitiesblock= ugb - ; comments } - in - let apply_to x f = Validate.apply ~f x in - let check_correctness_invariant (decorated_ast : typed_program) : - typed_program = - if - compare_untyped_program ast - (untyped_program_of_typed_program decorated_ast) - = 0 - then decorated_ast - else - raise_s - [%message - "Type checked AST does not match original AST. Please file a bug!" - (decorated_ast : typed_program)] - in - let check_correctness_invariant_validate = - Validate.map ~f:check_correctness_invariant - in - Validate.( - ok mk_typed_prog |> apply_to ufb |> apply_to udb |> apply_to utdb - |> apply_to upb |> apply_to utpb |> apply_to umb |> apply_to ugb - |> check_correctness_invariant_validate - |> get_with - ~with_ok:(fun ok -> Result.Ok ok) - ~with_errors:(fun errs -> Result.Error errs)) diff --git a/src/frontend/Semantic_check.mli b/src/frontend/Semantic_check.mli deleted file mode 100644 index 56e1d1e8bc..0000000000 --- a/src/frontend/Semantic_check.mli +++ /dev/null @@ -1,15 +0,0 @@ -(** Semantic validation of AST*) - -open Core_kernel - -val semantic_check_program : - Ast.untyped_program - -> (Ast.typed_program, Middle.Semantic_error.t list) result -(** Performs semantic check on AST and returns original AST embellished with type decorations *) - -val check_that_all_functions_have_definition : bool ref -(** A switch to determine whether we check that all functions have a definition *) - -val model_name : string ref -(** A reference to hold the model name. Relevant for checking variable - clashes and used in code generation. *) diff --git a/src/middle/Semantic_error.ml b/src/frontend/Semantic_error.ml similarity index 96% rename from src/middle/Semantic_error.ml rename to src/frontend/Semantic_error.ml index 00a25b24a3..68a7cfd48f 100644 --- a/src/middle/Semantic_error.ml +++ b/src/frontend/Semantic_error.ml @@ -1,4 +1,5 @@ open Core_kernel +open Middle (** Type errors that may arise during semantic check *) module TypeError = struct @@ -36,16 +37,10 @@ module TypeError = struct | NonReturningFnExpectedReturningFound of string | NonReturningFnExpectedNonFnFound of string | NonReturningFnExpectedUndeclaredIdentFound of string - | IllTypedStanLibFunctionApp of + | IllTypedFunctionApp of string * UnsizedType.t list * (SignatureMismatch.signature_error list * bool) - | IllTypedUserDefinedFunctionApp of - string - * (UnsizedType.autodifftype * UnsizedType.t) list - * UnsizedType.returntype - * UnsizedType.t list - * SignatureMismatch.function_mismatch | IllTypedBinaryOperator of Operator.t * UnsizedType.t * UnsizedType.t | IllTypedPrefixOperator of Operator.t * UnsizedType.t | IllTypedPostfixOperator of Operator.t * UnsizedType.t @@ -173,12 +168,8 @@ module TypeError = struct "A non-returning function was expected but an undeclared identifier \ '%s' was supplied." fn_name - | IllTypedStanLibFunctionApp (name, arg_tys, errors) -> + | IllTypedFunctionApp (name, arg_tys, errors) -> SignatureMismatch.pp_signature_mismatch ppf (name, arg_tys, errors) - | IllTypedUserDefinedFunctionApp - (name, listed_tys, return_ty, arg_tys, error) -> - SignatureMismatch.pp_signature_mismatch ppf - (name, arg_tys, ([((return_ty, listed_tys), error)], false)) | IllTypedBinaryOperator (op, lt, rt) -> Fmt.pf ppf "Ill-typed arguments supplied to infix operator %a. Available \ @@ -505,15 +496,8 @@ let nonreturning_fn_expected_nonfn_found loc name = let nonreturning_fn_expected_undeclaredident_found loc name = TypeError (loc, TypeError.NonReturningFnExpectedUndeclaredIdentFound name) -let illtyped_stanlib_fn_app loc name errors arg_tys = - TypeError (loc, TypeError.IllTypedStanLibFunctionApp (name, arg_tys, errors)) - -let illtyped_userdefined_fn_app loc name decl_arg_tys decl_return_ty error - arg_tys = - TypeError - ( loc - , TypeError.IllTypedUserDefinedFunctionApp - (name, decl_arg_tys, decl_return_ty, arg_tys, error) ) +let illtyped_fn_app loc name errors arg_tys = + TypeError (loc, TypeError.IllTypedFunctionApp (name, arg_tys, errors)) let illtyped_binary_op loc op lt rt = TypeError (loc, TypeError.IllTypedBinaryOperator (op, lt, rt)) diff --git a/src/middle/Semantic_error.mli b/src/frontend/Semantic_error.mli similarity index 95% rename from src/middle/Semantic_error.mli rename to src/frontend/Semantic_error.mli index b6b798818e..b264c61ff5 100644 --- a/src/middle/Semantic_error.mli +++ b/src/frontend/Semantic_error.mli @@ -1,3 +1,5 @@ +open Middle + type t val pp : Format.formatter -> t -> unit @@ -64,22 +66,13 @@ val nonreturning_fn_expected_nonfn_found : Location_span.t -> string -> t val nonreturning_fn_expected_undeclaredident_found : Location_span.t -> string -> t -val illtyped_stanlib_fn_app : +val illtyped_fn_app : Location_span.t -> string -> SignatureMismatch.signature_error list * bool -> UnsizedType.t list -> t -val illtyped_userdefined_fn_app : - Location_span.t - -> string - -> (UnsizedType.autodifftype * UnsizedType.t) list - -> UnsizedType.returntype - -> SignatureMismatch.function_mismatch - -> UnsizedType.t list - -> t - val illtyped_binary_op : Location_span.t -> Operator.t -> UnsizedType.t -> UnsizedType.t -> t diff --git a/src/middle/SignatureMismatch.ml b/src/frontend/SignatureMismatch.ml similarity index 95% rename from src/middle/SignatureMismatch.ml rename to src/frontend/SignatureMismatch.ml index 96f6878100..059aad37eb 100644 --- a/src/middle/SignatureMismatch.ml +++ b/src/frontend/SignatureMismatch.ml @@ -1,4 +1,5 @@ open Core_kernel +open Middle module TypeMap = Core_kernel.Map.Make_using_comparator (UnsizedType) let set ctx key data = ctx := TypeMap.set !ctx ~key ~data @@ -148,17 +149,27 @@ and check_compatible_arguments depth args1 args2 = let check_compatible_arguments_mod_conv = check_compatible_arguments 0 let max_n_errors = 5 -let stan_math_returntype name args = +let extract_function_types f = + let open Environment in + match f with + | {type_= UFun (args, return, _, mem); kind= `StanMath} -> + Some (return, args, (fun x -> Ast.StanLib x), mem) + | {type_= UFun (args, return, _, mem); _} -> + Some (return, args, (fun x -> UserDefined x), mem) + | _ -> None + +let returntype env name args = (* NB: Variadic arguments are special-cased in Semantic_check and not handled here *) let name = Utils.stdlib_distribution_name name in - Hashtbl.find_multi Stan_math_signatures.stan_math_signatures name - |> List.sort ~compare:(fun (x, _, _) (y, _, _) -> + Environment.find env name + |> List.filter_map ~f:extract_function_types + |> List.sort ~compare:(fun (x, _, _, _) (y, _, _, _) -> UnsizedType.compare_returntype x y ) (* Check the least return type first in case there are multiple options (due to implicit UInt-UReal conversion), where UInt List.fold_until ~init:[] - ~f:(fun errors (rt, tys, _) -> + ~f:(fun errors (rt, tys, funkind_constructor, _) -> match check_compatible_arguments 0 tys args with - | None -> Stop (Ok rt) + | None -> Stop (Ok (rt, funkind_constructor)) | Some e -> Continue (((rt, tys), e) :: errors) ) ~finish:(fun errors -> let errors = diff --git a/src/middle/SignatureMismatch.mli b/src/frontend/SignatureMismatch.mli similarity index 88% rename from src/middle/SignatureMismatch.mli rename to src/frontend/SignatureMismatch.mli index 3f4a5aa372..e2a7b1ffb5 100644 --- a/src/middle/SignatureMismatch.mli +++ b/src/frontend/SignatureMismatch.mli @@ -1,4 +1,5 @@ open Core_kernel +open Middle type type_mismatch = | DataOnlyError @@ -23,10 +24,13 @@ val check_compatible_arguments_mod_conv : -> (UnsizedType.autodifftype * UnsizedType.t) list -> function_mismatch option -val stan_math_returntype : - string +val returntype : + Environment.t + -> string -> (UnsizedType.autodifftype * UnsizedType.t) list - -> (UnsizedType.returntype, signature_error list * bool) result + -> ( UnsizedType.returntype * (bool Middle.Fun_kind.suffix -> Ast.fun_kind) + , signature_error list * bool ) + result val check_variadic_args : bool diff --git a/src/frontend/Symbol_table.ml b/src/frontend/Symbol_table.ml deleted file mode 100644 index a6d975ae21..0000000000 --- a/src/frontend/Symbol_table.ml +++ /dev/null @@ -1,79 +0,0 @@ -(** Symbol table to implement var map *) - -open Core_kernel - -(* TODO: I'm sure this implementation could be made more efficient if that's necessary. There's no need for all the string comparison. -We could just keep track of the count of the entry into the hash table and use that for comparison. *) -type 'a state = - { table: (string, 'a) Hashtbl.t - ; stack: string Stack.t - ; scopedepth: int ref - ; readonly: (string, unit) Hashtbl.t - ; isunassigned: (string, unit) Hashtbl.t - ; globals: (string, unit) Hashtbl.t } - -let initialize () = - { table= String.Table.create () - ; stack= Stack.create () - ; scopedepth= ref 0 - ; readonly= String.Table.create () - ; isunassigned= String.Table.create () - ; globals= String.Table.create () } - -let enter s str ty = - let _ : [`Duplicate | `Ok] = - if !(s.scopedepth) = 0 then Hashtbl.add s.globals ~key:str ~data:() - else `Ok - in - let _ : [`Duplicate | `Ok] = Hashtbl.add s.table ~key:str ~data:ty in - Stack.push s.stack str - -let look s str = Hashtbl.find s.table str - -let begin_scope s = - s.scopedepth := !(s.scopedepth) + 1 ; - Stack.push s.stack "-sentinel-new-scope-" - -(* using a string "-sentinel-new-scope-" here that can never be used as an identifier to indicate that new scope is entered *) -let end_scope s = - s.scopedepth := !(s.scopedepth) - 1 ; - while Stack.top_exn s.stack <> "-sentinel-new-scope-" do - (* we pop the stack down to where we entered the current scope and remove all variables defined since from the var map *) - Hashtbl.remove s.table (Stack.top_exn s.stack) ; - Hashtbl.remove s.readonly (Stack.top_exn s.stack) ; - Hashtbl.remove s.isunassigned (Stack.top_exn s.stack) ; - let _ : string = Stack.pop_exn s.stack in - () - done ; - let _ : string = Stack.pop_exn s.stack in - () - -let set_read_only s str = - let _ : [`Duplicate | `Ok] = Hashtbl.add s.readonly ~key:str ~data:() in - () - -let get_read_only s str = - match Hashtbl.find s.readonly str with Some () -> true | _ -> false - -let set_is_assigned s str = Hashtbl.remove s.isunassigned str - -let set_is_unassigned s str = - let _ : [`Duplicate | `Ok] = - if Hashtbl.mem s.isunassigned str then `Ok - else Hashtbl.add s.isunassigned ~key:str ~data:() - in - () - -let check_is_unassigned s str = Hashtbl.mem s.isunassigned str -let check_some_id_is_unassigned s = not (Hashtbl.length s.isunassigned = 0) - -let is_global s str = - match Hashtbl.find s.globals str with Some _ -> true | _ -> false - -let unsafe_clear_symbol_table s = - Hashtbl.clear s.table ; - Stack.clear s.stack ; - s.scopedepth := 0 ; - Hashtbl.clear s.readonly ; - Hashtbl.clear s.isunassigned ; - Hashtbl.clear s.globals diff --git a/src/frontend/Symbol_table.mli b/src/frontend/Symbol_table.mli deleted file mode 100644 index 60dae7583a..0000000000 --- a/src/frontend/Symbol_table.mli +++ /dev/null @@ -1,43 +0,0 @@ -(** Symbol table interface to implement var map *) - -type 'a state - -val initialize : unit -> 'a state -(** Creates a new symbol table *) - -val enter : 'a state -> string -> 'a -> unit -(** Enters a specified identifier with its specified type (or other) information - into a symbol table *) - -val look : 'a state -> string -> 'a option -(** Looks for an identifier in a symbol table and returns its information if found and None otherwise *) - -val begin_scope : 'a state -> unit -(** Used to start a new local scope which symbols added from now will end up in *) - -val end_scope : 'a state -> unit -(** Used to end a local scope, purging the symbol table of all symbols added in that scope *) - -val set_read_only : 'a state -> string -> unit -(** Used to add a read only label to an identifier *) - -val get_read_only : 'a state -> string -> bool -(** Used to check for a read only label for an identifier *) - -val set_is_assigned : 'a state -> string -> unit -(** Label an identifier as having been assigned to *) - -val set_is_unassigned : 'a state -> string -> unit -(** Label an identifier as not having been assigned to *) - -val check_is_unassigned : 'a state -> string -> bool -(** Check whether an identifier is labelled as unassigned *) - -val check_some_id_is_unassigned : 'a state -> bool -(** Used to check whether some identifier is labelled as unassigned *) - -val is_global : 'a state -> string -> bool -(** Used to check whether an identifier was declared in global scope *) - -val unsafe_clear_symbol_table : 'a state -> unit -(** Used to clear the whole symbol table *) diff --git a/src/frontend/Typechecker.ml b/src/frontend/Typechecker.ml index 2bb5a4319d..3848271f8a 100644 --- a/src/frontend/Typechecker.ml +++ b/src/frontend/Typechecker.ml @@ -411,7 +411,7 @@ let check_fn ~is_cond_dist loc tenv id es = Semantic_error.returning_fn_expected_undeclaredident_found loc id.name |> error | _ (* a function *) -> ( - match Env.returntype tenv id.name (get_arg_types es) with + match SignatureMismatch.returntype tenv id.name (get_arg_types es) with | Ok (Void, _) -> Semantic_error.returning_fn_expected_nonreturning_found loc id.name |> error @@ -424,7 +424,7 @@ let check_fn ~is_cond_dist loc tenv id es = | Error x -> es |> List.map ~f:(fun e -> e.emeta.type_) - |> Semantic_error.illtyped_stanlib_fn_app loc id.name x + |> Semantic_error.illtyped_fn_app loc id.name x |> error ) let check_reduce_sum ~is_cond_dist loc id es = @@ -687,7 +687,7 @@ let check_nrfn loc tenv id es = Semantic_error.nonreturning_fn_expected_undeclaredident_found loc id.name |> error | _ (* a function *) -> ( - match Env.returntype tenv id.name (get_arg_types es) with + match SignatureMismatch.returntype tenv id.name (get_arg_types es) with | Ok (Void, fnk) -> mk_typed_statement ~stmt:(NRFunApp (fnk (Fun_kind.suffix_from_name id.name), id, es)) @@ -698,8 +698,7 @@ let check_nrfn loc tenv id es = | Error x -> es |> List.map ~f:type_of_expr_typed - (* todo rename this to just illtyped_fn_app *) - |> Semantic_error.illtyped_stanlib_fn_app loc id.name x + |> Semantic_error.illtyped_fn_app loc id.name x |> error ) let check_nr_fn_app loc cf tenv id es = diff --git a/src/frontend/Typechecker.mli b/src/frontend/Typechecker.mli index 3e165beb45..b105c9176c 100644 --- a/src/frontend/Typechecker.mli +++ b/src/frontend/Typechecker.mli @@ -3,8 +3,7 @@ open Ast val check_program_exn : untyped_program -> typed_program (** Can raise Errors.SemanticError *) -val check_program : - untyped_program -> (typed_program, Middle.Semantic_error.t) result +val check_program : untyped_program -> (typed_program, Semantic_error.t) result val model_name : string ref (** A reference to hold the model name. Relevant for checking variable diff --git a/src/frontend/lexer.mll b/src/frontend/lexer.mll index 5ffb39f34d..204ac763c5 100644 --- a/src/frontend/lexer.mll +++ b/src/frontend/lexer.mll @@ -2,7 +2,6 @@ { module Stack = Core_kernel.Stack - module Errors = Middle.Errors open Lexing open Debugging open Preprocessor diff --git a/src/middle/Middle.ml b/src/middle/Middle.ml index d156410830..e426ee3ce0 100644 --- a/src/middle/Middle.ml +++ b/src/middle/Middle.ml @@ -1,4 +1,3 @@ -module Errors = Errors module Location = Location module Location_span = Location_span module Operator = Operator @@ -10,8 +9,6 @@ module Expr = Expr module UnsizedType = UnsizedType module SizedType = SizedType module Type = Type -module Semantic_error = Semantic_error -module SignatureMismatch = SignatureMismatch module Stmt = Stmt module Program = Program module Stan_math_signatures = Stan_math_signatures diff --git a/test/unit/Parse_tests.ml b/test/unit/Parse_tests.ml index 0c597ff817..68b127e81d 100644 --- a/test/unit/Parse_tests.ml +++ b/test/unit/Parse_tests.ml @@ -4,7 +4,7 @@ open Frontend let print_ast_of_string s = let ast = Frontend_utils.untyped_ast_of_string s - |> Result.map_error ~f:Middle.Errors.to_string + |> Result.map_error ~f:Errors.to_string |> Result.ok_or_failwith in print_s [%sexp (ast : Ast.untyped_program)] From d8a52b8cdf902c6d67eb585d71c8cd55f1e32f1f Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Mon, 4 Oct 2021 11:36:34 -0400 Subject: [PATCH 05/15] Also move warnings back to frontend --- src/frontend/Deprecation_analysis.mli | 2 +- src/frontend/Frontend_utils.ml | 1 - src/frontend/Input_warnings.mli | 2 +- src/frontend/Parse.mli | 4 ++-- src/frontend/Pretty_printing.ml | 2 +- src/{middle => frontend}/Warnings.ml | 3 +++ src/{middle => frontend}/Warnings.mli | 2 +- src/middle/Middle.ml | 1 - test/unit/Pedantic_analysis.ml | 2 +- 9 files changed, 10 insertions(+), 9 deletions(-) rename src/{middle => frontend}/Warnings.ml (87%) rename src/{middle => frontend}/Warnings.mli (79%) diff --git a/src/frontend/Deprecation_analysis.mli b/src/frontend/Deprecation_analysis.mli index f56f288468..87cb9210ea 100644 --- a/src/frontend/Deprecation_analysis.mli +++ b/src/frontend/Deprecation_analysis.mli @@ -1,7 +1,7 @@ open Core_kernel open Ast -type t = Middle.Warnings.t +type t = Warnings.t val find_udf_log_suffix : typed_statement -> (string * Middle.UnsizedType.t) option diff --git a/src/frontend/Frontend_utils.ml b/src/frontend/Frontend_utils.ml index c3cfc3148f..d07a3ef2b2 100644 --- a/src/frontend/Frontend_utils.ml +++ b/src/frontend/Frontend_utils.ml @@ -1,5 +1,4 @@ open Core_kernel -module Warnings = Middle.Warnings let untyped_ast_of_string s = let res, warnings = Parse.parse_string Parser.Incremental.program s in diff --git a/src/frontend/Input_warnings.mli b/src/frontend/Input_warnings.mli index 51cb28fe05..e6fd106e65 100644 --- a/src/frontend/Input_warnings.mli +++ b/src/frontend/Input_warnings.mli @@ -2,7 +2,7 @@ val init : unit -> unit (** As something of a hack, Input_warnings keeps track of which warnings the lexer has emitted as a form of hidden state, which must be initialized and [collect]ed.*) -val collect : unit -> Middle.Warnings.t list +val collect : unit -> Warnings.t list (** Returns all of the warnings issued since [init] was called. *) val add_warning : Middle.Location_span.t -> string -> unit diff --git a/src/frontend/Parse.mli b/src/frontend/Parse.mli index 7136257046..61699275b7 100644 --- a/src/frontend/Parse.mli +++ b/src/frontend/Parse.mli @@ -5,13 +5,13 @@ open Core_kernel val parse_file : (Lexing.position -> Ast.untyped_program Parser.MenhirInterpreter.checkpoint) -> string - -> (Ast.untyped_program, Errors.t) result * Middle.Warnings.t list + -> (Ast.untyped_program, Errors.t) result * Warnings.t list (** A helper function to take a parser, a filename and produce an AST. Under the hood, it takes care of Menhir's custom syntax error messages. *) val parse_string : (Lexing.position -> Ast.untyped_program Parser.MenhirInterpreter.checkpoint) -> string - -> (Ast.untyped_program, Errors.t) result * Middle.Warnings.t list + -> (Ast.untyped_program, Errors.t) result * Warnings.t list (** A helper function to take a parser, a string and produce an AST. Under the hood, it takes care of Menhir's custom syntax error messages. *) diff --git a/src/frontend/Pretty_printing.ml b/src/frontend/Pretty_printing.ml index 316347f5bc..b993196783 100644 --- a/src/frontend/Pretty_printing.ml +++ b/src/frontend/Pretty_printing.ml @@ -598,7 +598,7 @@ let pp_program ppf pp_block_list ppf blocks let check_correctness prog pretty = - let result_ast, (_ : Middle.Warnings.t list) = + let result_ast, (_ : Warnings.t list) = Parse.parse_string Parser.Incremental.program pretty in if diff --git a/src/middle/Warnings.ml b/src/frontend/Warnings.ml similarity index 87% rename from src/middle/Warnings.ml rename to src/frontend/Warnings.ml index 1b00ac264d..d647e8b5f5 100644 --- a/src/middle/Warnings.ml +++ b/src/frontend/Warnings.ml @@ -1,3 +1,6 @@ +module Location_span = Middle.Location_span +module Location = Middle.Location + type t = Location_span.t * string let pp ?printed_filename ppf (span, message) = diff --git a/src/middle/Warnings.mli b/src/frontend/Warnings.mli similarity index 79% rename from src/middle/Warnings.mli rename to src/frontend/Warnings.mli index 799602039f..ff33978c3c 100644 --- a/src/middle/Warnings.mli +++ b/src/frontend/Warnings.mli @@ -1,4 +1,4 @@ -type t = Location_span.t * string +type t = Middle.Location_span.t * string val pp : ?printed_filename:string -> t Fmt.t val pp_warnings : ?printed_filename:string -> t list Fmt.t diff --git a/src/middle/Middle.ml b/src/middle/Middle.ml index e426ee3ce0..38327819df 100644 --- a/src/middle/Middle.ml +++ b/src/middle/Middle.ml @@ -13,5 +13,4 @@ module Stmt = Stmt module Program = Program module Stan_math_signatures = Stan_math_signatures module Utils = Utils -module Warnings = Warnings module Transformation = Transformation diff --git a/test/unit/Pedantic_analysis.ml b/test/unit/Pedantic_analysis.ml index a785035b10..dd88d3c098 100644 --- a/test/unit/Pedantic_analysis.ml +++ b/test/unit/Pedantic_analysis.ml @@ -28,7 +28,7 @@ let sigma_example = let print_warn_pedantic p = p |> warn_pedantic - |> Fmt.strf "%a" (Middle.Warnings.pp_warnings ?printed_filename:None) + |> Fmt.strf "%a" (Warnings.pp_warnings ?printed_filename:None) |> print_endline let%expect_test "Unbounded sigma warning" = From 6cd7d345532a0db638610dd8ea1f9d6f1d4f276e Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Thu, 7 Oct 2021 14:00:46 -0400 Subject: [PATCH 06/15] Fix stan2tfp test output --- test/integration/tfp/dune | 5 ++-- .../tfp/tfp_models/python_kwrds.py | 27 ++++++++++++++++++- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/test/integration/tfp/dune b/test/integration/tfp/dune index 9d6fe179cf..09d75b094b 100644 --- a/test/integration/tfp/dune +++ b/test/integration/tfp/dune @@ -35,9 +35,8 @@ (targets python_kwrds.py.output) (deps (package stanc) (:stanfiles ./stan_models/python_kwrds.stan)) (action - (with-stdout-to %{targets} - (with-stderr-to stdout - (run %{bin:stan2tfp} %{stanfiles}))))) + (with-outputs-to %{targets} + (run %{bin:stan2tfp} %{stanfiles})))) (alias (name runtest) diff --git a/test/integration/tfp/tfp_models/python_kwrds.py b/test/integration/tfp/tfp_models/python_kwrds.py index 577802c943..096626332e 100644 --- a/test/integration/tfp/tfp_models/python_kwrds.py +++ b/test/integration/tfp/tfp_models/python_kwrds.py @@ -54,4 +54,29 @@ def parameter_bijectors(self): def parameter_names(self): return ["finally__"] -model = python_kwrds_model \ No newline at end of file +model = python_kwrds_modelWarning in 'stan_models/python_kwrds.stan', line 13, column 12: Found int division: + lambda / 3 +Values will be rounded towards zero. If rounding is not desired you can write +the division as + lambda / 3.0 +If rounding is intended please use the integer division operator %/%. +Identifier finally is a reserved word in python, renamed to finally__ +Identifier assert is a reserved word in python, renamed to assert__ +Identifier lambda is a reserved word in python, renamed to lambda__ +Identifier yield is a reserved word in python, renamed to yield__ +Identifier await is a reserved word in python, renamed to await__ +Identifier finally is a reserved word in python, renamed to finally__ +Identifier finally is a reserved word in python, renamed to finally__ +Identifier assert is a reserved word in python, renamed to assert__ +Identifier yield is a reserved word in python, renamed to yield__ +Identifier lambda is a reserved word in python, renamed to lambda__ +Identifier finally is a reserved word in python, renamed to finally__ +Identifier lambda is a reserved word in python, renamed to lambda__ +Identifier await is a reserved word in python, renamed to await__ +Identifier finally is a reserved word in python, renamed to finally__ +Identifier assert is a reserved word in python, renamed to assert__ +Identifier assert is a reserved word in python, renamed to assert__ +Identifier finally is a reserved word in python, renamed to finally__ +Identifier assert is a reserved word in python, renamed to assert__ +Identifier assert is a reserved word in python, renamed to assert__ +Identifier lambda is a reserved word in python, renamed to lambda__ \ No newline at end of file From 735de862d777c97a5630ce576971630e1c83572e Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Tue, 12 Oct 2021 10:01:26 -0400 Subject: [PATCH 07/15] Changes per review --- src/frontend/Typechecker.ml | 91 ++++++++++++++----------------------- 1 file changed, 34 insertions(+), 57 deletions(-) diff --git a/src/frontend/Typechecker.ml b/src/frontend/Typechecker.ml index 2005163359..feb6f27e7e 100644 --- a/src/frontend/Typechecker.ml +++ b/src/frontend/Typechecker.ml @@ -45,8 +45,8 @@ let context block = ; in_udf_dist_def= false ; loop_depth= 0 } -let calculate_autodifftype cf at ut = - match at with +let calculate_autodifftype cf origin ut = + match origin with | Env.(Param | TParam | Model | Functions) when not (UnsizedType.contains_int ut || cf.current_block = GQuant) -> UnsizedType.AutoDiffable @@ -61,28 +61,6 @@ let has_int_array_type ue = ue.emeta.type_ = UArray UInt let has_int_or_real_type ue = match ue.emeta.type_ with UInt | UReal -> true | _ -> false -let probability_distribution_name_variants id = - let name = id.name in - let open String in - List.map - ~f:(fun n -> {name= n; id_loc= id.id_loc}) - ( if name = "multiply_log" || name = "binomial_coefficient_log" then [name] - else if is_suffix ~suffix:"_lpmf" name then - [name; drop_suffix name 5 ^ "_lpdf"; drop_suffix name 5 ^ "_log"] - else if is_suffix ~suffix:"_lpdf" name then - [name; drop_suffix name 5 ^ "_lpmf"; drop_suffix name 5 ^ "_log"] - else if is_suffix ~suffix:"_lcdf" name then - [name; drop_suffix name 5 ^ "_cdf_log"] - else if is_suffix ~suffix:"_lccdf" name then - [name; drop_suffix name 6 ^ "_ccdf_log"] - else if is_suffix ~suffix:"_cdf_log" name then - [name; drop_suffix name 8 ^ "_lcdf"] - else if is_suffix ~suffix:"_ccdf_log" name then - [name; drop_suffix name 9 ^ "_lccdf"] - else if is_suffix ~suffix:"_log" name then - [name; drop_suffix name 4 ^ "_lpmf"; drop_suffix name 4 ^ "_lpdf"] - else [name] ) - (* -- General checks ---------------------------------------------- *) let reserved_keywords = [ "true"; "false"; "repeat"; "until"; "then"; "var"; "fvar"; "STAN_MAJOR" @@ -114,6 +92,31 @@ let verify_identifier id : unit = then Semantic_error.ident_is_keyword id.id_loc id.name |> error else () +let distribution_name_variants id = + let open String in + let name = id.name in + let names = + if name = "multiply_log" || name = "binomial_coefficient_log" then [name] + else if is_suffix ~suffix:"_lpmf" name then + [name; drop_suffix name 5 ^ "_lpdf"; drop_suffix name 5 ^ "_log"] + else if is_suffix ~suffix:"_lpdf" name then + [name; drop_suffix name 5 ^ "_lpmf"; drop_suffix name 5 ^ "_log"] + else if is_suffix ~suffix:"_lcdf" name then + [name; drop_suffix name 5 ^ "_cdf_log"] + else if is_suffix ~suffix:"_lccdf" name then + [name; drop_suffix name 6 ^ "_ccdf_log"] + else if is_suffix ~suffix:"_cdf_log" name then + [name; drop_suffix name 8 ^ "_lcdf"] + else if is_suffix ~suffix:"_ccdf_log" name then + [name; drop_suffix name 9 ^ "_lccdf"] + else if is_suffix ~suffix:"_log" name then + [name; drop_suffix name 4 ^ "_lpmf"; drop_suffix name 4 ^ "_lpdf"] + else [name] + in + List.map ~f:(fun n -> {id with name= n}) names + +(* verify that the variable being declared is previous unused. + allowed to shadow StanLib *) let verify_name_fresh_var tenv id = if Utils.is_unnormalized_distribution id.name then Semantic_error.ident_has_unnormalized_suffix id.id_loc id.name |> error @@ -123,6 +126,8 @@ let verify_name_fresh_var tenv id = then Semantic_error.ident_in_use id.id_loc id.name |> error else () +(* verify that the variable being declared is previous unused. + not allowed shadowing/overloading (yet)*) let verify_name_fresh_udf tenv id = if Stan_math_signatures.is_stan_math_function_name id.name @@ -145,7 +150,7 @@ let verify_name_fresh tenv id ~is_udf = let f = if is_udf then verify_name_fresh_udf tenv else verify_name_fresh_var tenv in - List.iter ~f (probability_distribution_name_variants id) + List.iter ~f (distribution_name_variants id) let is_of_compatible_return_type rt1 srt2 = UnsizedType.( @@ -177,8 +182,6 @@ let check_ternary_if loc pe te fe = fe.emeta.type_ |> error -let verify_operator _ = () - let check_binop loc op le re = let rt = [le; re] |> get_arg_types @@ -588,13 +591,9 @@ and check_expression cf tenv ({emeta; expr} : Ast.untyped_expression) : Warnings.pp Fmt.stderr (x.emeta.loc, s) | _ -> () in - verify_operator op ; warn_int_division le re ; check_binop loc op le re - | PrefixOp (op, e) -> - verify_operator op ; - ce e |> check_prefixop loc op - | PostfixOp (e, op) -> - verify_operator op ; - ce e |> check_postfixop loc op + warn_int_division le re ; check_binop loc op le re + | PrefixOp (op, e) -> ce e |> check_prefixop loc op + | PostfixOp (e, op) -> ce e |> check_postfixop loc op | Variable id -> verify_identifier id ; check_variable cf loc tenv id @@ -1327,23 +1326,6 @@ and verify_fundef_return_tys loc return_type body = then () else Semantic_error.incompatible_return_types loc |> error -(* Probably nothing to do here *) -and verify_autodifftype _ = () - -(* also does absolutely nothing right now *) -and verify_unsizedtype = function - | UnsizedType.UFun (l, rt, _, _) -> - verify_returntype rt ; - List.iter - ~f:(fun (at, ut) -> verify_autodifftype at ; verify_unsizedtype ut) - l - | UArray ut -> verify_unsizedtype ut - | _ -> () - -and verify_returntype = function - | Void -> () - | ReturnType ut -> verify_unsizedtype ut - and add_function tenv name type_ defined = (* if we're providing a definition, we remove prior declarations to simplify the environment *) @@ -1362,13 +1344,8 @@ and add_function tenv name type_ defined = else Env.add tenv name type_ defined and check_fundef loc cf tenv return_ty id args body = - let () = - List.iter args ~f:(fun (at, ut, id) -> - verify_autodifftype at ; verify_unsizedtype ut ; verify_identifier id - ) - in + let () = List.iter args ~f:(fun (_, _, id) -> verify_identifier id) in verify_identifier id ; - verify_returntype return_ty ; let arg_types = List.map ~f:(fun (w, y, _) -> (w, y)) args in let arg_identifiers = List.map ~f:(fun (_, _, z) -> z) args in let arg_names = List.map ~f:(fun x -> x.name) arg_identifiers in From 92ce1a812f5844311aede83f55819ea6aa1850c2 Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Tue, 12 Oct 2021 13:49:40 -0400 Subject: [PATCH 08/15] Clean up distribution suffix logic --- src/frontend/Typechecker.ml | 38 ++++++++++++----------------- src/middle/Utils.ml | 8 ++++++ test/integration/bad/stanc.expected | 4 +-- 3 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/frontend/Typechecker.ml b/src/frontend/Typechecker.ml index feb6f27e7e..ee2011608a 100644 --- a/src/frontend/Typechecker.ml +++ b/src/frontend/Typechecker.ml @@ -97,25 +97,19 @@ let distribution_name_variants id = let name = id.name in let names = if name = "multiply_log" || name = "binomial_coefficient_log" then [name] - else if is_suffix ~suffix:"_lpmf" name then - [name; drop_suffix name 5 ^ "_lpdf"; drop_suffix name 5 ^ "_log"] - else if is_suffix ~suffix:"_lpdf" name then - [name; drop_suffix name 5 ^ "_lpmf"; drop_suffix name 5 ^ "_log"] - else if is_suffix ~suffix:"_lcdf" name then - [name; drop_suffix name 5 ^ "_cdf_log"] - else if is_suffix ~suffix:"_lccdf" name then - [name; drop_suffix name 6 ^ "_ccdf_log"] - else if is_suffix ~suffix:"_cdf_log" name then - [name; drop_suffix name 8 ^ "_lcdf"] - else if is_suffix ~suffix:"_ccdf_log" name then - [name; drop_suffix name 9 ^ "_lccdf"] - else if is_suffix ~suffix:"_log" name then - [name; drop_suffix name 4 ^ "_lpmf"; drop_suffix name 4 ^ "_lpdf"] - else [name] + else + match Utils.split_distribution_suffix name with + | Some (stem, "lpmf") | Some (stem, "lpdf") | Some (stem, "log") -> + [stem ^ "_lpmf"; stem ^ "_lpdf"; stem ^ "_log"] + | Some (stem, "lcdf") | Some (stem, "cdf_log") -> + [stem ^ "_lcdf"; stem ^ "_cdf_log"] + | Some (stem, "lccdf") | Some (stem, "ccdf_log") -> + [stem ^ "_lccdf"; stem ^ "_ccdf_log"] + | _ -> [name] in List.map ~f:(fun n -> {id with name= n}) names -(* verify that the variable being declared is previous unused. +(* verify that the variable being declared is previous unused. allowed to shadow StanLib *) let verify_name_fresh_var tenv id = if Utils.is_unnormalized_distribution id.name then @@ -126,7 +120,7 @@ let verify_name_fresh_var tenv id = then Semantic_error.ident_in_use id.id_loc id.name |> error else () -(* verify that the variable being declared is previous unused. +(* verify that the variable being declared is previous unused. not allowed shadowing/overloading (yet)*) let verify_name_fresh_udf tenv id = if @@ -1022,7 +1016,7 @@ let try_compute_ifthenelse_statement_returntype loc srt1 srt2 = | Complete rt, AnyReturnType | AnyReturnType, Complete rt -> Complete rt | AnyReturnType, AnyReturnType -> AnyReturnType -(* statements which contain statements, and therefore need to be mutually recursive +(* statements which contain statements, and therefore need to be mutually recursive with check_statement *) let rec check_if_then_else loc cf tenv pred_e s_true s_false_opt = @@ -1096,9 +1090,9 @@ and check_foreach loc cf tenv loop_var foreach_e loop_body = and check_loop_body cf tenv loop_var loop_var_ty loop_body = verify_name_fresh tenv loop_var ~is_udf:false ; - (* Add to type environment as readonly. + (* Add to type environment as readonly. Check that function args and loop identifiers are not modified in - function. (passed by const ref) + function. (passed by const ref) *) let tenv = Env.add tenv loop_var.name loop_var_ty @@ -1327,7 +1321,7 @@ and verify_fundef_return_tys loc return_type body = else Semantic_error.incompatible_return_types loc |> error and add_function tenv name type_ defined = - (* if we're providing a definition, we remove prior declarations + (* if we're providing a definition, we remove prior declarations to simplify the environment *) if defined = `UserDefined then let existing_defns = Env.find tenv name in @@ -1377,7 +1371,7 @@ and check_fundef loc cf tenv return_ty id args body = List.fold2_exn arg_names arg_types_internal ~init:tenv ~f:(fun env name (origin, typ) -> Env.add env name typ - (* readonly so that function args and loop identifiers + (* readonly so that function args and loop identifiers are not modified in function. (passed by const ref) *) (`Variable {origin; readonly= true; global= false}) ) in diff --git a/src/middle/Utils.ml b/src/middle/Utils.ml index c1e790bd16..2985d46d89 100644 --- a/src/middle/Utils.ml +++ b/src/middle/Utils.ml @@ -19,6 +19,14 @@ let unnormalized_suffix = function | "_lpmf" -> "_lupmf" | x -> x +(** A wrapper around String.rsplit2 which handles _cdf_log and _ccdf_log *) +let split_distribution_suffix (name : string) : (string * string) option = + let open String in + if is_suffix ~suffix:"_cdf_log" name then Some (drop_suffix name 8, "cdf_log") + else if is_suffix ~suffix:"_ccdf_log" name then + Some (drop_suffix name 9, "ccdf_log") + else rsplit2 ~on:'_' name + let is_distribution_name s = (not ( String.is_suffix s ~suffix:"_cdf_log" diff --git a/test/integration/bad/stanc.expected b/test/integration/bad/stanc.expected index 4b865878c6..2e5d5aceed 100644 --- a/test/integration/bad/stanc.expected +++ b/test/integration/bad/stanc.expected @@ -1855,7 +1855,7 @@ Semantic error in 'redefine-ccdf1.stan', line 2, column 7 to column 23: 4: } ------------------------------------------------- -Identifier 'poisson_ccdf_log' clashes with Stan Math library function. +Identifier 'poisson_lccdf' clashes with Stan Math library function. $ ../../../../install/default/bin/stanc redefine-ccdf2.stan Semantic error in 'redefine-ccdf2.stan', line 2, column 7 to column 20: ------------------------------------------------- @@ -1889,7 +1889,7 @@ Semantic error in 'redefine-cdf1.stan', line 2, column 7 to column 22: 4: } ------------------------------------------------- -Identifier 'poisson_cdf_log' clashes with Stan Math library function. +Identifier 'poisson_lcdf' clashes with Stan Math library function. $ ../../../../install/default/bin/stanc redefine-cdf2.stan Semantic error in 'redefine-cdf2.stan', line 2, column 7 to column 19: ------------------------------------------------- From 00811c68d07cf4f2d0098057a470bb98dcd6fbbf Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Thu, 21 Oct 2021 09:31:32 -0400 Subject: [PATCH 09/15] Changes per review --- src/frontend/Environment.ml | 16 ++--- src/frontend/Environment.mli | 10 ++- src/frontend/SignatureMismatch.ml | 5 +- src/frontend/Typechecker.ml | 109 +++++++++++------------------- src/frontend/Typechecker.mli | 23 ++++++- src/middle/UnsizedType.ml | 2 +- 6 files changed, 80 insertions(+), 85 deletions(-) diff --git a/src/frontend/Environment.ml b/src/frontend/Environment.ml index 460a61b884..bff4284645 100644 --- a/src/frontend/Environment.ml +++ b/src/frontend/Environment.ml @@ -1,7 +1,6 @@ open Core_kernel open Middle -(** Origin blocks, to keep track of where variables are declared *) type originblock = | MathLibrary | Functions @@ -32,23 +31,18 @@ let create () = Hashtbl.to_alist Stan_math_signatures.stan_math_signatures |> List.map ~f:(fun (key, values) -> ( key - , List.map - ~f:(fun (rt, args, mem) -> + , List.map values ~f:(fun (rt, args, mem) -> let type_ = - UnsizedType.UFun (args, rt, Fun_kind.FnPlain, mem) + UnsizedType.UFun + (args, rt, Fun_kind.suffix_from_name key, mem) in - {type_; kind= `StanMath} ) - values ) ) + {type_; kind= `StanMath} ) ) ) |> String.Map.of_alist_exn in functions let add env key type_ kind = Map.add_multi env ~key ~data:{type_; kind} - -let add_all_raw env key data = - let env = Map.remove env key in - List.fold ~init:env ~f:(fun env data -> Map.add_multi env ~key ~data) data - +let set_raw env key data = Map.set env ~key ~data let find env key = Map.find_multi env key let mem env key = Map.mem env key let iter env f = Map.iter env ~f diff --git a/src/frontend/Environment.mli b/src/frontend/Environment.mli index ab4802856f..5927c80d94 100644 --- a/src/frontend/Environment.mli +++ b/src/frontend/Environment.mli @@ -1,5 +1,6 @@ open Middle +(** Origin blocks, to keep track of where variables are declared *) type originblock = | MathLibrary | Functions @@ -11,6 +12,7 @@ type originblock = | GQuant [@@deriving sexp] +(** Information available for each variable *) type varinfo = {origin: originblock; global: bool; readonly: bool} [@@deriving sexp] @@ -26,6 +28,9 @@ type info = type t val create : unit -> t +(** Return a new type environment which contains the Stan math library functions +*) + val find : t -> string -> info list val add : @@ -37,7 +42,10 @@ val add : | `UserDefined | `Variable of varinfo ] -> t +(** Add a new item to the type environment. Does not overwrite existing, but shadows *) + +val set_raw : t -> string -> info list -> t +(** Overwrite the existing items bound to a name *) -val add_all_raw : t -> string -> info list -> t val mem : t -> string -> bool val iter : t -> (info list -> unit) -> unit diff --git a/src/frontend/SignatureMismatch.ml b/src/frontend/SignatureMismatch.ml index 059aad37eb..b05bdf21c5 100644 --- a/src/frontend/SignatureMismatch.ml +++ b/src/frontend/SignatureMismatch.ml @@ -150,16 +150,15 @@ let check_compatible_arguments_mod_conv = check_compatible_arguments 0 let max_n_errors = 5 let extract_function_types f = - let open Environment in match f with - | {type_= UFun (args, return, _, mem); kind= `StanMath} -> + | Environment.({type_= UFun (args, return, _, mem); kind= `StanMath}) -> Some (return, args, (fun x -> Ast.StanLib x), mem) | {type_= UFun (args, return, _, mem); _} -> Some (return, args, (fun x -> UserDefined x), mem) | _ -> None let returntype env name args = - (* NB: Variadic arguments are special-cased in Semantic_check and not handled here *) + (* NB: Variadic arguments are special-cased in the typechecker and not handled here *) let name = Utils.stdlib_distribution_name name in Environment.find env name |> List.filter_map ~f:extract_function_types diff --git a/src/frontend/Typechecker.ml b/src/frontend/Typechecker.ml index ee2011608a..c225d5c34a 100644 --- a/src/frontend/Typechecker.ml +++ b/src/frontend/Typechecker.ml @@ -90,51 +90,43 @@ let verify_identifier id : unit = String.is_suffix id.name ~suffix:"__" || List.mem reserved_keywords id.name ~equal:String.equal then Semantic_error.ident_is_keyword id.id_loc id.name |> error - else () - -let distribution_name_variants id = - let open String in - let name = id.name in - let names = - if name = "multiply_log" || name = "binomial_coefficient_log" then [name] - else - match Utils.split_distribution_suffix name with - | Some (stem, "lpmf") | Some (stem, "lpdf") | Some (stem, "log") -> - [stem ^ "_lpmf"; stem ^ "_lpdf"; stem ^ "_log"] - | Some (stem, "lcdf") | Some (stem, "cdf_log") -> - [stem ^ "_lcdf"; stem ^ "_cdf_log"] - | Some (stem, "lccdf") | Some (stem, "ccdf_log") -> - [stem ^ "_lccdf"; stem ^ "_ccdf_log"] - | _ -> [name] - in - List.map ~f:(fun n -> {id with name= n}) names -(* verify that the variable being declared is previous unused. +let distribution_name_variants name = + if name = "multiply_log" || name = "binomial_coefficient_log" then [name] + else + match Utils.split_distribution_suffix name with + | Some (stem, "lpmf") | Some (stem, "lpdf") | Some (stem, "log") -> + [stem ^ "_lpmf"; stem ^ "_lpdf"; stem ^ "_log"] + | Some (stem, "lcdf") | Some (stem, "cdf_log") -> + [stem ^ "_lcdf"; stem ^ "_cdf_log"] + | Some (stem, "lccdf") | Some (stem, "ccdf_log") -> + [stem ^ "_lccdf"; stem ^ "_ccdf_log"] + | _ -> [name] + +(** verify that the variable being declared is previous unused. allowed to shadow StanLib *) -let verify_name_fresh_var tenv id = - if Utils.is_unnormalized_distribution id.name then - Semantic_error.ident_has_unnormalized_suffix id.id_loc id.name |> error +let verify_name_fresh_var loc tenv name = + if Utils.is_unnormalized_distribution name then + Semantic_error.ident_has_unnormalized_suffix loc name |> error else if - Env.mem tenv id.name - && not (Stan_math_signatures.is_stan_math_function_name id.name) - then Semantic_error.ident_in_use id.id_loc id.name |> error - else () + Env.mem tenv name + && not (Stan_math_signatures.is_stan_math_function_name name) + then Semantic_error.ident_in_use loc name |> error -(* verify that the variable being declared is previous unused. +(** verify that the variable being declared is previous unused. not allowed shadowing/overloading (yet)*) -let verify_name_fresh_udf tenv id = +let verify_name_fresh_udf loc tenv name = if - Stan_math_signatures.is_stan_math_function_name id.name + Stan_math_signatures.is_stan_math_function_name name (* variadic functions are currently not in math sigs *) - || Stan_math_signatures.is_reduce_sum_fn id.name - || Stan_math_signatures.is_variadic_ode_fn id.name - then Semantic_error.ident_is_stanmath_name id.id_loc id.name |> error - else if Utils.is_unnormalized_distribution id.name then - Semantic_error.udf_is_unnormalized_fn id.id_loc id.name |> error - else if Env.mem tenv id.name then + || Stan_math_signatures.is_reduce_sum_fn name + || Stan_math_signatures.is_variadic_ode_fn name + then Semantic_error.ident_is_stanmath_name loc name |> error + else if Utils.is_unnormalized_distribution name then + Semantic_error.udf_is_unnormalized_fn loc name |> error + else if Env.mem tenv name then (* adapt for overloading later *) - Semantic_error.ident_in_use id.id_loc id.name |> error - else () + Semantic_error.ident_in_use loc name |> error (** Checks that a variable/function name: - a function/identifier does not have the _lupdf/_lupmf suffix @@ -142,9 +134,10 @@ let verify_name_fresh_udf tenv id = *) let verify_name_fresh tenv id ~is_udf = let f = - if is_udf then verify_name_fresh_udf tenv else verify_name_fresh_var tenv + if is_udf then verify_name_fresh_udf id.id_loc tenv + else verify_name_fresh_var id.id_loc tenv in - List.iter ~f (distribution_name_variants id) + List.iter ~f (distribution_name_variants id.name) let is_of_compatible_return_type rt1 srt2 = UnsizedType.( @@ -356,7 +349,6 @@ let verify_fn_conditioning loc id = Utils.conditioning_suffices && not (String.is_suffix id.name ~suffix:"_cdf") then Semantic_error.conditioning_required loc |> error - else () (** `Target+=` can only be used in model and functions with right suffix (same for tilde etc) @@ -368,7 +360,6 @@ let verify_fn_target_plus_equals cf loc id = ( cf.in_lp_fun_def || cf.current_block = Model || cf.current_block = TParam ) then Semantic_error.target_plusequals_outisde_model_or_logprob loc |> error - else () (** Rng functions cannot be used in Tp or Model and only in function defs with the right suffix @@ -381,7 +372,6 @@ let verify_fn_rng cf loc id = && ( (cf.in_fun_def && not cf.in_rng_fun_def) || cf.current_block = TParam || cf.current_block = Model ) then Semantic_error.invalid_rng_fn loc |> error - else () (** unnormalized _lpdf/_lpmf functions can only be used in _lpdf/_lpmf/_lp udfs or the model block @@ -391,7 +381,6 @@ let verify_unnormalized cf loc id = Utils.is_unnormalized_distribution id.name && not ((cf.in_fun_def && cf.in_udf_dist_def) || cf.current_block = Model) then Semantic_error.invalid_unnormalized_fn loc |> error - else () let mk_fun_app ~is_cond_dist (x, y, z) = if is_cond_dist then CondDistApp (x, y, z) else FunApp (x, y, z) @@ -667,7 +656,6 @@ let verify_nrfn_target loc cf id = ( cf.in_lp_fun_def || cf.current_block = Model || cf.current_block = TParam ) then Semantic_error.target_plusequals_outisde_model_or_logprob loc |> error - else () let check_nrfn loc tenv id es = match Env.find tenv id.name with @@ -703,7 +691,6 @@ let check_nr_fn_app loc cf tenv id es = let verify_assignment_read_only loc is_readonly id = if is_readonly then Semantic_error.cannot_assign_to_read_only loc id.name |> error - else () (* Variables from previous blocks are read-only. In particular, data and parameters never assigned to @@ -758,10 +745,8 @@ let check_assignment loc cf tenv assign_lhs assign_op assign_rhs = (* target plus-equals / increment log-prob *) let verify_target_pe_expr_type loc e = - match e.emeta.type_ with - | UFun _ | UMathLibraryFunction -> - Semantic_error.int_or_real_container_expected loc e.emeta.type_ |> error - | _ -> () + if UnsizedType.is_fun_type e.emeta.type_ then + Semantic_error.int_or_real_container_expected loc e.emeta.type_ |> error let verify_target_pe_usage loc cf = if cf.in_lp_fun_def || cf.current_block = Model then () @@ -788,14 +773,12 @@ let verify_sampling_pdf_pmf id = || is_suffix id.name ~suffix:"_lupdf" || is_suffix id.name ~suffix:"_lupmf") then Semantic_error.invalid_sampling_pdf_or_pmf id.id_loc |> error - else () let verify_sampling_cdf_ccdf loc id = if String.( is_suffix id.name ~suffix:"_cdf" || is_suffix id.name ~suffix:"_ccdf") then Semantic_error.invalid_sampling_cdf_or_ccdf loc id.name |> error - else () (* Target+= can only be used in model and functions with right suffix (same for tilde etc) *) let verify_valid_sampling_pos loc cf = @@ -820,8 +803,7 @@ let verify_sampling_distribution loc tenv id arguments = && name <> "multiply" in let is_name_w_suffix_udf_sampling_dist suffix = - let f v = - match v with + let f = function | Env.({ kind= `UserDefined | `UserDeclared _ ; type_= UFun (listedtypes, ReturnType UReal, FnLpdf _, _) }) when UnsizedType.check_compatible_arguments_mod_conv name listedtypes @@ -849,8 +831,7 @@ let is_cumulative_density_defined tenv id arguments = Stan_math_signatures.stan_math_returntype (name ^ suffix) argumenttypes |> Option.value_map ~default:false ~f:is_real_rt and valid_arg_types_for_suffix suffix = - let f v = - match v with + let f = function | Env.({ kind= `UserDefined | `UserDeclared _ ; type_= UFun (listedtypes, ReturnType UReal, FnPlain, _) }) when UnsizedType.check_compatible_arguments_mod_conv name listedtypes @@ -1137,8 +1118,7 @@ and verify_valid_transformation_for_type loc is_global sized_ty trans = | _ -> false in if is_global && sized_ty = SizedType.SInt && is_real_transformation then - Semantic_error.non_int_bounds loc |> error - else () ; + Semantic_error.non_int_bounds loc |> error ; let is_transformation = match trans with Transformation.Identity -> false | _ -> true in @@ -1147,7 +1127,6 @@ and verify_valid_transformation_for_type loc is_global sized_ty trans = && SizedType.(inner_type sized_ty = SComplex) && is_transformation then Semantic_error.complex_transform loc |> error - else () and verify_transformed_param_ty loc cf is_global unsized_ty = if @@ -1155,7 +1134,6 @@ and verify_transformed_param_ty loc cf is_global unsized_ty = && (cf.current_block = Param || cf.current_block = TParam) && UnsizedType.contains_int unsized_ty then Semantic_error.transformed_params_int loc |> error - else () and check_sizedtype cf tenv sizedty = let check e msg = check_expression_of_int_type cf tenv e msg in @@ -1247,8 +1225,7 @@ and check_var_decl loc cf tenv sized_ty trans id init is_global = (* function definitions *) and exists_matching_fn_declared tenv id arg_tys rt = - let f v = - match v with + let f = function | Env.({kind= `UserDeclared _; type_= UFun (listedtypes, rt', _, _)}) when arg_tys = listedtypes && rt = rt' -> true @@ -1288,7 +1265,6 @@ and verify_fundef_dist_rt loc id return_ty = match return_ty with | UnsizedType.ReturnType UReal -> () | _ -> Semantic_error.non_real_prob_fn_def loc |> error - else () and verify_pdf_fundef_first_arg_ty loc id arg_tys = if String.is_suffix id.name ~suffix:"_lpdf" then @@ -1306,12 +1282,9 @@ and verify_pmf_fundef_first_arg_ty loc id arg_tys = and verify_fundef_distinct_arg_ids loc arg_names = let dup_exists l = - match List.find_a_dup ~compare:String.compare l with - | Some _ -> true - | None -> false + List.find_a_dup ~compare:String.compare l |> Option.is_some in if dup_exists arg_names then Semantic_error.duplicate_arg_names loc |> error - else () and verify_fundef_return_tys loc return_type body = if @@ -1334,11 +1307,11 @@ and add_function tenv name type_ defined = existing_defns in let new_fn = Env.{kind= `UserDefined; type_} in - Env.add_all_raw tenv name (new_fn :: defns) + Env.set_raw tenv name (new_fn :: defns) else Env.add tenv name type_ defined and check_fundef loc cf tenv return_ty id args body = - let () = List.iter args ~f:(fun (_, _, id) -> verify_identifier id) in + List.iter args ~f:(fun (_, _, id) -> verify_identifier id) ; verify_identifier id ; let arg_types = List.map ~f:(fun (w, y, _) -> (w, y)) args in let arg_identifiers = List.map ~f:(fun (_, _, z) -> z) args in diff --git a/src/frontend/Typechecker.mli b/src/frontend/Typechecker.mli index b105c9176c..a2f19c799a 100644 --- a/src/frontend/Typechecker.mli +++ b/src/frontend/Typechecker.mli @@ -1,9 +1,30 @@ +(** a type/semantic checker for Stan ASTs + + Functions which begin with "check_" return a typed version of their input + Functions which begin with "verify_" return unit if a check succeeds, or else + throw an [Errors.SemanticError] exception. + + All [Error.SemanticError] excpetions are caught by check_program + which turns the ast or exception into a [Result.t] for external usage + + A type environment {!val:Environment.t} is used to hold variables and functions, including + Stan math functions. This is a functional map, meaning it is handled immutably. +*) + open Ast val check_program_exn : untyped_program -> typed_program -(** Can raise Errors.SemanticError *) +(** + Type check a full Stan program. + Can raise [Errors.SemanticError] +*) val check_program : untyped_program -> (typed_program, Semantic_error.t) result +(** + The safe version of [check_program_exn]. This catches + all [Errors.SemanticError] exceptions and converts them + into a [Result.t] +*) val model_name : string ref (** A reference to hold the model name. Relevant for checking variable diff --git a/src/middle/UnsizedType.ml b/src/middle/UnsizedType.ml index 4a110ecee5..a04af343a3 100644 --- a/src/middle/UnsizedType.ml +++ b/src/middle/UnsizedType.ml @@ -149,7 +149,7 @@ let is_int_type = function UInt | UArray UInt -> true | _ -> false let is_eigen_type ut = match ut with UVector | URowVector | UMatrix -> true | _ -> false -let is_fun_type = function UFun _ -> true | _ -> false +let is_fun_type = function UFun _ | UMathLibraryFunction -> true | _ -> false (** Detect if type contains an integer *) let rec contains_int ut = From 17c5318816d104b3e4c30bbe1244b26a0510d055 Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Thu, 21 Oct 2021 09:35:56 -0400 Subject: [PATCH 10/15] Changes per review --- src/frontend/Typechecker.ml | 7 ++++--- test/integration/bad/stanc.expected | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/frontend/Typechecker.ml b/src/frontend/Typechecker.ml index c225d5c34a..807fd1981d 100644 --- a/src/frontend/Typechecker.ml +++ b/src/frontend/Typechecker.ml @@ -94,13 +94,14 @@ let verify_identifier id : unit = let distribution_name_variants name = if name = "multiply_log" || name = "binomial_coefficient_log" then [name] else + (* this will have some duplicates, but preserves order better *) match Utils.split_distribution_suffix name with | Some (stem, "lpmf") | Some (stem, "lpdf") | Some (stem, "log") -> - [stem ^ "_lpmf"; stem ^ "_lpdf"; stem ^ "_log"] + [name; stem ^ "_lpmf"; stem ^ "_lpdf"; stem ^ "_log"] | Some (stem, "lcdf") | Some (stem, "cdf_log") -> - [stem ^ "_lcdf"; stem ^ "_cdf_log"] + [name; stem ^ "_lcdf"; stem ^ "_cdf_log"] | Some (stem, "lccdf") | Some (stem, "ccdf_log") -> - [stem ^ "_lccdf"; stem ^ "_ccdf_log"] + [name; stem ^ "_lccdf"; stem ^ "_ccdf_log"] | _ -> [name] (** verify that the variable being declared is previous unused. diff --git a/test/integration/bad/stanc.expected b/test/integration/bad/stanc.expected index 2e5d5aceed..4b865878c6 100644 --- a/test/integration/bad/stanc.expected +++ b/test/integration/bad/stanc.expected @@ -1855,7 +1855,7 @@ Semantic error in 'redefine-ccdf1.stan', line 2, column 7 to column 23: 4: } ------------------------------------------------- -Identifier 'poisson_lccdf' clashes with Stan Math library function. +Identifier 'poisson_ccdf_log' clashes with Stan Math library function. $ ../../../../install/default/bin/stanc redefine-ccdf2.stan Semantic error in 'redefine-ccdf2.stan', line 2, column 7 to column 20: ------------------------------------------------- @@ -1889,7 +1889,7 @@ Semantic error in 'redefine-cdf1.stan', line 2, column 7 to column 22: 4: } ------------------------------------------------- -Identifier 'poisson_lcdf' clashes with Stan Math library function. +Identifier 'poisson_cdf_log' clashes with Stan Math library function. $ ../../../../install/default/bin/stanc redefine-cdf2.stan Semantic error in 'redefine-cdf2.stan', line 2, column 7 to column 19: ------------------------------------------------- From 067d664dce5f4236e004a8f69aa6131ab2f500d7 Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Fri, 22 Oct 2021 12:15:22 -0400 Subject: [PATCH 11/15] Don't directly print warnings --- src/frontend/Frontend_utils.ml | 6 ++++-- src/frontend/Typechecker.ml | 16 ++++++++++++---- src/frontend/Typechecker.mli | 5 +++-- src/stancjs/stancjs.ml | 4 ++-- .../math/functions/pretty.expected | 2 -- test/integration/tfp/tfp_models/python_kwrds.py | 14 +++++++------- 6 files changed, 28 insertions(+), 19 deletions(-) diff --git a/src/frontend/Frontend_utils.ml b/src/frontend/Frontend_utils.ml index f9f9f585f7..565a101298 100644 --- a/src/frontend/Frontend_utils.ml +++ b/src/frontend/Frontend_utils.ml @@ -12,7 +12,7 @@ let typed_ast_of_string_exn s = Typechecker.check_program ast |> map_error ~f:(fun e -> Errors.Semantic_error e)) |> Result.map_error ~f:Errors.to_string - |> Result.ok_or_failwith + |> Result.ok_or_failwith |> fst let get_ast_or_exit ?printed_filename ?(print_warnings = true) filename = let res, warnings = Parse.parse_file Parser.Incremental.program filename in @@ -24,7 +24,9 @@ let get_ast_or_exit ?printed_filename ?(print_warnings = true) filename = let type_ast_or_exit ast = match Typechecker.check_program ast with - | Result.Ok p -> p + | Result.Ok (p, warns) -> + Warnings.pp_warnings Fmt.stderr warns ; + p | Result.Error error -> Errors.pp_semantic_error Fmt.stderr error ; exit 1 diff --git a/src/frontend/Typechecker.ml b/src/frontend/Typechecker.ml index 807fd1981d..4516eaa6c8 100644 --- a/src/frontend/Typechecker.ml +++ b/src/frontend/Typechecker.ml @@ -19,6 +19,14 @@ module Env = Environment (* we only allow errors raised by this function *) let error e = raise (Errors.SemanticError e) +(* warnings are built up in a list *) +let warnings : Warnings.t list ref = ref [] + +let add_warning (span : Location_span.t) (message : string) = + warnings := (span, message) :: !warnings + +let attach_warnings x = (x, List.rev !warnings) + (* model name - don't love this here *) let model_name = ref "" let check_that_all_functions_have_definition = ref true @@ -570,9 +578,9 @@ and check_expression cf tenv ({emeta; expr} : Ast.untyped_expression) : desired you can write the division as" hint () Fmt.text "If rounding is intended please use the integer division \ - operator %/%.\n" + operator %/%." in - Warnings.pp Fmt.stderr (x.emeta.loc, s) + add_warning x.emeta.loc s | _ -> () in warn_int_division le re ; check_binop loc op le re @@ -1465,7 +1473,7 @@ let check_program_exn ; transformedparametersblock= tpb ; modelblock= mb ; generatedquantitiesblock= gqb - ; comments } as ast ) : typed_program = + ; comments } as ast ) = (* create a new type environment which has only stan-math functions *) let tenv = Env.create () in let tenv, typed_fb = check_toplevel_block Functions tenv fb in @@ -1487,7 +1495,7 @@ let check_program_exn ; comments } in verify_correctness_invariant ast prog ; - prog + attach_warnings prog let check_program ast = try Result.Ok (check_program_exn ast) with Errors.SemanticError err -> diff --git a/src/frontend/Typechecker.mli b/src/frontend/Typechecker.mli index a2f19c799a..39f198a283 100644 --- a/src/frontend/Typechecker.mli +++ b/src/frontend/Typechecker.mli @@ -13,13 +13,14 @@ open Ast -val check_program_exn : untyped_program -> typed_program +val check_program_exn : untyped_program -> typed_program * Warnings.t list (** Type check a full Stan program. Can raise [Errors.SemanticError] *) -val check_program : untyped_program -> (typed_program, Semantic_error.t) result +val check_program : + untyped_program -> (typed_program * Warnings.t list, Semantic_error.t) result (** The safe version of [check_program_exn]. This catches all [Errors.SemanticError] exceptions and converts them diff --git a/src/stancjs/stancjs.ml b/src/stancjs/stancjs.ml index a7a7ea2744..78e3a70894 100644 --- a/src/stancjs/stancjs.ml +++ b/src/stancjs/stancjs.ml @@ -45,8 +45,8 @@ let stan2cpp model_name model_string is_flag_set = |> Result.map_error ~f:(fun e -> Errors.Semantic_error e) in typed_ast - >>| fun typed_ast -> - let warnings = parser_warnings in + >>| fun (typed_ast, type_warnings) -> + let warnings = parser_warnings @ type_warnings in if is_flag_set "info" then r.return (Result.Ok (Info.info typed_ast), warnings, []) ; if is_flag_set "print-canonical" then diff --git a/test/integration/good/function-signatures/math/functions/pretty.expected b/test/integration/good/function-signatures/math/functions/pretty.expected index 18d091fe11..acdc5ed167 100644 --- a/test/integration/good/function-signatures/math/functions/pretty.expected +++ b/test/integration/good/function-signatures/math/functions/pretty.expected @@ -2467,7 +2467,6 @@ Values will be rounded towards zero. If rounding is not desired you can write the division as d_int * 1.0 / d_int If rounding is intended please use the integer division operator %/%. - Warning in 'operators_int.stan', line 26, column 27: Found int division: d_int / d_int Values will be rounded towards zero. If rounding is not desired you can write @@ -2569,7 +2568,6 @@ Values will be rounded towards zero. If rounding is not desired you can write the division as d_int * 1.0 / d_int If rounding is intended please use the integer division operator %/%. - Warning in 'operators_real.stan', line 69, column 27: Found int division: d_int / d_int Values will be rounded towards zero. If rounding is not desired you can write diff --git a/test/integration/tfp/tfp_models/python_kwrds.py b/test/integration/tfp/tfp_models/python_kwrds.py index 096626332e..1e89a75f2b 100644 --- a/test/integration/tfp/tfp_models/python_kwrds.py +++ b/test/integration/tfp/tfp_models/python_kwrds.py @@ -1,3 +1,9 @@ +Warning in 'stan_models/python_kwrds.stan', line 13, column 12: Found int division: + lambda / 3 +Values will be rounded towards zero. If rounding is not desired you can write +the division as + lambda / 3.0 +If rounding is intended please use the integer division operator %/%. import numpy as np__ import tensorflow as tf__ @@ -54,13 +60,7 @@ def parameter_bijectors(self): def parameter_names(self): return ["finally__"] -model = python_kwrds_modelWarning in 'stan_models/python_kwrds.stan', line 13, column 12: Found int division: - lambda / 3 -Values will be rounded towards zero. If rounding is not desired you can write -the division as - lambda / 3.0 -If rounding is intended please use the integer division operator %/%. -Identifier finally is a reserved word in python, renamed to finally__ +model = python_kwrds_modelIdentifier finally is a reserved word in python, renamed to finally__ Identifier assert is a reserved word in python, renamed to assert__ Identifier lambda is a reserved word in python, renamed to lambda__ Identifier yield is a reserved word in python, renamed to yield__ From b645b7f0896b7a1848e847f52643e8a338a67132 Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Mon, 25 Oct 2021 15:23:33 -0400 Subject: [PATCH 12/15] Remove broken test See #1011 --- test/integration/good/pretty.expected | 9 --------- test/integration/good/shadow.stan | 7 ------- 2 files changed, 16 deletions(-) delete mode 100644 test/integration/good/shadow.stan diff --git a/test/integration/good/pretty.expected b/test/integration/good/pretty.expected index 2381a79ac6..afa526335b 100644 --- a/test/integration/good/pretty.expected +++ b/test/integration/good/pretty.expected @@ -5411,15 +5411,6 @@ generated quantities { real sd_y = sd(y); } - $ ../../../../install/default/bin/stanc --auto-format shadow.stan -parameters { - real pow; -} -transformed parameters { - print(pow(1, 1)); - print(pow); -} - $ ../../../../install/default/bin/stanc --auto-format single-arg-conddist.stan functions { real foo_lpdf(real x) { diff --git a/test/integration/good/shadow.stan b/test/integration/good/shadow.stan deleted file mode 100644 index 2d2d2dea8f..0000000000 --- a/test/integration/good/shadow.stan +++ /dev/null @@ -1,7 +0,0 @@ -parameters { - real pow; -} -transformed parameters { - print(pow(1,1)); - print(pow); -} From 6e614c95ef310dadb8fd9515630b016ae2e9dcb0 Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Mon, 25 Oct 2021 16:50:32 -0400 Subject: [PATCH 13/15] Update information flow graphic --- docs/img/information-flow.png | Bin 119468 -> 37670 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/img/information-flow.png b/docs/img/information-flow.png index 05be35226ddb0fa931743492f27009b1a709a047..90b5b658822e52c927a7e23aa04f8fa663478ed8 100644 GIT binary patch literal 37670 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 T=Q_md00000NkvXXu0mjfHU(Tx literal 119468 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

GZX%voj{^lhq^a_~3%@{+b zysFvSZp8tG8jm&a5g#Ed$-Y%^fte4a6Z>~Gp@5GX+XAO(?}6eb{RVuHq=Y5`Tj=hd z6k^D!UQ0zqMfcU`Q^hkO!b@)aK`=R2tYbV&pt?%y1PV3LOza|0#xY^NKRs#rA>kiQ z;_Dutt;a-^r*&Ol2$sV0!2mEKwq7}+8$Vz&8))*^9UXj7h&7xZCkM+VXMA?V4DC=( zCMG3R@bFiMI1p;{0d9^?)z@KYnQx|UxgB$z$s0~?kOw4x4S;}kQ&SkUoZRWJtZUa( z=27i$NROM$!NHK-FhjEw_dZntz2O_|HtlEkPrQ$4>M;6ps%xtV9>bONQMp%r|E#J$ zoU?0~n1Q)sqzCfsUtGoUNaE9;7(d^JrRm^w?jaw?YB3`Y^6hX@6Lqr%Rw|))zTmxs z(=bOl#Mp-H0S)xSmh{qwhK8%R9Xrr>+XZF3B@kvaTk4jeHT?jB6_RD z7`T)+#LTKX_v}LgU4ttGHkV=+&~ESmV*vOC5tIje;N&tZnsYF!QKyfGn4ZWwx$P5y zV!+v&WV^p5GvJSz;U6zBa`G1 z7P0%&8JV%Z`XCgG#Gj8LLb2~;bJ?SbU<492Ius>-$jl?*_<$A(cGTVTyOr3>fpQY- zE^zt^Y~BjW3`jMEo}2X@0xJb%Tp`oBJ(E z{wGj0?ilrkyXfM&(WLt&CntBlI)NT!LWemV`bu=C>sdCEs1%f#8|I3@&|&(l6{p}N z(g{%6_yJNcbAi{040FL-Jc&dNn5T2gXfz%jNdOY5k+B8Xr3U`krJ0qP`JB<=p9<4f zHsa8*xl~;el+u`$l`vWDcM?kM6 zT_-w|_vt5}5TiSwM|>pLi8f4#nnk56W5XpV-*iq9fi3dkt8 zH_kQ^VP|(*chALNU-uJ!VgfP}bvRcL?rYa_*EzVsF5y&_tmSz6_VJLcn zWnxvX?AUOO^g9G+%PFM?=AB92HDl|SaySuj; zq;X?k5;HKh0po&JQV0J22LUp=y|(zZ@I=4#KjY%mtE(XV+JUw~(-Wn*wu_NXZ@epm zMq~q?jWmiOkO*%-rmnr@vL=~J282AVE-hPSl@A>xp4#r08z%fPZ)Z>68o`|Nahm`66?nnR zrrp&oH)A0@WZ@MtSNpH))hpy@*u54~e3kE_IE<7fkU{YbYIC2C?(lH6}gnGx7+dCVM!pvyC&ExGC)0KpuEPVI!U=t`*YA$bcfK z9PT?GaC6n2L96I|AS77}q0Zf6N3@uzx^B53EyywVEXoQXPDIHV@a$CCkJ9_kJ1E~IFcIMoB zu;l3hFGC5Nwt{&V6B(Z&LzxcMRR&$+2Jx$De&H>^CH^S?r3D3xiHaEK06Dm9$oRrA zAw{NxHg(Z^VP4Dxeoh@kHFBe{P!ay!ayw|$NQ_q|aMd5(H=Z*WsM+wp6QSL2)Xe2}pr!G0h>72A7{vlnbd&0QcH!f8V9Pjs7}tm! zW0WPQ{K}5I_)^LDhGlqBqv{MCb z8K_is&*A0U0F#QFva_*iK&MDUqye~}U*nC_7Oh}{{#AT{AEN|zjMhfn;g*DUh3Db? zEI9z>dCBYb8{!osB010&Ty4=9QApE`UZ4`rSZ12vP@-2jp$IRmKUnJBU2CqbN)(QG z6U0|xT92iS)c_;_Zx#$90uxzjRB^lg0z5~8&cL^>YrBLlB{(e1^8R%1dmy8d*a%fO zmyYnNk+LJOo0Ce4NN;iFlZS*nnwzLgP9n(Z2`s0mxqLx1+0<-qV`1)O0SgM7?Yhu@ zG{iOLQKZ5o(H&6yTHsFzi=h*ze24r`1XY3(P|H*Cd=r5mcZys`T;%tz?(Q%9h_a1P z!zcsE%ol2jCnJL+<3V~K0k7YCKNY(UN4}fFupboqY`9B+#B-vF%F}P@vSneeB0`t% z>Py$#?lYMa6F-iU{fi_E7;-m}{A~;uWhC;a7txA}{VSOP`TAim3L#1Xnr(7NA@0rx zP-;V(EPk0Fq{Nddj0`*hwN5@3%lci+K>lP>5y8!Zt0^821VILZAaV4FN*|vGu&3OM z*evfQ1_@S7{7ZGddw*R=OO|wHals#niKj<#IuYqI>>WfDM-nRVjkc%+kmCs+1spk= zh-5AwBwGOM6#;8O_+wN;38VI;xWfT@J(eY)j`E3IUKACZL!YCphNVZ8%Wp`svhpMhx*K1hZ(sE&$c2R>Th#FbMlZB%UH;R23U<>8C=xoacqmEl64e zQMrAui`jr?wE~fP4o-#tWdqceeZ<<9^qOVWvbsf&SmEHQ>V-1=D zdm&&eER5o1jsw#Kg~dLI*NOOrkfwxqik5d)SAiP!7Hs)3F0}4rXfV6p?zzjdYSpdE$zytLfq2Q1fXcZ*WxEebM zxl6VEHcoJE6B#o!t#3icoP$KX9SM8TIuJsFM3rNr1E|B&+FDjzWH@m>262Hg;Slyg zkA=$aIu3YR8uC$r$MS+!K)5v|EhK7*Flj)3*L$+(-Nk(k4hq0DJ?Z6fPM(ARBO2hu zoCAVfGEY^q6%V47IR)`QDL#RCXPs``f}uU%unLV{oD)K6DTLc z*c(3$UI8g?yFI2ySRo?9^RGzrChZ$$jjBRmP9`gm>Ym&@LcxKJjr03ml+qD~KlJe240GlZzs;|L5G9mVT{j>)1|NMgVw}t%Vn%8m%7r^_SEcUSjzbIJ?a@+ zkOe!Dgg2~EqrHq_gT{og^q>|#QWl^Qh3zVK^sZhIvapE?8S>Hr|rU8nVi}Tr}o@DRz&*r>>eyZYFGJT zRZZ;Cmfhi#}Jxy5D!Ei2XUlEhu+FS!uAA6e^WDIV!N-|}Z3Mt1>>9T9}oNIiyJ z1z-jHk-3FWbDd<&VO=44a;-~l{fr5TBq3Av(sWU$kdQQTLgDr%W5&P{ZiXOhhu1nh zd?1c$fHHStoC&h5R0zL=*>W2f~aSoVKk1bedk!#sj`hg(I4y-O=9mK}Y3s6n2KcilP>#qN8;T7B8Su|uls zUjHbZxD2+^;tx)R3*m9fp6h`&qugAY2)nSuC{r~Ta{B~l#*aoz{!Wr<0&+n^B@}vX z98xg$?j0QimRO}6fLgEr6ZOUUq_jGyDK5}?qaY@%?kB?MUTB5KMg2cX%*^^$=M@hS zBa2j*U6+Z`2$VB+9MSgvnt^Nt1qzOB5!1FD8+Pn%+=dR*?^d)uw_`%>2IS3mzAj2G z<2Q?SU9_l)GUUX+l;m8k>TnKQc4ejQrKcgxNp!L7g%7dVY*JR$+^ozv3`E#`CZR`N zPVnGXvVY6G+Fm2}qr7P|?$wVJFX)D-i|b|qI6G8RbsWdPI$#pj=UivEb%=_<-_*DEvE-WHDGg@HmFcjzg; zN_+mxnbxjg=EpR;9oKQsXO&GMeDOl-2j0~-N+wZZVH3toHoYHs4}d+Vya;asaRRXq zxxul+Znc0t5Ztj&ZqlUw{rj*E>rj`mItW@&m0>kNK(fIh6=;kGy$@VrgRJejGN(VP z=aPA;No|)-;51s>Mgp%o6(FnF^*iQy)2Iz(P!{f3c`Q?MP+KL&mIzjY)EHhhOk$E5 z2R$K2Ni@YZ&C+awfi0Bz|2!6blb8-74=1_7*ZNW;8#7>atK4T(*X%+bUUHuyiU#ay zUwRjWUtmMs7jIOSE@b|X}9|G&EDN8E0)qAy=EPVRMfVxbkS@rewYz$PhC}v7ndW-~ znsb)bI>2pC*RbWY&(ytrGj&7sr6^FrhBQhwjszPzH9-Pq`{{~wrgU~ zVL@%s!Ku&E4BS16G6|F9wt?ri4X@3W{!8KOk$C}Q2~k$4Jvzd}d$%ogbCCS)+qc8` zo?xhWQ));GT-J?h0?%4Yy;4(2Ct|M9J_2k&;Zkqx!5T=IQ~HvBUTTD2w&Q!<_g&?hch2{ z@pNPWC*CjMGG>crKsCEyAiFT{G9aaY)F#gJaef^% zR{LY{E4>S+4or`4S;p{ofb_s3BpE$y?+@S2kXO)T`;Gt(7!=cm4hQ*USAmxUpxrOK z?rN5IJc>Sxh^IAqcN*B3d+TDhN4b!jQ=>&&ON-M5d2?s~`F#?!n%mg3r9=cjycfbo zzg?FW+ei$}Up*sUHofK;mPXuu(V5;)cOM!CwbFk-d0kj*OP}e^sc9H)`N7Dj`%{1U zA8@wqnl;0$+2VQQS6;=x`A>K0Sk`nwf;_7?17ISJ%x(DlbHjl_q2_dslkC{@swJ>2 z$GF^C#(?&2ZB4GtyZmF#^2`Lih&rz4yu~OEPy)oegp(0H^8Gnmt34-&?W_A~LB2KB z(cY@gh5NB=(k~rlON@v=9CBOt;pz8;(rmRw<_KlbR-j1Stb~__)UDJ$-Zg8ia#>GZ zF&ow#1R`FMGHqoCVIa=X&FZfvYJ0mNRX-3i!f+>VZhog=rof|7z(8k~uG%nVqwHOR zFpT*@p;+F67NBAfji4rq6Co`>kshh(wZ1t1u`nl;Do8uNE(0a%N>n3-Ws|->KI$i& z`^0JD$3HQeFfahpT~mX0=l0pIW2*7aWdM$$hyDN>J)7mwpN7{wm3NnExVv=dg7d! zDgpHeV2Xeil!g8f!uC7lpgpyYd)`83tGlo*;O&qKZYqLXvBrLzAQ3QQiFl4fpe;4% z*|Qp@b#^5cNu*`p70{Wf;?5E;2hG=e*K9u}*asj5u7 zJ@1K;hnvEeEnD{E(5GbRE?Ll#TTGj*BICF*LW=n5z+Py88#|2t77@2J*oo3F$brei zJf!(!cF)G_^{AbWFg{`r7h6tpQ-uaJG&HKiPg_^s7kJ@ya=+OEXUeuMA3}v2$2kB@nth5vex5xAm0pDu+Owpf0HOlh-;pN0ARzCgJ{5aN zyYx3u9JDyg;2qd$JnHi3@#92b62CDHXu@=}`E5LkJT~HZIWtjB5G?gAOJ6Bs3v>$6*i+I9Moy%p0QH z1MzBsPp9BO?2?YqLm+^V%s@9%MzgC70yOmoL8}T<^nj5{Q|Jd=mVtYBqHl zc>T-~#^~7{C4(h~ta1Mykfj)j9@^+PLwxxtUWos5xY&RCRts zv7RQaWe$!XUKuj$nM%3xHxBj^3O0?n@Py@&027mQ?hy4U6xr(>nlj7;h!)2I(_d?P zm7yC>(%~B(O+_0HJWuBZJq^J?fLpwO>G9PCCfg){u-0+&_0hokAq=tMXbcD>(&GeUmm^hMI zFEavl{UE=IodzZW3)gW}2!d$Llj}gVTQVsCm8n29Y!>1pZ)1QJzLxBk@-Y-v-vBXa zsH-zTVaw9pRJI@CfmXx7_)w~S1z)HJivz6GXotx_yXkpbl^Z9_V$$wMVl4K7j}Jv8<_q9r2w%qMXWO+QV^p=D@aNK9nC%3}rxHqXS{mrk zN^vw;O?%lXccI3zfI97K+OxvK!cKaMO@gO)hA0|*oW8Uu$F74rBi#px;a$JO{GgG% z<$_^fS0Paz{6x)j*nnq;CW=L8-vgQVDTu!Umqx-w0d}GFUj=A|9D!oph(+0LT^}p% zr3SxHcII9#QH{yHrUZEF_6 z!CB89oYmq&P0&I?TkK3tqOd9*kwT>SCsCvwqr$7V`3eFsGqzWY{W0CX;RQ#OM&?Q; zNB-L-_UIq~jqHOM9B>eNUBk})im?^@@Z>?LN@A8d+T|Y(eK;(u?n}hgT?M)gE{lx6 z;^g6Znv(|gLH2AZ~N0O^>y39wF1zHL_RcC+`m( za%)aJ^7I4P&f+gI={WTFItoCQc~{Pn1WvO+{EU&r+#ubrBNKYiq0hx@DMJCf=ZOhQ zr{Y&DhuhqMq~S)mFaV25)q)1ZzaIHi0JhZ80X$oeL3q6m=4q=rQ&=!LZHfxe?_hEr z{>I9I70sKYN#5fLPkv4c@lA=+Gabwz>k8$b2EGvDdgkZGtROg{U?IcEpq799PS(Q0 z;sfIO2&jXdN9LF^7Vk^fxwj z&xZkk;i+Q=MRMKM1Nd)}5bF`x3@%xs-X2PO_L$(BByH`4ju-B0;^RRR3bI}V`+=DF zfhBH;?sr6Sll_N#S4Cwd6V8J*p%Q`Il5|LgX?VI0MiqR~U~bg^p(=p5VJ(VLk+k*m z7}!kU9g+kll6?<=?Jx#GULd#f{75Sv0D)$YWtj32;{${XXw9+F{O}1PI_j|L31Uv( zAh3d;)6)disMw?`f((0f-xh$kJTi(JATCpPbK6ZWIx{mf9Mz;CC5_9A*IN`JKsR+Y zD|(7{*atxGfJ04WS3O!BOXushi#veQ+(0{wj!Xc#F_OP8)z2se`TMK>lL!z)KLhX~ zfkekIs*ngtbsD5m#Z~cFq=+IO3?rTb+#;{{%0)gm#lIkucY>P2gSQ4KVYSMm(>up?9ku z^G_d;XZr69bFmcEc~~|^qxTdj#3_PDtd8|Dsq#KG*qT+U1y>!>q?J_dP7*ro$Uxy>_3$8t=G6pP|r(Kc^ zeaM9glXt;LfUuvsQbur-AVtJuD;_y|RC|g9O<*+>%nm4iFzaZfeObhmyLwpC5)VY4 zR@ey8V&c766fi)|LHa0EN1Pir1Rx_4#}YTmcPIG>1l}Zp4Oke%3g48e{Qu)oplG^^ ztQt!GW)u{sAcGGak)m8B_1dbXdW|jI-{15PuDqSjy@v=W0DLO@FhNlITQUTo!>uq` z5zYPIzv+)^DB$hw#ZZ&mG)FUh=l$<*+CR+azkmM&qW|{`$aDVx+H-(r(ro|2scJ<^hI{rj<{?;Py8^oLH{{_l??@8SRO zVdi2eo4|N;0|FtX9YE!jhOuX~=J-{<%K`TC<}%*^** z&VBB4u5-?HaE~&fXG4&di>w305n^F`es9WFCgpJ`_e!lmly@yiEe__*aVLF)LBG3# zwB#a@Q)IZatKI(l-a^y_zebD40H;Yw8fn9v(s(j$9XS)b*@8Z=;qpc{Nnvld5B!G% zIXP&M9t(@sraliQC@~cXSCOo2S$E&3Y&~0&7E*Hj&v95gpN8r&4N)Ovx$h^MR2KW5mAAyjmYcrqZng;h-&`@lfAb@9d_|L-90;vtc@ z5FTz=>Lqp48=aY?I+n2EV(AMpAV(0tlL#;}Dy=5rJ}bPK#ySyGm;}M_Drw5>h;}e1 zK0TX-EDRV2q-7YWDRzw>1zwChkFoEepmB;hyS@$q$y-YHqNGGrLc-3N=?MQEOjn`+ zowmd3B5xzTk}PsP052kbj>MR!-9r$M^#8U&l!gfO>!P9^qBPjV3I``UlQ{}-P7rrN zU4$R*@P;%*^q7y01Jp?YhV2xw`T>c6T;=8~s+O`?8?8)zdWu8s?iuhNJ4+ z88o9n95h0ZAEpcGzC?JG2&uz~2IS~|X>DEdiTFAN(_n+J|D!Pv%hA!z;kle7MvGud zDOT_ZGiH3(D)iMtK1I%19Oz{e@3DssX-K6$q^9%@Hq(X|cagbWP*bz-Svm?&@2V27 z;~0rQ^EOJXwPcmDV&J@xXci3n=61xu=AA?e1AX1PsxPD1JOb?zrT;e%H?X3bS^R>F zBtHeD^KfGx-*$m1yKzn(KrTrL1%T0i6NXTxaOLgD_0Z729a1dvyfo*QEmS;4%7>7+ za=#Bc4PhpjBoCC|y$8ayuEF&v?0?Nn9X6i_`*t961(30uY1u3HY_rNi=31QVs!}D_7+HXv#tpCR&fApalTB=00ph)v+)kbbN}`kG&_(!w1mp z!5M0HI2n-yFbg|?*f@j**j?`TgGhWUH%0A@Me=$?CI{T%Ll^ac319J(Un+~h6)vkT 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 Date: Mon, 25 Oct 2021 16:56:02 -0400 Subject: [PATCH 14/15] Update readme --- README.md | 11 ++++++----- docs/img/information-flow.png | Bin 37670 -> 56620 bytes 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d04104f5c8..af9bb34cfc 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,9 @@ digraph G { rankdir=TB; ranksep=.25; bgcolor=white; + size=5; node [shape="box"]; - + origin[style=invis]; stanc[label="stanc/stanc.ml"]; lexer[label="frontend/lexer.mll"]; @@ -32,9 +33,9 @@ digraph G { optimize[label="analysis_and_optimization/Optimize.ml"]; codegen[label="*_backend/*_code_gen.ml"]; output[shape="oval" label=".hpp file"] - - origin -> stanc[label=" .stan file path"]; + + origin -> stanc[label=" .stan file path"]; stanc -> lexer[label=" string"]; lexer -> parser[label=" tokens"]; parser -> type[label=" untyped AST"]; @@ -44,8 +45,8 @@ digraph G { transform -> codegen[label=" "]; optimize -> codegen[headlabel="optimized MIR "]; codegen -> output[label=" C++ code"]; - -} + +} ---> ![stanc3 information flow](docs/img/information-flow.png) diff --git a/docs/img/information-flow.png b/docs/img/information-flow.png index 90b5b658822e52c927a7e23aa04f8fa663478ed8..2956f7abaddb74eb5f90664ed028f4ebe2370fb9 100644 GIT binary patch literal 56620 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 T=Q_md00000NkvXXu0mjfHU(Tx From 31e04c11a9b84c42955656d477849f7e2fff3741 Mon Sep 17 00:00:00 2001 From: Brian Ward Date: Wed, 27 Oct 2021 14:52:41 -0400 Subject: [PATCH 15/15] Updates per latest review --- src/frontend/Environment.mli | 2 ++ src/frontend/Info.mli | 1 + src/frontend/Typechecker.ml | 2 ++ src/frontend/Typechecker.mli | 2 ++ test/integration/tfp/dune | 12 ++++++--- .../tfp/tfp_models/python_kwrds.py | 27 +------------------ test/integration/tfp/tfp_models/tfp.expected | 26 ++++++++++++++++++ 7 files changed, 43 insertions(+), 29 deletions(-) create mode 100644 test/integration/tfp/tfp_models/tfp.expected diff --git a/src/frontend/Environment.mli b/src/frontend/Environment.mli index 5927c80d94..74fdb80c87 100644 --- a/src/frontend/Environment.mli +++ b/src/frontend/Environment.mli @@ -1,3 +1,5 @@ +(** Type environments used during typechecking. Maps from strings to function or variable information *) + open Middle (** Origin blocks, to keep track of where variables are declared *) diff --git a/src/frontend/Info.mli b/src/frontend/Info.mli index 3c9898b72d..a21aa8f717 100644 --- a/src/frontend/Info.mli +++ b/src/frontend/Info.mli @@ -10,6 +10,7 @@ - [type]: the base type of the variable (["int"] or ["real"]). - [dimensions]: the number of dimensions ([0] for a scalar, [1] for a vector or row vector, etc.). + The JSON object also have the fields [stanlib_calls] and [distributions] containing the name of the standard library functions called and distributions used. diff --git a/src/frontend/Typechecker.ml b/src/frontend/Typechecker.ml index 9c3883404f..352b6a28b8 100644 --- a/src/frontend/Typechecker.ml +++ b/src/frontend/Typechecker.ml @@ -3,6 +3,8 @@ Functions which begin with "check_" return a typed version of their input Functions which begin with "verify_" return unit if a check succeeds, or else throw an Errors.SemanticError exception. + Other functions which begin with "infer"/"calculate" vary. Usually they return + a value, but a few do have error conditions. All Error.SemanticError excpetions are caught by check_program which turns the ast or exception into a Result.t for external usage diff --git a/src/frontend/Typechecker.mli b/src/frontend/Typechecker.mli index 39f198a283..3cc21e9f3d 100644 --- a/src/frontend/Typechecker.mli +++ b/src/frontend/Typechecker.mli @@ -3,6 +3,8 @@ Functions which begin with "check_" return a typed version of their input Functions which begin with "verify_" return unit if a check succeeds, or else throw an [Errors.SemanticError] exception. + Other functions which begin with "infer"/"calculate" vary. Usually they return + a value, but a few do have error conditions. All [Error.SemanticError] excpetions are caught by check_program which turns the ast or exception into a [Result.t] for external usage diff --git a/test/integration/tfp/dune b/test/integration/tfp/dune index 09d75b094b..a793f9cc3b 100644 --- a/test/integration/tfp/dune +++ b/test/integration/tfp/dune @@ -35,13 +35,19 @@ (targets python_kwrds.py.output) (deps (package stanc) (:stanfiles ./stan_models/python_kwrds.stan)) (action - (with-outputs-to %{targets} - (run %{bin:stan2tfp} %{stanfiles})))) + (with-stdout-to %{targets} + (with-stderr-to "tfp.output" + (run %{bin:stan2tfp} %{stanfiles}))))) (alias (name runtest) (action (diff ./tfp_models/python_kwrds.py python_kwrds.py.output))) + +(alias + (name runtest) + (action (diff ./tfp_models/tfp.expected tfp.output))) + (rule (targets transformed_data.py.output) (deps (package stanc) (:stanfiles ./stan_models/transformed_data.stan)) @@ -50,5 +56,5 @@ (run %{bin:stan2tfp} %{stanfiles})))) (alias - (name runtest) + (name runtest) (action (diff ./tfp_models/transformed_data.py transformed_data.py.output))) diff --git a/test/integration/tfp/tfp_models/python_kwrds.py b/test/integration/tfp/tfp_models/python_kwrds.py index 1e89a75f2b..577802c943 100644 --- a/test/integration/tfp/tfp_models/python_kwrds.py +++ b/test/integration/tfp/tfp_models/python_kwrds.py @@ -1,9 +1,3 @@ -Warning in 'stan_models/python_kwrds.stan', line 13, column 12: Found int division: - lambda / 3 -Values will be rounded towards zero. If rounding is not desired you can write -the division as - lambda / 3.0 -If rounding is intended please use the integer division operator %/%. import numpy as np__ import tensorflow as tf__ @@ -60,23 +54,4 @@ def parameter_bijectors(self): def parameter_names(self): return ["finally__"] -model = python_kwrds_modelIdentifier finally is a reserved word in python, renamed to finally__ -Identifier assert is a reserved word in python, renamed to assert__ -Identifier lambda is a reserved word in python, renamed to lambda__ -Identifier yield is a reserved word in python, renamed to yield__ -Identifier await is a reserved word in python, renamed to await__ -Identifier finally is a reserved word in python, renamed to finally__ -Identifier finally is a reserved word in python, renamed to finally__ -Identifier assert is a reserved word in python, renamed to assert__ -Identifier yield is a reserved word in python, renamed to yield__ -Identifier lambda is a reserved word in python, renamed to lambda__ -Identifier finally is a reserved word in python, renamed to finally__ -Identifier lambda is a reserved word in python, renamed to lambda__ -Identifier await is a reserved word in python, renamed to await__ -Identifier finally is a reserved word in python, renamed to finally__ -Identifier assert is a reserved word in python, renamed to assert__ -Identifier assert is a reserved word in python, renamed to assert__ -Identifier finally is a reserved word in python, renamed to finally__ -Identifier assert is a reserved word in python, renamed to assert__ -Identifier assert is a reserved word in python, renamed to assert__ -Identifier lambda is a reserved word in python, renamed to lambda__ \ No newline at end of file +model = python_kwrds_model \ No newline at end of file diff --git a/test/integration/tfp/tfp_models/tfp.expected b/test/integration/tfp/tfp_models/tfp.expected new file mode 100644 index 0000000000..1f544968d2 --- /dev/null +++ b/test/integration/tfp/tfp_models/tfp.expected @@ -0,0 +1,26 @@ +Warning in 'stan_models/python_kwrds.stan', line 13, column 12: Found int division: + lambda / 3 +Values will be rounded towards zero. If rounding is not desired you can write +the division as + lambda / 3.0 +If rounding is intended please use the integer division operator %/%. +Identifier finally is a reserved word in python, renamed to finally__ +Identifier assert is a reserved word in python, renamed to assert__ +Identifier lambda is a reserved word in python, renamed to lambda__ +Identifier yield is a reserved word in python, renamed to yield__ +Identifier await is a reserved word in python, renamed to await__ +Identifier finally is a reserved word in python, renamed to finally__ +Identifier finally is a reserved word in python, renamed to finally__ +Identifier assert is a reserved word in python, renamed to assert__ +Identifier yield is a reserved word in python, renamed to yield__ +Identifier lambda is a reserved word in python, renamed to lambda__ +Identifier finally is a reserved word in python, renamed to finally__ +Identifier lambda is a reserved word in python, renamed to lambda__ +Identifier await is a reserved word in python, renamed to await__ +Identifier finally is a reserved word in python, renamed to finally__ +Identifier assert is a reserved word in python, renamed to assert__ +Identifier assert is a reserved word in python, renamed to assert__ +Identifier finally is a reserved word in python, renamed to finally__ +Identifier assert is a reserved word in python, renamed to assert__ +Identifier assert is a reserved word in python, renamed to assert__ +Identifier lambda is a reserved word in python, renamed to lambda__ \ No newline at end of file