API Reference
Model Definition
StanBlocks.@slic Macro
Defines SlicModels (see test/slic.jl for usage examples).
The defining module is captured automatically via __module__, so that @deffun functions defined in the same module (e.g. a package extension) are found during symbol resolution.
A leading string literal inside the begin ... end block is captured as the model docstring and rendered as a // ... comment header in the generated Stan code.
StanBlocks.@deffun Macro
@deffun function_definitionDefine a Stan-compatible function with type inference and Stan code generation.
Parses a Julia-style function definition (with type-annotated arguments and return type), generates the corresponding Stan function, and registers type-inference signatures so the transpiler can propagate types through calls to this function. Definitions are Stan-only by default. Add @juliacompat to an eligible bodyful bare-symbol definition to install one callable Julia method from the original user-facing definition as well. Signature-only/type- token glue, qualified or pre-existing function extensions, and definitions whose own name is in the probability/RNG/ODE/reduce_sum family (*_lpdf, *_lpmf, *_lcdf, *_lccdf, *_cdf, *_rng, the elementwise *_lpdfs/*_lpmfs/… companions, and ode_*) remain Stan-only even when annotated.
The opt-in Julia target is a bounded deterministic compatibility layer: supported signatures, symbolic dimension checks, typed locals, control flow/mutation, nested deterministic calls, higher-order arguments, and varargs. In a @juliacompat definition, a direct probability/RNG/ODE/reduce_sum primitive call errors at expansion time. Remove the annotation when the definition is intentionally Stan-only. A probability-family definition is outside the layer by construction and gets no Julia method.
For functions ending in _lpdf/_lpmf/_lcdf/_lccdf, the return type is automatically set to real and companion _lpdfs/_rng stubs are generated for use in generated_quantities.
UDF bodies must not contain ~ sampling statements or target += increments — UDFs cannot introduce parameters or directly manipulate the log density. The macro errors at expansion time if either is found.
Standard Julia macros inside the body are expanded against the calling module before tracing, so @views, @., @inbounds, and user-defined macros work transparently.
Inlining
Annotating with @inline (or giving the function a Julia-convention trailing ! in its name) causes every call to be expanded at the call site instead of producing a Stan function:
@deffun @inline scale(x::vector[n], s::real)::vector[n] = x * s
@deffun set_first!(buf::vector[n])::vector[n] = (buf[1] = 42.; buf)Inline UDFs do not appear in Stan's functions {} block. Multi-statement bodies, vararg parameters, and higher-order function arguments are all supported. Locals are renamed per call site, and pre-statements hoist into the enclosing block.
@inline cannot be combined with @lhs / @lpxf.
Example
@deffun garch11_lpdf(y::vector[T], mu::real, alpha0::real, alpha1::real, beta1::real)::real = begin
sigma2 = alpha0
rv = 0.
for t in 1:T
rv += normal_lpdf(y[t], mu, sqrt(sigma2))
sigma2 = alpha0 + alpha1 * square(y[t] - mu) + beta1 * sigma2
end
return rv
endSee src/slic_stan/builtin.jl for many more examples.
StanBlocks.@juliacompat Macro
@juliacompat definitionOpt an eligible bodyful @deffun definition into the bounded deterministic Julia compatibility target while retaining the same SLIC/Stan lowering:
@deffun @juliacompat affine(x::real, a::real)::real = a * x + 1.0It may wrap one definition or a begin ... end group inside @deffun. Signature-only/type-token glue, qualified or pre-existing function extensions, and probability/RNG/ODE/reduce_sum-family definitions remain Stan-only. Within a @juliacompat begin ... end group, a nested @stanonly definition explicitly opts that member back out.
StanBlocks.@stanonly Macro
@stanonly definitionExplicitly mark a @deffun definition as Stan-only. This is the default, so the annotation is normally optional; it remains useful as documentation and to opt one member out of a surrounding @juliacompat begin ... end group:
@deffun @stanonly foo_rng(x::real)::real = stan_rng_primitive(x)It may wrap one definition or a begin ... end group inside @deffun.
StanBlocks.@defsig Macro
Utility macro to define function signatures (see src/slic_stan/builtin.jl for usage examples).
Note:
This macro is mainly useful for bulk built-in function signature definitions. StanBlocks.jl users should generally prefer using @deffun.
sourceStanBlocks.@usertype Macro
@usertype struct RaggedVector
mem :: vector
ends :: int[]
endDeclare a custom Stan-renderable record type. Lowers to a real Julia struct whose abstract supertype is StanBlocks.stan.types.usertype (added automatically); field type annotations are SLIC types and are kept only for documentation — fields are stored as Any so plain Julia construction works for data plumbing. Method dispatch on the type tag (Base.length(r::RaggedVector)) works via standard Julia. Stan-side, values render as positional tuples; field access (r.mem) reuses the existing ntup machinery.
Sampling-form Dispatch
StanBlocks.@lpxf Macro
@lpxf foo_lpdf
@lpxf begin foo_lpdf; bar_lpmf endRegister the three SLIC dispatch hooks (lpxf_expr, rng_expr, likelihood_expr) for one or more user-defined log-probability functions.
The argument(s) must be bare symbols ending in _lpdf, _lpmf, _lcdf, or _lccdf. For each foo_lpdf (or _lpmf/etc.), the macro emits the registrations:
StanBlocks.lpxf_expr(::typeof(foo)) = foo_lpdf
StanBlocks.rng_expr(::typeof(foo)) = foo_rng
StanBlocks.likelihood_expr(::typeof(foo)) = foo_lpdfsThe companion foo_rng and foo_lpdfs (resp. _lpmfs/_lcdfs/_lccdfs) names must already exist when the registrations execute. This macro does not parse function bodies and does not wrap @deffun.
StanBlocks.@lhs Macro
@lhs foo_lpdf(y::T, args...) = bodyInside a @deffun block, opt this method into base-level LHS inference. Without @lhs, only the _lpdf-keyed tracetype is registered (so the method dispatches when called explicitly), but lhs ~ foo(args...) cannot trace because the base foo has no tracetype keyed on its argument signature. @lhs registers tracetype(::CanonicalExpr{<:typeof(foo), <:Tuple{lhs_type[2:end]...}}) so the sampling form works.
Compose with @lpxf (any order — @lhs @lpxf … or @lpxf @lhs …) to also register the dispatch hooks for foo/foo_rng/foo_lpdfs.
Standalone @lhs (outside @deffun) is not supported and errors immediately.
Runtime Assertions
StanBlocks.@stan_assert Macro
@stan_assert cond
@stan_assert cond messageStan-compatible runtime assertion. Expands to if !cond; reject(msg); end, where Stan's reject aborts the current MCMC proposal with the message. Without an explicit message, a default "assertion failed: <cond>" is used.
Use inside @deffun bodies (control flow is not allowed in @slic model bodies — wrap the check in a helper if needed at the model level).
Example
@deffun safe_log(x::real)::real = begin
@stan_assert x > 0 "safe_log: argument must be positive"
return log(x)
endModel Inspection and Compilation
StanBlocks.return_type_of Function
return_type_of(f, args...) -> StanTypeInfer the Stan return type and shape of a SLIC-callable function for the given representative Julia arguments. The result is the same StanType used by the transpiler and prints as Stan syntax, for example real, vector[3], or matrix[2, 4].
Inside an @deffun body, return_type_of(f, args...) is a transpile-time type token and may be used in a computed type annotation:
@deffun element_type(x::real)::real = x
@deffun copy_like(x::vector[n]) = begin
out::return_type_of(element_type, x[1])[n]
for i in 1:n
out[i] = x[i]
end
out
endThe query is intentionally bounded to non-inline @deffun functions and @defsig-registered SLIC callables whose result is a scalar or sized Stan container. Inline functions, closures, sub-models, arbitrary Julia functions, and tuple/user-defined-type results require a full call-site trace and are not queryable through this API. Inside a UDF, spell symbolic output dimensions explicitly (return_type_of(f, x)[n]) when they are already bound by the surrounding signature.
StanBlocks.compile_slic_bundle Function
compile_slic_bundle(data, definitions, body;
udf_definitions=(), anonymous_submodels=(), name=nothing)Compile an ordered collection of @deffun UDF definitions, named SLIC sub-model definitions, anonymous sub-model dependencies, and one parent SLIC model body. Each udf_definitions value is either an expression accepted by @deffun or a named tuple with a required definition expression plus optional markers and assertions. definitions contains expressions shaped like f(args...) = begin ... end (without an outer @slic macro call); anonymous_submodels contains name => body_or_value pairs, where name is the Symbol used by the parent and the value is either an anonymous SLIC body expression (without an outer @slic) or an existing SlicModel; and body is the parent model expression. UDFs are installed first in their supplied order, then named SLIC definitions, then anonymous dependencies, in a fresh module. The parent is traced exactly once in that same module.
Structured UDF metadata is the macro-free spelling of trusted compiler-owned annotations. markers accepts one Symbol or a tuple/vector drawn from :stanonly, :juliacompat, :lhs, :lpxf, and :inline; :inline cannot be combined with :lhs or :lpxf. assertions is a tuple/vector of named tuples with a condition AST and optional string message. Assertions are prepended to one bodyful definition with the semantics of @stan_assert. Unknown fields, markers, duplicates, and malformed assertions fail before evaluation.
Each UDF or SLIC definition, and the parent body, may be written as either a bare expression or source_part => expression, where source_part is a Symbol or string. Labeled parts preserve that identity in diagnostic results. Bare expressions retain the legacy source-location behavior, with slic_bundle used when the expression has no source file.
Each anonymous dependency is either name => body_or_value or source_part => (name => body_or_value). A body expression is expanded by @slic inside the owned workspace, so it sees the bundle's earlier definitions without caller-side Core.eval. An existing SlicModel keeps its original defining module. In both forms the parent refers to the dependency by name, and repeated calls keep ordinary anonymous-submodel kwarg binding and hygienic LHS namespaces.
The result is a named tuple with:
model: the tracedStanModel, ready for cheap data rebinding;descriptor: itsModelDescriptor, withnameforwarded tostan_descriptor;code: the generated Stan source.
This is an integration boundary for already-parsed, trusted SLIC expressions. It does not parse or sandbox source, and it deliberately preserves @slic's macro-expansion semantics: macros inside a supplied expression can execute Julia code during expansion. Validate untrusted source before calling this function and isolate its execution when it comes from an anonymous user.
Example
definitions = [:(latent(scale) = begin
z ~ normal(shift_zero(0.0), scale)
return z
end)]
anonymous_submodels = ["local-prior" => (:local_prior => quote
z ~ normal(location, scale)
return z
end)]
udf_definitions = ["shift-zero" => :(shift_zero(x::real)::real = begin
x + 0.25
end), "safe-log" => (;
definition=:(safe_log(x::real)::real = begin
log(x)
end),
markers=:stanonly,
assertions=((;
condition=:(x > 0),
message="safe_log: x must be positive",
),),
)]
body = "parent" => quote
mu ~ latent(1.0)
offset ~ local_prior(; location=0.0, scale=1.0)
y ~ normal(mu + offset, 1.0)
end
result = compile_slic_bundle((; y=[0.1, -0.2]), definitions, body;
udf_definitions, anonymous_submodels, name=:hierarchical)
result.code
result.descriptor.inputsStanBlocks.stan_code Function
stan_code(model) -> StringReturn the generated Stan source for model (a SlicModel or StanModel) as a plain String. This is the intentional source-inspection API: ordinary terminal, Markdown, and HTML display shows a semantic model summary and never calls this function automatically.
For a SlicModel, tracing runs first via stan_model; for an already-traced StanModel, only the rendering pass runs. Output covers the full Stan program — data, transformed_data, parameters, transformed_parameters, model, and generated_quantities blocks — with automatic block placement applied.
Pair with transpiles for boolean smoke tests and stan_instantiate to compile the generated code via BridgeStan.
StanBlocks.stan_model Function
stan_model(slic::SlicModel) -> StanModelTrace slic end-to-end (forward / backward / distribute passes), returning the inferred StanModel — a fully resolved representation of the Stan blocks plus the data dictionary.
Tracing is the expensive step. A StanModel is cheap to re-data: call model(; new_kwargs...) to swap the data dict without re-tracing. Use this in preference to repeatedly calling stan_instantiate on the original SlicModel.
Errors during tracing are wrapped in a StanBlocksError tagged with phase = :transpile.
StanBlocks.stan_instantiate Function
stan_instantiate(model; kwargs...) -> StanProblemExported alias for StanBlocks.instantiate. Compiles model (a SlicModel or StanModel) via BridgeStan and returns a StanLogDensityProblems.StanProblem implementing the LogDensityProblems interface. See instantiate for the full kwarg list.
StanBlocks.instantiate Function
instantiate(model; nan_on_error=true, make_args=["STAN_THREADS=true"], warn=false, path=…) -> StanProblem
stan_instantiate(model; ...) -> StanProblemCompile model (a SlicModel or StanModel) via BridgeStan and return a StanLogDensityProblems.StanProblem. The returned value implements the LogDensityProblems interface — call LogDensityProblems.dimension, logdensity, and logdensity_and_gradient on it.
stan_instantiate is an exported alias for instantiate.
Keyword arguments
path::AbstractString— where to write the.stanfile. Defaults to"tmp/<hash>.stan", so identical generated code is cached on disk.nan_on_error::Bool = true— make BridgeStan returnNaNinstead of throwing on evaluation failures.make_args::Vector{String} = ["STAN_THREADS=true"]— extra arguments forwarded to Stan'smake.warn::Bool = false— forwarded to BridgeStan.
Errors during compilation are wrapped in a StanBlocksError tagged with phase = :compile.
Model Descriptors
StanBlocks.stan_descriptor Function
stan_descriptor(model; name=nothing) -> ModelDescriptorReflect model (a SlicModel or an already-traced StanModel) as one descriptor-bearing, executable declaration: stable identity, inputs, outputs with their generative semantics, included Stan definitions, and the operations DERIVED from them.
A SlicModel is traced first (via stan_model); prefer passing a StanModel when reflecting the same model repeatedly, since tracing is the expensive step.
name overrides the model's own (gensym'd, for an anonymous @slic begin … end) name. It is informational — id is derived from the generated Stan source, not from the name.
Derived operations
Nothing here is a hand-maintained list; each operation appears exactly when the traced model supports it.
| operation | offered when |
|---|---|
:transpile | always |
:instantiate | always (fails loudly at run time if a required input is unbound) |
:fit | the model has ≥1 parameter and ≥1 likelihood term — i.e. a non-held-out observation reaches the model block. A pure prior-predictive model, or one whose every observation is cv-held-out, offers no :fit |
:predict | ≥1 output with generative == :draw |
:pointwise_loglik | ≥1 output with generative == :pointwise_loglik |
Ask for one with stan_operation and run it with stan_execute; both fail closed on an operation the model does not offer.
Example
m = @slic begin
sigma ~ exponential(1.)
mu ~ normal(0., 10.)
y ~ normal(mu, sigma)
end (; y)
d = stan_descriptor(m; name=:simple)
d.id # "…" — stable, content-derived
required_inputs(d) # (:y,) — not the derived size `y_n`
[i.name for i in d.inputs if i.observed] # [:y]
[o.name for o in d.outputs if o.generative == :draw] # [:y_gen]
[f.name for f in d.definitions] # emitted `functions` inventory
[op.name for op in d.operations] # [:transpile, :instantiate, :fit, :predict, :pointwise_loglik]
stan_execute(d, :transpile) # the Stan source
prob = stan_execute(d, :fit) # a BridgeStan-backed StanProblem
stan_execute(d, :predict; problem=prob, draws=theta_unc, seed=1) # (; y_gen = […])See also stan_operation, stan_execute, stan_definition, stan_definition_closure, required_inputs.
StanBlocks.required_inputs Function
required_inputs(d::ModelDescriptor) -> Tuple{Vararg{Symbol}}The input names a consumer must actually supply — every input that is neither inlined (folded into the generated source; it never reaches the data JSON) nor derived (another input's declared size, re-derived when that container is re-bound). This is the set a generated form should collect, and it is what each operation's inputs field reports.
The data block itself is wider than this: d.inputs also carries the derived sizes, so a consumer that wants the full JSON payload can still see them.
StanBlocks.stan_definition Function
stan_definition(d::ModelDescriptor, name; signature=nothing) -> ModelDefinitionLook up one included Stan definition by its exact emitted name (a Symbol or string). The lookup fails closed when the name is absent. If valid Stan overloads make the emitted name ambiguous, it also fails closed and lists the available signatures; pass one back via signature= to select exactly.
StanBlocks.stan_definition_closure Function
stan_definition_closure(d::ModelDescriptor, selected...) -> Tuple{Vararg{ModelDefinition}}Select one or more emitted definition names (or ModelDefinition values) and return them with their complete transitive included-definition dependencies. The result preserves d.definitions' authoritative functions-block order. Name selection uses stan_definition, so an absent or overloaded-ambiguous name fails closed rather than returning a non-executable fragment.
StanBlocks.stan_operation Function
stan_operation(d::ModelDescriptor, name::Symbol) -> ModelOperationThe operation name of descriptor d, or a loud error naming the operations d actually offers.
Fails closed by design: which operations exist is DERIVED from the model (see stan_descriptor), so asking for one the model does not support is a statement about the model — a prior-predictive model has no :fit, a model with no _gen twin has no :predict — and silently returning nothing would push that discovery into the consumer.
StanBlocks.stan_execute Function
stan_execute(d::ModelDescriptor, name::Symbol; kwargs...)Run operation name of descriptor d. Errors loudly if d does not offer it (see stan_operation).
Per-operation contract
:transpile→String. Takes no keyword arguments.:instantiate,:fit→ aStanLogDensityProblems.StanProblemimplementing theLogDensityProblemsinterface. Data keyword arguments re-bind inputs before compiling (stan_execute(d, :fit; y=newy)); reservedinstantiatekeywords (path,nan_on_error,make_args,warn) are forwarded to it. Refuses, naming them, if any required input is still unbound.:predict,:pointwise_loglik→ aNamedTuplemapping each of the operation'soutputsto its drawn values. Required keyword arguments:draws— one unconstrained parameter vector (Vector{Float64}), or aMatrixwhose COLUMNS are such vectors, or a vector of them.seed::Int— seeds BridgeStan's RNG for the generated-quantities draw.
Optional:
problem— aStanProblemfrom a previous:fit/:instantiate, to skip recompilation. Any other keyword argument is forwarded to the compilation step exactly as for:fit. For a single draw each entry is aVector{Float64}(length 1 for a scalar output); for several, aMatrixwith one column per draw.
StanBlocks.ModelDescriptor Type
ModelDescriptorThe reflectable, executable declaration of one Stan model — the value returned by stan_descriptor.
Fields
id::String— stable identity, derived from the generated Stan source (the same keyinstantiatecaches the compiled artifact under). Two models with byte-identical Stan share anid; changing the model changes it. Independent of the process, of tracing order, and of the gensym'dname.name::Symbol— the model's name. Informational only —@slic begin … endproduces a gensym; passname=tostan_descriptorto set it.docstring::String— the model's leading docstring, if any.model::StanModel— the traced model the descriptor reflects.inputs::Tuple{Vararg{ModelInput}}outputs::Tuple{Vararg{ModelOutput}}definitions::Tuple{Vararg{ModelDefinition}}— included Stan definitions in the exact order used by thefunctionsblock emitter.operations::Tuple{Vararg{ModelOperation}}
StanBlocks.ModelInput Type
ModelInputOne entry of a descriptor's data block — see stan_descriptor.
Fields
name::Symbol— the Stan data variable name.type::Symbol— the declared Stan center type (:real,:int,:vector,:matrix,:simplex, …).size::Tuple— the declared size expressions, outermost first. Entries are emitted expressions: a literal, aSymbolnaming another input, or a larger expression. Resolve a symbolic entry against the other inputs'value.constraints::NamedTuple— thelower/upper/offset/multipliersubset actually spelled on the declaration. Empty does not mean unconstrained: a natively constrained center (simplex,cholesky_factor_corr, …) carries its support intype.value— the bound Julia value. Always present: a symbol with no value never reaches the data block (an unresolvable one fails at tracing time, not here).inlined::Bool—truefor a value the emitter folds into the generated source rather than passing as data (functions, closures, 0-dim type tokens).derived::Bool—truewhen this input is another input's declared size (y_nforvector[y_n] y). Re-binding the container re-derives it, so a consumer must never ask for it separately. Neither aninlinednor aderivedinput is part ofrequired_inputs, and neither belongs in a generated form.observed::Bool— this variable appears on the left of a~(it is data the model conditions on), as opposed to a covariate or a size.held_out::Bool— the cross-validation flag: this variable's likelihood contribution is dropped and it re-draws in generated quantities. Contagion- aware, not a record of what you marked — cv propagates through every expression it reaches, so marking one input viaStanBlocks.stan.maybecvcan make several inputs reportheld_out.
StanBlocks.ModelOutput Type
ModelOutputOne quantity the model produces — see stan_descriptor.
Fields
name::Symbol— the Stan variable name (matches BridgeStan'sparam_namesprefix; a container appears there asname.1,name.2, …).kind::Symbol— which Stan block declares it::parameter,:transformed_parameter, or:generated_quantity.type::Symbol,size::Tuple,constraints::NamedTuple— as forModelInput.generative::Symbol— what the quantity MEANS::posterior— a sampled parameter or a deterministic function of one.:draw— a predictive draw of an observation (the compiler-owned<obs>_gentwin).sourcenames the observation.:pointwise_loglik— the per-element log-likelihood of an observation (the compiler-owned<obs>_likelihoodcompanion).sourcenames it.:derived— any other generated quantity: a prior-only sample, a cv-flipped re-draw of a latent, a modelreturnvalue.
source::Union{Symbol,Nothing}— the observation a:draw/:pointwise_loglikderives from;nothingotherwise.segments::Union{Nothing,Vector{Int}}— group boundaries when this quantity is either the twin of a ragged observation or the emitted flat-memory carrier of a ragged plate result/member;nothingfor every dense quantity. The entries are the carrier's own inclusive 1-based end indices, so groupgof a flat carrier or:drawoccupiessegments[g-1]+1 : segments[g](withsegments[0] ≡ 0), while groupgof a:pointwise_loglikis elementg. Each ragged plate member reports its own layout; members may have different axes, so consumers must not copy segments from a sibling or an input. Publishing the layout here lets consumers restore groups without reaching into compiler-owned names or carrier tuples.
StanBlocks.ModelDefinition Type
ModelDefinitionOne included definition in a model's emitted Stan functions block — see stan_descriptor, stan_definition, and stan_definition_closure.
The descriptor is projected from the traced functions dictionary that the emitter itself prints. It is not reconstructed by parsing generated Stan.
Fields
name::Symbol— the exact emitted Stan callable name. This is the stable public lookup key and preserves leading underscores.binding::Union{Symbol,Nothing}— the author-side Julia binding when there is one. It can differ fromnamewhen StanBlocks specialises or renames a helper; compiler-lifted closures have no author binding and reportnothing.kind::Symbol—:functionor:closure.signature::String— the exact emitted return/name/argument signature, normalized onto one line. It distinguishes valid Stan overloads that share onename.source::String— the complete emitted definition, without the surroundingfunctions {}block.span::UnitRange{Int}— the string-index range ofsourceinstan_code(descriptor.model), soSubString(code, first(span), last(span)) == source.dependencies::Tuple{Vararg{Symbol}}— direct included-definition names in first-use order.dependency_signatures::Tuple{Vararg{String}}— exact dependency links, aligned withdependencies; these remain unambiguous when Stan overloads share a name.
StanBlocks.ModelOperation Type
ModelOperationOne executable operation DERIVED from a model declaration — never a consumer-maintained entry. See stan_descriptor for the derivation rules and stan_execute to run one.
Fields
name::Symbol—:transpile,:instantiate,:fit,:predict, or:pointwise_loglik.title::String— a human label a UI can render without a lookup table.inputs::Tuple{Vararg{Symbol}}— descriptor input names this operation consumes (empty for:transpile, which needs no data).outputs::Tuple{Vararg{Symbol}}— descriptor output names it produces.run— the executor, called asrun(descriptor; kwargs...).
Smoke Tests
StanBlocks.transpiles Function
transpiles(model; re=true) -> BoolReturn true if model (a SlicModel or StanModel) successfully transpiles to Stan source via stan_code, false otherwise.
This is the fast smoke-test for a model — it exercises the full SLIC tracing pipeline but stops short of invoking stanc / BridgeStan.
Set re=false to swallow the transpilation error and just return false (useful for batch regression dashboards); the default re=true rethrows so failures surface with their normal StanBlocksError trace.
StanBlocks.compiles Function
compiles(model; re=true) -> BoolReturn true if model (a SlicModel or StanModel) successfully transpiles and compiles via BridgeStan (i.e. stan_instantiate succeeds), false otherwise.
Strictly stronger than transpiles: a model that transpiles can still fail to compile if stanc rejects the generated Stan or the C++ build fails.
Set re=false to swallow the error and just return false; the default re=true rethrows.
StanBlocks.stanc_check Function
stanc_check(stan_code::AbstractString; warn_pedantic=true) -> (ok::Bool, output::String)Run the stanc compiler on stan_code (written to a temporary file) and return whether it accepted the code plus any compiler output (warnings, errors). Binary discovery: $STANC_PATH env var → BridgeStan's bin/stanc. Errors if neither is available.
Types
StanBlocks.SlicModel Type
The AST and the data, pre-tracing. Can be instantiated via stan_instantiate.
The mod field stores the defining module (set automatically by @slic), used for symbol resolution during tracing — functions defined via @deffun in package extensions are found by checking mod before falling back to Main.
Warning:
Repeatedly instantiating SlicModels is inefficient, as the tracing is redone for every instantiation. Instead, get the StanModel first (via model = stan_model(slic_model)) and update its data (via new_model = model(;x=new_x)).
StanBlocks.StanModel Type
The inferred Stan model, post-tracing. Can be instantiated via stan_instantiate.
Errors
StanBlocks.StanBlocksError Type
StanBlocksError <: ExceptionWraps errors that occur during transpilation, compilation, or evaluation of Stan models.
Fields
phase::Symbol: the pipeline stage where the error occurred (:transpile,:compile, or:evaluate)context::String: a description of what was being processed (e.g."model: eight_schools")cause::Any: the underlying error, typically an(exception, backtrace)tuple
StanBlocks.StanBlocksDiagnostic Type
StanBlocksDiagnosticMachine-readable location and classification for a SLIC failure.
source_part identifies the caller-supplied source/editor part. line and column are one-based when known and nothing when the compiler has no span at that granularity. code is a stable, coarse failure class; message is a concise user-facing description of the immediate cause.
StanBlocks.diagnostic Function
diagnostic(error; source_part=nothing, line_offset=0)Return a StanBlocksDiagnostic for a StanBlocksError or Julia Meta.ParseError, and nothing for unsupported exceptions. source_part can label a parser error (or supply a fallback label); line_offset maps a synthetic parser wrapper back to the caller's source, e.g. -1 for a leading begin line.
Stable SLIC codes are :slic_parse_error, :slic_trace_error, and :slic_lowering_error.