Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 39 additions & 3 deletions src/frontend/Semantic_check.ml
Original file line number Diff line number Diff line change
Expand Up @@ -290,9 +290,45 @@ let semantic_check_fn_normal ~is_cond_dist ~loc id es =
| 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)
| None -> (
let gen_prefix l = String.concat ~sep:"_" (List.rev l) in
match List.rev (String.split id.name ~on:'_') with
| (("lpmf" | "lupmf") as suffix) :: tl
when Utils.is_distribution_name
(String.concat ~sep:"_" (List.rev tl @ ["lpdf"])) ->
Semantic_error.returning_fn_expected_wrong_dist_suffix_found loc
(gen_prefix tl, suffix)
|> error
| (("lpdf" | "lupdf") as suffix) :: tl
when Utils.is_distribution_name
(String.concat ~sep:"_" (List.rev tl @ ["lpmf"])) ->
Semantic_error.returning_fn_expected_wrong_dist_suffix_found loc
(gen_prefix tl, suffix)
|> error
| suffix :: tl
when List.mem Utils.cumulative_distribution_suffices_w_rng suffix
~equal:String.equal ->
let prefix = gen_prefix tl in
let known_families =
List.map
~f:(fun (_, y, _, _) -> y)
Stan_math_signatures.distributions
in
let is_known_family s =
List.mem known_families s ~equal:String.equal
in
if is_known_family prefix then
Semantic_error.returning_fn_expected_undeclared_dist_suffix_found
loc (prefix, suffix)
|> error
else
Semantic_error.returning_fn_expected_undeclaredident_found loc
id.name
|> error
| _ ->
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 =
Expand Down
28 changes: 28 additions & 0 deletions src/middle/Semantic_error.ml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ module TypeError = struct
| ReturningFnExpectedNonReturningFound of string
| ReturningFnExpectedNonFnFound of string
| ReturningFnExpectedUndeclaredIdentFound of string
| ReturningFnExpectedUndeclaredDistSuffixFound of string * string
| ReturningFnExpectedWrongDistSuffixFound of string * string
| NonReturningFnExpectedReturningFound of string
| NonReturningFnExpectedNonFnFound of string
| NonReturningFnExpectedUndeclaredIdentFound of string
Expand Down Expand Up @@ -168,6 +170,22 @@ module TypeError = struct
"A returning function was expected but an undeclared identifier \
'%s' was supplied."
fn_name
| ReturningFnExpectedUndeclaredDistSuffixFound (prefix, suffix) ->
Fmt.pf ppf "Function '%s_%s' is not implemented for distribution '%s'."
prefix suffix prefix
| ReturningFnExpectedWrongDistSuffixFound (prefix, suffix) ->
let newsuffix =
match suffix with
| "lpdf" -> "lpmf"
| "lupdf" -> "lupmf"
| "lpmf" -> "lpdf"
| "lupmf" -> "lupdf"
| _ -> raise_s [%message "This should never happen."]
in
Fmt.pf ppf
"Function '%s_%s' is not implemented for distribution '%s', use \
'%s_%s' instead."
prefix suffix prefix prefix newsuffix
| NonReturningFnExpectedUndeclaredIdentFound fn_name ->
Fmt.pf ppf
"A non-returning function was expected but an undeclared identifier \
Expand Down Expand Up @@ -496,6 +514,16 @@ let returning_fn_expected_nonfn_found loc name =
let returning_fn_expected_undeclaredident_found loc name =
TypeError (loc, TypeError.ReturningFnExpectedUndeclaredIdentFound name)

let returning_fn_expected_undeclared_dist_suffix_found loc (prefix, suffix) =
TypeError
( loc
, TypeError.ReturningFnExpectedUndeclaredDistSuffixFound (prefix, suffix)
)

let returning_fn_expected_wrong_dist_suffix_found loc (prefix, suffix) =
TypeError
(loc, TypeError.ReturningFnExpectedWrongDistSuffixFound (prefix, suffix))

let nonreturning_fn_expected_returning_found loc name =
TypeError (loc, TypeError.NonReturningFnExpectedReturningFound name)

Expand Down
6 changes: 6 additions & 0 deletions src/middle/Semantic_error.mli
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ val returning_fn_expected_nonfn_found : Location_span.t -> string -> t
val returning_fn_expected_undeclaredident_found :
Location_span.t -> string -> t

val returning_fn_expected_undeclared_dist_suffix_found :
Location_span.t -> string * string -> t

val returning_fn_expected_wrong_dist_suffix_found :
Location_span.t -> string * string -> t

val illtyped_reduce_sum :
Location_span.t
-> string
Expand Down
5 changes: 5 additions & 0 deletions src/middle/Utils.ml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ let conditioning_suffices =
["_lpdf"; "_lupdf"; "_lupmf"; "_lpmf"; "_cdf"; "_lcdf"; "_lccdf"]

let conditioning_suffices_w_log = conditioning_suffices @ ["_log"]
let cumulative_distribution_suffices = ["cdf"; "lcdf"; "lccdf"]

let cumulative_distribution_suffices_w_rng =
cumulative_distribution_suffices @ ["rng"]

let is_user_ident = Fn.non (String.is_suffix ~suffix:"__")

let unnormalized_suffix = function
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
data {
}
model {
target += von_mises_ccdf_log(1, 0,1);
}
1 change: 1 addition & 0 deletions test/integration/bad/missing_dist_suffix/dune
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
(include ../dune)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
data {
}
model {
// known family, known suffix, not implemented
target += binomial_lpdf(1|0,1);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
data {
}
model {
// known family, known suffix, not implemented
target += normal_lpmf(1|0,1);
}
3 changes: 3 additions & 0 deletions test/integration/bad/missing_dist_suffix/no_rng_suffix.stan
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
generated quantities {
real x = multi_gp_cholesky_rng([[0,0],[0,0]], [1,0]);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
data {
}
model {
target += von_mises_cdf(1|0,1);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
data {
}
model {
target += von_mises_lcdf(1|0,1);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
data {
}
model {
target += von_mises_lccdf(1|0,1);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
data {
}
model {
target += von_mises_notasuffix(1,0,1);
}
120 changes: 120 additions & 0 deletions test/integration/bad/missing_dist_suffix/stanc.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
$ ../../../../../install/default/bin/stanc deprecated_suffix.stan
Semantic error in 'deprecated_suffix.stan', line 4, column 14 to column 40:
-------------------------------------------------
2: }
3: model {
4: target += von_mises_ccdf_log(1, 0,1);
^
5: }
-------------------------------------------------

A returning function was expected but an undeclared identifier 'von_mises_ccdf_log' was supplied.
$ ../../../../../install/default/bin/stanc lpmf_lpdf_replacement1.stan
Semantic error in 'lpmf_lpdf_replacement1.stan', line 5, column 14 to column 34:
-------------------------------------------------
3: model {
4: // known family, known suffix, not implemented
5: target += binomial_lpdf(1|0,1);
^
6: }
-------------------------------------------------

Function 'binomial_lpdf' is not implemented for distribution 'binomial', use 'binomial_lpmf' instead.
$ ../../../../../install/default/bin/stanc lpmf_lpdf_replacement2.stan
Semantic error in 'lpmf_lpdf_replacement2.stan', line 5, column 14 to column 32:
-------------------------------------------------
3: model {
4: // known family, known suffix, not implemented
5: target += normal_lpmf(1|0,1);
^
6: }
-------------------------------------------------

Function 'normal_lpmf' is not implemented for distribution 'normal', use 'normal_lpdf' instead.
$ ../../../../../install/default/bin/stanc no_rng_suffix.stan
Semantic error in 'no_rng_suffix.stan', line 2, column 12 to column 55:
-------------------------------------------------
1: generated quantities {
2: real x = multi_gp_cholesky_rng([[0,0],[0,0]], [1,0]);
^
3: }
-------------------------------------------------

Function 'multi_gp_cholesky_rng' is not implemented for distribution 'multi_gp_cholesky'.
$ ../../../../../install/default/bin/stanc non_existing_distribution_suffix1.stan
Semantic error in 'non_existing_distribution_suffix1.stan', line 4, column 14 to column 34:
-------------------------------------------------
2: }
3: model {
4: target += von_mises_cdf(1|0,1);
^
5: }
-------------------------------------------------

Function 'von_mises_cdf' is not implemented for distribution 'von_mises'.
$ ../../../../../install/default/bin/stanc non_existing_distribution_suffix2.stan
Semantic error in 'non_existing_distribution_suffix2.stan', line 4, column 14 to column 35:
-------------------------------------------------
2: }
3: model {
4: target += von_mises_lcdf(1|0,1);
^
5: }
-------------------------------------------------

Function 'von_mises_lcdf' is not implemented for distribution 'von_mises'.
$ ../../../../../install/default/bin/stanc non_existing_distribution_suffix3.stan
Semantic error in 'non_existing_distribution_suffix3.stan', line 4, column 14 to column 36:
-------------------------------------------------
2: }
3: model {
4: target += von_mises_lccdf(1|0,1);
^
5: }
-------------------------------------------------

Function 'von_mises_lccdf' is not implemented for distribution 'von_mises'.
$ ../../../../../install/default/bin/stanc non_existing_distribution_suffix4.stan
Semantic error in 'non_existing_distribution_suffix4.stan', line 4, column 14 to column 41:
-------------------------------------------------
2: }
3: model {
4: target += von_mises_notasuffix(1,0,1);
^
5: }
-------------------------------------------------

A returning function was expected but an undeclared identifier 'von_mises_notasuffix' was supplied.
$ ../../../../../install/default/bin/stanc user_defined.stan
Semantic error in 'user_defined.stan', line 7, column 13 to column 27:
-------------------------------------------------
5: }
6: model {
7: target += bar_lpmf(19.2);
^
8: }
-------------------------------------------------

Function 'bar_lpmf' is not implemented for distribution 'bar', use 'bar_lpdf' instead.
$ ../../../../../install/default/bin/stanc user_defined_no_cdf.stan
Semantic error in 'user_defined_no_cdf.stan', line 7, column 14 to column 29:
-------------------------------------------------
5: }
6: model {
7: target += bar_lcdf(1|0,1);
^
8: }
-------------------------------------------------

A returning function was expected but an undeclared identifier 'bar_lcdf' was supplied.
$ ../../../../../install/default/bin/stanc user_defined_no_rng.stan
Semantic error in 'user_defined_no_rng.stan', line 7, column 12 to column 23:
-------------------------------------------------
5: }
6: generated quantities {
7: real x = bar_rng(10);
^
8: }
-------------------------------------------------

A returning function was expected but an undeclared identifier 'bar_rng' was supplied.
8 changes: 8 additions & 0 deletions test/integration/bad/missing_dist_suffix/user_defined.stan
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
functions {
real bar_lpdf(real x){
return 1.0;
}
}
model {
target += bar_lpmf(19.2);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
functions {
real bar_lpdf(real x){
return 1.0;
}
}
model {
target += bar_lcdf(1|0,1);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
functions {
real bar_lpdf(real x){
return 1.0;
}
}
generated quantities {
real x = bar_rng(10);
}
9 changes: 9 additions & 0 deletions test/integration/tfp/stan_models/test_mat_corr.stan
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
data {
int K;
}
parameters {
cholesky_factor_corr[K] L;
}
model {
target += lkj_corr_cholesky_lpdf(L|2.5);
}